OpenCV imread如何在16位和8位之间进行转换

时间:2014-10-16 16:13:35

标签: c++ opencv

我目前正在处理从kinect传感器检索到的深度图像,这些图像已保存为16位灰度PNG' s。目前我只是使用带有imread()标志的CV_LOAD_IMAGE_GRAYSCALE函数加载这些图像,一切正常。我这样做的原因是因为一些OpenCV函数依赖于 8位的输入。

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

以下是我用于测试的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 个答案:

答案 0 :(得分:3)

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

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

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

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

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