标签:
本文仅对 Opencv图像读取与保存进行阐述,重在探讨图像读取与保存过程中应注意的细节问题。
首先看一下,imread函数的声明:
// C++: Mat based
Mat imread(const string& filename, int flags=1 );
// C: IplImage based
IplImage* cvLoadImage(const char* filename, int iscolor=CV_LOAD_IMAGE_COLOR );
// C: CvMat based
CvMat* cvLoadImageM(const char* filename, int iscolor=CV_LOAD_IMAGE_COLOR );
此处,就不列出python
的函数声明。随着2.x和3.x版本不断更新, Opencv的C++
版本数据结构和C
版本有较大差异,前者减少了指针的大量使用,用法更加便捷,因此建议多使用前者。以C++
版本函数进行分析,形参列表包括:
filename
: 待加载图像(包括:文件路径和文件名,图像在工程默认路径下的可省略文件路径);flags
: 标志符,指定图像加载颜色类型,默认值为1:
如果你喜欢使用
imread("file.jpg")
缺省参数的形式加载图像,务必要留意你所加载后的图像可能已经不是你原本想要的图像了!
从 Opencv源码枚举类型中也可以看到上述标识符含义:
// highgui.hpp
enum
{
// 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.h
enum
{
/* 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已经支持目前很多图像格式,但是并非全部。主要包括:
*.bmp
, *.dib
(always supported)*.jpeg
, *.jpg
, *.jpe
(see the Notes section)*.jp2
,*.jpf
,*.jpx
(see the Notes section)*.png
(see the Notes section)*.webp
(see the Notes section)*.pbm
, *.pgm
, *.ppm
(always supported)*.sr
, *.ras
(always supported)TIFF files *.tiff
, *.tif
(see the Notes section)
Notes
- 1 The function determines the type of an image by the content, not by the file extension.
- 2 On 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.
- 3 On 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.
- 4 In the case of color images, the decoded images will have the channels stored in B G R order.
对于常见的支持4通道的图像格式来说, Opencv读取结果是有差异的:
// 1.tif, 1.jp2 and 1.png are color images with 4 channels: R, G, B, A
cv::Mat imageTif = cv::imread("E:\\1.tif"); // the default flags is 1
cv::Mat imageJp2 = cv::imread("E:\\1.jp2"); // the default flags is 1
cv::Mat imagePng = cv::imread("E:\\1.png"); // the default flags is 1
std::cout << imageTif.channels() << std::endl; // prints 3
std::cout << imageJp2.channels() << std::endl; // prints 3
std::cout << imagePng.channels() << std::endl; // prints 3
cv::Mat imageTif2 = cv::imread("E:\\1.tif", -1); // flags = -1
cv::Mat imageJp22 = cv::imread("E:\\1.jp2", -1);
cv::Mat imagePng2 = cv::imread("E:\\1.png", -1);
std::cout << imageTif2.channels() << std::endl; // prints 3
std::cout << imageJp22.channels() << std::endl; // prints 3
std::cout << imagePng2.channels() << std::endl; // prints 4
由此可见,目前 Opencv能够直接读取4通道图像并保留Alpha通道的貌似只有PNG格式,对于非PNG格式数据,需要保留Alpha通道的应用,如果坚持使用 Opencv库,建议转格式吧~
首先来看,imwrite函数的声明:
// c++: Mat based
bool imwrite(const string& filename, InputArray img, const vector<int>& params=vector<int>() );
// C: CvMat and IplImage based
int cvSaveImage(const char* filename, const CvArr* image, const int* params=0 );
仍旧以C++
版本为例,其形参列表为:
filename
:待保存图像名(包括:文件路径和文件名,图像在工程默认路径下的可省略文件路径);img
:待保存的图像对象;params
:特定图像存储编码参数设置,以类似pairs
类型的方式,(paramId_1, paramValue_1)
,(paramId_2, paramValue_2)
paramId_1
就是标志符值,paramValue_1
标识符值对应的后续参数设置:vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION); // paramId_1, png compression
compression_params.push_back(9); // paramValue_2, compression level is 9
在 Opencv中,主要对JPEG,PNG和PXM的编码方式进行了特别声明:
// highgui.hpp
enum
{
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.h
enum
{
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
};
上述的标识符含义,显而易见,就不累述。值得强调的是,imwrite函数支持存储的图像类型是有限的只包括:1,3,4通道的图像,但是对于不同的图像格式,也是有差异的:
Mat::convertTo()
和cvtColor()
函数进行转换后,再保存。当然,也可以使用通用的方法利用FileStorage
I/O操作,将图像存为XML或YAML格式。对于多通道图像,如果想对其每个通道单独进行保存,当然也是可行的,一方面自己可以根据图像的信息和图层信息写出相应的存储函数,另一方面 Opencv也提供了专门的函数split
可以将图像的每个通道提取出保存到vector
中:
cv::Mat img = imread( "C:\\Users\\Leo\\Desktop\\Panda.png", CV_LOAD_IMAGE_UNCHANGED );
std::vector<cv::Mat> 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]);
附上 Opencv文档源码:
#include <vector>
#include <stdio.h>
#include <opencv2/opencv.hpp>
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<Vec4b>(i, j);
bgra[0] = UCHAR_MAX; // Blue
bgra[1] = saturate_cast<uchar>((float (mat.cols - j)) / ((float)mat.cols) * UCHAR_MAX); // Green
bgra[2] = saturate_cast<uchar>((float (mat.rows - i)) / ((float)mat.rows) * UCHAR_MAX); // Red
bgra[3] = saturate_cast<uchar>(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<int> 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;
}
运行结果为:
标签:
原文地址:http://blog.csdn.net/yhl_leo/article/details/49737357