基於Python的OpenCV輪廓檢測聚類

簡介

OpenCV的“findContours”功能經常被計算機視覺工程師用來檢測物體。OpenCV的存在,使得我們只需要編寫幾行程式碼就可以檢測輪廓(物件)。然而,OpenCV檢測到的輪廓通常是分散的。例如,一個功能豐富的影象可能有數百到數千個輪廓,但這並不意味著影象中有那麼多物件。一些屬於同一物件的輪廓是單獨檢測的,因此我們感興趣的是對它們進行分組,使一個輪廓對應一個物件。

實現思路

當我在專案中遇到這個問題時,我花了很多時間嘗試使用不同的引數或不同的OpenCV函式來檢測輪廓,但沒有一個有效。然後,我做了更多的研究,在OpenCV的論壇上找到了一篇帖子,它提到了凝聚聚類。但是,沒有給出原始碼。我還發現sklearn支援聚合聚類,但我沒有使用它,原因有兩個:

這個功能對我來說似乎很複雜。我不知道如何輸入正確的引數,我懷疑輪廓檢測的資料型別是否適合該函式。

我需要使用python 2。7、OpenCV 3。3。1和Numpy 1。11。3。它們與sklearn的版本(0。20+)不相容,後者支援聚類。

原始碼

為了分享我編寫的函式,我在Github中對其進行了開源,並將其作為要點發布在下面。以下版本適用於Python3,若需要要在Python2。7中使用它,只需將“range”更改為“xrange”。

#!/usr/bin/env python3import osimport cv2import numpydef calculate_contour_distance(contour1, contour2): x1, y1, w1, h1 = cv2。boundingRect(contour1) c_x1 = x1 + w1/2 c_y1 = y1 + h1/2 x2, y2, w2, h2 = cv2。boundingRect(contour2) c_x2 = x2 + w2/2 c_y2 = y2 + h2/2 return max(abs(c_x1 - c_x2) - (w1 + w2)/2, abs(c_y1 - c_y2) - (h1 + h2)/2)def merge_contours(contour1, contour2): return numpy。concatenate((contour1, contour2), axis=0)def agglomerative_cluster(contours, threshold_distance=40。0): current_contours = contours while len(current_contours) > 1: min_distance = None min_coordinate = None for x in range(len(current_contours)-1): for y in range(x+1, len(current_contours)): distance = calculate_contour_distance(current_contours[x], current_contours[y]) if min_distance is None: min_distance = distance min_coordinate = (x, y) elif distance < min_distance: min_distance = distance min_coordinate = (x, y) if min_distance < threshold_distance: index1, index2 = min_coordinate current_contours[index1] = merge_contours(current_contours[index1], current_contours[index2]) del current_contours[index2] else: break return current_contours

注意:

“calculate_contour_distance”函式獲取輪廓的邊界框,並計算兩個矩形之間的距離。

“merge_contours”函式,我們只需使用‘numpy。concatenate’即可,因為每個輪廓只是一個點的numpy陣列。

使用聚類演算法,我們不需要事先知道有多少個聚類。相反,可以向函式提供閾值距離,例如40個畫素,因此如果所有輪廓中最近的距離大於閾值,則函式將停止處理。

結果

要視覺化叢集效果,請參見下面的兩幅影象。第一幅影象顯示最初檢測到12個輪廓,聚類後只剩下4個輪廓,如第二幅影象所示。這兩個小物件是由於噪聲造成的,它們沒有合併,因為與閾值距離相比,它們離太遠。

基於Python的OpenCV輪廓檢測聚類

基於Python的OpenCV輪廓檢測聚類