斑点检测
FROM:?http://www.cnblogs.com/ronny/p/3895883.html
1. 什么是斑點
斑點通常是指與周圍有著顏色和灰度差別的區(qū)域。在實際地圖中,往往存在著大量這樣的斑點,如一顆樹是一個斑點,一塊草地是一個斑點,一棟房子也可以是一個斑點。由于斑點代表的是一個區(qū)域,相比單純的角點,它的穩(wěn)定性要好,抗噪聲能力要強,所以它在圖像配準上扮演了很重要的角色。
同時有時圖像中的斑點也是我們關心的區(qū)域,比如在醫(yī)學與生物領域,我們需要從一些X光照片或細胞顯微照片中提取一些具有特殊意義的斑點的位置或數(shù)量。
比如下圖中天空的飛機、向日葵的花盤、X線斷層圖像中的兩個斑點。
?????
在視覺領域,斑點檢測的主要思路都是檢測出圖像中比它周圍像素灰度值大或比周圍灰度值小的區(qū)域。一般有兩種方法來實現(xiàn)這一目標:
這里我們重點介紹第一種方法,主要檢測LOG斑點。而OpenCV中SimpleBlobDetector斑點檢測算子就實現(xiàn)了第二種方法,我們這里也會介紹它的接口使用方法。
2. LOG斑點檢測
2.1 基本原理
利用高斯拉普通拉斯(Laplace of Gaussian,LOG)算子檢測圖像斑點是一種十分常用的方法,對于二維高斯函數(shù):
G(x,y;σ)=12πσ2exp(?x2+y22σ2)
它的拉普拉斯變換為:
?2g=?2g?x2+?2g?y2
規(guī)范化的高斯拉普變換為:
?2norm=σ2?2g=σ2(?2g?x2+?2g?y2)=?12πσ2[1?x2+y2σ2]?exp(?x2+y22σ2)
規(guī)范化算法子在二維圖像上顯示是一個圓對稱函數(shù),如下圖所示。我們可以用這個算子來檢測圖像中的斑點,并且可以通過改變σ的值,可以檢測不同尺寸的二維斑點。
???
2.2 LOG原理解釋
其實從更直觀的角度去解釋為什么LOG算子可以檢測圖像中的斑點是:
圖像與某一個二維函數(shù)進行卷積運算實際就是求取圖像與這一函數(shù)的相似性。同理,圖像與高斯拉普拉斯函數(shù)的卷積實際就是求取圖像與高斯拉普拉斯函數(shù)的相似性。當圖像中的斑點尺寸與高斯拉普拉斯函數(shù)的形狀趨近一致時,圖像的拉普拉斯響應達到最大。
從概率的角度解釋為:假設原圖像是一個與位置有關的隨機變量X的密度函數(shù),而LOG為隨機變量Y的密度函數(shù),則隨機變量X+Y的密度分布函數(shù)即為兩個函數(shù)的卷積形式(這一部分的理論,可以參見本博客概率與統(tǒng)計相關文章)。如果想讓X+Y能取到最大值,則X與Y能保持步調一致最好,即X上升時,Y也上升,X最大時,Y也最大。
那么LOG算子是怎么被構想出來的呢?
事實上我們知道Laplace可以用來檢測圖像中的局部極值點,但是對噪聲敏感,所以在我們對圖像進行Laplace卷積之前,我們用一個高斯低通濾波對圖像進行卷積,目標是去除圖像中的噪聲點。這一過程 可以描述為:
先對圖像f(x,y)用方差為σ的高斯核進行高斯濾波,去除圖像中的噪點。
L(x,y;σ)=f(x,y)?G(x,y;σ)
然后對圖像的拉普拉斯圖像則為:
?2=?2L?x2+?2L?y2
而實際上有下面等式:
?2[G(x,y)?f(x,y)]=?2[G(x,y)]?f(x,y)
所以,我們可以先求高斯核的拉普拉斯算子,再對圖像進行卷積。也就是一開始描述的步驟。
2.3 LOG算子的實現(xiàn)
Mat Feat::getHOGKernel(Size& ksize, double sigma) {Mat kernel(ksize, CV_64F);Point centPoint = Point((ksize.width -1)/2, ((ksize.height -1)/2));// first calculate Gaussianfor (int i=0; i < kernel.rows; i++){double* pData = kernel.ptr<double>(i);for (int j = 0; j < kernel.cols; j++){double param = -((i - centPoint.y) * (i - centPoint.y) + (j - centPoint.x) * (j - centPoint.x)) / (2*sigma*sigma);pData[j] = exp(param);}}double maxValue;minMaxLoc(kernel, NULL, &maxValue);for (int i=0; i < kernel.rows; i++){double* pData = kernel.ptr<double>(i);for (int j = 0; j < kernel.cols; j++){if (pData[j] < EPS* maxValue){pData[j] = 0;}}}double sumKernel = sum(kernel)[0];if (sumKernel != 0){kernel = kernel / sumKernel;}// now calculate Laplacianfor (int i=0; i < kernel.rows; i++){double* pData = kernel.ptr<double>(i);for (int j = 0; j < kernel.cols; j++){double addition = ((i - centPoint.y) * (i - centPoint.y) + (j - centPoint.x) * (j - centPoint.x) - 2*sigma*sigma)/(sigma*sigma*sigma*sigma);pData[j] *= addition;}}// make the filter sum to zerosumKernel = sum(kernel)[0];kernel -= (sumKernel/(ksize.width * ksize.height)); return kernel; }2.4 多尺度檢測
我們注意到當σ尺度一定時,只能檢測對應半徑的斑點,那么檢測的是多大半徑的斑點呢,我們可以通過對規(guī)范化的二維拉普拉斯高斯算子求導:
規(guī)范化的高斯拉普拉斯函數(shù)為:
?2norm=?12πσ2[1?x2+y2σ2]?exp(?x2+y22σ2)
求?2norm的極點值等價于求取下式:
?(?2norm)?σ=0
得到:
(x2+y2?2σ2)?exp(?(x2+y2)2σ2)
r2?2σ2=0
對于圖像中的斑點,在尺度σ=r/2√時,高斯拉普拉斯響應值達到最大。同理,如果圖像中的圓形斑點黑白反向,那么,它的高斯拉普拉斯響應值在σ=r/2√時達到最小。將高斯拉普拉斯響應達到峰值時的尺度σ值,稱為特征尺度。
那么在多尺度的情況下,同時在空間和尺度上達到最大值(或最小值)的點就是我們所期望的斑點。對于二維圖像I(x,y),計算圖像在不同尺度下的離散拉普拉斯響應值,然后檢查位置空間中的每個點;如果該點的拉普拉斯響應值都大小于或小于其他26個立方空間領域(9+8+9)的值,那么該點就是被檢測到的圖像斑點。
3 OpenCV進行斑點檢測
opencv中檢測Blobs的類為SimpleBlobDetector,這個類在opencv中的定義如下:
class SimpleBlobDetector : public FeatureDetector { public: struct Params {Params();float thresholdStep;float minThreshold;float maxThreshold;size_t minRepeatability;float minDistBetweenBlobs;bool filterByColor;uchar blobColor;bool filterByArea;float minArea, maxArea;bool filterByCircularity;float minCircularity, maxCircularity;bool filterByInertia;float minInertiaRatio, maxInertiaRatio;bool filterByConvexity;float minConvexity, maxConvexity; };SimpleBlobDetector(const SimpleBlobDetector::Params ¶meters = SimpleBlobDetector::Params());protected:... };算法的大致步驟如下:
同時該支持提取特征的方法,一共有5個選項,這里就不多加描述了,默認是提取黑色圓形的Blob特征。下面是一個示例
int main(int argc, char** argv)?
{?
??? Mat image = imread(argv[1]);?
??? vector<KeyPoint> keyPoints;?
??? SimpleBlobDetector::Params params;
??? SimpleBlobDetector blobDetect(params);?
??? blobDetect.create("SimpleBlob");?
??? blobDetect.detect(image, keyPoints);?
??? cout << keyPoints.size() << endl;?
??? drawKeypoints(image, keyPoints, image, Scalar(255,0,0));
??? namedWindow("blobs");?
??? imshow("blobs", image);?
??? waitKey();?
??? return 0;?
}
??
總體來說,OpenCV的斑點檢測效果還算不錯,但是在有些圖像的效果上明顯不如LOG算子檢測的檢測效果。
4. 擴展閱讀
一個與LOG濾波核近似的是高斯差分DOG濾波核,它的定義為:
D(x,y,σ)=(G(x,y,kσ)–G(x,y,σ))?I(x,y)=L(x,y,kσ)?L(x,y,σ)
其中k為兩個相鄰尺度間的比例因子。
DOG可以看作為LOG的一個近似,但是它比LOG的效率更高。
前面介紹的微分算子在近圓的斑點檢測方面效果很好,但是這些檢測算子被限定于只能檢測圓形斑點,而且不能估計斑點的方向,因為LOG算子等都是中心對稱的。如果我們定義一種二維高斯核的變形,記它在X方向與Y方向上具有不同的方差,則這種算子可以用來檢測帶有方向的斑點。
G(x,y)=A?exp(?[(ax2+2bxy+cy2)])
a=cos2θ2σ2x+sin2θ2σ2y,b=?sin2θ2σ2x+sin2θ4σ2y,c=sin2θ2σ2x+cos2θ2σ2y
其中A是規(guī)一性因子。
5. 參考資料
1. 《現(xiàn)代數(shù)字圖像 -- 處理技術提高與應用案例詳解》
2. 《圖像局部不變性特征與描述》
3.? Lindeberg, T. Feature Detection with Automatic Scale Selection
4. Hui Kong. A Generalized Laplacian Of Gaussian Filter for Blob Detection and Its Applications.
5.?OpenCV2馬拉松第20圈——blob特征檢測原理與實現(xiàn)
《新程序員》:云原生和全面數(shù)字化實踐50位技術專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
總結
- 上一篇: 图像的矩特征
- 下一篇: SIFT定位算法关键步骤的说明