Part11. 图像的轮廓
在该系列第三篇文章中,曾经简单地介绍过轮廓和轮廓发现。
11.1 轮廓的基本概念
图像的轮廓是指图像中具有相同颜色或灰度值的连续点的曲线。轮廓和边缘是有联系的,边缘是轮廓的基础,轮廓是边缘的连续集合。
轮廓和边缘的区别是:
轮廓是连续的,边缘可以是连续的,也可以是离散的。
轮廓是完整的,边缘可以是完整的,也可以是不完整的。
轮廓可以有各种形状,边缘通常是线性的。
21.2 轮廓发现和轮廓提取
轮廓发现是指在图像中找到所有可能的轮廓。
轮廓提取是指从图像中找到所有有效的轮廓和轮廓的具体信息。
轮廓发现是轮廓提取的前提,轮廓提取在轮廓发现的基础上进一步提取轮廓的形状和位置信息等等。
下面的代码,经过一系列操作找到二值图像的有效轮廓后,获取这些轮廓的最小外接矩形,最后用线在原图中框出这些外接矩形,从而在原图中找到比较明显的苹果。
#include#include"opencv2/imgproc.hpp" #include"opencv2/highgui.hpp" usingnamespacestd; usingnamespacecv; boolascendSort(vector a,vector b) { returncontourArea(a)>contourArea(b); } intmain(intargc,char**argv){ Matsrc=imread(".../apple.jpg"); imshow("src",src); Mathsv,edge; cvtColor(src,hsv,cv::COLOR_BGR2HSV);//BGR转换到HSV色彩空间 imshow("hsv",hsv); cv::Scalarlower_red(0,43,46); cv::Scalarupper_red(10,255,255);//定义红色的HSV范围 Matmask; inRange(hsv,lower_red,upper_red,mask);//通过inRange函数实现二值化 imshow("mask",mask); Matkernel=getStructuringElement(MORPH_RECT,Size(15,15)); morphologyEx(mask,mask,MORPH_CLOSE,kernel);//形态学操作 morphologyEx(mask,mask,MORPH_OPEN,kernel);//形态学操作 imshow("morphology",mask); vector >contours; vector hierarchy; findContours(mask,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE); sort(contours.begin(),contours.end(),ascendSort);//ascendingsort for(size_ti=0;i< contours.size(); i++) { double area = contourArea(contours[i]); if (area < 22000) { continue; } cout << "area = " << area << endl; RotatedRect rrt = minAreaRect(contours[i]); Point2f pt[4]; rrt.points(pt); line(src, pt[0], pt[1], Scalar(255, 0, 0), 8, 8); line(src, pt[1], pt[2], Scalar(255, 0, 0), 8, 8); line(src, pt[2], pt[3], Scalar(255, 0, 0), 8, 8); line(src, pt[3], pt[0], Scalar(255, 0, 0), 8, 8); } imshow("result", src); waitKey(0); return 0; }
展示原图
将原图转换成 HSV 类型,用于提取特定颜色。
hsv.png
通过 inRange 函数实现二值化。inRange 函数用于将图像中的像素值限制在指定的范围内,它会将满足条件的像素设置为 255,不满足条件的像素设置为 0,从而形成一个二值图像。
二值化.png
对二值图像进行一些形态学的操作,便于后续的轮廓分析。
形态学操作.png
通过 findContours() 函数进行轮廓发现。最后,筛选出有效的轮廓,并获取最小外接矩形,用线画出在原图上展示出来。
Part22. 轮廓特征的分类
图像的轮廓特征可以分为以下几类:
基础特征:面积、周长、质心、凸包、最小外接矩形等。这些特征可以直接从轮廓序列中计算得到。
矩特征:Hu 矩、中心矩、惯性矩等。这些特征可以用于描述轮廓的形状和大小。
几何特征:最小闭合圆、拟合椭圆等。这些特征可以用于描述轮廓的几何形状。
Part33. 轮廓的基础特征
33.1 面积、周长、最小外接矩形
轮廓面积 contourArea()
轮廓周长 arcLength()
轮廓外接矩形 boundingRect()
轮廓最小外接矩形 minAreaRect()
下面的例子获取图中回形针的轮廓,以及轮廓的面积、周长、最小外接矩形等。
#include#include"opencv2/imgproc.hpp" #include"opencv2/highgui.hpp" usingnamespacestd; usingnamespacecv; boolascendSort(vector a,vector b) { returncontourArea(a)>contourArea(b); } intmain(intargc,char**argv){ Matsrc=imread(".../paperclip.jpg"); imshow("src",src); Matgray,thresh; cvtColor(src,gray,cv::COLOR_BGR2GRAY); imshow("gray",gray); threshold(gray,thresh,0,255,THRESH_BINARY_INV|THRESH_OTSU); imshow("thresh",thresh); vector >contours; vector hierarchy; findContours(thresh,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE); sort(contours.begin(),contours.end(),ascendSort);//ascendingsort for(size_ti=0;i< contours.size(); i++) { double area = contourArea(contours[i]); double length = arcLength(contours[i],true); if (area < 1000) { continue; } cout << "area = " << area << ", length = " << length << endl; RotatedRect rrt = minAreaRect(contours[i]);// 获取最小外接矩形 Point2f pt[4]; rrt.points(pt); line(src, pt[0], pt[1], Scalar(255, 0, 0), 8, 8); line(src, pt[1], pt[2], Scalar(255, 0, 0), 8, 8); line(src, pt[2], pt[3], Scalar(255, 0, 0), 8, 8); line(src, pt[3], pt[0], Scalar(255, 0, 0), 8, 8); Point center = rrt.center; circle(src, center, 2,Scalar(0, 0, 255), 8, 8); // 绘制最小外接矩形的中心点 } imshow("result", src); waitKey(0); return 0; }
执行结果:
area=101573,length=2461.71 area=41757.5,length=1256.08 area=41348,length=1152.56 area=39717.5,length=1616.13 area=37503,length=1230.47 area=36742.5,length=1037.21 area=4142,length=706.357
外接矩形是指可以包围轮廓所有点的矩形,而最小外接矩形是指包含轮廓中所有点的最小矩形。
下面的例子,获取图中最大轮廓的外接矩形和最小外接矩形,分别用黄色和蓝色表示。
#include"opencv2/imgproc.hpp" #include"opencv2/highgui.hpp" usingnamespacestd; usingnamespacecv; boolascendSort(vectora,vector b) { returncontourArea(a)>contourArea(b); } intmain(intargc,char**argv){ Matsrc=imread(".../fruit.jpg"); imshow("src",src); Matgray,thresh; cvtColor(src,gray,cv::COLOR_BGR2GRAY); threshold(gray,thresh,0,255,THRESH_BINARY|THRESH_OTSU); vector >contours; vector hierarchy; findContours(thresh,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE); sort(contours.begin(),contours.end(),ascendSort);//ascendingsort RotatedRectrrt=minAreaRect(contours[0]);//获取最大轮廓的最小外接矩形 Point2fpt[4]; rrt.points(pt); line(src,pt[0],pt[1],Scalar(255,0,0),8,8); line(src,pt[1],pt[2],Scalar(255,0,0),8,8); line(src,pt[2],pt[3],Scalar(255,0,0),8,8); line(src,pt[3],pt[0],Scalar(255,0,0),8,8); Rectrect=boundingRect(contours[0]);//获取最大轮廓的外接矩形 rectangle(src,rect,Scalar(0,255,255),8,8);//绘制外接矩形 imshow("result",src); waitKey(0); return0; }
通过上述例子可以看到,最小外接矩形能够更精确地描述轮廓的形状和大小。
外接矩形和最小外接矩形有各自的使用场景,例如在对象检测中,可以使用外接矩形来粗略定位物体,而使用最小外接矩形来精确定位物体。
43.2 凸包
凸包(Convex Hull)是计算几何(图形学)中的概念。在一个实数向量空间 V 中,对于给定集合 X,所有包含 X 的凸集的交集 S 被称为 X 的 凸包。
在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。
平面的一个子集 S 被称为是“凸”的,当且仅当对于任意两点 p,s ∈S,线段 ps 都完全属于S。
一个点集 P 的凸包CH(P),就是包含 P 的最小凸集——即包含P的所有凸集的交。
凸包的性质:
凸包是凸集。
凸包的周长是最小的。
凸包的面积是最小的。
凸包的质心是所有点的质心的均值。
OpenCV 提供了 convexHull() 函数寻找轮廓的凸包以及 isContourConvex() 函数用于判断轮廓是否为凸轮廓。凸轮廓是指所有内角都小于或等于 180 度的轮廓。
#include#include"opencv2/imgproc.hpp" #include"opencv2/highgui.hpp" usingnamespacestd; usingnamespacecv; intmain(intargc,char**argv){ Matsrc=imread(".../hand.jpg"); imshow("src",src); Matgray,thresh; cvtColor(src,gray,cv::COLOR_BGR2GRAY); threshold(gray,thresh,0,255,THRESH_BINARY_INV|THRESH_OTSU); imshow("thresh",thresh); Matmask; Matkernel=getStructuringElement(MORPH_RECT,Size(31,31)); morphologyEx(thresh,mask,MORPH_CLOSE,kernel);//形态学操作 imshow("morphology",mask); vector >contours; vector hierarchy; findContours(mask,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE); vector >hull(contours.size()); Matdrawing=Mat::zeros(mask.size(),CV_8UC3); for(size_ti=0;i< contours.size(); i++) { double area = contourArea(contours[i]); if (area < 100) { continue; } convexHull(contours[i], hull[i], false); bool isHull = isContourConvex(contours[i]); cout << "isHull = " << isHull << endl; drawContours(drawing, contours, i, Scalar(0, 0, 255), 8, 8); drawContours(drawing, hull, i, Scalar(255, 0, 0), 8, 8); drawContours(src, hull, i, Scalar(255, 0, 0), 8, 8); } imshow("result",src); imshow("drawing",drawing); waitKey(0); return 0; }
执行结果:
isHull=0 isHull=0
Part44. 总结
轮廓的基础特征是计算机视觉中的重要工具,这些特征可以应用于对象检测、形状识别、测量等各种应用场景。后续还会介绍更多的轮廓特征。
审核编辑:汤梓红
-
图像
+关注
关注
2文章
1078浏览量
40364 -
代码
+关注
关注
30文章
4708浏览量
68176 -
OpenCV
+关注
关注
29文章
623浏览量
41202
原文标题:OpenCV4之图像的轮廓和轮廓的基础特征
文章出处:【微信号:CVSCHOOL,微信公众号:OpenCV学堂】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论