OpenCV:如何可视化深度图像

时间:2012-12-12 12:40:09

标签: c++ opencv visualization kinect depth

我正在使用一个数据集,其中包含图像,其中每个像素都是16位无符号int,以mm为单位存储该像素的深度值。我试图通过执行以下操作将其可视化为灰度深度图像:

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 image greyscale image

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

4 个答案:

答案 0 :(得分:21)

根据documentation,函数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);

答案 1 :(得分:20)

添加到samg&#39;回答,您可以扩展显示图像的范围。

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);

结果应该类似于下面的

enter image description here

答案 2 :(得分:2)

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

因此,您无需将divisor除以255。

答案 3 :(得分: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);