python 生成任意形狀的凸包圖程式碼
一、效果圖:
在左圖的白色區域周圍,畫任意形狀的凸包圖。
二、程式碼
import cv2 import numpy as np def generate_poly(image,n,area_thresh): """ 隨機生成凸包 :param image: 二值圖 :param n: 頂點個數 :param area_thresh: 刪除小於此面積閾值的凸包 :return: 凸包圖 """ row,col = np.where(image[:,:,0] == 255) # 行,列 point_set = np.zeros((n,1,2),dtype=int) for j in range(n): index = np.random.randint(0,len(row)) point_set[j,0] = col[index] point_set[j,1] = row[index] hull = [] hull.append(cv2.convexHull(point_set,False)) drawing_board = np.zeros(image.shape,dtype=np.uint8) cv2.drawContours(drawing_board,hull,-1,(255,255,255),-1) cv2.namedWindow('drawing_board',0),cv2.imshow('drawing_board',drawing_board),cv2.waitKey() # 如果生成面積過小,重新生成 if cv2.contourArea(hull[0]) < area_thresh: drawing_board = generate_poly(image,area_thresh) # 如果生成洞,重新生成 is_hole = image[drawing_board == 255] == 255 if is_hole.all() == True: # 洞,則drawing_board所有為255的地方,image也是255,all()即為所有位置 drawing_board = generate_poly(image,area_thresh) return drawing_board img = np.zeros((256,256,3),np.uint8) cv2.circle(img,(100,100),50,-1) cv2.namedWindow('img',cv2.imshow('img',img),cv2.waitKey() img_hull = generate_poly(img,8,100) cv2.namedWindow('img_hull',cv2.imshow('img_hull',img_hull),cv2.waitKey()
補充知識:opencv python 輪廓特徵/凸包/外接矩形/外接圓/擬合矩形/擬合直線/擬合圓
Contour Features
1 影象的矩
cv2.moments()
影象的矩可以幫助計算物體的某些特徵,如物件的質心,物件的區域等.
程式碼:
import cv2 import numpy as np img = cv2.imread('img7.png',0) ret,thresh = cv2.threshold(img,127,0) im2,contours,hierarchy = cv2.findContours(thresh,2) cnt = contours[0] M = cv2.moments(cnt) print( M )
輸出:
{'m00': 283.0,'m10': 8260.666666666666,'m01': 34747.666666666664,'m20': 251349.8333333333,'m11': 1008063.0,'m02': 4274513.166666666,'m30': 7941981.4,'m21': 30484543.9,'m12': 123258620.46666667,'m03': 526819846.70000005,'mu20': 10223.989595602674,'mu11': -6208.702394974302,'mu02': 8080.874165684916,'mu30': 8302.495426246896,'mu21': -14552.154961312423,'mu12': 11791.528133469663,'mu03': -3268.923251092434,'nu20': 0.12765785058625623,'nu11': -0.07752253611575,'nu02': 0.10089867729257346,'nu30': 0.006162296011483629,'nu21': -0.010800931752771139,'nu12': 0.008751933371317017,'nu03': -0.0024262672459139235}
此刻,可以提取有用的資料,如面積,質心等.
質心由關係給出:
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
2輪廓面積
cv2.contourArea(contour[,oriented])
3輪廓周長
cv2.arcLength(curve,closed)
第二個引數指定形狀是否為閉合輪廓
4輪廓近似
它根據我們指定的精度將輪廓形狀近似為具有較少頂點數的另一個形狀.它是Douglas-Peucker演算法的一種實現方式.
cv2.approxPolyDP(curve,epsilon,closed[,approxCurve])
第二個引數epsilon,它是從輪廓到近似輪廓的最大距離.第三個引數指定曲線是否閉合.
下面,在第二幅影象中,綠線表示epsilon =弧長的10%的近似曲線. 第三幅影象顯示相同的epsilon =弧長的1%.
程式碼:
import cv2 import numpy as np img = cv2.imread('img8.png') cv2.imshow('src',img) imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret,thresh = cv2.threshold(imgray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) cnt = contours[1] epsilon = 0.1*cv2.arcLength(cnt,True) approx = cv2.approxPolyDP(cnt,True) cv2.polylines(img,[approx],True,(0,2) cv2.imshow('show',img) cv2.waitKey()
5凸包
凸包看起來類似輪廓近似,但是它不是(兩者在某些情況下可能提供相同的結果).
convexHull(points[,hull[,clockwise[,returnPoints]]]):檢查曲線的凸性缺陷並進行修正.
points:傳入的輪廓
hull:輸出
clockwise:方向標誌,如果為True,則順時針方向輸出凸包.
returnPoints:預設情況下為True,然後它返回hull points的座標; 如果為False,則返回與hull points對應的輪廓點的索引
下面的手形影象. 紅線表示手的凸包, 雙面箭頭標記顯示凸起缺陷.
程式碼:
import cv2 import numpy as np img = cv2.imread('img8.png') imgray = cv2.cvtColor(img,cv2.CHAIN_APPROX_SIMPLE) cnt = contours[1] hull = cv2.convexHull(cnt)
returnPoints = True,得到以下值:
array([[[192,135]],[[ 9,12]],[[192,12]]],dtype=int32)
如果想找到凸性缺陷,需要傳遞returnPoints = False,得到以下結果:
array([[129],[ 67],[ 0],[142]],dtype=int32)
這些是輪廓中相應點的索引,檢查第一個值:
cnt[129]
Out[3]: array([[192,dtype=int32)
與第一個結果相同.
6 檢查凸性
cv2.isContourConvex(contour):檢查曲線是否凸起
7 外接矩形
7.1 直邊外接矩形
它是一個直的矩形,它不考慮物件的旋轉。因此,邊界矩形的面積不會最小.
cv.boundingRect()
設(x,y)為矩形的左上角座標,(w,h)為寬度和高度
程式碼:
import cv2 import numpy as np img = cv2.imread('img7.png') imgray = cv2.cvtColor(img,cv2.CHAIN_APPROX_SIMPLE) cnt = contours[0] x,y,w,h = cv2.boundingRect(cnt) cv2.rectangle(img,(x,y),(x+w,y+h),img) cv2.waitKey()
7.2 最小外接矩形
cv.minAreaRect返回一個Box2D結構,其中包含以下detals - (center(x,y),(width,height),rotation of rotation)
cv.boxPoints畫上述矩形.
程式碼:
rect = cv2.minAreaRect(cnt) box = cv2.boxPoints(rect) box = np.int0(box) cv2.drawContours(img,[box],2)
8 最小封閉圈
(x,radius = cv2.minEnclosingCircle(cnt) center = (int(x),int(y)) radius = int(radius) cv2.circle(img,center,radius,2)
9 擬合橢圓
ellipse = cv2.fitEllipse(cnt)
cv2.ellipse(img,ellipse,2)
10 擬合直線
rows,cols = img.shape[:2] [vx,vy,x,y] = cv2.fitLine(cnt,cv2.DIST_L2,0.01,0.01) lefty = int((-x*vy/vx) + y) righty = int(((cols-x)*vy/vx)+y) cv2.line(img,(cols-1,righty),lefty),2)
以上這篇python 生成任意形狀的凸包圖程式碼就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。