Opencv image reading and storage problems
This article only elaborates on the reading and saving of Opencv images, focusing on the details that should be paid attention to during image reading and storage.
1. Image reading
First, let's take a look at the imread function declaration:
// C++: Mat basedMat imread(const string& filename, int flags=1 );// C: IplImage basedIplImage* cvLoadImage(const char* filename, int iscolor=CV_LOAD_IMAGE_COLOR );// C: CvMat basedCvMat* cvLoadImageM(const char* filename, int iscolor=CV_LOAD_IMAGE_COLOR );
Not listed herepython
Function declaration. As versions 2.x and 3.x are updatedC++
Version data structure andC
There are major differences in versions. The former reduces the large amount of pointer usage and makes usage easier. Therefore, we recommend that you use the former more. ToC++
Version functions are analyzed. The parameter list includes:
filename
: Image to be loaded (including file path and file name, which can be omitted from the default project path );
flags
: Identifier, which specifies the image loading color type. The default value is 1:
IMREAD_UNCHANGED/CV_LOAD_IMAGE_UNCHANGED: The Source image is loaded without changes. IMREAD_GRAYSCALE/CV_LOAD_IMAGE_GRAYSCALE: converts an image to a grayscale image (GRAY, Channel 1 ). IMREAD_COLOR/CV_LOAD_IMAGE_COLOR: Convert the image into a color chart (BGR, 3 channels ). IMREAD_ANYDEPTH/CV_LOAD_IMAGE_ANYDEPTH: Any bit depth. If the loaded image is not a 16-bit Bitmap or 32-bit Bitmap, it is converted to an 8-bit Bitmap. IMREAD_ANYCOLOR/CV_LOAD_IMAGE_ANYCOLOR: Any color. It is equivalent to IMREAD_UNCHANGED/CV_LOAD_IMAGE_UNCHANGED when used separately. > 0: The color graph of 3 channels is returned, but if it is a 4-channel (RGBA), Alpha needs to be retained, we do not recommend this because once this is used, this will cause Alpha channel to be stripped away. A negative value is recommended. = 0: returns a grayscale image. <0: returns an image with an Alpha channel.
If you likeimread("file.jpg")
By default, images are loaded in the form of parameters. You must note that the loaded images may not be the ones you originally wanted!
The meanings of the above identifiers can also be seen from the Opencv source code Enumeration type:
// highgui.hppenum{ // 8bit, color or not IMREAD_UNCHANGED =-1, // 8bit, gray IMREAD_GRAYSCALE =0, // ?, color IMREAD_COLOR =1, // any depth, ? IMREAD_ANYDEPTH =2, // ?, any color IMREAD_ANYCOLOR =4};// highui_c.henum{/* 8bit, color or not */ CV_LOAD_IMAGE_UNCHANGED =-1,/* 8bit, gray */ CV_LOAD_IMAGE_GRAYSCALE =0,/* ?, color */ CV_LOAD_IMAGE_COLOR =1,/* any depth, ? */ CV_LOAD_IMAGE_ANYDEPTH =2,/* ?, any color */ CV_LOAD_IMAGE_ANYCOLOR =4};
Opencv supports many image formats, but not all. It mainly includes:
Windows bitmaps ->
*.bmp
,
*.dib
(Always supported) JPEG files ->
*.jpeg
,
*.jpg
,
*.jpe
(See the Notes section) JPEG 2000 files ->
*.jp2
,
*.jpf
,
*.jpx
(See the Notes section) Portable Network Graphics ->
*.png
(See the Notes section) WebP ->
*.webp
(See the Notes section) Portable image format ->
*.pbm
,
*.pgm
,
*.ppm
(Always supported) Sun rasters ->
*.sr
,
*.ras
(Always supported)
TIFF files -> *.tiff
,*.tif
(See the Notes section)
Notes
1The function determines the type of an image by the content, not by the file extension.
2On Microsoft Windows * OS and MacOSX *, the codecs shipped with an OpenCV image (libjpeg, libpng, libtiff, and libjasper) are used by default. so, OpenCV can always read JPEGs, PNGs, and TIFFs. on MacOSX, there is also an option to use native MacOSX image readers. but beware that currently these native image loaders give images with different pixel values because of the color management embedded into MacOSX.
3On Linux *, BSD flavors and other Unix-like open-source operating systems, OpenCV looks for codecs supplied with an OS image. install the relevant packages (do not forget the development files, for example, "libjpeg-dev", in Debian * and Ubuntu *) to get the codec support or turn on the OPENCV_BUILD_3RDPARTY_LIBS flag in CMake.
4In the case of color images, the decoded images will have the channels stored in B G R order.
For common 4-channel image formats, Opencv reading results are different:
// 1.tif, 1.jp2 and 1.png are color images with 4 channels: R, G, B, Acv::Mat imageTif = cv::imread("E:\\1.tif"); // the default flags is 1cv::Mat imageJp2 = cv::imread("E:\\1.jp2"); // the default flags is 1cv::Mat imagePng = cv::imread("E:\\1.png"); // the default flags is 1std::cout << imageTif.channels() << std::endl; // prints 3std::cout << imageJp2.channels() << std::endl; // prints 3std::cout << imagePng.channels() << std::endl; // prints 3cv::Mat imageTif2 = cv::imread("E:\\1.tif", -1); // flags = -1cv::Mat imageJp22 = cv::imread("E:\\1.jp2", -1);cv::Mat imagePng2 = cv::imread("E:\\1.png", -1);std::cout << imageTif2.channels() << std::endl; // prints 3std::cout << imageJp22.channels() << std::endl; // prints 3std::cout << imagePng2.channels() << std::endl; // prints 4
It can be seen that currently, Opencv can directly read 4-channel images and retain the Alpha channel only in PNG format. For non-PNG format data, the application of Alpha channel needs to be retained. If you insist on using the Opencv library, it is recommended to convert the format ~
2. Image Storage
First, the imwrite function declaration:
// c++: Mat basedbool imwrite(const string& filename, InputArray img, const vector
& params=vector
() );// C: CvMat and IplImage basedint cvSaveImage(const char* filename, const CvArr* image, const int* params=0 );
StillC++
For example, the parameter list is as follows:
filename
: Name of the image to be saved (including the file path and file name, which can be omitted from the default project path );
img
: The image object to be saved;
params
: Encoding parameter settings for specific image storage, similar
pairs
Type,
(paramId_1, paramValue_1)
,
(paramId_2, paramValue_2)
... , Where
paramId_1
Is the Identifier value,
paramValue_1
Subsequent parameter settings corresponding to the Identifier value:
vector
compression_params;compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION); // paramId_1, png compressioncompression_params.push_back(9); // paramValue_2, compression level is 9
In Opencv, the encoding methods of JPEG, PNG, and PXM are specifically stated:
// highgui.hppenum{ IMWRITE_JPEG_QUALITY =1, // quality from 0 to 100, default value is 95. IMWRITE_PNG_COMPRESSION =16, // compression level from 0 to 9, default value is 3. IMWRITE_PNG_STRATEGY =17, IMWRITE_PNG_BILEVEL =18, IMWRITE_PNG_STRATEGY_DEFAULT =0, IMWRITE_PNG_STRATEGY_FILTERED =1, IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY =2, IMWRITE_PNG_STRATEGY_RLE =3, IMWRITE_PNG_STRATEGY_FIXED =4, IMWRITE_PXM_BINARY =32 // binary format flag: 0 or 1, default value is 1.};// highui_c.henum{ CV_IMWRITE_JPEG_QUALITY =1, CV_IMWRITE_PNG_COMPRESSION =16, CV_IMWRITE_PNG_STRATEGY =17, CV_IMWRITE_PNG_BILEVEL =18, CV_IMWRITE_PNG_STRATEGY_DEFAULT =0, CV_IMWRITE_PNG_STRATEGY_FILTERED =1, CV_IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY =2, CV_IMWRITE_PNG_STRATEGY_RLE =3, CV_IMWRITE_PNG_STRATEGY_FIXED =4, CV_IMWRITE_PXM_BINARY =32};
The meanings of the above identifiers are obviously not described. It is worth noting that the imwrite function supports a limited number of storage image types, including: 1, 3, and 4 channels, but there are also differences between different image formats:
For single-channel 8-bit Bitmap (or 16-bit Bitmap (CV_16U/CV_16UC1 PNG, JPEG 2000 and TIFF) or 3-channel (Channel sequence: B G R) images, all imwrite functions are supported. Functions can be used for the format, depth, or channel order inconsistent with the above
Mat::convertTo()
And
cvtColor()
After the function is converted, save it. Of course, general methods can also be used.
FileStorage
I/O operation. Save the image in XML or YAML format. For PNG images, you can save their Alpha channels and create an 8-bit or 16-bit 4-channel Bitmap (the channel sequence is B G R ), if a fully transparent Alpha channel is set to 0, otherwise the opacity is set to 255/65535.
For multi-channel images, it is also feasible to save each channel separately. On the one hand, you can write the corresponding storage function based on the Image Information and layer information, on the other hand, Opencv also provides specialized functionssplit
Each channel of the image can be extracted and savedvector
Medium:
PNG source Image
cv::Mat img = imread( "C:\\Users\\Leo\\Desktop\\Panda.png", CV_LOAD_IMAGE_UNCHANGED );std::vector
imageChannels;cv::split( img, imageChannels );cv::imwrite("E:\\0.jpg", imageChannels[0]);cv::imwrite("E:\\1.jpg", imageChannels[1]);cv::imwrite("E:\\2.jpg", imageChannels[2]);cv::imwrite("E:\\3.jpg", imageChannels[3]);
B G R A vcnPIE9wZW5jds7EtbXUtMLro7o8L3A + DQo8cHJlIGNsYXNzPQ = "brush: java;">
#include #include #include using namespace cv;using namespace std;void createAlphaMat(Mat &mat){ CV_Assert(mat.channels() == 4); for (int i = 0; i < mat.rows; ++i) { for (int j = 0; j < mat.cols; ++j) { Vec4b& bgra = mat.at (i, j); bgra[0] = UCHAR_MAX; // Blue bgra[1] = saturate_cast ((float (mat.cols - j)) / ((float)mat.cols) * UCHAR_MAX); // Green bgra[2] = saturate_cast ((float (mat.rows - i)) / ((float)mat.rows) * UCHAR_MAX); // Red bgra[3] = saturate_cast (0.5 * (bgra[1] + bgra[2])); // Alpha } }}int main(int argv, char **argc){ // Create mat with alpha channel Mat mat(480, 640, CV_8UC4); createAlphaMat(mat); vector compression_params; compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION); compression_params.push_back(9); try { imwrite("alpha.png", mat, compression_params); } catch (runtime_error& ex) { fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what()); return 1; } fprintf(stdout, "Saved PNG file with alpha data.\n"); return 0;}
The running result is: