2014-10-16 100 views
1

我目前正在处理从保存为16位灰度PNG的kinect传感器检索的深度图像。目前我只是使用imread()函数和CV_LOAD_IMAGE_GRAYSCALE标志加载这些图像,并且一切正常。我这样做的原因是因为一些OpenCV函数依赖于输入8位OpenCV如何在16位和8位之间进行imread转换

下面是问题:下一步是直接使用由16位传感器捕获的深度帧。我虽然这将足以使用covertTo(dst, CV_8U, 1.0/256.0)来缩放和转换值,但由于某种原因,生成的图像与加载为8位的图像看起来非常不同。那么,OpenCV如何将图像加载为8位时进行转换。

这里是我用于测试的image,这里是一些代码,显示问题:

int main(int argc, char *argv[]){ 

    Mat depth8 = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE); 
    Mat depth16 = imread(argv[1], CV_LOAD_IMAGE_ANYDEPTH); 

    depth16.convertTo(depth16, CV_8U, 1.0/256.0); 

    Mat diff; 
    absdiff(depth8, depth16, diff); 

    //imshow("depth8", depth8*255.0/16.0); 
    //imshow("depth16", depth16*255.0/16.0); 
    imshow("diff", diff > 0); 
    waitKey(0); 

    return 0; 
} 

代码的输出可以发现here

如果您想知道为什么测试图像太暗,这是因为16位的最大值比kinect产生的值(可达4000左右)大得多。

另一件事:作为8位加载的图像似乎比转换的好得多。如果你在两行中发表评论,你可以看到我的意思。

再说一遍:OpenCV如何进行转换?

在此先感谢。

+1

可能只是从16位值中获取8个最高有效位。 – 2014-10-16 16:21:50

+0

是的,就是这样。我测试了它,他们真的只是抓住了一点点。这很奇怪,因为每当用户想要在类型间转换时,他们正在应用saturate_cast <>。在文档中他们说他们正在这样做“不仅仅是通过采取一些输入来形成结果”。 – thomas 2014-10-16 17:08:07

回答

3
  1. imread函数最终会调用imread_(...)highgui/src/loadsave.cpp

  2. 将在imread_函数中确定正确的解码器,并根据imread()中的第二个参数初始化矩阵mat

  3. mat传递给解码器的readData()方法。在这种情况下,调用png解码器。

  4. 根据mat的深度,可能会调用png解码器中的png_set_strip_16highgui/src/grfmt_png.cpp)。

  5. png_set_strip_16()使libpng最终调用png_do_chop()。 (它只是丢弃低字节,参见libpng中的pngrtran.c