轮廓拟合
矩形包围轮廓
1,函数cv2.boundingRect()能够绘制轮廓的矩形边界
retval = cv2.boundingRect( array)
retval 表示返回矩形边界左上角顶点的坐标值及矩形边界的宽和高 , 也可以是4个返回值形式
x , y ,w ,h = cv2.boundingRect( array)
array 是灰度图像或轮廓
然后使用函数cv2.drawContours()来绘制矩形包围框
1 importcv22 importnumpy as np3 o = cv2.imread("cc.bmp")4 cv2.imshow("original", o)5 gray =cv2.cvtColor(o , cv2.COLOR_BGR2GRAY)6 ret , binary = cv2.threshold(gray , 127 , 255,cv2.THRESH_BINARY)7 contours , hierarchy =cv2.findContours(binary , cv2.RETR_LIST ,8 cv2.CHAIN_APPROX_SIMPLE)9 x,y,w,h =cv2.boundingRect(contours[0])10 brcnt = np.array([[[x,y]] ,[[x+w , y]] , [[x+w , y+h]] , [[x,y+h]]] )11 cv2.drawContours(o , [brcnt] , -1 ,(255,255,255) , 2)12 cv2.imshow("result",o)13 cv2.waitKey()14 cv2.destroyAllWindows()
原图
效果图
2,使用函数cv2.boundingRect() 即cv2.rectangle()绘制矩形包围框
1 importcv22 importnumpy as np3 o = cv2.imread("cc.bmp")4 gray =cv2.cvtColor(o , cv2.COLOR_BGR2GRAY)5 ret , binary = cv2.threshold(gray , 127 , 255,cv2.THRESH_BINARY)6 contours , hierarchy =cv2.findContours(binary , cv2.RETR_LIST ,7 cv2.CHAIN_APPROX_SIMPLE)8 x,y,w,h =cv2.boundingRect(contours[0])9 cv2.rectangle(o , (x,y) , (x+w , y+h) ,(255,255,255) , 2)10 cv2.imshow("result",o)11 cv2.waitKey()12 cv2.destroyAllWindows()
效果图
3。,最小包围矩形框函数cv2.minAreaRect()
该函数能绘制轮廓的最小包围矩形框,函数形式:
retval = cv2.minAreaRect( points )
返回值retval表示返回矩阵特征的信息,结构为(最小外接矩形的中心(x,y) , (宽度, 高度) , 旋转角度)
points为轮廓
返回值retval 结构不能用于函数cv2.drawContours() 参数结构要求, 需要将其转换为合适的参数结构,
即使用函数cv2.boxPoints(box)
importcv2importnumpy as np
o= cv2.imread("cc.bmp")
cv2.imshow("original", o)
gray=cv2.cvtColor(o , cv2.COLOR_BGR2GRAY)
ret , binary= cv2.threshold(gray , 127, 255, cv2.THRESH_BINARY)
contours , hierarchy=cv2.findContours(binary , cv2.RETR_LIST ,
cv2.CHAIN_APPROX_SIMPLE)
rect=cv2.minAreaRect(contours[0])print("rect:\n", rect)
points=cv2.boxPoints(rect)print("\npoints_back:\n", points)
points=np.int0(points)
binary= cv2.drawContours(o , [points] , 0 ,(255,255,255) , 2)
cv2.imshow("result", o)
cv2.waitKey()
cv2.destroyAllWindows()
rect:
((280.3699951171875, 138.58999633789062), (154.99778747558594, 63.78103256225586), -8.130102157592773)
points_back:
[[208.16002 181.12]
[199.14 117.979996]
[352.57996 96.06]
[361.59998 159.2 ]]
rect表示返回的矩形特征信息
points是一些点,时能够用作函数cv2.drawContours()参数的点
4,最小包围圆形函数cv2.minEnclosingCircle()
该函数构造一个对象的面积最小包围圆形,函数形式
center , radius = cv2.minEnclosingCircle( points)
center为最小包围圆形的中心
radius为最小包围圆形的半径
points轮廓
1 importcv22 o = cv2.imread("cc.bmp")3 cv2.imshow("original", o)4 gray =cv2.cvtColor(o , cv2.COLOR_BGR2GRAY)5 ret , binary = cv2.threshold(gray , 127 , 255,cv2.THRESH_BINARY)6 contours , hirrarchy =cv2.findContours( binary , cv2.RETR_LIST ,7 cv2.CHAIN_APPROX_SIMPLE)8 (x,y) , radius =cv2.minEnclosingCircle(contours[0])9 center =(int(x) , int(y))10 radius =int(radius)11 cv2.circle(o , center , radius , (255,255,255) , 2)12 cv2.imshow("resultl", o)13 cv2.waitKey()14 cv2.destroyAllWindows()
5,最优拟合椭圆函数cv2.fitEllipse()
可以构造最优拟合椭圆, 函数形式:
retval = cv2.fitEllipse( points )
retval 是RotatedRect()类型的值,这是因为该函数返回的是 拟合椭圆的外接矩形,包含外接矩形的质心,宽, 高,旋转角度
,正好与椭圆的中心点,轴长度,旋转角度等信息吻合
1 importcv22 o = cv2.imread("cc.bmp")3 gray =cv2.cvtColor( o , cv2.COLOR_BGR2GRAY)4 ret , binary = cv2.threshold(gray , 127 , 255, cv2.THRESH_BINARY)5 contours , hierarchy =cv2.findContours(binary , cv2.RETR_LIST ,6 cv2.CHAIN_APPROX_SIMPLE)7 cv2.imshow("original", o)8 ellipse =cv2.fitEllipse(contours[0])9 print("ellipse=", ellipse)10 cv2.ellipse(o , ellipse ,(0 , 255, 0) , 3)11 cv2.imshow("result", o)12 cv2.waitKey()13 cv2.destroyAllWindows()
6,最优拟合直线 函数cv2.fitLine()
函数形式: line = cv2.fitLine( points , distType , param , reps , aeps )
line 返回的是最优拟合直线参数
points是轮廓
distType是距离类型,
param是距离参数,与算选激励类型有关, 当参数设置为0时,会自动选择最优值
reps表示拟合直线所需的径向精度,通常被设置为0.01
aeps表示拟合直线所需的角度精度,通常被设置为0.01
importcv2
o= cv2.imread("cc.bmp")
cv2.imshow("original", o)
gray=cv2.cvtColor(o , cv2.COLOR_BGR2GRAY)
ret , binary= cv2.threshold(gray , 127 ,255, cv2.THRESH_BINARY)
contours , hierarchy=cv2.findContours(binary ,cv2.RETR_LIST ,
cv2.CHAIN_APPROX_SIMPLE)
rows , cols= binary.shape[:2]
[vx , vy , x, y]= cv2.fitLine(contours[0] , cv2.DIST_L2, 0,0.01 , 0.01)
lefty= int((-x*vy/vx) +y)
righty= int(((cols - x) * vy/vx) +y )
cv2.line(o , (cols-1 ,righty) , (0,lefty) , (0,255,0) , 2)
cv2.imshow("result", o)
cv2.waitKey()
cv2.destroyAllWindows()
7,最优外包三角形函数 cv2.minEnclosingTriangle()
retval , triangle = cv2.minEnclosingTreangle( points )
retval 为最小外包三角形的面积
triangle 最小外包三角形的三个顶点集
points轮廓
1 importcv22 o = cv2.imread("cc.bmp")3 cv2.imshow("original", o)4 gray =cv2.cvtColor(o , cv2.COLOR_BGR2GRAY)5 ret , binary = cv2.threshold(gray , 127 , 255, cv2.THRESH_BINARY)6 contours , hierarchy =cv2.findContours(binary , cv2.RETR_LIST ,7 cv2.CHAIN_APPROX_SIMPLE)8 area , trgl =cv2.minEnclosingTriangle(contours[0])9 print("area =", area)10 print("trgl:", trgl)11 for i in range(0,3):12 cv2.line(o , tuple(trgl[i][0]),13 tuple(trgl[(i+1) % 3][0]) , (255,255,255) , 2)14 cv2.imshow("result", o)15 cv2.waitKey()16 cv2.destroyAllWindows()
8,逼近多边形函数cv2.approxPolyDP()
该函数用来构造指定精度的逼近多边形曲线,函数形式:
approxCurve = cv2.approxPolyDP( curve , epsilon , closed)
返回值approxCurve为逼近多边形的点集
curve为轮廓
epsilon为精度,原始轮廓的边界点与逼近多边形边界之间的最大值
colsed为布尔值该值为True,毕竟多边形是封闭的,否则多边形不封闭
该函数采用的是Douglas-Peucker算法,首先杂i轮廓上找到距离最远的两个点连接起来,然后在轮廓上找到离直线最远的点
连接之前的点形成封闭的多边形,此时为三角形,按此方式不断的迭代将找到的离多边形最远的点加入,形成新的多边形
当最远距离小于参数epsilon的值时,就停止迭代,该参数多设置为百分比形式
importcv2
o= cv2.imread("cc.bmp")
cv2.imshow("original", o)
gray=cv2.cvtColor(o , cv2.COLOR_BGR2GRAY)
ret , binary= cv2.threshold(gray , 127 , 255,cv2.THRESH_BINARY)
contours , hierarchy=cv2.findContours(binary , cv2.RETR_LIST ,
cv2.CHAIN_APPROX_SIMPLE)#epsilon = 0.1 * 周长
adp =o.copy()
epsilon= 0.1*cv2.arcLength(contours[0] , True)
approx=cv2.approxPolyDP(contours[0] , epsilon , True)
adp= cv2.drawContours(adp , [approx] , 0 ,( 0 , 0 ,255) , 2)
cv2.imshow("result0.1", adp)#epsilon = 0.09 * 周长
adp =o.copy()
epsilon= 0.09*cv2.arcLength(contours[0] , True)
approx=cv2.approxPolyDP(contours[0] , epsilon , True)
adp= cv2.drawContours(adp , [approx] , 0 ,( 0 , 0 ,255) , 2)
cv2.imshow("result0.09", adp)#epsilon = 0.055 * 周长
adp =o.copy()
epsilon= 0.055*cv2.arcLength(contours[0] , True)
approx=cv2.approxPolyDP(contours[0] , epsilon , True)
adp= cv2.drawContours(adp , [approx] , 0 ,( 0 , 0 ,255) , 2)
cv2.imshow("result0.055", adp)#epsilon = 0.05 * 周长
adp =o.copy()
epsilon= 0.05*cv2.arcLength(contours[0] , True)
approx=cv2.approxPolyDP(contours[0] , epsilon , True)
adp= cv2.drawContours(adp , [approx] , 0 ,( 0 , 0 ,255) , 2)
cv2.imshow("result0.05", adp)#epsilon = 0.02* 周长
adp =o.copy()
epsilon= 0.02*cv2.arcLength(contours[0] , True)
approx=cv2.approxPolyDP(contours[0] , epsilon , True)
adp= cv2.drawContours(adp , [approx] , 0 ,( 0 , 0 ,255) , 2)
cv2.imshow("result0.02", adp)#cv2.waitKey()
cv2.destroyAllWindows()
epsilon = 0.1 * 周长
epsilon = 0.09 * 周长
epsilon = 0.055* 周长
epsilon = 0.05 * 周长
epsilon = 0.02 * 周长