OpenCV  4.10.0
开源计算机视觉
加载中...
搜索中...
无匹配项
图像操作

前一个教程: 矩阵上掩模操作
下一个教程: 使用 OpenCV 添加(混合)两张图像

兼容性OpenCV >= 3.0

输入/输出

图像

从文件中加载图像

如果您读取 jpg 文件,默认会创建一个 3 通道图像。如果您需要灰度图像,请使用

注意
文件格式由其内容(前几个字节)决定。要将图像保存到文件
注意
文件格式由其扩展名决定。
使用 cv::imdecodecv::imencode 从内存或文件中读取和写入图像,而不是文件。

图像基本操作

访问像素强度值

为了获取像素强度值,您必须知道图像的类型和通道数。对于单通道灰度图像(类型 8UC1)和像素坐标 x 和 y 来说,以下是一个示例

仅限 C++ 版本:intensity.val[0] 包含 0 至 255 的值。 请注意 x 和 y 的顺序。 由于在 OpenCV 中图像由与矩阵相同的结构表示,因此对两种情况我们都使用相同的惯例 - 基于 0 的行索引(或 y 坐标)在先,基于 0 的列索引(或 x 坐标)在后。 或者,可以使用以下符号(仅限 C++

标量强度 = img.at<uchar>(点(x, y));

现在让我们考虑一个具有 BGR 颜色顺序(imread 返回的默认格式)的三通道图像

C++代码

Vec3b intenstiy = img.at<Vec3b>(y, x);
uchar 蓝色 = intenstiy.val[0];
uchar 绿色 = intenstiy.val[1];
uchar 红色 = intenstiy.val[2];

Python Python

_蓝色 = img[y,x,0]
_绿色 = img[y,x,1]
_红色 = img[y,x,2]

对于浮点图像,可以使用相同的方法(例如,可以通过对 3 通道图像运行 Sobel 获得此类图像)(仅限 C++

Vec3f 强度 = img.at<Vec3f>(y, x);
float 蓝色 = 强度.val[0];
float 绿色 = intensity.val[1];
float 红色 = intensity.val[2];
_Tp val[m *n]
矩阵元素
定义 matx.hpp:218

可以使用相同的方法来更改像素强度

OpenCV 中有函数,尤其是来自 calib3d 模块的函数,例如 cv::projectPoints,以 Mat 的形式接受阵列的 2D 或 3D 点。 矩阵应仅包含一列,每行对应一个点,矩阵类型应分别为 32FC2 或 32FC3。可以很容易地从 std::vector(仅限 C++)构建此类矩阵

vector<Point2f> 点;
//... 填充数组
Mat 点矩阵 = 矩阵(点);

可以使用相同的方法 Mat::at(仅限 C++)访问此矩阵中的点

Point2f 点 = 点矩阵.at<Point2f>(i, 0);

内存管理和引用计数

Mat 是一种可以保留矩阵/图像特征(行数和列数、数据类型等)并指向数据的结构。因此,同一数据对应于多个 Mat 实例不会受到任何限制。Mat 会保存一个引用计数,当销毁一个特定的 Mat 实例时,该计数会告知数据是否要解除分配。以下是一个创建 Mat 的示例,不会复制数据(仅限 C++

std::vector<Point3f> points;
// .. 填充数组
Mat pointsMat = Mat(points).reshape(1);

结果中,我们会得到一个 32FC1 矩阵,有 3 列,而不是 32FC3 矩阵,有 1 列。pointsMat 使用 points 的数据,并且在销毁时不会解除内存的分配。然而,在此特定实例中,开发者必须确保 points 的生命周期比 pointsMat 的生命周期更长。如果我们需要复制数据,可以使用 cv::Mat::copyTocv::Mat::clone

可以向每个函数提供一个空输出 Mat。每个实现都会针对一个目标矩阵调用 Mat::create。如果矩阵为空,此方法会为矩阵分配数据。如果矩阵不为空,并且具有正确的大小和类型,则此方法不会执行任何操作。但是,如果大小或类型不同于输入参数,那么数据会解除分配(丢失),然后会分配新的数据。例如

原始操作

在矩阵上定义了多个便捷的算子。例如,以下是如何从现有的灰度图像 img 中创建一幅黑色图像

选择感兴趣的区域

从彩色转换为灰度

转换图像类型从 8UC1 到 32FC1

可视化图像

在开发过程中,查看算法的中间结果非常有用。OpenCV 提供了一种方便的方法可视化图像。可以使用以下方法显示一个 8U 图像

调用 waitKey() 会开启一个消息传递循环,等待在“image”窗口中按下按键。需要将 32F 图像转换成 8U 类型。例如

注意
此处 cv::imshow。尽管如此,仍可使用它来更改窗口属性或使用