C++ OpenCV读取、显示、保存图像

正文索引 [隐藏]

OpenCV有三个最基本的操作:读取图像显示图像保存图像

读取图像

imread

C++中 imread 函数定义如下:

#include <opencv2/imgcodecs.hpp>
Mat cv::imread(const string& filename, int flags = IMREAD_COLOR );

返回值是Mat类型, 即返回读取的图像,读取图像失败时返回一个空的矩阵对象(Mat::data == NULL) 参数1 filename,读取的图片文件名,可以使用相对路径或者绝对路径,但必须带完整的文件扩展名(有图片格式后缀),参数1支持读取的图像格式有:

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

参数2 flags 用来选择读取图片的方式,flag值的设定与用什么颜色格式读取图片有关,默认值为IMREAD_COLOR,会将图片转为3通道BGR彩图,读入后类型就变成了CV_8UC3,如果想以原类型读取,那就选择IMREAD_UNCHANGED。参数2可以采用cv::ImreadModes值,如下:

enum ImreadModes {
    IMREAD_UNCHANGED = -1, //如果设置,则按原样返回加载的图像(使用Alpha通道,否则会被裁剪)
    IMREAD_GRAYSCALE = 0,  //如果设置,则始终将图像转换为单通道灰度图像(编解码器内部转换)
    IMREAD_COLOR = 1,  //如果设置,请始终将图像转换为3通道BGR彩色图像
    IMREAD_ANYDEPTH = 2,  //如果设置,则在输入具有相应深度时返回16位/ 32位图像,否则将其转换为8位
    IMREAD_ANYCOLOR = 4,  //如果设置,则以任何可能的颜色格式读取图像
    IMREAD_LOAD_GDAL = 8,  //如果设置,使用gdal驱动程序加载图像
    IMREAD_REDUCED_GRAYSCALE_2  = 16, //如果设置,则始终将图像转换为单通道灰度图像,图像尺寸减小1/2
    IMREAD_REDUCED_COLOR_2 = 17, //如果设置,则始终将图像转换为3通道BGR彩色图像,图像尺寸减小1/2
    IMREAD_REDUCED_GRAYSCALE_4 = 32, //如果设置,则始终将图像转换为单通道灰度图像,图像尺寸减小1/4
    IMREAD_REDUCED_COLOR_4 = 33, //如果设置,则始终将图像转换为3通道BGR彩色图像,图像尺寸减小1/4
    IMREAD_REDUCED_GRAYSCALE_8 = 64, //如果设置,则始终将图像转换为单通道灰度图像,图像尺寸减小1/8
    IMREAD_REDUCED_COLOR_8 = 65 //如果设置,则始终将图像转换为3通道BGR彩色图像,图像尺寸减小1/8
    IMREAD_IGNORE_ORIENTATION = 128 //如果设置,请不要根据EXIF的方向标志旋转图像
};

这个参数主要在读取一些16位或者32为浮点型图像时就比较有用,因为一些计算需要这样的类型,有时候也为了计算提高精度。

imreadmulti

C++中 imreadmulti 是用来从文件加载多个图像的,函数定义如下:

#include <opencv2/imgcodecs.hpp>
bool cv::imreadmulti(const string& filename, std::vector<Mat>& mats, int flags = IMREAD_ANYCOLOR);

参数1 filename 是要加载的文件名。参数2 mats 是可包含多个Mat对象的vector。参数3 flag 可以采用cv::ImreadModes值(默认为IMREAD_ANYCOLOR)的标志。

显示图像:

imshow

C++中 imshow 是用来在指定的窗口中显示图像的,函数定义如下:

#include <opencv2/highgui.hpp>
void cv::imshow	(const string& winname, InputArray mat)

imshow 函数默认显示窗口模式是WINDOW_AUTOSIZEnameWindow可供选择的值如下:

enum WindowFlags {
    WINDOW_NORMAL = 0x00000000, //用户可以无限制地调整窗口大小,也可以将全屏窗口切换为正常大小
    WINDOW_AUTOSIZE = 0x00000001, //用户无法调整窗口大小,该图像自动调整大小显示,受屏幕分辨率的限制
    WINDOW_OPENGL = 0x00001000, //opengl支持的窗口
    WINDOW_FULLSCREEN = 1, //将窗口更改为全屏
    WINDOW_FREERATIO = 0x00000100, //窗口大小自适应比例
    WINDOW_KEEPRATIO = 0x00000000, //窗口大小保持比例
    WINDOW_GUI_EXPANDED =0x00000000, //显示色彩变暗色
    WINDOW_GUI_NORMAL = 0x00000010 //显示色彩正常
};

如果需要显示大于屏幕分辨率的图像,则在调整窗口大小时需要在 imshow 之前调用 namedWindow,并将参数2设置为WINDOW_NORMAL。在用imshow显示图像的时候,我们可以选中窗口,对图片进行复制和保存。

保存图像:

imwrite

C++中 imwrite 是用来在指定的窗口中显示图像的,函数定义如下:

#include <opencv2/imgcodecs.hpp>
bool cv::imwrite(const string& filename, InputArray img, const std::vector<int>& params = std::vector<int>() )

参数1 filename是需要写入的文件名,参数2 img是需要保存的图像,参数3 params 表示为特定格式保存的参数编码。注意:想要保存图片为哪种格式,就记得带这种格式的后缀。ImwriteFlags可供选择的值如下:

enum ImwriteFlags {
    IMWRITE_JPEG_QUALITY = 1,
    IMWRITE_JPEG_PROGRESSIVE = 2,
    IMWRITE_JPEG_OPTIMIZE = 3,
    IMWRITE_JPEG_RST_INTERVAL = 4,
    IMWRITE_JPEG_LUMA_QUALITY = 5,
    IMWRITE_JPEG_CHROMA_QUALITY = 6,
    IMWRITE_PNG_COMPRESSION = 16,
    IMWRITE_PNG_STRATEGY = 17,
    IMWRITE_PNG_BILEVEL = 18,
    IMWRITE_PXM_BINARY = 32,
    IMWRITE_WEBP_QUALITY = 64
};

为了验证上面所学的知识,我写了一段简单的程序来看了一下Lena,并把她的照片换了一种图像格式保存。

#include <opencv2/opencv.hpp>
#include <bits/stdc++.h>
using namespace std;
using namespace cv;
string IMG_PATH = "D:/Code/CppCode/OpencvProject/img/";

int main() {
    cout << "Built with OpenCV " << CV_VERSION << endl;
    Mat src = imread(IMG_PATH+"lena.png");
    scr.depth();
    namedWindow("Lena", WINDOW_FREERATIO);
    imshow("Lena",src);
    imwrite(IMG_PATH+"lena.jpg",src);
    waitKey(0);
    destroyAllWindows();
    return 0;
}