代码先锋网 代码片段及技术文章聚合

Opencvsharp—matchshape算子实现简单的形状匹配

技术标签: OpenCV  opencv

算子:

matchShapes( InputArray contour1, InputArray contour2, int method, double parameter )

(1)参数1是待匹配轮廓或者灰度图像

(2)参数2同参数1

(3)比较参数1和2相似度的方法,opencv提供了三种如下:

            CV_CONTOURS_MATCH_I1
            CV_CONTOURS_MATCH_I2
            CV_CONTOURS_MATCH_I3

(4)参数4为目前还不支持,使用时赋个0就ok。

针对三种匹配方法进行比较,结果如下:
在这里插入图片描述
形状匹配过程:

  1. 将待识别图像 -> 灰度处理 -> 自动阈值分割

  2. 通过轮廓检索函数 cv.findContours 找到待识别图像所有轮廓

  3. 模板图像 -> 灰度图像 -> 自动阈值分割

  4. 通过轮廓检索函数 cv.findContours 找到模板图像中目标的外轮廓

  5. 将第2步得到的轮廓逐一和第4步得到的轮廓 通过 cv.matchShapes 函数进行形状匹配。找到其中最小值,最小值对应的待识别图像中的轮廓即为匹配到的模板图像

  6. 标出在待识别图像中找到的模板图像

注意:利用mathshape得到的匹配分值越小,则两个轮廓越相似,越大则越不相似。在匹配过程中会通过匹配分值与设定的分值进行比较,在保证匹配效果完美的情况下,设定的分值越低越好,如果设定的匹配分值略高,可能会导致两个完全不相似的形状匹配成功(亲身实验,分值设高,利用三角形会匹配到圆形)。

另外,matchShapes函数其实比较的是两个轮廓的Hu不变矩。Hu矩特性:具有旋转,缩放和平移不变性。由Hu矩组成的特征量对图片进行识别,优点就是速度很快,缺点是识别率比较低。 因此Hu不变矩一般用来识别图像中大的物体,对于物体的形状描述得比较好,图像的纹理特征不能太复杂。

代码:

(1)创建形状轮廓模板

vector<Point> ImageTemplateContours(Mat img_template)
{
	//灰度化
	Mat gray_img_template;
	cvtColor(img_template, gray_img_template, COLOR_BGR2GRAY);
 
	//阈值分割
	Mat thresh_img_template;
	threshold(gray_img_template, thresh_img_template, 0, 255, THRESH_OTSU);
	//膨胀处理
	Mat ellipse = getStructuringElement(MORPH_ELLIPSE, Size(15, 15));
	Mat erode_img_template;
	//erode(thresh_img_template, erode_img_template, ellipse);
	morphologyEx(thresh_img_template, thresh_img_template, MORPH_OPEN, ellipse, Point(-1, -1), 1);
 
	//寻找边界
	vector<vector<Point>> contours_template;
	vector<Vec4i> hierarchy;
	findContours(thresh_img_template, contours_template, hierarchy, RETR_LIST, CHAIN_APPROX_NONE, Point());
 
	//绘制边界
	drawContours(img_template, contours_template, 0, Scalar(0, 0, 255), 1, 8, hierarchy);
 
 
	return contours_template[0];
}

注:之所以返回findContours算子发现的所有轮廓中的第0个,这是因为第0个就是我想要的圆形模板

(2)进行形状模板匹配

