首頁 > 軟體

OpenCV凸包檢測和凸缺陷學習範例

2022-06-07 14:06:42

1、凸包檢測與凸缺陷定義

凸包是將最外層的點連線起來構成的凸多邊形,它能包含點選中所有的點。物體的凸包檢測常應用在物體識別、手勢識別及邊界檢測等領域。

凸包檢測常常用在輪廓分析之後。對二值影象進行輪廓分析之後,可以構建每個輪廓的凸包,構建完成之後會返回該凸包包含的點集。根據返回的凸包點集可以繪製該輪廓對應的凸包。一般來說,凸性曲線總是凸出來的,至少是平的。如果有地方凹進去了就被叫做凸性缺陷。

下圖可以更加直接的瞭解凸包和凸缺陷的定義:

2、opencv相關實現函數

OpenCV中提供了函數convexHull 用於對物體輪廓凸包進行檢測,函數convexityDefect進行凸缺陷的檢測。首先來了解一下各引數意義:

hull = cv2.convexHull(points, clockwise, returnpoints)

各引數意義: 

points:輸入的輪廓點集 

clockwise:方向標誌,如果設定為True,輸出的凸包是順時針方向的,否則為逆時針方向。 

returnPoints:是否返回點集 

hull : 輸出凸包結果,當引數returnPoints為ture的時候返回凸包的頂點座標是個點集、returnPoints為false的是返回與凸包點對應的輪廓上的點對應的index

下面這個函數可以幫助我們找到凸缺陷:

convexityDefects = cv2.convexityDefect(contour, convexhull)

注意:

進行凸檢測時,凸包檢測中的returnPoints要設定為False 

凸缺陷返回一個陣列,每一行包含值是起點,終點,最遠的點,到最遠點的近似距離,返回的前三個點都是輪廓索引。

contour: 檢測到的輪廓,可以呼叫findContours函數得到 

convexhull:檢測到的凸包,可以呼叫convexHull函數得到。 

convexityDefects:輸出引數,檢測到的最終結果,返回一個陣列,其中每一行包含的值是[起點,終點,最遠的點,到最遠點的近似距離]。前三個點都是輪廓索引。 

前三個值得含義分別為:凸缺陷的起始點,凸缺陷的終點,凸缺陷的最深點(即邊緣點到凸包距離最大點)

3、程式碼實踐

我們可以在一張圖上顯示輪廓的凸包和凸缺陷。

我們將起點和終點用一條紅線 連線,在最遠點畫一個藍色的圓圈,要記住的是返回結果的前三個值是輪廓點的索引。 所以我們還要到輪廓點中去找它們。

前三個值得含義分別為:凸缺陷的起始點,凸缺陷的終點,凸缺陷的最深點(即邊緣點到凸包距離最大點)。

凸包檢測和凸缺陷檢測的程式碼如下:

# 凸包檢測和凸缺陷
import cv2 as cv
# 讀取影象
src1 = cv.imread("000.jpg")
# 轉換為灰度影象
gray = cv.cvtColor(src1, cv.COLOR_BGR2GRAY)
# 二值化
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
# 獲取結構元素
k = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
# 開操作
binary = cv.morphologyEx(binary, cv.MORPH_OPEN, k)
# 輪廓發現
contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# 在原圖上繪製輪廓,以方便和凸包對比,發現凸缺陷
cv.drawContours(src1, contours, -1, (0, 225, 0), 3)
for c in range(len(contours)):
    # 是否為凸包
    ret = cv.isContourConvex(contours[c])
    # 凸缺陷
    # 凸包檢測,returnPoints為false的是返回與凸包點對應的輪廓上的點對應的index
    hull = cv.convexHull(contours[c], returnPoints=False)
    defects = cv.convexityDefects(contours[c], hull)
    print('defects', defects)
    for j in range(defects.shape[0]):
        s, e, f, d = defects[j, 0]
        start = tuple(contours[c][s][0])
        end = tuple(contours[c][e][0])
        far = tuple(contours[c][f][0])
        # 用紅色連線凸缺陷的起始點和終止點
        cv.line(src1, start, end, (0, 0, 225), 2)
        # 用藍色最遠點畫一個圓圈
        cv.circle(src1, far, 5, (225, 0, 0), -1)
# 顯示
cv.imshow("result", src1)
cv.waitKey(0)
cv.destroyAllWindows()

凸缺陷的部分輸出:前三個為凸缺陷的起始點,凸缺陷的終點,凸缺陷的最深點(即邊緣點到凸包距離最大點)。凸包檢測輸出的也是輪廓上的點的索引。

凸缺陷檢測的效果圖: 

紅色為凸包,藍色點為凸缺陷的最深點(即邊緣點到凸包距離最大點),綠色是輪廓。紅色與綠色之間的區域即為凸缺陷。

4、總結

(1)cv2.convexityDefect函數進行凸缺陷檢測時,凸包檢測函數中cv2.convexHull中的returnPoints要設定為False,返回輪廓中與凸包點對應的輪廓點的index。

(2)cv2.convexityDefect函數的返回值是一系列陣列,[凸缺陷的起點,凸缺陷的終點,凸缺陷的最深的點,到最遠點的近似距離],前三個是索引值,終點和起點連線即得到凸包。

(3)凸缺陷的最深的點:即邊緣點到凸包距離最大點到最遠點的近似距離:邊緣點到凸包的最大距離。

(4)利用凸包檢測可以得到進一步的輪廓資訊,可進行邊界檢測,結合凸缺陷可以實現手勢識別和物體識別。

以上就是OpenCV凸包檢測和凸缺陷學習範例的詳細內容,更多關於OpenCV凸包檢測和凸缺陷的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com