python opencv 轮廓属性

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/TingHW/article/details/84560177
import cv2
import numpy as np

img = cv2.imread('zhua.jpg',0)
ret,thresh = cv2.threshold(img,100,255,0)
image,contours,hierarchy = cv2.findContours(thresh, 1, 2)
cnt = contours[0]
# 函数cv2.moments()会给你一个字典,包含所有矩值
M = cv2.moments(cnt)

print(M)
{'m00': 6232.5, 'm10': 1447203.0, 'm01': 1809901.1666666665, 'm20': 353678359.9166666, 'm11': 421580616.7083333, 'm02': 560193863.0833333, 'm30': 90102739020.40001, 'm21': 103128286116.0, 'm12': 130864394995.8, 'm03': 184233465551.75, 'mu20': 17633991.972984314, 'mu11': 1316774.2528981566, 'mu02': 34603452.637868285, 'mu30': -211631726.01593018, 'mu21': -190471290.52419376, 'mu12': 21121550.328198433, 'mu03': 1457182366.1941833, 'nu20': 0.45396886101420764, 'nu11': 0.03389898944701885, 'nu02': 0.8908300517114065, 'nu30': -0.06901207029499672, 'nu21': -0.062111755823628025, 'nu12': 0.006887634209812285, 'nu03': 0.4751800393143934}
# 重心
cx=int(M['m10']/M['m00'])
cy=int(M['m01']/M['m00'])
print(cx,cy)
232 290
# 轮廓面积
# 轮廓面积由函数cv2.contourArea()得到或者从矩里得到M['m00']
area=cv2.contourArea(cnt)
print(area)
6232.5
# 轮廓周长
# 可以用cv2.arcLength()函数得到。第二个参数指定形状是否是闭合的轮廓(如果传True)。或者只是一个曲线。

perimeter=cv2.arcLength(cnt,True)
print(perimeter)
1863.9179503917694
# 轮廓近似
# 这会把轮廓形状近似成别的边数少的形状,边数由我们指定的精确度决定。这是Douglas-Peucker算法的实现。


epsilon = 0.1*cv2.arcLength(cnt,True)#epsilon,是从轮廓到近似轮廓的最大距离。是一个准确率参数
approx = cv2.approxPolyDP(cnt,epsilon,True)#第三个参数指定曲线是否闭合

print(approx)
[[[212 177]]

 [[263 459]]]
# 凸形外壳

# hull = cv2.convexHull(points[, hull[, clockwise[, returnPoints]]
# ·points 是我们传入的轮廓
# ·hull 是输出,一般我们不用传
# ·clockwise: 方向标示,如果是True,输出凸形外壳是顺时针方向的。否则,是逆时针的。
# ·returnPoints:默认是True。然后会返回外壳的点的坐标。如果为False,它会返回轮廓对应外壳点的索引。

hull=cv2.convexHull(cnt)
print(hull)



[[[323 292]]

 [[322 298]]

 [[320 308]]

 [[319 311]]

 [[265 457]]

 [[263 459]]

 [[261 459]]

 [[207 454]]

 [[205 452]]

 [[204 450]]

 [[131 287]]

 [[130 284]]

 [[128 277]]

 [[126 267]]

 [[125 260]]

 [[125 252]]

 [[127 247]]

 [[131 242]]

 [[132 241]]

 [[201 181]]

 [[204 179]]

 [[212 177]]

 [[217 177]]

 [[222 178]]

 [[227 180]]

 [[282 204]]

 [[286 206]]

 [[293 212]]

 [[295 214]]

 [[299 222]]

 [[321 279]]

 [[322 284]]

 [[323 291]]]
# 检查凸面
# 有一个函数用来检查是否曲线是凸面, cv2.isContourConvex().它返回True或False

k=cv2.isContourConvex(cnt)
print(k)
False
# 边界矩形
# 有两种边界矩形

# a.正边界矩形
# 这个矩形不考虑对象的旋转,所以边界矩形的面积不是最小的,函数是cv2.boundingRect()。
x,y,w,h = cv2.boundingRect(cnt)  #假设矩形左上角的坐标是(x,y), (w, h)是它的宽和高
img1 = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
# cv2.imshow('img1',img1)
# cv2.waitKey(0)
# cv2.destroyAllWindows()

# b.渲染矩形
# 这个边界矩形是用最小面积画出来的,所以要考虑旋转。函数是cv2.minAreaRect().
# 它返回一个Box2D结构,包含了(左上角(x,y),(width, height),旋转角度)。但是要画这个矩形我们需要4个角。这四个角用函数cv2.boxPoints()得到
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
img2 = cv2.drawContours(img,[box],0,(0,0,255),2)
cv2.imshow('img2',img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 最小闭包圆
# 我们找一个目标的外接圆可以用函数cv2.minEnclosingCircle().这个圆用最小面积完全包围目标。

(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
img3 = cv2.circle(img,center,radius,(0,255,0),2)
cv2.imshow('img3',img3)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 椭圆
# 用一个椭圆来匹配目标。它返回一个旋转了的矩形的内接椭圆

ellipse=cv2.fitEllipse(cnt)
img4=cv2.ellipse(img,ellipse,(0,255,0),2)
cv2.imshow('img4',img4)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 直线
# 类似的我们可以匹配一根直线,下面的图像包含一系列的白色点,我们可以给它一条近似的直线。

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)
img5 = cv2.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)

cv2.imshow('img5',img5)
cv2.waitKey(0)
cv2.destroyAllWindows()

猜你喜欢

转载自blog.csdn.net/TingHW/article/details/84560177
今日推荐