2016-02-29 62 views
1

我想將我的圖像分析腳本之一從Mathematica移植到Python OpenCV,但是我遇到了涉及的某個函數的問題。OpenCV簡單的Blob檢測器沒有檢測到所有的斑點

我設法將圖像進行二值化和分水嶺化,就像Mathematica中的一樣。但是,篩選連接組件的屬性的步驟似乎無法正常工作。

輸入圖像是如下:

Input image

然而,我試圖運行下面的代碼:

import cv2 
import numpy as np 

img = cv2.imread('test2.4.png', 1) 
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 

# Set up the detector and configure its params. 
params = cv2.SimpleBlobDetector_Params() 
params.minDistBetweenBlobs = 0 
params.filterByColor = True 
params.blobColor = 255 
params.filterByArea = True 
params.minArea = 10 
params.maxArea = 300000 
params.filterByCircularity = False 
params.filterByConvexity = False 
params.filterByInertia = True 
params.minInertiaRatio = 0.01 
params.maxInertiaRatio = 1 
detector = cv2.SimpleBlobDetector_create(params) 

# Detect blobs. 
keypointsb = detector.detect(img) 

# Draw detected blobs as red circles. 
im_with_keypoints = cv2.drawKeypoints(img, keypointsb, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 

# Show keypoints 
cv2.imwrite('test3.png',im_with_keypoints) 

如該代碼所示,我已經爲團塊的參數檢測儘可能寬容。然而,大部分的斑點沒有被檢測到,也沒有檢測到分水斑點。

我檢查了documentation for the function,並調整了其中的大部分閾值和repeatability(因爲圖像已經被二進制化)。爲了讓函數能夠檢測到所有的斑點,是否還有其他配置需要執行?

enter image description here

或者,是否有任何其他最近/孔更新的庫,通過成分測量是能夠過濾的?

回答

2

我知道它已經很久了,但我在這裏與你有類似的任務。對如何使用width = 1行分隔連接的斑點感興趣。

然而,我玩了一會兒與SimpleBlobDetector和它做什麼是簡要地執行以下步驟(從讀取它的源代碼):

  1. 雙穩態使用不同的閾值從minThreshold圖像與步驟thresholdStep到maxThreshold
  2. 找到每個二值化圖像中的輪廓,在這裏應用濾波器,例如區域,顏色,圓度,凸度,慣性等
  3. 結合所有過濾輪廓根據它們的位置,即距離比minDistBetweenBlobs更大和不重疊
  4. 存儲並用於所有斑點返回關鍵點(輪廓)保持

因此,我使用下面的簡單代碼檢查了SimpleBlobDetector的每一步,發現用於分隔連接的斑點的width = 1行被發現爲單獨的輪廓/斑點(輪廓/斑點顯示爲紅色,特別是對於非水平/垂直線(1像素輪廓),輪廓/斑點的中心在附圖中以綠色顯示)。那些小輪廓然後被minArea或blobColor = 255過濾掉。這就是爲什麼你的分割斑點被檢測爲更大斑點的原因。

import cv2 
import numpy as np 

img = cv2.imread('test3.png', 1) 
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 

ret, bin_img = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) 

out_img = img 
temp_bin_img = bin_img.copy() 
ret, contours = cv2.findContours(temp_bin_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) 
for i in range(len(contours)): 
    M = cv2.moments(contours[i]) 
    if(M['m00'] == 0.0): 
     continue 
    x, y = int(M['m10']/M['m00']), int(M['m01']/M['m00']) 

    out_img = cv2.drawContours(out_img, contours, i, (0,0,255), 1) 
    cv2.circle(out_img, (x, y), 1, (0,255,0), -1) 

cv2.imwrite('test3-contours.png', out_img) 

test3-contours.png

提高,可能會嘗試先侵蝕,增加邊界的寬度,然後用SimpleBlobDetector或使用findContours自己。像這樣:

import cv2 
import numpy as np 

img = cv2.imread('YUSAQ.png', 1) 
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 

ret, bin_img = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) 

kernel = np.ones((3,3),np.uint8) 
erosion = cv2.erode(bin_img, kernel, iterations = 1) 

out_img = img 
temp_bin_img = erosion.copy() 
ret, contours = cv2.findContours(temp_bin_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) 
for i in range(len(contours)): 
    M = cv2.moments(contours[i]) 
    if(M['m00'] == 0.0): 
     continue 
    x, y = int(M['m10']/M['m00']), int(M['m01']/M['m00']) 

    out_img = cv2.drawContours(out_img, contours, i, (0,0,255), 1) 
    cv2.circle(out_img, (x, y), 1, (0,255,0), -1) 

cv2.imwrite('test3-erosion.png', out_img) 

使用3x3內核做腐蝕導致找到的斑點比原始斑點小1〜2個像素。我沒有爲此做過修正(甚至沒有試圖去想它)。如果你願意,我想你可以自己做。希望這可以幫助。

test3-erosion.png

+0

@C王驚人的工作我必須嘗試一下:D –