blob
或者叫斑點,就是在一幅圖像上,暗背景上的亮區域,或者亮背景上的暗區域。由於斑點代表的是一個區域,相比單純的角點,它的穩定性要好,抗噪聲能力要強,所以它在圖像配准上扮演了很重要的角色。
同時有時圖像中的斑點也是我們關心的區域,比如在醫學與生物領域,我們需要從一些X光照片或細胞顯微照片中提取一些具有特殊意義的斑點的位置或數量。
比如天空的飛機、向日葵的花盤、X線斷層圖像中的兩個斑點。
1. 可選算法
1.1. Laplacian of Gaussian (LoG)
這是速度最慢,可是最准確的一種算法。簡單來說,就是對一幅圖先進行一系列不同尺度的高斯濾波,然后對濾波后的圖像做Laplacian運算。將全部的圖像進行疊加。局部最大值就是所要檢測的blob,這個算法對於大的blob檢測會非常慢,還有就是該算法適合於檢測暗背景下的亮blob。
1.2. Difference of Gaussian (DoG)
這是LoG算法的一種高速近似,對圖像進行高斯濾波之后,不做Laplacian運算,直接做減法。相減后的圖做疊加。找到局部最大值,這個算法的缺陷與LoG相似。
如果需要利用 LoG 或 DoG 檢測亮背景上的暗blob,能夠將圖像做反相,這樣亮背景就變成了暗背景,而暗blob就變成了亮blob,然后就能夠用這兩個算法了,檢測完之后再反回來就好了。
1.3. Determinant of Hessian (DoH)
這是最快的一種算法,不須要做多尺度的高斯濾波,運算速度自然提升非常多,這個算法對暗背景上的亮blob或者亮背景上的暗blob都能檢測。
缺點是小尺寸的blob檢測不准確。
2. skimage 代碼實現
from matplotlib import pyplot as plt
from skimage import data
from skimage.feature import blob_dog, blob_log, blob_doh
from math import sqrt
from skimage.color import rgb2gray
image = data.hubble_deep_field()[0:500, 0:500]
image_gray = rgb2gray(image)
plt.imshow(image)
blobs_log = blob_log(image_gray, max_sigma=30, num_sigma=10, threshold=.1)
# Compute radii in the 3rd column.
blobs_log[:, 2] = blobs_log[:, 2] * sqrt(2)
blobs_dog = blob_dog(image_gray, max_sigma=30, threshold=.1)
blobs_dog[:, 2] = blobs_dog[:, 2] * sqrt(2)
blobs_doh = blob_doh(image_gray, max_sigma=30, threshold=.01)
blobs_list = [blobs_log, blobs_dog, blobs_doh]
colors = ['yellow', 'lime', 'red']
titles = ['Laplacian of Gaussian', 'Difference of Gaussian',
'Determinant of Hessian']
sequence = zip(blobs_list, colors, titles)
fig,axes = plt.subplots(1, 3, sharex=True, sharey=True, subplot_kw={'adjustable':'box-forced'})
axes = axes.ravel()
for blobs, color, title in sequence:
ax = axes[0]
axes = axes[1:]
ax.set_title(title)
ax.imshow(image, interpolation='nearest')
for blob in blobs:
y, x, r = blob
c = plt.Circle((x, y), r, color=color, linewidth=2, fill=False)
ax.add_patch(c)
plt.show()
效果圖:
3. 基於 OpenCV
SimpleBlobDetector,是非常簡單的模塊,算法使用如下參數控制,且執行之后的流程:
-
Thresholding, 閾值處理
通過使用從minThreshold開始的閾值對源圖像進行閾值處理,將源圖像轉換成多個二進制圖像。這些閾值以thresholdStep大小依次遞增直到maxThreshold,所以第一個閾值是minThreshold,第二個是minThreshold+thresholdStep,依此類推。
-
Grouping, 分組
在每個二進制圖像中,連接白色像素被分成一組,我們稱為二進制斑點(binary blobs)
-
Merging, 合並
計算二進制圖像中二進制斑點的重心,並合並距離小於minDistBetweenBlobs的斑點
-
Center & Radius Calculation, 中心和半徑計算
計算並返回新合並的blobs的中心和半徑。
import cv2
import numpy as np
#讀圖片
im = cv2.imread('blod.jpg', cv2.IMREAD_GRAYSCALE)
#創建一個檢測器並使用默認參數
detector = cv2.SimpleBlobDetector()
#檢測斑點
keypoints = detector.detect(im)
#將檢測到的斑點圈上紅色的圓圈
#DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS保證圓的大小和斑點大小一樣
im_with_keypoints = cv2.drawKeypoints(im, keypoints, np.array([]), (0,0,255),
cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
#顯示檢測到的點
cv2.imshow('keypoints', im_with_keypoints)
cv2.waitKey(0)
3.1. 過濾斑點
可以設置SimpleBlobDetector的參數來過濾我們想要的斑點類型:
-
按顏色
首先你需要設置filterByColor=1,設置blobColor=0選擇顏色更暗的斑點,blobColor=255選擇顏色更淺的斑點
注意:此功能已經損壞,我檢查了代碼,它似乎有一個邏輯錯誤。
-
按大小
可以通過設置參數filterByArea=1以及minArea和maxArea的適當值來根據大小過濾斑點,例如,設置minArea=100將過濾掉所有小於100像素的斑點
-
按形狀:現在形狀有三種不同的參數
-
Circularity, 圓度
這只是測量斑點的圓形接近程度,例如正六邊形具有比正方形更高的圓度,要按照圓度過濾,請設置
filterByCircularity=1
然后為minCircularity和maxCircularity
設置適當的值。 -
Convexity, 凸度
設置
filterByConvexity=1
,然后設置0<= minConvexity<=1
和maxConvexity<=1
。 -
Ratio, 慣性比(長度)
設定
filterByInertia=1
,並設置0 ≤ minInertiaRatio <= 1
和maxInertiaRatio<=1
。
-