OpenCV图像转换出错

OpenCV image conversion goes wrong

本文关键字:出错 转换 图像 OpenCV      更新时间:2023-10-16

我有一个算法做一些事情。其中,如果我正在处理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_16UC3是一个3通道,每个通道16位。我在测试期间保存的图像(在image . convertto之前)实际上每个通道号都有匹配的位,这一事实加强了这个想法。奇怪的是,保存的inputSource(类型CV_64FC3)是一个8bpc的图像。

我错过了什么?

您会混淆imwriteimread在OpenCV中的工作方式。来自OpenCV文档

imwrite

imwrite函数将图像保存到指定的文件中。图像格式是根据文件名扩展名选择的(参见imread()的扩展名列表)。只有8位(或16位无符号(CV_16U)在PNG、JPEG 2000和TIFF的情况下)单通道或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 <opencv2opencv.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;
}