OpenCV image conversion goes wrong

匿名 (未验证) 提交于 2019-12-03 01:26:01

问题:

I have an algorithm that does some stuff. Among them, there is a conversion that works fine if I'm working on a CV_8UC3 image but goes wrong if the file type is C_16UC3. This is some code:

             //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 

The problem is that the CV_16UC3 image's processing result is an image of the right dimensions but fully black. The problem is in the conversion because saving the image right before will give a legit one while saving it right after will give an almost completely white one.

EDIT:

I made some changes: cut off some useless code and added the inputSource declaration. Now, while I was trying stuff, I arrived at the conclusion that either I haven't understood the CV Types, or something strange is happening. I always thought that the number in the type was indicating the number of bits per channel. So, in my head, CV_16UC3 is a 3 channel with 16bits per channel. That idea is strengthened by the fact that the image I save during as tests (before the img.convertTo) actually had matching bits per channel number. The strange thing, is that the saved inputSource (type CV_64FC3) is an 8bpc image.

What's am I missing?

回答1:

You get confused with the way imwrite and imread work in OpenCV. From the OpenCV documentation

imwrite

The function imwrite saves the image to the specified file. The image format is chosen based on the filename extension (see imread() for the list of extensions). Only 8-bit (or 16-bit unsigned (CV_16U) in case of PNG, JPEG 2000, and TIFF) single-channel or 3-channel (with ‘BGR’ channel order) images can be saved using this function. If the format, depth or channel order is different, use Mat::convertTo() , and cvtColor() to convert it before saving. Or, use the universal FileStorage I/O functions to save the image to XML or YAML format.

imread

The function imread loads an image from the specified file and returns it. Possible flags are:

  • IMREAD_UNCHANGED : If set, return the loaded image as is (with alpha channel, otherwise it gets cropped).
  • IMREAD_GRAYSCALE : If set, always convert image to the single channel grayscale image.
  • IMREAD_COLOR : If set, always convert image to the 3 channel BGR color image.
  • IMREAD_ANYDEPTH : If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.
  • IMREAD_ANYCOLOR : If set, the image is read in any possible color format.

So for your case, CV_16U are saved without conversion, while CV_64F is converted and saved as CV_8U. If you want to store double data, you should use FileStorage. You should also take care to use imread the image with the appropriate flag.

This example should clarify:

#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; } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!