【opencv】Opencv(Python)教程-轮廓(2)轮廓特征求取⽬标
查轮廓的不同特征,例如⾯积,周长,重⼼,边界框等,这些特征在未来的图像识别中,会⼤量的⽤到。
矩的概念
图像识别的⼀个核⼼问题是图像的特征提取,简单描述即为⽤⼀组简单的数据(图像描述量)来描述整个图像,这组数据越简单越有代表性越好。良好的特征不受光线、噪点、⼏何形变的⼲扰。图像识别发展⼏⼗年,不断有新的特征提出,⽽图像不变矩就是其中⼀个。
矩是概率与统计中的⼀个概念,是随机变量的⼀种数字特征。设为随机变量,为常数,为正整数。则量称为关于点的阶矩
⽐较重要的有两种情况:
1. 。这时称为的阶原点矩
2. 。这时称为的阶中⼼矩。
⼀阶原点矩就是期望。⼀阶中⼼矩μ1=0,⼆阶中⼼矩μ2就是X的⽅差Var(X)。在统计学上,⾼于4阶的矩极少使⽤。μ3可以去衡量分布是否有偏。μ4可以去衡量分布(密度)在均值附近的陡峭程度如何。
针对于⼀幅图像,我们把像素的坐标看成是⼀个⼆维随机变量(X,Y),那么⼀幅灰度图像可以⽤⼆维灰度密度函数来表⽰,因此可以⽤矩来描述灰度图像的特征。
不变矩(Invariant Moments)是⼀处⾼度浓缩的图像特征,具有平移、灰度、尺度、旋转不变性。M.K.Hu在1961年⾸先提出了不变矩的概念。1979年M.R.Teague根据正交多项式理论提出了Zernike矩。
[python]
01. import cv2
02. import numpy as np
03. img = cv2.imread('star.jpg',0)
04. img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #彩⾊转灰度
05. ret,thresh = cv2.threshold(img,127,255,0) #⼆值化
06. image,contours,hierarchy = cv2.findContours(thresh, 1, 2)
07. cnt = contours[0] #选取其中的第⼀个轮廓
08. M = s(cnt) #对第⼀个轮廓
09. print (M) #打印出所有计算的M的参数,其各个数值的计算公式参考
blog.csdn/qq_18343569/article/details/46913501
10. cx = int(M['m10']/M['m00']) #X⽅向的重⼼,其中M['m10']表⽰的是x⽅向的⼀阶空间矩,M['m00']表⽰⾯
积,M['m00']也可以通过urArea() 计算得到
11. cy = int(M['m01']/M['m00']) #Y⽅向的重⼼
12.
另外,关于轮廓的函数还包括如下
轮廓周长
cv2.arcLength()
[python]
01. perimeter = cv2.arcLength(cnt,True)
这个函数的第⼆参数可以⽤来指定对象的形状是闭合的(True),还是打开的(⼀条曲线)。假如是⼀条闭合的曲线,那种⽅法计算结果⼀致,如果是开曲线,则两者计算结果不同,其中闭合的⽅法,会在最后将起始点和终⽌点连⼀起的长度加进去。
轮廓近似
将轮廓形状近似到另外⼀种由更少点组成的轮廓形状,新轮廓的点的数⽬由我们设定的准确度来决定。使⽤的Douglas-Peucker算法,你可以到获得更多此算法的细节。为了帮助理解,假设我们要在⼀幅图像中查⼀个矩形,但是由于图像的种种原因,我们不能得到⼀个完美的矩形,⽽是⼀个“坏形状”(如下图所⽰)。现在你就可以使⽤这个函数来近似这个形状了。这个函数的第⼆个参数叫epsilon,它是从原始轮廓到近似轮廓的最⼤距离。它是⼀个准确度参数。选择⼀个好的 epsilon 对于得到满意结果⾮常重要。
[python]
01. epsilon = 0.1*cv2.arcLength(cnt,True)
02. approx = cv2.approxPolyDP(cnt,epsilon,True)
下边,第⼆幅图中的绿线是当 epsilon = 10% 时得到的近似轮廓,第三幅图是当 epsilon = 1% 时得到的近似轮廓。第三个参数设定弧线是否闭合。
凸包
凸包与轮廓近似相似,但不同,虽然有些情况下它们给出的结果是⼀样的。函数 vexHull() 可以⽤来检测⼀个曲线是否具有凸性缺陷,并能纠正缺陷。⼀般来说,凸性曲线总是凸出来的,⾄少是平的。如果有地⽅凹进去了就被叫做凸性缺陷。例如下图中的⼿。红⾊曲线显⽰了⼿的凸包,凸性缺陷被双箭头标出来了。
参考代码为:
[python]
01. hull = vexHull(points, hull, clockwise, returnPoints)
points 我们要传⼊的轮廓· hull 输出,通常不需要· clockwise ⽅向标志。如果设置为 True,输出的凸包是顺时针⽅向的。否则为逆时针⽅向。· returnPoints 默认值为 True。它会返回凸包上点的坐标。如果设置为 False,就会返回与凸包点对应的轮廓上的点。
rectangle函数opencv凸性检测
函数 cv2.isContourConvex() 可以可以⽤来检测⼀个曲线是不是凸的。它只能返回 True 或 False。
[python]
01. k = cv2.isContourConvex(cnt)
边界矩形
直边界矩形 ⼀个直矩形(就是没有旋转的矩形)。它不会考虑对象是否旋转。所以边界矩形的⾯积不
是最⼩的。可以使⽤函数
cv2.boundingRect() 查得到。(x,y)为矩形左上⾓的坐标,(w,h)是矩形的宽和⾼。
[python]
01. x,y,w,h = cv2.boundingRect(cnt)
02. img = angle(img,(x,y),(x+w,y+h),(0,255,0),2)
旋转的边界矩形 这个边界矩形是⾯积最⼩的,因为它考虑了对象的旋转。⽤到的函数为 cv2.minAreaRect()。返回的是⼀个 Box2D 结构,其中包含矩形左上⾓⾓点的坐标(x,y),矩形的宽和⾼(w,h),以及旋转⾓度。但是要绘制这个矩形需要矩形的 4 个⾓点,可以通过函数 cv2.boxPoints() 获得。
[python]
01.
rect = cv2.minAreaRect(cnt)
box = cv2.cv.BoxPoints(rect)
box = np.int0(box)
cv2.drawContours(img, [box], 0, (0, 0, 255), 2)
把这两中边界矩形显⽰在下图中,其中绿⾊的为直矩形,红的为旋转矩形。完整代码如下:
最⼩外接圆
函数 cv2.minEnclosingCircle() 可以帮我们到⼀个对象的外切圆。它是所有能够包括对象的圆中⾯积最⼩的⼀个。
椭圆拟合
使⽤的函数为 cv2.ellipse(),返回值其实就是旋转边界矩形的内切圆[python]
01.
# ⽤绿⾊(0, 255, 0)来画出最⼩的矩形框架 02.
x, y, w, h = cv2.boundingRect(cnt) 03.
05.
# ⽤红⾊表⽰有旋转⾓度的矩形框架 06.
rect = cv2.minAreaRect(cnt) 07.
box = cv2.cv.BoxPoints(rect) 08.
box = np.int0(box) 09.
cv2.drawContours(img, [box], 0, (0, 0, 255), 2) 10. cv2.imwrite('contours.png', img)
[python]
01.
(x,y),radius = cv2.minEnclosingCircle(cnt) 02.
center = (int(x),int(y)) 03. radius = int(radius) 04. img = cv2.circle(img,center,radius,(0,255,0),2)
[python]
01.
ellipse = cv2.fitEllipse(cnt) 02. im = cv2.ellipse(im,ellipse,(0,255,0),2)
直线拟合
我们可以根据⼀组点拟合出⼀条直线,同样我们也可以为图像中的⽩⾊点拟合出⼀条直线。
[python]
01.
rows,cols = img.shape[:2] 02.
[vx,vy,x,y] = cv2.fitLine(cnt, cv2.DIST_L2,0,0.01,0.01) 03.
lefty = int((-x*vy/vx) + y) 04.
righty = int(((cols-x)*vy/vx)+y) 05. img = cv2.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论