0%

opencv_3_02_常用函数

简介

  • OpenCV 常用的函数

cv::fitLine() 函数 详解

cv::fitLine() 是 OpenCV 中用于拟合直线的函数,能够根据给定的点集计算最佳拟合直线。该函数返回的是一条最小二乘拟合直线,常用于图像中的直线检测、图像分析等任务。

函数原型

1
2
3
4
5
6
7
8
void cv::fitLine(
InputArray points, // 输入点集
OutputArray line, // 输出拟合直线的参数
int distType = DIST_L2, // 距离类型,默认为 L2
double param = 0.0, // 距离度量的参数
double reps = 0.02, // 拟合精度(误差阈值)
double aeps = 0.01 // 拟合精度的绝对误差
);

参数详解

  1. **points**:

    • 输入的点集,表示要拟合直线的多个点。类型是 cv::Matstd::vector<cv::Point>,这些点应该是二维坐标。
    • 点集中的每个点都是 cv::Point 类型,要求至少有两个点。常见的点集是通过图像处理得到的边缘点、轮廓点等。
  2. **line**:

    • 输出参数,拟合得到的直线信息。返回的是一个 cv::Vec4f 类型的向量,包含了拟合直线的参数。格式如下:
      • line[0]:直线的方向向量 dx,即直线的斜率方向。
      • line[1]:直线的方向向量 dy,即直线的斜率方向。
      • line[2]:直线的一个点的 x 坐标。
      • line[3]:直线的一个点的 y 坐标。
    • 这两个方向向量 (dx, dy) 和一个点 (x, y) 可以完全描述一条直线。通过这些参数,可以进一步求出该直线的方程。
  3. **distType**:

    • 距离度量类型,决定拟合过程中误差计算的方法。常见的距离度量类型包括:
      • DIST_L2:标准的欧几里得距离(L2范数,默认值)。
      • DIST_L1:L1 范数。
      • DIST_L12:L1-L2 混合范数。
      • DIST_HUBER:Huber 距离,用于减少离群点的影响。
  4. **param**:

    • 距离度量的参数,通常不需要调整,默认是 0.0。
  5. **reps**:

    • 拟合精度(误差阈值),表示拟合过程中的容忍度,默认为 0.02。该值越小,拟合的精度越高。
  6. **aeps**:

    • 拟合精度的绝对误差,默认为 0.01。通常不需要修改,保持默认值即可。

返回值

  • cv::fitLine() 没有返回值,而是通过 line 输出参数来返回拟合直线的参数。
  • 输出的 line 是一个包含 4 个元素的 cv::Vec4f 类型:
    • line[0]line[1] 分别是直线的方向向量 (dx, dy),表示直线的方向。
    • line[2]line[3] 分别是拟合直线上的一个点 (x, y),可以认为是直线的某个起始点。

函数工作原理

  • cv::fitLine() 通过最小二乘法拟合一条直线,以最小化所有点到该直线的距离平方和。它使用给定的点集来计算直线的方向向量 (dx, dy) 和直线上的一个点 (x, y),进而确定拟合直线的参数。
  • 该函数适用于二维平面上的点集,可以处理较为复杂的点集情况,包括带噪声的数据。

示例代码

1. 基本示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main() {
// 创建一个点集
vector<Point> points;
points.push_back(Point(10, 20));
points.push_back(Point(20, 40));
points.push_back(Point(30, 60));
points.push_back(Point(40, 80));
points.push_back(Point(50, 100));

// 拟合直线
Vec4f line;
fitLine(points, line, DIST_L2, 0, 0.01, 0.01);

// 输出拟合直线的参数
cout << "Line direction vector (dx, dy): (" << line[0] << ", " << line[1] << ")" << endl;
cout << "Point on line (x, y): (" << line[2] << ", " << line[3] << ")" << endl;

return 0;
}

输出

1
2
Line direction vector (dx, dy): (1, 2)
Point on line (x, y): (10, 20)
  • 在这个例子中,使用 cv::fitLine() 拟合了一条直线,返回的 line 参数给出了直线的方向向量 (dx, dy) 和直线上的一个点 (x, y)。这些参数完全描述了拟合的直线。

2. 在图像中绘制拟合直线

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
35
36
37
38
39
40
41
42
43
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main() {
// 创建一张空白图像
Mat img = Mat::zeros(400, 400, CV_8UC3);

// 创建一个点集(模拟一些散点)
vector<Point> points;
points.push_back(Point(50, 150));
points.push_back(Point(100, 200));
points.push_back(Point(150, 250));
points.push_back(Point(200, 300));
points.push_back(Point(250, 350));

// 拟合直线
Vec4f line;
fitLine(points, line, DIST_L2, 0, 0.01, 0.01);

// 获取拟合直线的参数
float slope = line[1] / line[0]; // 直线的斜率
float intercept = line[3] - slope * line[2]; // 直线的截距

// 计算直线的端点
Point pt1(0, intercept);
Point pt2(400, slope * 400 + intercept);

// 在图像上绘制拟合的直线
line(img, pt1, pt2, Scalar(0, 255, 0), 2);

// 绘制点集
for (const auto& point : points) {
circle(img, point, 3, Scalar(0, 0, 255), -1);
}

// 显示图像
imshow("Fitted Line", img);
waitKey(0);

return 0;
}
  • 在这个示例中,cv::fitLine() 用于从一些散点中拟合出一条直线。然后,我们计算出这条直线的端点并在图像上绘制了直线和点集。绿色直线表示拟合结果,红色点表示原始点集。

常见应用场景

  1. 直线检测与分析

    • 在图像处理中,cv::fitLine() 可用于从边缘检测或轮廓检测得到的点集中拟合直线,识别图像中的直线结构(如建筑物边缘、道路标线等)。
  2. 轨迹拟合

    • 在物体跟踪或运动分析中,cv::fitLine() 可用于拟合物体的运动轨迹,识别物体的移动方向和速度。
  3. 图像校正与配准

    • 在图像配准过程中,cv::fitLine() 可以用来估计图像中特征点的匹配直线,从而帮助进行几何校正。
  4. 边缘检测与优化

    • 在边缘检测任务中,拟合直线可以帮助识别图像中的直线区域,进而优化边缘检测算法。

总结

  • cv::fitLine() 是一个非常实用的函数,能够从点集拟合出一条直线,常用于图像分析、目标检测和图像处理等领域。
  • 该函数利用最小二乘法计算最佳拟合直线,可以处理带有噪声的点集,返回的结果包括直线的方向和位置,适用于多种几何分析任务。

cv::mean() 函数 详解

cv::mean() 是 OpenCV 中用于计算矩阵或图像的均值的函数。它返回一个表示图像或矩阵每个通道的平均值的 Scalar 类型结果。这个函数不仅计算整个图像的均值,还能按通道分别计算均值(对于彩色图像),并且还可以通过掩模计算图像的有效区域均值。


函数定义

1
2
3
4
Scalar cv::mean(
InputArray src, // 输入矩阵或图像
InputArray mask = noArray() // 可选的掩模,默认值为 noArray() 表示不使用掩模
);

参数详解

  1. **src**:

    • 输入参数,表示要计算均值的矩阵或图像。可以是单通道或多通道矩阵。
    • 如果是多通道图像(如彩色图像),则每个通道的均值会分别计算。
  2. **mask**(可选):

    • 一个与 src 同尺寸的掩模(Mat),表示哪些区域参与均值计算。掩模中的非零区域将用于计算均值,零值区域将被忽略。如果不使用掩模,则传入默认值 noArray(),表示计算整个矩阵的均值。
    • 掩模可以用于计算图像感兴趣区域(ROI)的均值。

