opencv图像轮廓
1.1什么是轮廓 cv2.findContours()
轮廓可以简单认为成连续的点(连着边界)连在一起的曲线,具有相同的颜色或者灰度。轮廓在形状分析和物体的检测和识别中很有用。为了准确,要使用二值化图像。需要进行阀值化处理或者Canny边界检测。查找轮廓的函数会修改原始图像。如果之后想继续使用原始图像,应该将原始图像储存到其他变量中。在OpenCV中,查找轮廓就像在黑色背景中超白色物体。你应该记住,要找的物体应该是白色而背景应该是黑色。
如何在一个二值图像中查找轮廓。
函数cv2.findContours()有三个参数,第一个是输入图像,第二个是轮廓检索模式,第三个是轮廓近似方法。返回值有三个,第一个是图像,第二个是轮廓,第三个是(轮廓的)层析结构。轮廓(第二个返回值)是一个Python列表,其中储存这图像中所有轮廓。每一个轮廓都是一个Numpy数组,包含对象边界点(x,y)的坐标。
1.2怎样绘制轮廓 cv2.drawContours()
函数cv2.drawContours()可以被用来绘制轮廓。它可以根据你提供的边界点绘制任何形状。它的第一个参数是原始图像,第二个参数是轮廓,一个python列表,第三个参数是轮廓的索引(在绘制独立轮廓是很有用,当设置为-1时绘制所有轮廓)。接下来的参数是轮廓的颜色和厚度。
在一幅图像上绘制所有的轮廓:
img = cv2.imread('gray.png')
imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
image ,contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
#绘制所有轮廓
#imag = cv2.drawContours(img,contours,-1,(0,255,0),3)
#绘制独立轮廓,如第四个轮廓
# imag = cv2.drawContours(img,contours,3,(0,255,0),3)
#但是大多数时候,下面方法更有用
cnt = contours[3]
imag = cv2.drawContours(img, [cnt], 0, (0,255,0), 3)
while(1):cv2.imshow('img',img)cv2.imshow('imgray',imgray)cv2.imshow('image',image)cv2.imshow('imag',imag)if cv2.waitKey(1) == ord('q'): break
cv2.destroyAllWindows()
1.3轮廓的近似方法
之前提到轮廓是一个形状具有相同灰度值的边界,它会存储形状边界上所有的(x,y)坐标。实际上我们不需要所有的点,当需要直线时,找到两个端点即可。cv2.CHAIN_APPROX_SIMPLE可以实现。它会将轮廓上的冗余点去掉,压缩轮廓,从而节省内存开支。
2. 轮廓特征
2.1矩 cv2.moments()
图像的矩可以帮助我们计算图像的质心,面积等。
函数cv2.moments()会将计算得到的矩以一个字典的形式返回。
img = cv2.imread('rectangle.png',0)
ret,thresh = cv2.threshold(img,127,255,0)
image,contours,hierarchy=cv2.findContours(thresh,1,2)
cnt=contours[0]
M=cv2.moments(cnt)
print(M)
根据这些矩的值,我们可以计算出对象的重心:
cx=int(M['m10']/M['m00'])
cy=int(M['m01']/M['m00'])
2.2轮廓面积 cv2.contourArea()
可以使用函数cv2.contourArea()计算得到,也可以用矩(0阶矩),M['m00']。
area=cv2.contourArea(cnt)
2.3轮廓周长 cv2.arcLength()
也被称为弧长。可以使用函数cv2.arcLength()计算得到。这个函数的第二参数可以用来指定对象的形状是闭合的(True),还是打开的(一条曲线)。
perimeter= cv2.arcLength(cnt,True)
2.4轮廓近似 cv2.approxPolyDP()
将轮廓形状近似到另外一种由更少点组成的轮廓形状,新轮廓的点的数目由我们设定的准确度来决定,使用的Douglas-Peucker算法。
算法步骤
连接曲线首尾两点A、B形成一条直线AB;
计算曲线上离该直线段距离最大的点C,计算其与AB的距离d;
比较该距离与预先给定的阈值threshold的大小,如果小于threshold,则以该直线作为曲线的近似,该段曲线处理完毕。
如果距离大于阈值,则用点C将曲线分为两段AC和BC,并分别对两段曲线进行步骤[1~3]的处理。
当所有曲线都处理完毕后,依次连接各个分割点形成折线,作为原曲线的近似。
假设我们要在一幅图像中查找一个矩形,但是由于图像的种种原因我们不能得到一个完美的矩形,而是一个“坏形状”,现在就可以使用这个函数来近似这个形状,第二个参数是epsilon,它是从原始轮廓到近似轮廓的最大距离,它是一个准确度参数。
epsilon=0.1*cv2.arcLength(cnt,True)
approx= cv2.approxPolyDP(cnt,epsilon,True)
temp = cv2.cvtColor(image.copy(), cv2.COLOR_GRAY2BGR)
cv2.drawContours(temp, [approx], -1, (0, 255, 0), 2)
epsilon2=0.01*cv2.arcLength(cnt,True)
approx2= cv2.approxPolyDP(cnt,epsilon2,True)
temp2 = cv2.cvtColor(image.copy(), cv2.COLOR_GRAY2BGR)
cv2.drawContours(temp2, [approx2], -1, (0, 255, 0), 2)
plt.subplot(231),plt.imshow(img,'gray'),plt.title('original')
plt.subplot(232),plt.imshow(temp,'gray'),plt.title(' epsilon = 10%')
plt.subplot(233),plt.imshow(temp2,'gray'),plt.title(' epsilon = 1%')
plt.show()
2.5凸包 cv2.convexHull()
凸包与轮廓近似相似,但不同,虽然有些情况下它们给出的结果是一样的。函数cv2.convexHull()可以用来检测一个曲线是否具有凸性缺陷,并能纠正缺陷。一般来说,凸性曲线总是凸出来的,至少是平的。如果有地方凹进去了就被叫做凸性缺陷。例如下图中的手,红色曲线显示了手的凸包,凸性缺陷被双箭头标出来了。
hull= cv2.convexHull(points,hull,clockwise,returnPoints)
参数:
points我们要传入的轮廓
hull输出,通常不需要
clockwise方向标志,如果设置为True,输出的凸包是顺时针方向的,否则为逆时针方向。
returnPoints默认值为True。它会返回凸包上点的坐标,如果设置为False,就会返回与凸包点对应的轮廓上的点。
要获得上图的凸包,可以用下面命令:
hull=cv2.convexHull(cnt)
但是如果你想获得凸性缺陷,需要把returnPoints设置为False。以上面矩形为例,首先我们找到他的轮廓从cnt。现在把returnPoints设置为True查找凸包,得到的就是矩形的四个角点。把returnPoints设置为False,得到的是轮廓点的索引。
2.6凸性检测 cv2.isContourConvex()
函数cv2.isContourConvex()可以检测一个曲线是不是凸的。它只能返回True或者False。
k=cv2.isContourConvex(cnt)
2.7边界矩形 cv2.boundingRect() cv2.minAreaRect()
直边界矩形,一个直矩形,没有旋转。不会考虑对象是否旋转。所以边界矩形的面积不是最小的。可以使用函数cv2.boundingRect()查找得到
#(x,y)为矩形左上角的坐标,(w,h)是矩形的宽和高
x,y,w,h=cv2.boundingRect(cnt)
img=cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
旋转的边界矩形,这个边界矩形是面积最小的,因为它考虑了对象的旋转。用函数cv2.minAreaRect()。返回的是一个Box2D结构,其中包含矩形最上角角点坐标(x,y)矩形的宽和高(w,h)以及旋转角度。但是要绘制这个矩形需要矩形的4个角点,可以通过函数cv2.boxPoints()获得。
其中绿色的为直矩形,红色为旋转矩形。
2.8最小外接圆 cv2.minEnclosingCircle()
函数cv2.minEnclosingCircle()可以帮我们找到一个对象的外接圆。它是所有能够包括对象的圆中面积最小的一个。
(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
img = cv2.circle(img,center,radius,(0,255,0),2)
2.9椭圆拟合 cv2.ellipse()
使用函数cv2.ellipse(),返回值其实就是旋转边界矩形的内切圆。
ellipse= cv2.fitEllipse(cnt)
img= cv2.ellipse(img,ellipse,(0,255,0),2)
2.10直线拟合
可以根据一组点拟合出一条直线,同样我们也可以为图像中的白色点拟合出一条直线。
rows,cols =img.shape[:2]
[vx,vy,x,y]=cv2.fitLine(cnt,cv2.DIST_L2,0,0.01,0.01)
lefty=int((x*vy/vx)+y)
righty=int(((cols-x)*vy/vx)+y)
img= cv2.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)
3.轮廓的性质
3.1长宽比 cv2.boundingRect()
边界矩形的宽高比
x,y,w,h=cv2.boundingRect(cnt)
aspect_ratio = float(w)/h
3.2.Extent cv2.contourArea() cv2.boundingRect()
轮廓面积与边界矩形面积的比
area=cv2.contourArea(cnt)
x,y,w,h=cv2.boundingRect(cnt)
rect_area=w*h
extent=float(area)/rect_area
3.3.Solidity cv2.contourArea() cv2.convexHull()
轮廓面积与凸包面积的比
area=cv2.contourArea(cnt)
hull=cv2.convexHull(cnt)
hull_area=cv2.contourArea(hull)
solidity=float(area)/hull_area
3.4.与轮廓面积相等的圆形的直径 cv2.contourArea()
area=cv2.contourArea(cnt)
equi_diameter=np.sqrt(4*area/np.pi)
3.5.方向 cv2.fitEllipse()
对象的方向,下面的方法还会返回长轴和短轴的长度
(x,y),(MA,ma),angle=cv2.fitEllipse(cnt)
3.6.掩模和像素点
有时我们需要构成对象的所有像素点
mask=np.zeros(imgray.shate,np.uint8)
#这里一定要使用参数-1,绘制填充的轮廓
cv2.drawContours(mask,[cnt],0,255,-1)
pixelpoints=np.transpose(np.nonzero(mask))
3.7.最大值和最小值及它们的位置 cv2.minMaxLoc()
可以使用掩模图像得到这些参数
min_val,max_val,min_loc,max_loc=cv2.minMaxLoc(imgray,mask=mask)
3.8.平均颜色及平均灰度 cv2.mean()
同样使用相同的掩模来求得
mean_val=cv2.mean(im,mask=mask)
3.9.极点
一个对象最上,最下,最左,和最右的点
leftmost=tuple(cnt[cnt[:,:,0].argmin()[0])
rightmost=tuple(cnt[cnt[:,:,0].argmax()[0])
topmost=tuple(cnt[cnt[:,:,1].argmin()[0])
bottommost=tuple(cnt[cnt[:,:,1].argmax()[0])
参考:
https://www.jianshu.com/p/2b60802306a8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
opencv图像轮廓相关推荐
- 发现你的身形——OpenCV图像轮廓
文章目录 写在最前 轮廓发现算法 边缘检测 写在最后 写在最前 我的意思不是说你长得很胖,emmmm,而是你的轮廓很大. --五星上将詹姆斯下士如是说 果然有图没图,理解是不一样的,这就体现了计算机视 ...
- 《OpenCv视觉之眼》Python图像处理十二 :Opencv图像轮廓提取之基于一阶导数的Roberts算法、Prewitt算法及Sobel算法
本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...
- 《OpenCv视觉之眼》Python图像处理十四 :Opencv图像轮廓提取之Scharr算法和Canny算法
本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...
- OpenCV 图像轮廓检测
本文是OpenCV图像视觉入门之路的第15篇文章,本文详细的介绍了图像轮廓检测的各种操作,例如:轮廓检索模式.轮廓逼近算子等操作. 图像轮廓是具有相同颜色或灰度的连续点的曲线,轮廓在形状分析和物体的检 ...
- OPENCV图像轮廓检测
前面在图像转换的时候学到canny算子,可以检测出图像的轮廓信息,但是,该算子检测到的轮廓信息还需要我们手动的用眼睛去识别,而实际工程应用中,我们需要得到轮廓的具体数学信息,这就涉及到今天的主题,图像 ...
- 8.opencv——图像轮廓,霍夫变换
图像轮廓,霍夫变换 图像轮廓 查找轮廓 绘制轮廓 轮廓特征 1.轮廓的矩 2.轮廓面积 3.轮廓的长度 4. 轮廓的近似多边形 5.轮廓的凸包 6.轮廓的直边界矩形 7.轮廓的旋转矩形 8.轮廓的最小 ...
- 【笔记】opencv图像轮廓 获得平均灰度值在原图上画轮廓 观察灰度图的分解
调整大小: image = cv2.resize(image,dst=None,fx=0.5,fy = 0.5,dsize=None) img = cv2.resize(img,dst=None,fx ...
- 图像轮廓提取算法(Opencv基于C++实现)
Opencv图像轮廓提取 0. 实现结果如下: 1. 打开图像代码 2. 轮廓提取函数 3. 代码实现 本文主要实现了图像的轮廓提取,首先先给出直观的轮廓实现结果: 0. 实现结果如下: 1. 打开图 ...
- 【opencv】(6) 图像轮廓处理
各位同学好,今天和大家分享一下opencv中如何获取图像轮廓,以及对轮廓的一些其他操作.内容有: (1)轮廓检测:cv2.findContours():(2)轮廓绘制:cv2.drawContours ...
最新文章
- 公式没有编号_知乎公式编辑器的一些小技巧 amp; 使用规范
- (转)android 在电脑上显示真机屏幕
- tablestore换mysql_mysql数据迁移到tablestore
- 《AI 3.0》作者梅拉妮·米歇尔:今天的机器距离真正像人一样理解世界还有多远...
- 为什么“how to say”是错的?
- python中实例和对象的区别_通过Python中对象实例的属性比较对象实例是否相等
- MySQL Innodb_flush_method
- HighCharts:隐藏最下方logo
- TCP通讯知识点总结
- SI4463的数据冲撞解决办法
- 【Git项目管理工具推荐】Sourcetree、Sourcegear-DiffMerge
- linux俄罗斯方块游戏
- Mac 在启动时显示的禁止符号、问号、空白屏幕、锁定等各种界面图标说明
- python 高精度时间_如何基于Python代码实现高精度免费OCR工具
- python迭代法求解方程_第一部分:趣味算法入门;第六题牛顿迭代法求一元三次方程的根...
- 安克创新能否锚定全球家用储能市场 隆起新的增长极?
- Mysql的创建和维护
- 小麦盒子cdn_国内外优秀的 CDN 加速服务商,让你的网站访问速度飞起来
- ASP.NET 基础(7)
- 台式电脑CPU散热器怎么选?
热门文章
- error: operator ‘‘ has no right operand #if (BEKEN_USING_IIC RT_USING_I2C)
- Apache IoTDB PMC 乔嘉林荣获 2022 杰出开源贡献者|开源技术强大,开源文化活跃...
- Oracle gsd服务是什么,RAC节点服务ora.rac2.gsd的offline问题解决方法
- 四级英语听力软件测试,英语四级听力分值一题多少分
- 蹒跚学步Linux(1)之Vmwave安装Ubuntu
- 英雄联盟掉线怎么不显示重新连接服务器,Win7系统玩英雄联盟掉线总是显示正在尝试重新连接怎么办?...
- 2022-2027年中国重金属污染治理行业发展监测及投资战略研究报告
- G1-Card Table和Remember Set
- Retrofit框架(二)
- 【视频聊天】一个简单demo