图像轮廓匹配

一、原理

(1)最常用到的轮廓匹配就是字符的匹配,而两个轮廓最最简洁的方式就是比较它们的轮廓矩。

矩就是通过对轮廓上所有点进行积分运算活求和运算而得到一个粗略的特征,对一幅图像I(x,y)

求普通矩公式为:

                                             

其中p对应x维度上的矩,q对应y维度上的矩,阶数表示对应的部分的指数,该计算是对轮廓边界上

所有像素(数目为n)进行求和。

各阶矩的物理意义:0阶矩(m00)表示目标区域的质量,m00实际上对应轮廓边界上点的数目。

                                   1阶矩(m01,m10)表示目标区域质心

                                    2阶矩(m02,m20,m11)表示旋转半径

                                   3阶矩(m03,m30,m12,m21,)表示描述目标的方位和斜度,反应目标的扭曲程度

但矩要能够作为一种特征描述方法得到应用,其要与目标空间变换(平移、尺度、旋转)无关。因此在几何

矩的基本定义基础上,进一步构造平移不变。尺度不变和旋转不变矩。

(2)中心矩:构造平移不变性

质心坐标为:

                                            

为了使矩具有平移不变性,利用质心坐标构造中心矩:

                                                                                                 

(3)归一化中心矩;构造尺度不变性。为抵消尺度变化对中心矩的影响,用零阶中心矩u00对其余各个中心矩

进行归一化处理,得到归一化中心矩为:

                                                                         

其中r=(p+q)/2+1。

(4)hu矩:构造旋转不变性.hu矩是归一化中心矩的线性组合。hu矩是从中心矩中计算得到,其计算公式如下:

 

根据公式可以看到,每个图像对应7个hu矩。通过观察可以发现当阶数变高时,hu矩一般会变小。根据定义,高阶hu矩

由多个归一化矩的高阶幂计算得到,而归一化矩都是小于1的,所以指数越大,计算所得的值越小。

很自然,使用hu矩就可以比较两个物体判断他们的相似性。


以下是基于OpenCV的C++代码实现图像轮廓匹配中的轮廓筛选: ```cpp #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main() { // 读取模板图像和目标图像 Mat templateImg = imread("template.jpg", IMREAD_GRAYSCALE); Mat targetImg = imread("target.jpg", IMREAD_GRAYSCALE); // 定义轮廓存储变量 vector<vector<Point>> templateContours, targetContours; vector<Vec4i> templateHierarchy, targetHierarchy; // 寻找模板图像和目标图像的轮廓 findContours(templateImg, templateContours, templateHierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); findContours(targetImg, targetContours, targetHierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); // 定义轮廓筛选阈值 double minArea = 100; double maxArea = 1000; // 对模板图像轮廓进行筛选 vector<vector<Point>> filteredTemplateContours; for (int i = 0; i < templateContours.size(); i++) { double area = contourArea(templateContours[i]); if (area > minArea && area < maxArea) { filteredTemplateContours.push_back(templateContours[i]); } } // 对目标图像轮廓进行筛选 vector<vector<Point>> filteredTargetContours; for (int i = 0; i < targetContours.size(); i++) { double area = contourArea(targetContours[i]); if (area > minArea && area < maxArea) { filteredTargetContours.push_back(targetContours[i]); } } // 显示筛选后的模板图像和目标图像轮廓 Mat templateContoursImg = Mat::zeros(templateImg.size(), CV_8UC3); drawContours(templateContoursImg, filteredTemplateContours, -1, Scalar(0, 255, 0), 2); imshow("Filtered Template Contours", templateContoursImg); Mat targetContoursImg = Mat::zeros(targetImg.size(), CV_8UC3); drawContours(targetContoursImg, filteredTargetContours, -1, Scalar(0, 255, 0), 2); imshow("Filtered Target Contours", targetContoursImg); waitKey(0); return 0; } ``` 注:以上代码中的`template.jpg`和`target.jpg`分别为模板图像和目标图像,可以根据实际情况进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值