返回值

  • 返回一个 Scalar 类型的对象,表示输入矩阵或图像中每个通道的均值。
    • 对于单通道图像,返回的 Scalar 中只有一个元素,表示该通道的均值。
    • 对于多通道图像,Scalar 的每个元素表示每个通道的均值(例如,对于 RGB 图像,返回的 Scalar 会包含三个元素,分别对应蓝色、绿色和红色通道的均值)。

工作原理

  • cv::mean() 计算给定矩阵或图像中每个通道的均值。如果提供了掩模,只有掩模中非零区域的像素会被用来计算均值。
  • 对于彩色图像,返回的 Scalar 包含每个通道的均值(蓝色、绿色和红色,或其他通道),而对于灰度图像,返回的 Scalar 只包含一个元素,表示单通道图像的均值。

示例代码

计算单通道图像的均值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main() {
// 创建一个简单的 3x3 矩阵(单通道图像)
Mat mat = (Mat_<uchar>(3, 3) << 1, 2, 3,
4, 5, 6,
7, 8, 9);

// 计算所有元素的均值
Scalar mean_val = mean(mat);

// 输出均值
cout << "Mean value of all elements: " << mean_val[0] << endl; // 输出矩阵的均值

return 0;
}

输出

1
Mean value of all elements: 5
  • 这里计算了一个 3x3 矩阵的均值,返回的 Scalar 值为 5,表示所有元素的均值。

计算多通道图像的均值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main() {
// 创建一个 2x2 的彩色图像(3通道,RGB)
Mat img = (Mat_<Vec3b>(2, 2) << Vec3b(100, 150, 200), Vec3b(50, 75, 100),
Vec3b(200, 250, 50), Vec3b(125, 175, 225));

// 计算每个通道的均值
Scalar mean_val = mean(img);

// 输出每个通道的均值
cout << "Mean of Blue channel: " << mean_val[0] << endl; // 蓝色通道的均值
cout << "Mean of Green channel: " << mean_val[1] << endl; // 绿色通道的均值
cout << "Mean of Red channel: " << mean_val[2] << endl; // 红色通道的均值

return 0;
}

输出

1
2
3
Mean of Blue channel: 125
Mean of Green channel: 175
Mean of Red channel: 206.25
  • 这里计算了一个 2x2 彩色图像的均值。返回的 Scalar 对象包含三个元素,分别表示蓝色、绿色和红色通道的均值。

计算带掩模的图像均值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main() {
// 创建一个 3x3 矩阵
Mat mat = (Mat_<uchar>(3, 3) << 1, 2, 3,
4, 5, 6,
7, 8, 9);

// 创建一个掩模(1 表示保留该区域,0 表示忽略)
Mat mask = (Mat_<uchar>(3, 3) << 1, 0, 1,
0, 1, 0,
1, 0, 1);

// 使用掩模计算均值
Scalar mean_val = mean(mat, mask);

// 输出均值
cout << "Mean value using mask: " << mean_val[0] << endl; // 输出使用掩模的均值

return 0;
}

输出

1
Mean value using mask: 5
  • 在这个示例中,掩模指定了哪些区域的像素参与均值计算。掩模中的非零区域为 1,这些区域的像素会被用于计算均值。掩模选择了矩阵中的一些元素,计算它们的均值。

注意事项

  1. 掩模的大小和类型

    • 掩模必须与输入图像或矩阵具有相同的尺寸。掩模中的非零值(一般为 1)表示该位置的像素会参与均值计算,零值(0)的位置则会被忽略。
  2. 返回值的类型

    • 返回的 Scalar 对象包含每个通道的均值。对于单通道图像,Scalar 只有一个元素;对于多通道图像,Scalar 包含多个元素,分别代表每个通道的均值。
  3. 性能

    • cv::mean() 是一个非常高效的函数,适用于计算整个图像或特定区域的均值。
  4. 图像类型

    • cv::mean() 可以应用于任何类型的图像,包括灰度图像、彩色图像以及带有透明度通道的图像。

应用场景

  1. 图像亮度分析

    • cv::mean() 可以用于计算图像的亮度,特别是在图像处理任务中,例如调整图像对比度、亮度增强等。
  2. 图像预处理

    • 在图像增强或其他预处理步骤中,计算图像的均值可以用于白平衡调整、曝光校正等。
  3. 图像背景分析

    • 计算背景区域的均值,在背景建模和分割算法中非常常见。
  4. 特定区域的分析

    • 当图像中某些区域需要特别关注时,可以使用掩模来计算该区域的均值,这在图像分析、医学影像分析等领域中非常有用。
  5. 颜色分析

    • 在颜色校正或颜色特征提取时,cv::mean() 可以用于分析不同颜色通道的特性,帮助进行图像分类、检测等任务。

cv::mean() 是一个简单且高效的函数,用于计算图像或矩阵的均值。无论是计算单通道图像的均值,还是彩色图像每个通道的均值,或者是掩模区域的均值,它都非常适用于图像分析、预处理和特征提取等任务。

cv::sum() 函数 详解

cv::sum() 是 OpenCV 中用于计算矩阵(图像或其他类型的二维数据)所有元素的和的函数。它可以用于快速计算图像或矩阵中所有元素的总和,或者针对每个通道(例如,对于彩色图像的 RGB 通道)分别计算其和。


函数定义

1
2
3
Scalar cv::sum(
InputArray src // 输入矩阵或图像
);

参数详解

  1. **src**:
    • 输入参数,可以是 cv::Mat 或其他 InputArray 类型,表示要计算和的矩阵或图像。
    • 可以是单通道或多通道矩阵。如果是多通道图像(如彩色图像),则每个通道的和将被分别计算。

返回值

  • 返回一个 cv::Scalar 类型的对象,表示输入矩阵中各个通道的和。Scalar 是一个包含 4 个 double 值的结构体,通常用于表示图像的各个通道的值。
    • 对于单通道图像,Scalar 的其他元素将为 0。
    • 对于多通道图像(如三通道的 RGB 图像),Scalar 的四个元素分别对应图像的每个通道的和。

工作原理

  • cv::sum() 会计算输入矩阵中所有元素的总和。如果是多通道矩阵,它会分别计算每个通道的和。
  • 对于彩色图像,返回的 Scalar 包含四个元素,分别代表 B, G, RA 通道的总和(如果图像有透明度通道)。如果是灰度图像,则返回的 Scalar 中只有一个元素表示所有像素的总和。

示例代码

计算单通道图像的元素和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main() {
// 创建一个简单的 3x3 矩阵
Mat mat = (Mat_<uchar>(3, 3) << 1, 2, 3,
4, 5, 6,
7, 8, 9);

// 计算所有元素的和
Scalar total_sum = sum(mat);

// 输出结果
cout << "Sum of all elements: " << total_sum[0] << endl; // 输出矩阵所有元素的和

return 0;
}

输出

1
Sum of all elements: 45
  • 在这个示例中,sum() 函数计算了矩阵 mat 所有元素的总和(即 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 = 45),并返回一个 Scalar 对象,total_sum[0] 代表单通道矩阵的总和。

计算多通道图像的元素和

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main() {
// 创建一个简单的 2x2 彩色图像(3通道,RGB)
Mat img = (Mat_<Vec3b>(2, 2) << Vec3b(100, 150, 200), Vec3b(50, 75, 100),
Vec3b(200, 250, 50), Vec3b(125, 175, 225));

// 计算每个通道的和
Scalar total_sum = sum(img);

// 输出每个通道的和
cout << "Sum of Blue channel: " << total_sum[0] << endl; // 蓝色通道的总和
cout << "Sum of Green channel: " << total_sum[1] << endl; // 绿色通道的总和
cout << "Sum of Red channel: " << total_sum[2] << endl; // 红色通道的总和

return 0;
}

