我有一个算法可以做一些事情。其中,如果我正在处理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图像。
我错过了什么?
答案 0 :(得分:0)
您对imwrite
和imread
在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从指定文件加载图像并返回它。可能的标志是:
因此,对于您的情况,我会保存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;
}