Я использую набор данных, в котором есть изображения, где каждый пиксель является 16-битным без знака, храня значение глубины этого пикселя в мм. Я пытаюсь визуализировать это как изображение глубины серого, выполнив следующие действия:
cv::Mat depthImage;
depthImage = cv::imread("coffee_mug_1_1_1_depthcrop.png", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR ); // Read the file
depthImage.convertTo(depthImage, CV_32F); // convert the image data to float type
namedWindow("window");
float max = 0;
for(int i = 0; i < depthImage.rows; i++){
for(int j = 0; j < depthImage.cols; j++){
if(depthImage.at<float>(i,j) > max){
max = depthImage.at<float>(i,j);
}
}
}
cout << max << endl;float divisor = max / 255.0;
cout << divisor << endl;
for(int i = 0; i < depthImage.rows; i++){
for(int j = 0; j < depthImage.cols; j++){
cout << depthImage.at<float>(i,j) << ", ";
max = depthImage.at<float>(i,j) /= divisor;
cout << depthImage.at<float>(i,j) << endl;
}
}imshow("window", depthImage);
waitKey(0);
Тем не менее, он показывает только два цвета, потому что все значения находятся близко друг к другу, то есть в диапазоне 150-175 + маленькие значения, которые отображаются черным (см. Ниже).
Есть ли способ нормализовать эти данные так, чтобы они отображали различные уровни серого, чтобы выделить эти небольшие различия в глубине?
Согласно документация, Функция imshow может использоваться с различными типами изображений. Он поддерживает 16-битные изображения без знака, так что вы можете отобразить свое изображение, используя
cv::Mat map = cv::imread("image", CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);
cv::imshow("window", map);
В этом случае диапазон значений изображения отображается из диапазона [0, 255 * 256] в диапазон [0, 255].
Если ваше изображение содержит только значения в нижней части этого диапазона, вы увидите неясное изображение. Если вы хотите использовать полный диапазон отображения (от черного до белого), вам следует настроить изображение так, чтобы оно охватывало ожидаемый динамический диапазон, один из способов сделать это
double min;
double max;
cv::minMaxIdx(map, &min, &max);
cv::Mat adjMap;
cv::convertScaleAbs(map, adjMap, 255 / max);
cv::imshow("Out", adjMap);
Добавив к ответу samg ‘, вы можете еще больше расширить диапазон отображаемого изображения.
double min;
double max;
cv::minMaxIdx(map, &min, &max);
cv::Mat adjMap;
// expand your range to 0..255. Similar to histEq();
map.convertTo(adjMap,CV_8UC1, 255 / (max-min), -min);
// this is great. It converts your grayscale image into a tone-mapped one,
// much more pleasing for the eye
// function is found in contrib module, so include contrib.hpp
// and link accordingly
cv::Mat falseColorsMap;
applyColorMap(adjMap, falseColorsMap, cv::COLORMAP_AUTUMN);
cv::imshow("Out", falseColorsMap);
Результат должен быть примерно таким, как показано ниже
Еслиimshow
вход имеет тип данных с плавающей запятой, тогда функция предполагает, что значения пикселей находятся в [0; 1] диапазон. В результате все значения выше 1 отображаются белым.
Так что вам не нужно делить divisor
на 255.
В дополнение к ответу Сэмми, если исходный цвет диапазона равен [-min, max] и вы хотите выполнить выравнивание гистограммы и отобразить цвет глубины, код должен быть таким, как показано ниже:
double min;
double max;
cv::minMaxIdx(map, &min, &max);
cv::Mat adjMap;
// Histogram Equalization
float scale = 255 / (max-min);
map.convertTo(adjMap,CV_8UC1, scale, -min*scale);
// this is great. It converts your grayscale image into a tone-mapped one,
// much more pleasing for the eye
// function is found in contrib module, so include contrib.hpp
// and link accordingly
cv::Mat falseColorsMap;
applyColorMap(adjMap, falseColorsMap, cv::COLORMAP_AUTUMN);
cv::imshow("Out", falseColorsMap);