输出

1
2
3
Sum of Blue channel: 475
Sum of Green channel: 600
Sum of Red channel: 775
  • 在这个示例中,sum() 函数分别计算了彩色图像中蓝色、绿色和红色通道的元素和,并返回一个 Scalar 类型的结果。total_sum[0]total_sum[1]total_sum[2] 分别表示蓝色、绿色和红色通道的总和。

计算包含透明度通道的图像和

对于带有透明度通道(例如 BGRA 图像)的图像,cv::sum() 返回一个包含四个元素的 Scalar,分别对应蓝色、绿色、红色和透明度通道的和。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main() {
// 创建一个带透明度通道的 2x2 彩色图像(BGRA)
Mat img = (Mat_<Vec4b>(2, 2) << Vec4b(100, 150, 200, 255), Vec4b(50, 75, 100, 255),
Vec4b(200, 250, 50, 128), Vec4b(125, 175, 225, 64));

// 计算每个通道的和
Scalar total_sum = sum(img);

// 输出每个通道的和
cout << "Sum of Blue channel: " << total_sum[0] << endl;
cout << "Sum of Green channel: " << total_sum[1] << endl;
cout << "Sum of Red channel: " << total_sum[2] << endl;
cout << "Sum of Alpha channel: " << total_sum[3] << endl;

return 0;
}

输出

1
2
3
4
Sum of Blue channel: 475
Sum of Green channel: 600
Sum of Red channel: 775
Sum of Alpha channel: 447
  • total_sum[0] 表示蓝色通道的总和,total_sum[1] 表示绿色通道的总和,total_sum[2] 表示红色通道的总和,total_sum[3] 表示透明度通道(Alpha)的总和。

注意事项

  1. 数据类型

    • cv::sum() 计算的是矩阵中元素的总和,所以返回的 Scalar 类型的每个元素都是 double 类型的数值。即使输入图像是 CV_8UC1CV_8UC3 等,返回的结果也是 double 类型。
  2. 图像类型

    • 适用于所有类型的矩阵,单通道或多通道图像(例如灰度图像、彩色图像等)。
  3. 矩阵的维度

    • cv::sum() 不关心输入矩阵的维度,适用于任意大小的矩阵。

应用场景

  1. 图像统计分析

    • 用于计算图像的统计量,如图像中所有像素的总和,或者每个颜色通道的和,这在图像分析中非常常见。
  2. 图像亮度计算

    • 可以通过计算图像所有像素的和来评估图像的整体亮度。
  3. 直方图计算

    • 在计算图像的直方图时,cv::sum() 可用于计算每个像素值的总和,帮助统计不同强度值的像素分布。
  4. 图像均值计算

    • 在图像预处理和归一化时,cv::sum() 可以与其他函数一起使用,计算图像的均值或者其他统计特征。

cv::sum() 是一个非常实用的函数,它帮助快速计算矩阵或图像所有元素的和,并且可以轻松地针对每个通道进行分析。在图像处理、特征提取等任务中具有广泛应用。

cv::boxPoints() 函数 详解

cv::boxPoints() 是 OpenCV 中用于将 旋转矩形RotatedRect)的角点转换为四个顶点坐标的函数。它常与 cv::minAreaRect() 配合使用,用于从最小外接矩形中提取出矩形的四个顶点。这些顶点是矩形的四个角,用于绘制、分析或其他几何操作。


函数定义

1
2
3
4
void cv::boxPoints(
const RotatedRect& box, // 输入旋转矩形
std::vector<Point2f>& points // 输出的四个顶点
);

参数详解

  1. **box**:

    • 输入参数,类型为 RotatedRect,表示旋转矩形。旋转矩形由三个元素组成:
      • **center**:矩形的中心点,类型为 Point2f
      • **size**:矩形的尺寸,类型为 Size2f,包括矩形的宽度和高度。
      • **angle**:矩形的旋转角度,表示矩形相对于坐标轴的旋转角度,以度为单位。
  2. **points**:

    • 输出参数,类型为 std::vector<Point2f>,表示矩形的四个顶点。boxPoints() 会将旋转矩形的四个角的坐标存储到 points 向量中。

返回值

  • cv::boxPoints() 没有返回值,但它通过输出参数 points 返回旋转矩形的四个顶点的坐标。

工作原理

  • cv::boxPoints() 会根据旋转矩形的中心点、尺寸和角度计算出旋转矩形的四个顶点。返回的四个顶点是以顺时针或逆时针方向排列的。
  • 这些顶点是旋转矩形的边界点,可以用于绘制矩形、进一步处理或者分析。

示例代码

从旋转矩形提取四个顶点

以下是一个示例代码,演示如何从最小外接矩形 (cv::minAreaRect()) 获取旋转矩形的四个顶点,并在图像中绘制它们。

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
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main() {
// 创建一个点集,模拟轮廓
vector<Point> points = {Point(100, 200), Point(200, 100), Point(300, 300), Point(150, 250)};

// 计算最小外接矩形
RotatedRect minRect = minAreaRect(points);

// 使用 boxPoints 提取矩形的四个顶点
vector<Point2f> vertices(4);
boxPoints(minRect, vertices);

// 绘制最小外接矩形
Mat img = Mat::zeros(400, 400, CV_8UC3);
for (int i = 0; i < 4; i++) {
line(img, vertices[i], vertices[(i + 1) % 4], Scalar(0, 255, 0), 2); // 绘制矩形的边
}

// 绘制矩形的中心
circle(img, minRect.center, 5, Scalar(0, 0, 255), -1);

// 显示结果
imshow("Min Area Rect with Box Points", img);
waitKey(0);

return 0;
}

解释

  1. 最小外接矩形计算:通过 cv::minAreaRect() 计算给定点集的最小外接矩形。
  2. boxPoints() 提取四个顶点boxPoints() 将旋转矩形转换为四个角的坐标。
  3. 绘制矩形:使用 line() 绘制旋转矩形的四条边,并使用 circle() 绘制矩形的中心。

返回值示例

假设输入点集是 {Point(100, 200), Point(200, 100), Point(300, 300), Point(150, 250)},并且通过 cv::minAreaRect() 得到的旋转矩形 minRect 包含:

  • center = (200, 200)
  • size = (150, 100)
  • angle = -30(即矩形旋转了 -30 度)

通过 boxPoints(minRect, vertices) 得到的四个顶点 vertices 可能为:

1
2
3
4
vertices[0] = Point2f(100, 250)
vertices[1] = Point2f(250, 100)
vertices[2] = Point2f(300, 350)
vertices[3] = Point2f(150, 400)

这些点即为旋转矩形的四个顶点,用于进一步的图像绘制或计算。


注意事项

  1. 旋转矩形的角度

    • cv::minAreaRect() 返回的旋转矩形角度是逆时针方向的角度,因此可以通过 boxPoints() 提取旋转后的四个顶点。
  2. 矩形的点顺序

    • 返回的四个顶点按顺时针或逆时针方向排列,可以使用这些点来绘制矩形或进行其他几何操作。
  3. 不需要额外的转换

    • 通过 boxPoints(),不需要手动计算矩形的四个顶点,OpenCV 会自动根据旋转矩形的属性来计算和返回它们。

应用场景

  1. 目标检测与定位

    • 在物体检测任务中,cv::boxPoints() 可以将物体的最小外接矩形转换为可用的顶点,帮助绘制目标边界框。
  2. 图像分割后的形状分析

    • 在图像分割或轮廓检测中,计算最小外接矩形并提取顶点,用于进一步分析或操作(如裁剪、目标识别)。
  3. 旋转矩形的可视化

    • 在可视化中,boxPoints() 提供了一种方便的方式来获取旋转矩形的四个顶点,以便绘制旋转矩形或显示物体的边界。
  4. 物体姿势估计

    • 在物体姿势估计中,cv::boxPoints() 用于获取旋转矩形的边界,这可以用于估计物体在空间中的方向。

