文章目录
1、点多边形测试
1.1、计算像素点是在轮廓内部、外部或边界上:cv::pointPolygonTest()
1.2、计算最小值和最大值及其位置:cv::minMaxLoc()
1.3、实战案例
2、矩
2.1、计算多边形或光栅化形状的三阶以下的所有力矩:cv::moments()
2.2、计算轮廓面积:cv::contourArea()
2.3、计算曲线长度或闭合轮廓周长:cv::arcLength()
2.4、实战案例
3、凸包
3.1、计算凸包:cv::convexHull()
3.2、实战案例
4、映射
4.1、像素重映射:cv::remap()
4.2、实战案例
5、反向投影
5.1、将指定通道从输入阵列复制到输出阵列的指定通道:cv::mixChannels()
5.2、计算直方图的反向投影:cv::calcBackProject()
5.3、实战案例
1、点多边形测试
1.1、计算像素点是在轮廓内部、外部或边界上:cv::pointPolygonTest()
#include <opencv2/imgproc.hpp>
函数说明:double cv::pointPolygonTest( InputArray contour, Point2f pt, bool measureDist );
输入参数:
contour 输入轮廓。
pt 测试点坐标。
measureDist 是否返回距离值。
返回值: 若measureDist=True,返回点到最近轮廓边的有符号距离。
若measureDist=False时,返回值分别为+1(内部)、-1(外部)和0(边界上)。
1
2
3
4
5
6
7
8
9
10
1.2、计算最小值和最大值及其位置:cv::minMaxLoc()
该函数不适用于多通道阵列。如果需要在所有通道中找到最小或最大元素,请首先使用Mat::整形将数组重新解释为单个通道。或者,您可以使用extractImageCOI、mixChannels或split提取特定频道。
#include <opencv2/core.hpp>
函数说明:void cv::minMaxLoc( InputArray src, double * minVal, double * maxVal = 0, Point * minLoc = 0, Point * maxLoc = 0, InputArray mask = noArray() );
输入参数:
src 输入单通道阵列。
minVal 最小值;如果不需要,则使用NULL。
maxVal = 0 最大值;如果不需要,则使用NULL。
minLoc = 0 最小位置(在2D情况下);如果不需要,则使用NULL。
maxLoc = 0 最大位置(在2D情况下);如果不需要,则使用NULL。
mask = noArray() 用于选择子阵列的可选掩码。如果掩码不是空数组,则在指定的数组区域中搜索极值。
1
2
3
4
5
6
7
8
9
1.3、实战案例
#include <opencv2/opencv.hpp>
//using namespace cv;
//using namespace std;
int main(int argc, const char* argv[])
{
//(1)构建一张单通道8位400 x 400的图像,
const int r = 100;
cv::Mat src = cv::Mat::zeros(r * 4, r * 4, CV_8UC1);
//(2)绘制自定义六边形(通过line绘制六次)
std::vector<cv::Point2f> vert(6);
vert[0] = cv::Point(3 * r / 2, static_cast<int>(1.34 * r));
vert[1] = cv::Point(1 * r, 2 * r);
vert[2] = cv::Point(3 * r / 2, static_cast<int>(2.866 * r));
vert[3] = cv::Point(5 * r / 2, static_cast<int>(2.866 * r));
vert[4] = cv::Point(3 * r, 2 * r);
vert[5] = cv::Point(5 * r / 2, static_cast<int>(1.34 * r));
for (int ii = 0; ii < 6; ii++)
{
cv::line(src, vert[ii], vert[(ii+1) % 6], cv::Scalar(255), 3, 8, 0);
}
//(3)轮廓检测
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierachy;
cv::Mat src_contours = src.clone();
cv::findContours(src_contours, contours, hierachy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
//(4)对图像中所有像素点进行【点多边形测试】:测试像素点是在多边形内部、边界或外部上
cv::Mat raw_dist = cv::Mat::zeros(src_contours.size(), CV_32FC1);
for (int row = 0; row < raw_dist.rows; row++)
{
for (int col = 0; col < raw_dist.cols; col++)
{
//输入参数:输入轮廓,测试点,是否返回距离值。(False:1表示在内部,0表示在边界上,-1表示在外部)(True表示返回实际距离值)
double dist = cv::pointPolygonTest(contours[0], cv::Point2f(static_cast<float>(col), static_cast<float>(row)), true);
raw_dist.at<float>(row, col) = static_cast<float>(dist);
}
}
//(5)按内部、边界、外部三个区域分开,并且内/外部依据距离远近动态赋值,形成渐变色(也可以自定义为固定值)
double minValue, maxValue;
cv::minMaxLoc(raw_dist, &minValue, &maxValue, 0, 0, cv::Mat()); //计算最大值和最小值
cv::Mat dst = cv::Mat::zeros(src.size(), CV_8UC3);
for (int row = 0; row < dst.rows; row++)
{
for (int col = 0; col < dst.cols; col++)
{
float dist = raw_dist.at<float>(row, col);
if (dist > 0)
dst.at<cv::Vec3b>(row, col)[0] = (uchar)(abs(1.0 - (dist / maxValue)) * 255); //内部
else if (dist < 0)
dst.at<cv::Vec3b>(row, col)[2] = (uchar)(abs(1.0 - (dist / minValue)) * 255); //外部
else
{
dst.at<cv::Vec3b>(row, col)[0] = (uchar)(abs(255 - dist)); //边界
dst.at<cv::Vec3b>(row, col)[1] = (uchar)(abs(255 - dist)); //边界
dst.at<cv::Vec3b>(row, col)[2] = (uchar)(abs(255 - dist)); //边界
}
}
}
//(6)显示图像
cv::imshow("src", src);
cv::imshow("dst", dst);
cv::waitKey(0);
return 0;
}
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
2、矩
cv::moments是OpenCV中一个常用的函数,用于计算图像区域的各阶矩。如:计算输入图像中一个区域的几何矩、中心矩和归一化中心矩。
几何矩:是用来描述图像区域的形状和位置的;
中心矩:是关于区域质心的矩,它可以用于计算区域的方向;
归一化中心矩:是中心矩的归一化版本,可以用于不同尺度的比较。
常用于形状分析、图像识别、目标跟踪等领域。
在形状分析方面,可以用来计算图像中各个对象的重心、面积、方向和轮廓等信息,从而实现图像分割和形状匹配。
在图像识别方面,可以用来计算图像中特定对象的各种特征,如Hu矩,用于快速分类和识别目标。
在目标跟踪方面,可以用来计算目标位置和方向,从而实现实时跟踪。
2.1、计算多边形或光栅化形状的三阶以下的所有力矩:cv::moments()
spatial moments(空间距) central moments(中心矩) central no