OpenCV 图片的读取与存储

翻译自OpenCV 3.1.0 Docs - Image file reading and writing

Enumerations

Imread flags

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum cv::ImreadModes
{
cv::IMREAD_UNCHANGED = -1, // 导入原始图片,包括透明度通道
cv::IMREAD_GRAYSCALE = 0, // 图片转化为单通道灰度图
cv::IMREAD_COLOR = 1, // 图片转化为三通道*BGR*图片
cv::IMREAD_ANYDEPTH = 2, // 若输入图片是16或32位深度图直接读入,否则转化位8位深度图
cv::IMREAD_ANYCOLOR = 4, // 任何形式的图片格式都直接读入
cv::IMREAD_LOAD_GDAL = 8, // 使用GDAL驱动读入图片
cv::IMREAD_REDUCED_GRAYSCALE_2 = 16, // 图片转化位单通道灰度图,尺寸缩小1/2
cv::IMREAD_REDUCED_COLOR_2 = 17, // 图片转化为三通道BGR图,尺寸缩小1/2
cv::IMREAD_REDUCED_GRAYSCALE_4 = 32, // 图片转化位单通道灰度图,尺寸缩小1/4
cv::IMREAD_REDUCED_COLOR_4 = 33, // 图片转化为三通道BGR图,尺寸缩小1/4
cv::IMREAD_REDUCED_GRAYSCALE_8 = 64, // 图片转化位单通道灰度图,尺寸缩小1/8
cv::IMREAD_REDUCED_COLOR_8 = 65 // 图片转化为三通道BGR图,尺寸缩小1/8
}

Imwrite flags

1
2
3
4
5
6
7
8
9
10
11
12
13
14
enum cv::ImwriteFlags
{
cv::IMWRITE_JPEG_QUALITY = 1, // 存为JPEG图片,质量从0到100,默认95
cv::IMWRITE_JPEG_PROGRESSIVE = 2, // 使用JPEG特性,0或1,默认FALSE
cv::IMWRITE_JPEG_OPTIMIZE = 3, // 使用JPEG特性,0或1,默认FALSE
cv::IMWRITE_JPEG_RST_INTERVAL = 4, // JPEG restart interval, 0 - 65535, default is 0 - no restart.
cv::IMWRITE_JPEG_LUMA_QUALITY = 5, // 单独的亮度质量水平,从0到100,默认0,不使用
cv::IMWRITE_JPEG_CHROMA_QUALITY = 6,// 单独的色度质量水平,从0到100,默认0,不使用
cv::IMWRITE_PNG_COMPRESSION = 16, // 对于PNG图片, 压缩水平从0到9,值越大图片越小,默认3,
cv::IMWRITE_PNG_STRATEGY = 17, // One of cv::ImwritePNGFlags, default is IMWRITE_PNG_STRATEGY_DEFAULT.
cv::IMWRITE_PNG_BILEVEL = 18, // Binary level PNG, 0 or 1, default is 0.
cv::IMWRITE_PXM_BINARY = 32, // For PPM, PGM, or PBM, it can be a binary format flag, 0 or 1. Default value is 1.
cv::IMWRITE_WEBP_QUALITY = 64 // For WEBP, it can be a quality from 1 to 100 (the higher is the better). By default (without any parameter) and for quality above 100 the lossless compression is used.
}

Imwrite PNG specific flags

这些flags会修改PNG图片压缩的方式,并被传递到接下来zlib处理阶段。

  • IMWRITE_PNG_STRATEGY_FILTERED的效果force more Huffman coding and less string matching,处于IMWRITE_PNG_STRATEGY_DEFAULTIMWRITE_PNG_STRATEGY_HUFFMAN_ONLY之间。
  • IMWRITE_PNG_STRATEGY_RLE的速度几乎和IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY一样快,但对于PNG图片有更好的压缩效果。
  • 策略参数(strategy parameter)只影响压缩率,不影响压缩后数据的正确性。
  • IMWRITE_PNG_STRATEGY_FIXED避免dynamic Huffman codes,对特殊的应用允许简单的解码器。
1
2
3
4
5
6
7
8
9
10
11
enum cv::ImwritePNGFlags
{
cv::IMWRITE_PNG_STRATEGY_DEFAULT = 0, // Use this value for normal data
cv::IMWRITE_PNG_STRATEGY_FILTERED = 1, // Use this value for data produced by a filter (or predictor).
// Filtered data consists mostly of small values with a somewhat random distribution.
// In this case, the compression algorithm is tuned to compress them better.
cv::IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY = 2, // Use this value to force Huffman encoding only (no string match)
cv::IMWRITE_PNG_STRATEGY_RLE = 3, // Use this value to limit match distances to one (run-length encoding)
cv::IMWRITE_PNG_STRATEGY_FIXED = 4 // Using this value prevents the use of dynamic Huffman codes,
// allowing for a simpler decoder for special applications
}