vector<Point2d> ShapeTemplateMatch(Mat image, vector<Point> imgTemplatecontours, double minMatchValue)
{
	vector<Point2d> image_coordinates;
	//灰度化
	Mat gray_img;
	cvtColor(image, gray_img, COLOR_BGR2GRAY);
 
	//阈值分割
	Mat thresh_img;
	threshold(gray_img, thresh_img, 0, 255, THRESH_OTSU);
	
	//寻找边界
	vector<vector<Point>> contours_img;
	vector<Vec4i> hierarchy;
	findContours(thresh_img, contours_img, hierarchy, RETR_LIST, CHAIN_APPROX_NONE, Point());
	//根据形状模板进行匹配
	int min_pos = -1;
	double	min_value = minMatchValue;//匹配分值,小于该值则匹配成功
	for (int i = 0; i < contours_img.size(); i++)
	{
	        //计算轮廓面积,筛选掉一些没必要的小轮廓
		if (contourArea(contours_img[i])>12000)
		{
	                //得到匹配分值 
			double value = matchShapes(contours_img[i], imgTemplatecontours, CONTOURS_MATCH_I3, 0.0);
	                //将匹配分值与设定分值进行比较 
			if (value < min_value)
			{
				min_pos = i;
				//绘制目标边界
				drawContours(image, contours_img, min_pos, Scalar(0, 0, 255), 1, 8, hierarchy, 0);
 
				//获取重心点
				Moments M;
				M = moments(contours_img[min_pos]);
				double cX = double(M.m10 / M.m00);
				double cY = double(M.m01 / M.m00);
				//显示目标中心并提取坐标点
				circle(image, Point2d(cX, cY), 1, Scalar(0, 255, 0), 2, 8);
				//putText(image, "center", Point2d(cX - 20, cY - 20), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 1, 8);
	                        //将目标的重心坐标都存在数组中 
				image_coordinates.push_back(Point2d(cX, cY));//向数组中存放点的坐标
			}
		}
	}
	return image_coordinates;
}
版权声明:本文为the_future_way原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/the_future_way/article/details/117000423

智能推荐

opencv简单形状匹配

两张图像进行比较,查看轮廓形状相似度...

SparkCore的RDD算子实现对数据的重新分区Coalesce和Repartition

SparkCore的RDD算子实现对数据的重新分区Coalesce和Repartition 1、coalesce可以改变RDD的分区数 当 shuffle=true时,可以将原来的rdd的分区数变多和变少 当 shuffle=false时,只能将原来的rdd的分区数变少(哪怕给一个更多的分区数,实际结果只会保持原来的分区数) 2、repartition的实质就是调用了coalesce coales...

spark中使用不同算子实现wordcount的案例

数据准备 groupBy groupByKey recduceByKey aggregateByKey foldByKey combineByKey countByKey cogroup aggregate fold 打印结果...

python与openCV对图像处理的canny算子实现源码分析,单个图片123

另外可以自定义函数,不过运行CannyAlogrithm(img,30,50)报错,出现不知道什么问题,。嘿嘿,未完待续...

窗体事件的监听(WindowListener)(简单代码例子实现)

运行结果(建议一个监听一个监听的试效果,一起就显得杂乱):...

猜你喜欢

Spark算子实现WordCount_11种方式

Top1:GroupBy Top2:GroupByKey Top3: Reduce Top4:ReduceBykey Top5:Aggregate Top6:AggregateByKey Top7:CountBykey Top8:CountByValue Top9:Fold Top10:FoldByKey Top11:CombineBykey...

基于OpencvSharp实现的setMouseBack

基于OpencvSharp实现的setMouseBack 背景 SetMouseCallback CvMouseCallback 代码实现 参考资料 背景 由于是使用C#编写程序界面,因此选择了Opencvsharp作为opencv替代品。最近需要使用鼠标画图功能,了解到opencv自带的setMouseBack函数具备相应功能,通过上网查找相应代码,发现大部分都是基于Python和C++的,没有...

spark 算子实例

RDD转换算子Transformation(lazy):懒汉模式 (转换) 一个数据集分成两个RDD,两个可能合并 map 输入变换函数应用于RDD中所有元素 flatMap *输入变换函数应用于RDD中所有元素,将所有对象合并为一个对象。 filter mapValues 在mapvalues上一个RDD中的Key不变与新的Values一起组成新的RDD MapPartitions 由于单独运行...

spark算子实战

spark算子 什么是算子 百度百科上对算子的解释是这样的,算子是一个函数空间到函数空间上的映射O:X→X。广义的讲,对任何函数进行某一项操作都可以认为是一个算子,甚至包括求幂次,开方都可以认为是一个算子,只是有的算子我们用了一个符号来代替他所要进行的运算罢了,所以大家看到算子就不要纠结,他和f(x)的f没区别,它甚至和加减乘除的基本运算符号都没有区别,只是他可以对单对象操作罢了(有的符...

php swoole 简单例子实现

PHP 代码如下:前提是需要在本地配好swoole的环境 /**********************以下是客户端的代码*****************************************/...