千萬注意opencv的輪廓檢測和邊緣檢測是兩碼事
本文鏈接:https://blog.csdn.net/wsp_1138886114/article/details/82945328
1 獲取輪廓
OpenCV2獲取輪廓主要是用 cv2.findContours()
import cv2 img = cv2.imread('wujiaoxing.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret,binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) _,contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) draw_img0 = cv2.drawContours(img.copy(),contours,0,(0,255,255),3) draw_img1 = cv2.drawContours(img.copy(),contours,1,(255,0,255),3) draw_img2 = cv2.drawContours(img.copy(),contours,2,(255,255,0),3) draw_img3 = cv2.drawContours(img.copy(), contours, -1, (0, 0, 255), 3) print ("contours:類型:",type(contours)) print ("第0 個contours:",type(contours[0])) print ("contours 數量:",len(contours)) print ("contours[0]點的個數:",len(contours[0])) print ("contours[1]點的個數:",len(contours[1])) cv2.imshow("img", img) cv2.imshow("draw_img0", draw_img0) cv2.imshow("draw_img1", draw_img1) cv2.imshow("draw_img2", draw_img2) cv2.imshow("draw_img3", draw_img3) cv2.waitKey(0) cv2.destroyAllWindows() 輸出: contours:類型: <class 'list'> 第0 個contours: <class 'numpy.ndarray'> contours 數量: 3 contours[0]點的個數: 6 contours[1]點的個數: 74
其中,cv2.findContours() 的第二個參數主要有
cv2.RETR_LIST:檢測的輪廓不建立等級關系
cv2.RETR_TREE:L建立一個等級樹結構的輪廓。
cv2.RETR_CCOMP:建立兩個等級的輪廓,上面的一層為外邊界,里面的一層為內孔的邊界信息。
cv2.RETR_EXTERNAL:表示只檢測外輪廓
cv2.findContours() 的第三個參數 method為輪廓的近似辦法
cv2.CHAIN_APPROX_NONE存儲所有的輪廓點,相鄰的兩個點的像素位置差不超過1,即max(abs(x1-x2),abs(y2-y1))==1
cv2.CHAIN_APPROX_SIMPLE壓縮水平方向,垂直方向,對角線方向的元素,只保留該方向的終點坐標,例如一個矩形輪廓只需4個點來保存輪廓信息
cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
1.1 返回值:image, contours, hierarchy
contour返回值
cv2.findContours()函數首先返回一個list,list中每個元素都是圖像中的一個輪廓,用numpy中的ndarray表示。
hierarchy返回值
該函數還可返回一個可選的hiararchy結果,這是一個ndarray,其中的元素個數和輪廓個數相同,每個輪廓contours[i]對應4個hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分別表示后一個輪廓、前一個輪廓、父輪廓、內嵌輪廓的索引編號,如果沒有對應項,則該值為負數。
2 繪出輪廓
cv2.drawContours()函數
cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]])
第一個參數是指明在哪幅圖像上繪制輪廓;
第二個參數是輪廓本身,在Python中是一個list。
第三個參數指定繪制輪廓list中的哪條輪廓,如果是-1,則繪制其中的所有輪廓。后面的參數很簡單。其中thickness表明輪廓線的寬度,如果是-1(cv2.FILLED),則為填充模式。繪制參數將在以后獨立詳細介紹。
為了看到自己畫了哪些輪廓,可以使用 cv2.boundingRect()函數獲取輪廓的范圍,即左上角原點,以及他的高和寬。然后用cv2.rectangle()方法畫出矩形輪廓
""" x, y, w, h = cv2.boundingRect(img) 參數: img 是一個二值圖 x,y 是矩陣左上點的坐標, w,h 是矩陣的寬和高 cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2) img: 原圖 (x,y): 矩陣的左上點坐標 (x+w,y+h):是矩陣的右下點坐標 (0,255,0): 是畫線對應的rgb顏色 2: 線寬 """ for i in range(0,len(contours)): x, y, w, h = cv2.boundingRect(contours[i]) cv2.rectangle(image, (x,y), (x+w,y+h), (153,153,0), 5)
3 獲取輪廓區域
new_image=image[y+2:y+h-2,x+2:x+w-2] # 先用y確定高,再用x確定寬 input_dir=("E:/cut_image/") if not os.path.isdir(input_dir): os.makedirs(input_dir) cv2.imwrite( nrootdir+str(i)+".jpg",newimage) print (i)
4 獲取物體最小外界矩陣
使用 cv2.minAreaRect(cnt) ,返回點集cnt的最小外接矩形,cnt是所要求最小外接矩形的點集數組或向量,這個點集不定個數。
其中:cnt = np.array([[x1,y1],[x2,y2],[x3,y3],[x4,y4]]) # 必須是array數組的形式
rect = cv2.minAreaRect(cnt) # 得到最小外接矩形的(中心(x,y), (寬,高), 旋轉角度)
box = np.int0(cv2.boxPoints(rect)) #通過box會出矩形框