OpenCV 斑點檢測

  • 2019 年 10 月 7 日
  • 筆記

斑點通常是指與周圍有著顏色和灰度差別的區域。有時影像中的斑點也是我們關心的區域,比如在醫學影像中或品質檢測領域,我們需要從一些X光圖片或普通光學照片中提取一些具有特殊意義的斑點的數量和坐標資訊。

Opencv中提供了SimpleBlobDetector的特徵點檢測方法,正如它的名稱,該演算法使用最簡單的方式來檢測斑點類的特徵點。該演算法大致有如下步驟:

1.首先通過一系列連續的閾值把輸入的灰度影像轉換為一個二值影像的集合。閾值範圍為[T1,T2],步長為t,則所有閾值為:

T1,T1+t,T1+2t,T1+3t,……,T2 (1)

2.第二步是利用Suzuki提出的演算法通過檢測每一幅二值影像的邊界的方式提取出每一幅二值影像的連通區域,我們可以認為由邊界所圍成的不同的連通區域就是該二值影像的斑點。不是所有的二值影像的連通區域都可以認為是二值影像的斑點,我們往往通過一些限定條件來得到更準確的斑點。這些限定條件包括顏色,面積和形狀等等。斑點的形狀又可以用圓度,偏心率,或凸度來表示。

3.第三步是根據所有二值影像斑點的中心坐標對二值影像斑點進行分類,從而形成灰度影像的斑點,屬於一類的那些二值影像斑點最終形成灰度影像的斑點,具體來說就是,灰度影像的斑點是由中心坐標間的距離小於閾值Tb的那些二值影像斑點所組成的,即這些二值影像斑點屬於該灰度影像斑點;

4.最後就是確定灰度影像斑點的資訊——位置和尺寸。位置是屬於該灰度影像斑點的所有二值影像斑點中心坐標的加權和,即公式2,權值q等於該二值影像斑點的慣性率的平方,它的含義是二值影像的斑點的形狀越接近圓形,越是我們所希望的斑點,因此對灰度影像斑點位置的貢獻就越大。尺寸則是屬於該灰度影像斑點的所有二值影像斑點中面積大小居中的半徑長度。

(2)

我們以下面的蝌蚪找媽媽圖為例來介紹源碼的實現。

首先載入圖片並進行高斯模糊以降噪。

import cv2  import numpy as np  from matplotlib import pyplot as plt    img0 = cv2.imread("tadpoles.jpg")  gray = cv2.cvtColor(img0, cv2.COLOR_BGR2GRAY)  gauss = cv2.GaussianBlur(gray, (9,9), 0) #高斯模糊,X,Y 方向的Ksiez分別為9和9

再細化檢測參數

params = cv2.SimpleBlobDetector_Params()  #斑點檢測的可選參數  #params.minThreshold= 10 #亮度最小閾值控制  #params.maxThreshold = 255 #亮度最大閾值控制  params.thresholdStep = 9 #亮度閾值的步長控制,越小檢測出來的斑點越多    params.filterByColor = True #顏色控制  params.blobColor = 0 #只檢測黑色斑點  #params.blobColor = 255 #只檢測白色色斑點    params.filterByArea = True #像素麵積大小控制  params.minArea = 20  #params.maxArea=2000    #params.filterByCircularity = True #圓度控制,圓度的定義是(4π×面積)/(周長的平方)  #params.minCircularity = 0.3    #params.filterByConvexity =True #凸度控制,凸性的定義是(斑點的面積/斑點凸包的面積  #params.minConvexity = 1.0    #params.filterByInertia = True# 慣性率控制  #params.minInertiaRatio = 0.2#圓形的慣性率等於1,慣性率越接近1,圓度越高

然後執行斑點檢測:

detector = cv2.SimpleBlobDetector_create(params)#創建斑點檢測器  keypoints = detector.detect(gauss) #在哪個圖上檢測斑點  print("共檢測出%d個斑點" %len(keypoints))    #在原圖上畫出檢測到的斑點  im_with_keypoints=cv2.drawKeypoints(img0, keypoints, np.array([]), (0, 0, 255),                                      cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)  print("斑點中心坐標為:")  for (x,y) in keypoints[0].convert(keypoints):      print(x,",", y)      cv2.circle(im_with_keypoints, (x,y), 1, (255,255,255), 1) #以白色標記處斑點中心(以斑點中心為中心畫圓)    #繪出檢測結果圖  plt.subplot(1,1,1)  plt.imshow(cv2.cvtColor(im_with_keypoints, cv2.COLOR_BGR2RGB))  plt.title("OpenCV 斑點檢測n之小蝌蚪找媽媽",fontSize =16, color="b")  plt.show()

可以看到,除了全部的蝌蚪都被檢測出來了外,青蛙的眼珠也被檢測出來了。當然,後者很容易通過斑點面積過濾掉。