opencv c++ 轮廓匹配

1、几何矩和Hu矩

1.1几何矩

a)几何计算公式:

        

        p、q为阶数,当p+q = 1时,几何矩为一阶矩,p+q = 2,几何矩为二阶矩,依次类推。。

因此,对于二值图像有:

        所有前景像素的x坐标之和:m_{10}

        所有前景像素的y坐标之和:m_{01}

        所有前景像素的个数:m_{00}

        注:前景像素为像素值为对应类型的满像素值的像素。

b)几何中心矩计算公式

        

         

1.2 Hu矩

Hu矩计算公式:

        

         性质:Hu矩具有放缩不变性旋转不变性

        利用下述7个值来进行轮廓匹配:

        

 2、基于Hu矩的轮廓匹配

        两个轮廓的参数计算公式(这里的h_{i}即为上面的\phi值)。

        

        两个轮廓的相似度计算公式: 

        

         在常规使用时,常预设一个阈值将相似度值与阈值进行比较,设定相似度大于阈值的两个轮廓为同一轮廓。

3、代码

步骤:
    1、任选图像2中的一个轮廓,计算其Hu矩
    2、对图像1所有轮廓计算Hu矩,将图像2的Hu矩与图像1的所有Hu进行比较
    3、相似度阈值操作。

void QuickDemo::contourGet(Mat& image, vector<vector<Point>>& contours)
{
	//高斯模糊
	Mat dst;
	GaussianBlur(image, dst, Size(3, 3), 0);
	Mat gray;
	cvtColor(dst, gray, COLOR_BGR2GRAY);

	Mat binary;
	threshold(gray, binary, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
	/*namedWindow("THRESH_OTSU", WINDOW_FREERATIO);
	imshow("THRESH_OTSU", binary);*/
	//查找轮廓
	vector<Vec4i> hierachy;
	findContours(binary, contours, hierachy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());
	cout << contours.size() << endl;
}
void QuickDemo::contourMatch(Mat& image1, Mat&image2)
{
	vector<vector<Point>> contours1;
	vector<vector<Point>> contours2;
	contourGet(image1, contours1);
	contourGet(image2, contours2);

	/*
	* 步骤:
	* 1、任选图像2中的一个轮廓,计算其Hu矩
	* 2、对图像1所有轮廓计算Hu矩,将图像2的Hu矩与图像1的所有Hu进行比较
	* 3、相似度阈值操作。
	*/
	//Hu矩计算
	Moments mm2 = moments(contours2[0]);//先计算几何矩
	Mat hu2;
	HuMoments(mm2, hu2);
	for (size_t t = 0; t < contours1.size(); ++t) {
		Moments mm = moments(contours1[t]);//先计算几何矩
		Mat hu;
		HuMoments(mm, hu);
		double sim_value = matchShapes(hu, hu2, CONTOURS_MATCH_I1, 0);
		//在原图绘制相似轮廓
		if (sim_value < 1) {
			cout << "第" << t << "个轮廓的相似度值为:" << (float)(1 - sim_value) << endl;
			drawContours(image1, contours1, t, Scalar(0, 255, 0), 2, 8);
			drawContours(image2, contours2, 0, Scalar(0, 255, 0), 2, 8);
		}
		
		//获取图像1轮廓的中心位置
		double cx = mm.m10 / mm.m00;
		double cy = mm.m01 / mm.m00;
		circle(image1, Point(cx, cy), 2, Scalar(255, 0, 0), 2, 8);//在中心位置画圆
	}
	namedWindow("contours1", WINDOW_FREERATIO);
	imshow("contours1", image1);
	namedWindow("image2", WINDOW_FREERATIO);
	imshow("image2", image2);
}

 结果:

  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是基于OpenCVC++代码实现图像轮廓匹配中的轮廓筛选: ```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`分别为模板图像和目标图像,可以根据实际情况进行修改。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值