1.OpenCV模块
OpenCV 现在已经发展得比较庞大了,针对不同的应用,它划分了不同的模块,每个模块专注于不同的功能。一个模块下面可能有类、 全局函数、枚举、全局变量等。所有全局函数或变量都在命名空间 cv 下。

这些模块有的经过多个版本的更新已经较为完善,包含较多的功能, 有的模块还在逐渐发展中,包含的功能相对较少。接下来按照文件夹的顺序(字母顺序)介绍模块的功能。
-
calib3d: 这个模块名称由 calibration(校准)和 3D 这两个单词的缩写组合而成的,通过名字可以知道,模块主要包含相机标定与立体视觉等功能,例如物体位姿估计、三维重建、 摄像头标定等。
-
core: 核心功能模块,主要包含 OpenCV 库的基础结构以及基本操作,例如 OpenCV 基本数据结构、绘图函数、数组操作相关函数、动态数据结构等。
-
dnn: 深度学习模块,这个模块是 OpenCV 4 版本的一个特色,其主要包括构建神经网络、加载序列化网络模型等。但是该模块目前仅适用于正向传递计算(测试网络),原则上不 支持反向计算(训练网络)。
-
features2d: 这个模块名称是由 features(特征)和 2D 这两个单词的缩写组合而成的,其功能主要为处理图像特征点,例如特征检测、描述与匹配等。
-
flann: 这个模块名称是 Fast Library for Approximate Nearest Neighbors (快速近似最近邻库)的缩写,这个模块是高维的近似近邻快速搜索算法库,主要包含快速近似最近邻搜索与聚类等。
-
highgui: 高层 GUI 图形用户界面,包含创建和操作显示图像的窗口、处理鼠标事件以及键 盘命令、提供图形交互可视化界面等。
-
imgcodecs: 图像文件读取与保存模块,主要用于图像文件读取与保存。
-
imgproc: 这个模块名称由 image(图像)和 process(处理)两个单词的缩写组合而成的,是重要的图像处理模块,主要包括图像滤波、几何变换、直斱图、特征检测与目标检测等。
-
ml: 机器学习模块,主要为统计分类、回归和数据聚类等。
-
objdetect: 目标检测模块,主要用于图像目标检测,例如检测 Haar 特征。
-
photo: 计算摄影模块,主要包含图像修复和去噪等。
-
stitching: 图像拼接模块,主要包含特征点寻找与匹配图像、估计旋转、自动校准、接缝 估计等图像拼接过程的相关内容。
-
video: 视频分析模块,主要包含运动估计、背景分离、对象跟踪等视频处理相关内容。
-
videoio: 视频输入输出模块,主要用于读取与写入视频或者图像序列。
通过对 OpenCV 4.5 模块构架的介绍,我们对 OpenCV 4.5 整体架构有了一定的了解。其实简单来说, OpenCV 就是将众多图像处理和视觉处理工具集成在一起的软件开发(Software Development Kit, SDK),其自身并不复杂,只要通过学习都可以轻松掌握其使用方式。
2.图像输入输出模块 imgcodecs
要处理图像,第一步就是把图像文件从磁盘上读取到内存,处理完毕后再保存到内存。所以我们先来看图像文件读取与保存模块 imgproc。 imgproc 提供了一系列全局函数用于读取或保存图像文件。
imgproc 模块中的函数都在 opencv2/imgcodecs.hpp 中声明。由于 opencv2\opencv.hpp 中已经包含 opencv2/imgcodecs.hpp, 因此程序中也可以只包含 opencv2\opencv.hpp,比如:
cpp
#include<opencv2\opencv.hpp>
因为 opencv.hpp 中有如下代码:
cpp
#ifdef HAVE_OPENCV_IMGCODECS
#include "opencv2/imgcodecs.hpp"
#endif
2.1 imread 读取图像文件
函数 imread 用于读取图像文件(或叫加载图像文件) 。该函数声明如下:
cpp
Mat cv::imread (const String & filename, int flags = IMREAD_COLOR );
其中参数 filename 表示要读取的图像文件名。 flags 表示读取模式, flags 可以从枚举cv::ImreadModes 中取值,默认取值是 IMREAD_COLOR,表示始终将图像转换为三通道 BGR 彩色图像。如果从指定文件加载图像成功,就返回 Mat 矩阵,如果无法读取图像(由于缺少文件、权限不正确、格式不受支持或无效),函数就返回空矩(Mat::data==NULL)。
imread 支持常见的图像格式,某些图像格式需要(免费提供的)第三方类库。 在 Windows 操作系统下, OpenCV 的 imread 函数支持如下类型的图像载入:
c
JPEG 文件 - *.jpeg, *.jpg, *.jpe
JPEG 2000 文件- *.jp2
PNG 图片 - *.png
便携文件格式- *.pbm, *.pgm, *.ppm
Sun rasters 光栅文件 - *.sr, *.ras
TIFF 文件 - *.tiff, *.tif
Windows 位图- *.bmp,*.dib
如果读取失败,通常可以用两种方式来判断:直接判断是否为 NULL,或者调用 Mat::empty()函数,比如:
cpp
Mat img;
...
//开始判断是否加载成功
if (img.data == NULL) puts("load failed");
//if (img.empty()) puts("load failed");
值得注意的是,函数 imread 根据内容而不是文件扩展名来确定图像的类型,比如我们把某个BMP 文件改为后缀名为.jpg, imread 依然能探测到这个文件是 BMP 图像文件。
另外, imread 的第一个参数一般是图像文件的绝对路径或相对路径。 对于绝对路径, imread除了不支持单右斜线形式(\) 外,其他斜线形式都支持,比如双右斜线形式(\)、双左斜线形式(//)、单左斜线形式(/)等。但通常相对路径更加方便点,只要把图像文件放在工程目录下即可。
cpp
#include <iostream>
#include <opencv2\opencv.hpp>
using namespace std;
using namespace cv;
#pragma comment(lib, "opencv_world450d.lib") //引用引入库
int main(int argc, char* argv[])
{
Mat img;
//string imgpath = "d:\\我的图片\\p1.jpg"; //--1--双右斜线法,路径中含有中文
//string imgpath = "d://test//p1.jpg"; //-- 2 --双左斜线法
// string imgpath = "d:/test/p1.jpg"; //-- 3 --单左斜线法
// string imgpath = "d:/test//test2\\test3//test4//p1.jpg";//-- 4 --以上三种混合法
string imgpath = "p1.jpg";////-- 5 --相对路径法, 放工程目录下
//string imgpath = argv[1];//-- 6 --命令行参数法
img = imread(imgpath, 1);
if (img.data == NULL) //或 img.empty()
puts("load failed");
else imshow("img", img);
waitKey(0);
return 0;
}
对上面 6 种路径进行了测试,任何一种都是支持的,都可以成功读取并显示图片。较常用的是相对路径方式,也就是第 5 种。 如果在工程中运行程序,相对路径就是把图像文件放到工程目录下即可,如果是直接双击生成的可执行程序 test.exe,则要把图像文件和 test.exe 放在同一路径下。
2.2 imwrite 保存图片
函数 imwrite 可以用来输出图像到文件,其声明如下:
cpp
bool cv::imwrite (const String & filename, InputArray img,
const std::vector<int>& params = std::vector< int >());
其中参数 filename 表示需要写入的文件名,必须加上后缀,比如 123.png,注意要保存图片为哪种格式,就带什么后缀; img 表示 Mat 类型的图像数据,就是要保存到文件中的源图像数据; 参数 params 表示为特定格式保存的参数编码,它有一个默认值 std::vector< int >(),所以一般情况下不用写。
通常,使用此函数能保存8位单通道或三通道(具有BGR通道顺序)图像。16位无符号(CV_16U)图像可以保存为 PNG、 JPEG 2000 和 TIFF 格式。 32 位浮点(CV_32F)图像可以保存为 PFM、 TIFF、OpenEXR 和 Radiance HDR 格式; 三通道(CV_32FC3) TIFF 图像将使用 LogLuv 高动态范围编码(每像素 4 字节)保存。
另外, 使用此函数可以保存带有 alpha 通道的 PNG 图像。为此,创建 8
位(或 16 位) 4 通道图像 BGRA,其中 alpha 通道最后到达。完全透明的像素应该将 alpha 通道设置为 0,完全不透明的像素应该将 alpha 设置为 255/65535。如果格式、深度或通道顺序不同, 就在保存之前使用 Mat::convertTo 和 cv::cvtColor 进行转换。或者,使用通用文件存储 I/O 函数将图像保存为 XML 或 YAML 格式。
下面的示例将演示如何创建 BGRA 图像并将其保存到 PNG 文件中, 还将演示如何设置自定义压缩参数。
cpp
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/utils/logger.hpp>
using namespace cv; //所有 OpenCV 类都在命名空间 cv 下
using namespace std;
static 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; // 蓝色
bgra[1] = saturate_cast<uchar>((float(mat.cols - j)) /
((float)mat.cols) * UCHAR_MAX); // 绿色
bgra[2] = saturate_cast<uchar>((float(mat.rows - i)) /
((float)mat.rows) * UCHAR_MAX); // 红色
bgra[3] = saturate_cast<uchar>(0.5 * (bgra[1] + bgra[2])); // Alpha
}
}
}
int main()
{
// 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);
bool result = false;
try
{
result = imwrite("alpha.png", mat, compression_params);
}
catch (const cv::Exception& ex)
{
fprintf(stderr, "Exception converting image to PNG format: %s\n",
ex.what());
}
if (result)
printf("Saved PNG file with alpha data.\n");
else
printf("ERROR: Can't save PNG file.\n");
return result ? 0 : 1;
}

在代 码 中 , createAlphaMat 是 一 个 自 定 义 函 数 , 用 于 使 用 alpha 通 道 创 建 材 质 。compression_params 用于存放压缩参数。函数 imwrite 把图像矩阵以compression_params 压缩参数保存到工程目录下的 alpha.png 中,文件 alpha.png 会自动创建。