OpenCV图像转换出错了

时间:2015-08-07 21:32:14

标签: c++ opencv

我有一个算法可以做一些事情。其中,如果我正在处理CV_8UC3图像,则转换可以正常工作,但如果文件类型为C_16UC3则会出错。 这是一些代码:

             //new image is created
             Mat3w img(100,100,Vec3w(1000,0,0));
             //Image Conversion - ERROR!
             cv::Mat inputSource;
             //saving the image here will work
             img.convertTo(inputSource, CV_64FC3);
             //saving the image here will not work -> black image

问题是CV_16UC3图像的处理结果是正确尺寸但完全黑色的图像。 问题出在转换中,因为之前保存图像会产生合法的图像,而在保存之后会立即保留图像。

修改

我做了一些更改:切断一些无用的代码并添加了inputSource声明。 现在,在我尝试的时候,我得出的结论是,我还没有理解CV类型,或者发生了一些奇怪的事情。 我一直认为类型中的数字表示每个通道的位数。所以,在我看来,CV_16UC3是一个3通道,每通道16位。由于我在测试期间(在img.convertTo之前)实际保存的图像实际上具有每个通道编号的匹配位,因此这一想法得到了加强。奇怪的是,保存的inputSource(类型CV_64FC3)是一个8bpc图像。

我错过了什么?

1 个答案:

答案 0 :(得分:0)

您对imwriteimread在OpenCV中的工作方式感到困惑。来自OpenCV documentation

<强> imwrite

函数imwrite将图像保存到指定文件。基于文件扩展名选择图像格式(有关扩展名列表,请参阅imread())。对于PNG,JPEG 2000和TIFF,只有8位(或16位无符号(CV_16U)单通道或3通道(带'BGR'通道顺序)图像可以使用此功能保存。如果格式,深度或渠道顺序不同,请在保存之前使用Mat::convertTo()cvtColor()进行转换。或者,使用通用FileStorage I / O函数将图像保存为XML或YAML格式。

<强> imread

函数imread从指定文件加载图像并返回它。可能的标志是:

  • IMREAD_UNCHANGED:如果设置,则按原样返回加载的图像(使用Alpha通道,否则会被裁剪)。
  • IMREAD_GRAYSCALE:如果设置,请始终将图像转换为单通道灰度图像。
  • IMREAD_COLOR:如果设置,请始终将图像转换为3通道BGR彩色图像。
  • IMREAD_ANYDEPTH:如果设置,当输入具有相应深度时返回16位/ 32位图像,否则将其转换为8位。
  • IMREAD_ANYCOLOR:如果设置,则以任何可能的颜色格式读取图像。

因此,对于您的情况,我会保存CV_16U而不进行转换,而CV_64F会被转换并保存为CV_8U。如果您要存储double数据,则应使用FileStorage。 您还应该注意使用imread图像和相应的标记。

这个例子应该澄清:

#include <opencv2\opencv.hpp>
using namespace cv;

int main()
{
    // Create a 16-bit 3 channel image
    Mat3w img16UC3(100, 200, Vec3w(1000, 0, 0));
    img16UC3(Rect(0, 0, 20, 50)) = Vec3w(0, 2000, 0);

    // Convert to 64-bit (double) 3 channel image
    Mat3d img64FC3;
    img16UC3.convertTo(img64FC3, CV_64FC3);

    // Save to disk
    imwrite("16UC3.png", img16UC3); // No conversion
    imwrite("64FC3.png", img64FC3); // Converted to CV_8UC3

    FileStorage fout("64FC3.yml", FileStorage::WRITE);
    fout << "img" << img64FC3; // No conversion
    fout.release();


    Mat img_maybe16UC3_a = imread("16UC3.png" /*, IMREAD_COLOR*/);  // Will be CV_8UC3
    Mat img_maybe16UC3_b = imread("16UC3.png", IMREAD_ANYDEPTH);    // Will be CV_16UC1
    Mat img_maybe16UC3_c = imread("16UC3.png", IMREAD_UNCHANGED);   // Will be CV_16UC3 

    Mat img_maybe64FC3_a = imread("64FC3.png" /*, IMREAD_COLOR*/);  // Will be CV_8UC3
    Mat img_maybe64FC3_b = imread("64FC3.png", IMREAD_ANYDEPTH);    // Will be CV_8UC1
    Mat img_maybe64FC3_c = imread("64FC3.png", IMREAD_UNCHANGED);   // Will be CV_8UC3

    Mat img_mustbe64FC3;
    FileStorage fin("64FC3.yml", FileStorage::READ);
    fin["img"] >> img_mustbe64FC3; // Will be CV_64FC3
    fin.release();

    return 0;
}