24

我正在使用一个数据集,其中包含图像,其中每个像素都是 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 范围内 + 显示为黑色的小值(见下文)。

rgb 图像 灰度图像

有没有办法对这些数据进行标准化,使其显示各种灰度级以突出这些小的深度差异?

4

4 回答 4

27

根据文档,函数 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);
于 2012-12-12T15:02:20.850 回答
25

添加到 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);

结果应该类似于下面的结果

在此处输入图像描述

于 2012-12-12T15:43:17.823 回答
2

如果imshow输入具有浮点数据类型,则该函数假定像素值在 [0; 1]范围。结果,所有大于 1 的值都显示为白色。

所以你不需要除以divisor255。

于 2012-12-12T12:48:41.890 回答
2

添加到 Sammy 的答案中,如果原始范围颜色为 [-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);
于 2013-05-25T03:25:49.163 回答