opencv学习记录之图像轮廓之三

轮廓拟合

矩形包围轮廓

1,函数cv2.boundingRect()能够绘制轮廓的矩形边界

retval = cv2.boundingRect( array)

retval 表示返回矩形边界左上角顶点的坐标值及矩形边界的宽和高 , 也可以是4个返回值形式 

    x , y ,w ,h  = cv2.boundingRect( array)

array 是灰度图像或轮廓

然后使用函数cv2.drawContours()来绘制矩形包围框

 1 import cv2 
 2 import numpy as np                                                               
 3 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 import cv2                                                                       
 2 import numpy as np 
 3 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)

import cv2                                                                       
import numpy 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:
" , rect)
points = cv2.boxPoints(rect)
print("
points_back:
" , 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 import cv2                                                                       
 2 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 import cv2                                                                       
 2 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

import cv2                                                                       
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 import cv2                                                                       
 2 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的值时,就停止迭代,该参数多设置为百分比形式

import cv2
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 * 周长

 

原文地址:https://www.cnblogs.com/miaorn/p/12264072.html