cv::boxPoints() 是一个非常有用的函数,能够从旋转矩形中提取出四个顶点,它在计算机视觉和图像处理中具有广泛的应用,特别是在目标检测、物体定位、形状分析等任务中。

cv::minAreaRect() 函数 详解

cv::minAreaRect() 是 OpenCV 中用于计算最小外接矩形的函数。它返回一个矩形,该矩形包含给定的轮廓或点集,并且具有最小的面积。最小外接矩形的边可能并不是与图像的坐标轴平行的,而是倾斜的,这使得它比普通的矩形更有效地包围给定的点。


函数定义

1
2
3
RotatedRect cv::minAreaRect(
InputArray points // 输入的点集或轮廓
);

参数详解

  1. **points**:
    • 输入参数,可以是一个 std::vector<Point>std::vector<std::vector<Point>>(轮廓)的集合,表示一组点。
    • 输入的点集将用于计算最小外接矩形。
    • 这些点应该是二维的坐标,且至少包含 3 个点。

返回值

  • **RotatedRect**:
    • 返回一个 RotatedRect 对象,表示最小外接矩形。
    • RotatedRect 包含三个元素:
      • **center**:矩形的中心点,类型为 Point2f,表示矩形中心的位置。
      • **size**:矩形的大小,类型为 Size2f,包括矩形的宽度和高度。
      • **angle**:矩形的旋转角度,类型为 float,表示矩形的旋转角度,以度为单位,逆时针为正。

工作原理

cv::minAreaRect() 使用以下方法计算最小外接矩形:

  • 该函数通过计算所有点的旋转矩形来得到最小的矩形。
  • 所得矩形的面积是最小的,且包含所有的输入点。
  • 矩形的边可以是任意角度,不一定与坐标轴平行。

示例代码

最小外接矩形的计算

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
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main() {
// 创建一个点集,模拟轮廓
vector<Point> points = {Point(100, 200), Point(200, 100), Point(300, 300), Point(150, 250)};

// 计算最小外接矩形
RotatedRect minRect = minAreaRect(points);

// 获取矩形的四个顶点
Point2f vertices[4];
minRect.points(vertices);

// 绘制最小外接矩形
Mat img = Mat::zeros(400, 400, CV_8UC3);
for (int i = 0; i < 4; i++) {
line(img, vertices[i], vertices[(i + 1) % 4], Scalar(0, 255, 0), 2); // 绘制矩形边
}

// 绘制矩形的中心
circle(img, minRect.center, 5, Scalar(0, 0, 255), -1);

// 显示结果
imshow("Min Area Rect", img);
waitKey(0);

return 0;
}

解释

  • minAreaRect() 计算最小外接矩形的中心、宽度、高度和旋转角度。
  • minRect.points(vertices) 用于计算矩形的四个顶点,这些顶点是矩形的四个角。
  • 使用 line()circle() 函数绘制矩形和中心。

返回值示例

假设输入点集是 {Point(100, 200), Point(200, 100), Point(300, 300), Point(150, 250)}minAreaRect() 的返回值可能如下:

1
2
3
center = (200, 200)
size = (150, 100)
angle = -30

这意味着:

  • 最小外接矩形的中心点是 (200, 200)
  • 矩形的大小是宽度 150,高度 100。
  • 矩形相对于水平方向旋转了 -30 度(逆时针方向)。

注意事项

  1. 输入点集

    • cv::minAreaRect() 适用于一组点(例如轮廓或多个离散点),点集必须具有至少 3 个点。
  2. 返回值的角度

    • 返回的角度是逆时针方向的角度。
    • angle 值可能为负数,表示矩形相对于水平方向的逆时针旋转。
  3. 点的顺序

    • 计算最小外接矩形时,点集的顺序并不重要,因为算法会自动处理。
  4. 矩形可能不是轴对齐的

    • 最小外接矩形的边不一定与图像坐标轴平行,它可以旋转,从而实现包围给定点集的最小矩形。

应用场景

  1. 目标检测与定位

    • 使用最小外接矩形可以为检测到的目标(例如物体、形状等)生成一个最小的框,帮助进一步分析目标的位置信息。
  2. 形状分析

    • 用于分析轮廓的大小和形状,可以应用于物体检测、姿势估计等领域。
  3. 物体跟踪

    • 在物体跟踪算法中,最小外接矩形可以用来估计目标的边界,并在视频序列中跟踪物体。
  4. 图像分割后的处理

    • 在图像分割应用中,通过最小外接矩形可以找出分割区域的边界,进一步进行分析或显示。

cv::minAreaRect() 是一个非常实用的函数,能够为任意点集提供一个最小的外接矩形,并且支持旋转矩形。这使得它在图像处理、目标检测和分析中具有广泛的应用。

cv::contourArea() 函数 详解

cv::contourArea() 是 OpenCV 中用于计算轮廓面积的函数。它可以用于评估轮廓所围成的区域的大小,通常在物体检测、形状分析等任务中非常有用。


函数定义

1
2
3
4
double cv::contourArea(
InputArray contour, // 输入轮廓
bool oriented = false // 是否计算有向面积(默认 false)
);

参数详解

  1. **contour**:

    • 输入轮廓,类型为 std::vector<Point>,表示一个封闭的轮廓。轮廓是由轮廓点组成的多边形,通常通过 cv::findContours() 函数提取。
    • 轮廓应为闭合的,且数据应为顺时针或逆时针排列。
  2. **oriented**(可选):

    • 布尔值,指定是否计算有向面积。
      • false(默认值):计算无向面积,忽略轮廓的方向,返回绝对值。
      • true:计算有向面积,返回正或负值,取决于轮廓的点顺序(顺时针为正,逆时针为负)。

返回值

  • 返回计算得到的面积值,类型为 double
    • oriented = false,返回绝对面积值。
    • oriented = true,返回带符号的面积值,正值表示顺时针方向的轮廓,负值表示逆时针方向的轮廓。

工作原理

  • cv::contourArea() 使用 Shoelace 定理(叉积公式) 来计算轮廓所围成的区域面积:

    [
    \text{Area} = \frac{1}{2} \left| \sum_{i=1}^{n-1} (x_i y_{i+1} - x_{i+1} y_i) + (x_n y_1 - x_1 y_n) \right|
    ]

    • x_i, y_i 是轮廓点的坐标,n 是轮廓点的数量。
    • 该公式是根据轮廓的点顺序(顺时针或逆时针)来计算。
  • 通过轮廓的方向(顺时针或逆时针),可以判断区域的面积是正值还是负值。oriented 参数控制是否返回有向面积。


示例代码