Functions

imdecode & imencode

函数cv::imdecode从内存中的缓存读取图片,如果缓存太短或包含不合法的数据,则返回一个空矩阵,即Mat::data==NULL
注意对于彩色图片,颜色通道安装B G R的顺序存储。

1
2
3
4
Mat cv::imdecode(
InputArray buf, // input array or vector of bytes.
int flags // The same flags as in cv::imread
)

下面是为了方便定义的一个重载函数,区别主要是接收的参数。

1
2
3
4
5
6
7
Mat cv::imdecode(
InputArray buf,
int flags,
Mat* dst // The optional output placeholder for the decoded matrix.
// It can save the image reallocations when the function is
// called repeatedly for images of the same size.
)

函数cv::imencode压缩图片并将其存储在合适大小的内存缓冲区,支持的图片格式和flags描述见函数cv::imwrite

1
2
3
4
5
6
bool cv::imencode(
const String& ext, // File extension that defines the output format.
InputArray img, // Image to be written.
std::vector<uchar>& buf, // Output buffer resized to fit the compressed image.
const std::vector<int>& params = std::vector<int>() // Format-specific parameters. See cv::imwrite and cv::ImwriteFlags.
)

imread & imwrite

函数cv::imread从给定的文件中读取并返回图片,如果图片不能被正确读取(由于文件丢失,没有读取权限,不支持或不合法的格式等等),函数返回一个空矩阵,即Mat::data==NULL

1
2
3
4
Mat cv::imread(
const String& filename, // Name of file to be loaded.
int flags = IMREAD_COLOR // Flag that can take values of cv::ImreadModes
)

目前支持的格式包括:

  • Windows bitmaps - .bmp, .dib (always supported)
  • JPEG files - .jpeg, .jpg, *.jpe (see the Notes section)
  • JPEG 2000 files - *.jp2 (see the Notes section)
  • Portable Network Graphics - *.png (see the Notes section)
  • WebP - *.webp (see the Notes section)
  • Portable image format - .pbm, .pgm, .ppm .pxm, *.pnm (always supported)
  • Sun rasters - .sr, .ras (always supported)
  • TIFF files - .tiff, .tif (see the Notes section)
  • OpenEXR Image files - *.exr (see the Notes section)
  • Radiance HDR - .hdr, .pic (always supported)
  • Raster and Vector geospatial data supported by Gdal (see the Notes section)

注意:

  • The function determines the type of an image by the content, not by the file extension.
  • In the case of color images, the decoded images will have the channels stored in B G R order.
  • 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.
  • 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.
  • In the case you set WITH_GDAL flag to true in CMake and IMREAD_LOAD_GDAL to load the image, then GDAL driver will be used in order to decode the image by supporting the following formats: Raster, Vector.

函数cv::imreadmulti从给定的文件读入multi-page image并存储在一个包含Matstd::vector对象中。

1
2
3
4
5
bool cv::imreadmulti(
const String & filename, // Name of file to be loaded.
std::vector<Mat> & mats, // Flag that can take values of cv::ImreadModes, default with cv::IMREAD_ANYCOLOR.
int flags = IMREAD_ANYCOLOR // A vector of Mat objects holding each page, if more than one.
)

函数cv::imwrite将图片保存到给定的文件中,图片格式根据文件的扩展名确定,只有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能够使用这个函数保存。如果格式format、深度depth或通道顺序channel order不是这些,需要在保存前使用Mat::convertTocv::cvtColor函数将图片转化,或者使用更通用的FileStorage I/O函数将图片保存为XMLYAML格式。

1
2
3
4
5
6
7
bool cv::imwrite(
const String & filename, // Name of the file.
InputArray img, // Image to be saved.
const std::vector<int> & params = std::vector<int>() // Format-specific parameters
// encoded as pairs (paramId_1, paramValue_1, paramId_2, paramValue_2, ... .) see cv::ImwriteFlags

)

使用这个函数在存储PNG图片时能够同时保存透明度alpha channel,要这样做,创建一个8-bit (or 16-bit) 4-channel image BGRA,完全透明(transparent)的像素的alpha值为0,完全不透明(opaque)的像素的alpha值为255/65535

下面的例子展示了怎样来创建这样一个BGRA图片,并存储为PNG文件,例子同时说明了怎样设置一个压缩参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#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(IMWRITE_PNG_COMPRESSION);
compression_params.push_back(9);
try {
imwrite("alpha.png", mat, compression_params);
}
catch (cv::Exception& 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;
}

Reference