天天看點

OpenCV—Python 輪廓檢測 繪出矩形框(findContours\ boundingRect\rectangle)

文章目錄

  • ​​1 擷取輪廓​​
  • ​​1.1 傳回值:image, contours, hierarchy​​
  • ​​2 繪出輪廓​​
  • ​​3 擷取輪廓區域​​
  • ​​4 擷取物體最小外界矩陣​​

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      
OpenCV—Python 輪廓檢測 繪出矩形框(findContours\ boundingRect\rectangle)

其中,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會出矩形框

繼續閱讀