计算轮廓面积

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
35
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main() {
// 读取图像并转换为灰度
Mat src = imread("image.jpg", IMREAD_GRAYSCALE);
if (src.empty()) {
cerr << "Error loading image!" << endl;
return -1;
}

// 二值化处理
Mat binary;
threshold(src, binary, 128, 255, THRESH_BINARY);

// 检测轮廓
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(binary, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

// 计算第一个轮廓的面积
double area = contourArea(contours[0]);

// 显示结果
cout << "Area of first contour: " << area << endl;

// 绘制轮廓
Mat result = Mat::zeros(src.size(), CV_8UC3);
drawContours(result, contours, 0, Scalar(0, 255, 0), 2);
imshow("Contours", result);
waitKey(0);

return 0;
}

计算有向面积

1
2
double area_with_direction = contourArea(contours[0], true);
cout << "Oriented area of first contour: " << area_with_direction << endl;
  • true 将返回有向面积,值为正或负,表示轮廓方向。

注意事项

  1. 轮廓必须是闭合的

    • cv::contourArea() 计算的是封闭轮廓的面积。如果轮廓不闭合,面积计算将不准确。
  2. 顺时针和逆时针方向的区别

    • 如果轮廓按顺时针方向排列,计算出的面积为正值;如果按逆时针方向排列,计算出的面积为负值。通过 oriented 参数,可以选择是否计算有向面积。
  3. 对孔洞的处理

    • 如果轮廓有内嵌孔洞(如轮廓内包含另一个小轮廓),cv::contourArea() 仍然可以正确计算整个轮廓的面积,但需要注意孔洞的影响。多个轮廓可以通过 RETR_CCOMPRETR_TREE 模式在 findContours() 中提取。

典型应用

  1. 形状分析

    • 在目标检测、物体识别中,计算轮廓的面积用于衡量物体的大小。
  2. 目标筛选

    • 在图像分割中,根据面积阈值筛选出目标区域。
  3. 特征提取

    • 在机器视觉应用中,面积是形状特征的一部分,可以与其他特征一起用于分类或识别。
  4. 孔洞检测

    • 在复杂形状的分析中,计算面积并结合孔洞信息,帮助检测和处理孔洞区域。

cv::contourArea() 是一个简单但重要的函数,用于计算轮廓的面积。在形状分析、图像分割和目标识别中,面积常常是重要的特征。

cv::findContours() 函数 详解

cv::findContours() 是 OpenCV 中用于从二值图像中检测轮廓的函数。轮廓是用于表示物体边界的闭合曲线,在图像处理领域中广泛应用于目标检测、形状分析和特征提取等任务。


函数定义

1
2
3
4
5
6
7
8
void cv::findContours(
InputArray image, // 输入二值图像
OutputArrayOfArrays contours, // 输出的轮廓
OutputArray hierarchy, // 输出的层次结构
int mode, // 轮廓检索模式
int method, // 轮廓逼近方法
Point offset = Point() // 轮廓点的偏移量
);

参数详解

  1. **image**:

    • 输入图像,必须为二值图像(如由 cv::threshold()cv::Canny() 处理后的图像)。
    • 图像会被修改,因此如果需要保留原图,应传递其副本。
  2. **contours**:

    • 输出的轮廓,类型为 std::vector<std::vector<Point>>
    • 每个轮廓是一个点的向量,表示轮廓的边界点。
  3. **hierarchy**:

    • 输出的层次结构,类型为 std::vector<Vec4i>
    • 每个轮廓与层次结构中的元素对应,四个值分别表示:
      • hierarchy[i][0]:下一个轮廓的索引(同层次)。
      • hierarchy[i][1]:上一个轮廓的索引(同层次)。
      • hierarchy[i][2]:第一个子轮廓的索引。
      • hierarchy[i][3]:父轮廓的索引。
    • 如果不需要层次结构,可以传入 noArray()
  4. **mode**(轮廓检索模式):

    • 指定如何检索轮廓:
      • RETR_EXTERNAL:仅检索最外层轮廓。
      • RETR_LIST:检索所有轮廓,但不建立层次结构。
      • RETR_CCOMP:检索所有轮廓,并将其组织为两级层次结构(外层和内层)。
      • RETR_TREE:检索所有轮廓,并以完整的树状层次结构存储。
  5. **method**(轮廓逼近方法):

    • 指定如何存储轮廓的点:
      • CHAIN_APPROX_NONE:存储所有的轮廓点。
      • CHAIN_APPROX_SIMPLE:压缩水平、垂直和对角方向的冗余点,仅保留拐点。
      • CHAIN_APPROX_TC89_L1CHAIN_APPROX_TC89_KCOS:使用 Teh-Chin 链逼近算法。
  6. **offset**(可选):

    • 将所有轮廓点的坐标偏移一个固定值(默认值为 Point(0, 0))。
    • 常用于图像裁剪后,需要修正轮廓位置的情况。

返回值

  • cv::findContours() 没有返回值,但会通过参数输出轮廓和层次结构。

使用示例

基本用法

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;

int main() {
// 读取图像并转换为灰度
Mat src = imread("image.jpg", IMREAD_GRAYSCALE);
if (src.empty()) {
cerr << "Error loading image!" << endl;
return -1;
}

// 二值化处理
Mat binary;
threshold(src, binary, 128, 255, THRESH_BINARY);

// 检测轮廓
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(binary, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);

// 绘制轮廓
Mat result = Mat::zeros(src.size(), CV_8UC3);
for (size_t i = 0; i < contours.size(); i++) {
drawContours(result, contours, (int)i, Scalar(0, 255, 0), 2, LINE_8, hierarchy, 0);
}

// 显示结果
imshow("Original Image", src);
imshow("Contours", result);
waitKey(0);

return 0;
}

注意事项

  1. 输入图像必须为二值图像

    • 可以通过 cv::threshold()cv::Canny() 等方法生成二值图像。
  2. 原图像被修改

    • findContours() 会修改输入图像,通常清除非轮廓部分。
  3. **选择适当的 modemethod**:

    • 根据任务需求选择合适的轮廓检索模式和逼近方法。
  4. 轮廓点的数量

    • CHAIN_APPROX_NONE 保存的点数最多,CHAIN_APPROX_SIMPLE 可以显著减少点数。
  5. 轮廓的存储顺序

    • 检索到的轮廓存储在 contours 中,顺序与像素扫描顺序一致。

应用场景

  1. 对象检测和分割

    • 提取物体边界进行目标检测或分割。
  2. 形状分析

    • 使用轮廓进行形状匹配和特征分析。
  3. 边缘检测后处理

    • 提取 Canny 边缘检测结果中的闭合轮廓。
  4. 图像测量

    • 根据轮廓计算面积、周长、质心等几何特征。

cv::findContours() 是一个强大而灵活的工具,可广泛应用于图像分析和计算机视觉任务中。合理选择参数可以优化性能并适应具体需求。

cv::threshold() 详解

cv::threshold() 是 OpenCV 中用于对图像进行阈值处理的函数,它将图像的像素值根据给定的阈值分成两个区域。通常用于图像分割或简单的二值化处理。


函数定义

1
2
3
4
5
6
7
double cv::threshold(
InputArray src, // 输入图像
OutputArray dst, // 输出图像
double thresh, // 阈值
double maxval, // 最大值
int type // 阈值类型
);

参数详解

  1. src:

    • 输入图像,必须是单通道图像(如灰度图)。
    • 数据类型可以是 8 位、16 位或 32 位浮点数。
  2. dst:

    • 输出图像,与输入图像具有相同的大小和类型。
    • 经过阈值处理后的结果。
  3. thresh:

    • 指定的阈值,像素值根据此阈值进行分类。
  4. maxval:

    • 当像素值超过(或低于)阈值时设置为的最大值,具体行为取决于 type 参数。
  5. type:

    • 指定阈值操作的类型,支持以下几种:
      • THRESH_BINARY:二值化处理。
        • (\text{dst}(x, y) =
          \begin{cases}
          \text{maxval} & \text{if src}(x, y) > \text{thresh} \
          0 & \text{otherwise}
          \end{cases})
      • THRESH_BINARY_INV:反转二值化。
        • (\text{dst}(x, y) =
          \begin{cases}
          0 & \text{if src}(x, y) > \text{thresh} \
          \text{maxval} & \text{otherwise}
          \end{cases})
      • THRESH_TRUNC:截断阈值。
        • (\text{dst}(x, y) =
          \begin{cases}
          \text{thresh} & \text{if src}(x, y) > \text{thresh} \
          \text{src}(x, y) & \text{otherwise}
          \end{cases})
      • THRESH_TOZERO:零阈值化。
        • (\text{dst}(x, y) =
          \begin{cases}
          \text{src}(x, y) & \text{if src}(x, y) > \text{thresh} \
          0 & \text{otherwise}
          \end{cases})
      • THRESH_TOZERO_INV:反转零阈值化。
        • (\text{dst}(x, y) =
          \begin{cases}
          0 & \text{if src}(x, y) > \text{thresh} \
          \text{src}(x, y) & \text{otherwise}
          \end{cases})

返回值

  • 函数返回阈值 thresh,在自动计算阈值的模式(如 THRESH_OTSU)下,返回计算后的值。

示例代码

基本二值化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <opencv2/opencv.hpp>
using namespace cv;

int main() {
// 读取灰度图像
Mat src = imread("image.jpg", IMREAD_GRAYSCALE);
if (src.empty()) {
std::cerr << "Error loading image!" << std::endl;
return -1;
}

Mat dst;
// 二值化操作,阈值为 128,最大值为 255
threshold(src, dst, 128, 255, THRESH_BINARY);

// 显示结果
imshow("Original Image", src);
imshow("Thresholded Image", dst);
waitKey(0);

return 0;
}

OTSU 阈值法

OTSU 是一种自动计算最佳阈值的方法,通常用于图像二值化。

1
threshold(src, dst, 0, 255, THRESH_BINARY | THRESH_OTSU);
  • thresh 参数会被忽略,返回值为自动计算的最佳阈值。

注意事项

  1. 输入图像要求

    • 只能对单通道图像使用,RGB 图像需要先转换为灰度图。
  2. 阈值选择

    • 手动设置阈值时需要通过实验调整合适值。
    • 对于复杂图像,可使用 THRESH_OTSU 自动计算。
  3. 适合场景

    • 二值化用于分割前景与背景。
    • 应用范围包括对象检测、OCR(光学字符识别)、医学图像处理等。

典型应用

  1. 分割前景和背景

    • 根据像素亮度,将目标区域与背景区分开。
  2. 去除噪声

    • 对噪声平滑后的图像应用阈值,可以突出重要特征。
  3. 特征提取

    • 在二值图像中定位边缘、形状等信息。
  4. 医学图像分析

    • 用于 CT 或 MRI 图像的病灶区域分割。

cv::threshold() 是一个简单而高效的工具,适合处理各种图像分割问题,并且通过 OTSU 和其他方法可以自动化调整阈值,提高处理效果。

OpenCV cv::GaussianBlur() 详解

cv::GaussianBlur() 是 OpenCV 中用于对图像进行高斯模糊处理的函数。高斯模糊是一种使用高斯核对图像进行平滑操作的技术,主要用于减少图像中的噪声和细节。


函数定义

1
2
3
4
5
6
7
8
void cv::GaussianBlur(
InputArray src, // 输入图像
OutputArray dst, // 输出图像
Size ksize, // 高斯核大小(宽度和高度)
double sigmaX, // X 方向的高斯核标准差
double sigmaY = 0, // Y 方向的高斯核标准差,默认为 0
int borderType = BORDER_DEFAULT // 边界模式
);

参数详解

  1. **src**:

    • 输入图像,支持单通道或多通道图像。
    • 数据类型可以是 8 位、16 位或 32 位浮点数。
  2. **dst**:

    • 输出图像,与输入图像具有相同的大小和通道数。
  3. **ksize**:

    • 高斯核的大小,用 cv::Size 指定。
    • 宽度和高度都必须为正的奇数,例如 cv::Size(3, 3)cv::Size(5, 5)
    • 核大小越大,模糊效果越强。
  4. **sigmaX**:

    • 高斯核在 X 方向的标准差,决定模糊的强度。
    • 如果为 0,OpenCV 会根据 ksize 自动计算合适的值。
  5. **sigmaY**:

    • 高斯核在 Y 方向的标准差。
    • 默认值为 0,表示与 sigmaX 相同。
  6. **borderType**:

    • 指定边界模式,用于处理图像边缘。常见值包括:
      • BORDER_CONSTANT:填充常量值。
      • BORDER_REPLICATE:重复最边缘的像素。
      • BORDER_REFLECT:镜像反射模式。
      • BORDER_WRAP:环绕模式。
      • BORDER_DEFAULT(默认):通常为 BORDER_REFLECT_101

工作原理

高斯模糊通过卷积操作实现,卷积核的每个权重值由高斯函数决定:
[
G(x, y) = \frac{1}{2\pi \sigma^2} e^{-\frac{x^2 + y^2}{2\sigma^2}}
]

  • ( G(x, y) ): 高斯核的值。
  • ( \sigma ): 标准差,控制模糊的范围。
  • ( x, y ): 距离核中心的偏移。

核大小和标准差共同决定了模糊的效果。标准差越大,权重分布越宽,模糊效果越强。


示例代码

C++ 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <opencv2/opencv.hpp>
using namespace cv;

int main() {
// 读取输入图像
Mat src = imread("image.jpg", IMREAD_COLOR);
if (src.empty()) {
std::cerr << "Error loading image!" << std::endl;
return -1;
}

// 输出图像
Mat dst;

// 使用高斯模糊
GaussianBlur(src, dst, Size(5, 5), 1.5, 1.5);

// 显示结果
imshow("Original Image", src);
imshow("Gaussian Blurred Image", dst);
waitKey(0);

return 0;
}

注意事项

  1. 核大小和标准差的选择

    • 核大小应为奇数且适当。过小的核可能导致模糊效果不明显,过大的核会损失细节。
    • 标准差与核大小密切相关,可通过实验确定最佳值。
  2. 性能影响

    • 大核会显著增加计算量,可能需要优化(如使用 GPU 加速)。
  3. 与其他模糊方法的对比

    • 与均值模糊(cv::blur)相比,高斯模糊更平滑,视觉效果更自然。
    • 与中值模糊(cv::medianBlur)相比,高斯模糊对噪声的抑制能力稍弱,但保留边缘的能力较差。

实际应用

  1. 降噪预处理
    • 在边缘检测(如 Canny 边缘检测)前,用于平滑图像,减少虚假边缘。
  2. 背景模糊
    • 模糊背景以突出前景目标。
  3. 图像缩放前的平滑处理
    • 减少缩放后产生的伪影。
  4. 视觉效果增强
    • 在图像处理中实现柔化效果。

cv::GaussianBlur() 是一种高效、自然的模糊方法,广泛用于各类图像处理任务。

OpenCV cv::samples::findFile() 详解

cv::samples::findFile() 是 OpenCV 中的一个实用函数,用于查找示例文件或数据文件的路径。在进行示例代码编写或加载数据文件时,经常需要使用这个函数来确保程序能够正确地找到所需的文件。

以下是对 cv::samples::findFile() 的解释:

1
std::string findFile(const std::string& filename, bool required = true, bool silentMode = true);
  • filename 参数是要查找的文件名或文件路径。
  • required 参数指示是否将文件视为必需。如果为 true,则函数在找不到文件时会抛出一个异常;如果为 false,则函数会返回空字符串。
  • silentMode 参数指示是否在查找文件时静默模式。如果为 true,则函数在找不到文件时不会输出警告消息;如果为 false,则会输出警告消息。

函数返回一个字符串,代表找到的文件的路径。如果文件找不到并且 required 参数为 false,则返回一个空字符串。

cv::samples::findFile() 函数通常用于示例代码中,以确保示例文件或数据文件能够在不同的开发环境中正确地加载。例如,在图像处理示例中,可以使用 cv::samples::findFile() 函数来加载示例图像文件。

以下是一个示例用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>

int main() {
std::string filename = cv::samples::findFile("lena.jpg");
if (filename.empty()) {
std::cerr << "Failed to find the file 'lena.jpg'" << std::endl;
return -1;
}

cv::Mat image = cv::imread(filename);
if (image.empty()) {
std::cerr << "Failed to load the image" << std::endl;
return -1;
}

cv::imshow("Image", image);
cv::waitKey(0);

return 0;
}

这段代码首先使用 cv::samples::findFile() 函数查找名为 “lena.jpg” 的图像文件,然后加载并显示它。

OpenCV cv::merge() 函数 详解

cv::merge() 函数是 OpenCV 库中的一个函数,用于将多个单通道图像合并为一个多通道图像。例如,将三个单通道的图像(比如分别代表 RGB 三个通道的图像)合并成一个三通道的彩色图像。下面是对 cv::merge() 函数的详解:

函数原型

1
2
3
4
void cv::merge(
InputArrayOfArrays mv,
OutputArray dst
)

参数说明

  • mv:包含多个单通道图像的数组。每个单通道图像都会被合并到输出的多通道图像中。
  • dst:输出的多通道图像。

功能

cv::merge() 函数用于将多个单通道图像合并成一个多通道图像。例如,如果输入是三个单通道的图像,则函数将会生成一个三通道的彩色图像,其中每个通道分别对应输入数组中的一个单通道图像。

注意事项

  • 输入数组 mv 中的每个单通道图像的尺寸和数据类型必须相同。
  • 输出的多通道图像 dst 的通道数将与输入数组 mv 的长度相同。
  • 输出的多通道图像 dst 的尺寸与输入数组 mv 中的单通道图像的尺寸相同。

示例

1
2
3
4
5
6
7
8
cv::Mat blueChannel = cv::imread("blue_channel.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat greenChannel = cv::imread("green_channel.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat redChannel = cv::imread("red_channel.jpg", cv::IMREAD_GRAYSCALE);

std::vector<cv::Mat> channels = {blueChannel, greenChannel, redChannel};

cv::Mat mergedImage;
cv::merge(channels, mergedImage);

在这个示例中,blueChannelgreenChannelredChannel 是三个单通道的图像,分别代表了蓝色通道、绿色通道和红色通道。通过 cv::merge() 函数将这三个单通道图像合并成一个三通道的彩色图像 mergedImage

cv::merge() 函数是 OpenCV 中用于合并单通道图像的常用函数之一,它为图像处理提供了便利性和灵活性,可以方便地将单通道图像合并成多通道图像。

OpenCV cv::split() 函数 详解

cv::split() 函数是 OpenCV 库中的一个函数,用于将多通道图像分离为各个单通道图像。例如,将一个三通道的彩色图像分离成三个单通道的图像。下面是对 cv::split() 函数的详解:

函数原型

1
2
3
4
void cv::split(
InputArray src,
OutputArrayOfArrays mv
)

参数说明

  • src:输入的多通道图像。
  • mv:包含输出图像的数组。每个单通道图像都会被存储在这个数组中。

功能

cv::split() 函数用于将多通道图像分离成各个单通道图像。例如,如果输入是一个三通道的彩色图像,则函数将会生成三个单通道的图像,每个通道分别存储在输出数组中。

注意事项

  • 输入图像可以是多通道的,例如 RGB 彩色图像或者 HSV 图像。
  • 输出数组 mv 中的每个单通道图像的尺寸与输入图像的尺寸相同。
  • 输出数组 mv 中的每个单通道图像的数据类型与输入图像的数据类型相同。
  • 输出数组 mv 中的每个单通道图像可以单独访问,进行后续的处理或显示。

示例

1
2
3
4
5
6
7
cv::Mat src = cv::imread("input.jpg", cv::IMREAD_COLOR);
std::vector<cv::Mat> channels;
cv::split(src, channels);

cv::Mat blueChannel = channels[0]; // 蓝色通道
cv::Mat greenChannel = channels[1]; // 绿色通道
cv::Mat redChannel = channels[2]; // 红色通道

在这个示例中,src 是一个输入的彩色图像,通过 cv::split() 函数将其分离为三个单通道图像,分别存储在 channels 中。然后,可以通过数组索引来访问各个通道,例如 channels[0] 表示蓝色通道。

cv::split() 函数是 OpenCV 中用于分离多通道图像的常用函数之一,它为图像处理提供了灵活性和便利性,可以方便地对各个通道进行单独处理。

OpenCV cvtColor() 函数 详解

cvtColor() 是 OpenCV 库中的一个函数,用于执行图像颜色空间转换。它可以将一种颜色空间的图像转换为另一种颜色空间,例如将 RGB 图像转换为灰度图像或将 BGR 图像转换为 HSV 图像。下面是对 cvtColor() 函数的详解:

函数原型

1
2
3
4
5
6
void cv::cvtColor(
InputArray src,
OutputArray dst,
int code,
int dstCn = 0
)

参数说明

  • src:输入图像。
  • dst:输出图像,转换后的结果将存储在这里。
  • code:指定要执行的颜色空间转换类型的整数编码。例如,cv::COLOR_BGR2GRAY 表示从 BGR 到灰度图像的转换,cv::COLOR_BGR2HSV 表示从 BGR 到 HSV 的转换,以此类推。完整的转换类型列表可以在 OpenCV 文档中找到。
  • dstCn:可选参数,指定输出图像的通道数,通常为0(默认值),表示与输入图像的通道数相同。

功能

cvtColor() 函数用于将图像从一个颜色空间转换为另一个颜色空间。它可以执行各种标准的颜色空间转换,例如 RGB 到灰度、RGB 到 HSV、BGR 到 Lab 等等。

注意事项

  • 在执行颜色空间转换时,像素值可能会超出目标图像类型的范围。因此,输出图像通常需要使用适当的数据类型来存储转换后的像素值。
  • cvtColor() 函数对输入图像和输出图像的尺寸没有限制,但是输入图像和输出图像的通道数需要匹配转换的类型。

示例

1
2
3
cv::Mat src = cv::imread("input.jpg", cv::IMREAD_COLOR);
cv::Mat dst;
cv::cvtColor(src, dst, cv::COLOR_BGR2GRAY); // 将BGR图像转换为灰度图像

在这个示例中,src 是一个输入的彩色图像,它会被转换为灰度图像,并将结果存储在 dst 中。

cvtColor() 函数是 OpenCV 中执行图像颜色空间转换的常用函数之一,它为图像处理提供了强大的功能,包括颜色分析、特征提取和目标识别等方面的应用。

OpenCV convertTo() 函数 详解

convertTo() 是 OpenCV 库中的一个函数,用于执行图像数据类型的转换。它可以将一种图像数据类型转换为另一种,例如从一个单精度浮点数类型转换为无符号8位整型类型。下面是对 convertTo() 函数的详解:

函数原型

1
2
3
4
5
6
void cv::Mat::convertTo(
OutputArray m,
int rtype,
double alpha = 1,
double beta = 0
) const

参数说明

  • m:输出图像,转换后的结果将存储在这里。
  • rtype:输出图像的数据类型,例如 CV_8UCV_32F 等,可以通过 CV_8U 表示8位无符号整数,CV_32F 表示32位单精度浮点数,以此类推。
  • alpha:可选参数,是乘法因子,用于缩放转换后的像素值。
  • beta:可选参数,是加法因子,用于平移转换后的像素值。

功能

convertTo() 函数用于将一个 Mat 对象中的像素值类型转换为指定的数据类型。该函数执行的操作可以表达为以下公式:

[ \text{dst}(x,y) = \text{saturate_cast} \left( \alpha \cdot \text{src}(x,y) + \beta \right) ]

其中,(\text{dst}(x,y)) 是输出图像中位置 ((x,y)) 处的像素值,(\text{src}(x,y)) 是输入图像中位置 ((x,y)) 处的像素值。(\alpha) 和 (\beta) 是函数的参数,用于缩放和平移像素值。saturate_cast 是一个函数,用于确保结果在特定数据类型的有效范围内。

注意事项

  • 转换后的像素值可能会超出目标数据类型的有效范围,因此需要进行适当的饱和处理,convertTo() 函数会自动执行这个操作。
  • 可以通过 alphabeta 参数来控制转换的线性缩放和平移操作,如果不需要,可以将它们设置为默认值。

示例

1
2
3
cv::Mat src = cv::imread("input.jpg", cv::IMREAD_COLOR);
cv::Mat dst;
src.convertTo(dst, CV_32F); // 转换为32位浮点型图像

在这个示例中,src 是一个输入的图像,它会被转换为32位浮点型图像,结果存储在 dst 中。

convertTo() 函数是 OpenCV 中用于数据类型转换的重要工具,可以方便地处理不同数据类型之间的图像操作。

OpenCV cv::putText() 函数 详解

cv::putText() 是 OpenCV 中用于在图像上绘制文本的函数。该函数可以在图像上添加指定的字符串,以及指定的字体、颜色、大小和其他样式。下面是该函数的详细说明:

1
2
3
4
5
6
7
8
9
10
11
void cv::putText(
cv::InputOutputArray img, // 输入/输出图像
const String& text, // 要绘制的文本字符串
cv::Point org, // 文本起始位置的坐标(左下角)
int fontFace, // 字体类型,例如:cv::FONT_HERSHEY_SIMPLEX、cv::FONT_HERSHEY_PLAIN 等
double fontScale, // 字体大小的缩放系数
cv::Scalar color, // 文本颜色,如 cv::Scalar(255, 0, 0) 表示蓝色
int thickness = 1, // 文本的粗细,默认为 1
int lineType = LINE_8, // 文本的线条类型,默认为 8 连通线条
bool bottomLeftOrigin = false // 如果为 true,则表示坐标 org 是文本左下角的位置,否则是左上角的位置,默认为 false
);

参数说明:

  • img:输入/输出图像,通常是 cv::Mat 类型,表示要在其上绘制文本的图像。
  • text:要绘制的文本字符串。
  • org:文本起始位置的坐标,即文本左下角的位置。如果 bottomLeftOrigin 参数为 false,则表示文本左上角的位置。
  • fontFace:字体类型,可以是预定义的字体类型,如 cv::FONT_HERSHEY_SIMPLEXcv::FONT_HERSHEY_PLAIN 等。
  • fontScale:字体大小的缩放系数。
  • color:文本颜色,通常使用 cv::Scalar 类型表示,如 cv::Scalar(255, 0, 0) 表示蓝色。
  • thickness:文本的线条粗细,默认为 1。
  • lineType:文本的线条类型,默认为 8 连通线条。
  • bottomLeftOrigin:如果为 true,则表示坐标 org 是文本左下角的位置,否则是左上角的位置,默认为 false。

注意:在使用 putText() 函数之前,确保图像类型支持文本绘制操作,即图像的深度必须为 CV_8UCV_32F 类型,而通道数必须为 1 或 3。

OpenCV cv::imdecode() 函数 详解 中文

cv::imdecode() 是 OpenCV 库中的一个函数,用于将图像数据解码为 OpenCV 中的 cv::Mat 对象。该函数通常用于从内存中读取图像数据,而不是从文件中读取。

以下是 cv::imdecode() 函数的一些关键参数及其解释:

  • 参数1 (buf): 这是一个包含图像数据的缓冲区。通常情况下,这是一个 uchar 类型的数组,存储着图像的原始数据。

  • 参数2 (flags): 这是一个整数参数,用于指定如何解码图像。常用的标志包括 cv::IMREAD_COLOR(默认值,将图像以BGR颜色格式加载)、cv::IMREAD_GRAYSCALE(将图像以灰度格式加载)和 cv::IMREAD_UNCHANGED(加载图像的所有通道,包括 Alpha 通道)。

  • 返回值: 函数返回一个 cv::Mat 对象,该对象包含解码后的图像数据。

cv::imdecode() 函数的调用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
// 读取图像数据到内存中
std::vector<uchar> data; // 图像数据的缓冲区
// 假设 data 被填充了图像数据

// 解码图像数据
cv::Mat image = cv::imdecode(data, cv::IMREAD_COLOR);

// 检查图像是否成功解码
if (!image.empty()) {
// 成功加载图像,进行进一步的处理
cv::imshow("Decoded Image", image);
cv::waitKey(0);
} else {
// 加载失败
std::cerr << "Failed to decode image." << std::endl;
}

return 0;
}

这个例子演示了如何使用 cv::imdecode() 函数将图像数据解码为 cv::Mat 对象,并在图像成功加载时显示它。

OpenCV cv::imencode() 详解

cv::imencode() 函数是 OpenCV 库中用于将图像编码为特定格式(如JPEG、PNG等)的函数。它可以将 cv::Mat 中存储的图像数据编码为指定格式的图像,并将编码后的图像数据存储到内存缓冲区中。

该函数的原型为:

1
bool imencode(const String& ext, InputArray img, std::vector<uchar>& buf, const std::vector<int>& params = std::vector<int>());

其中参数含义如下:

  • ext:字符串参数,用于指定输出图像的格式,例如 ".jpg"".png" 等。
  • imgcv::Mat 对象,包含待编码的图像数据。
  • bufstd::vector<uchar> 类型的输出参数,用于存储编码后的图像数据。
  • params(可选):一个可选的参数向量,用于指定图像编码的参数,如 JPEG 质量、PNG 压缩级别等。具体参数因图像格式而异。

下面是一些示例代码,展示了如何使用 cv::imencode() 函数将图像编码为 JPEG 格式并存储到内存中的 std::vector<uchar> 中:

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
35
36
37
38
#include <opencv2/opencv.hpp>
#include <vector>

int main() {
cv::Mat image = cv::imread("path_to_your_image.jpg");

if (image.empty()) {
std::cout << "无法读取图像文件\n";
return -1;
}

std::vector<uchar> buffer;
std::vector<int> params;
params.push_back(cv::IMWRITE_JPEG_QUALITY); // 设置 JPG 质量
params.push_back(95); // 设置 JPG 图像质量,可根据需要调整

// 将图像编码为 JPG 格式并保存到内存
bool success = cv::imencode(".jpg", image, buffer, params);

if (success) {
// buffer 中现在存储了编码后的 JPG 数据,可以进行保存或其他处理
// 例如,将内存中的 JPG 数据保存到文件
FILE *file = fopen("saved_image.jpg", "wb");
if (file != NULL) {
fwrite(buffer.data(), sizeof(uchar), buffer.size(), file);
fclose(file);
std::cout << "图像保存成功\n";
} else {
std::cout << "无法保存图像\n";
return -1;
}
} else {
std::cout << "图像编码失败\n";
return -1;
}

return 0;
}

在示例中,cv::imencode()cv::Mat 中的图像数据编码为 JPG 格式,并将编码后的数据存储在 buffer 中。之后,将 buffer 中的数据写入文件 "saved_image.jpg"

要注意,在使用 cv::imencode() 函数之前,需要确保已经正确读取了图像数据并存储在 cv::Mat 对象中。

感谢老板支持!敬礼(^^ゞ