前面說過,圖像特徵點檢測包括角點和斑點,今天來講說斑點,斑點是指二維圖像中和周圍顏色有顏色差別和灰度差別的區域,由於斑點表明的是一個區域,因此其相對於單純的角點,具備更好的穩定性和更好的抗干擾能力.算法
視覺領域的斑點檢測的主要思路是檢測出圖像中比周圍像素灰度打或者比周圍區域灰度值小的區域,通常來講,有兩種基本方法函數
1.基於求導的微分方法,這成爲微分檢測器code
2.基於局部極值的分水嶺算法,OPENCV中提供了simpleBlobDetector特徵檢測器來實現這種基本的斑點檢測算法.blog
LOG斑點檢測圖片
使用高斯拉普拉斯算子檢測圖像斑點是一種比較常見的辦法,對一個二維的高斯函數G(x,y,o),進過規範化的拉普拉斯變換之後,結果在二維圖像上呈現爲一個圓對稱函數,咱們能夠用這個函數來檢測圖像的斑點,而且能夠經過改動o的值ci
來檢測不一樣尺寸的二維斑點.圖像以下it
對上面這段話的直觀理解是:一個圖像和一個二維函數進行卷積運算,實際上就是求取圖像和這個函數的類似性,同理,圖像與高斯拉普拉斯函數進行卷積,就是求取圖像和高斯拉普拉斯函數的類似性,當圖像中的斑點尺寸與高斯拉普拉斯函數的形opencv
狀趨於一致的時候,圖像對應位置的拉普拉斯響應達到最大.class
實際上,lapacian算子自己能夠檢測圖像的極值點,設其爲L算子,可是由於L算子並不能消除干擾,圖像M中的噪聲會影響求取到的結果,因此對圖像M進行名爲G的高斯濾波去除干擾,獲得圖像M',公式以下M' = M*G*L=M*(G*L);括號裏面就是channel
高斯拉普拉斯算子.
經過上面的那種算法,咱們能夠獲得斑點,可是沒有多尺度的斑點,當高斯協方差o必定的時候,咱們只能檢測對應o的半徑的斑點,具體的半徑經過對標準化的高斯拉普拉斯算子進行求導獲得,當o=r/根號2時,響應最大,圖像黑白反相時,響應最小,因
此將高斯拉普拉斯算子響應達到峯值的o值,成爲特徵尺度.
對應二維圖像,計算圖像在不一樣尺度下的離散高斯拉普拉斯響應值,而後檢查不一樣尺度位置中的每一個值,若是某個尺度下的高斯拉普拉斯響應值,都小於或者大於其餘尺度的值,那麼該點就是被檢測到的圖像斑點位置.
2.基於局部極值的分水嶺算法斑點檢測simpleBlobDetector
這種檢測方法分爲如下幾步
a.對一張圖片,設定一個低閾值,設定一個高閾值,在設定一個閾值步進,而後從低閾值到高閾值按照閾值步進取一系列的閾值
b.用每個閾值對圖像進行二值化,而後使用findcontours查找邊,並計算每個輪廓的中心
c.對應每個圖片的輪廓的中心,進行抑制,定義一個最小距離,在這個距離區域內的特徵中心被定義爲一個blob,獲得特徵點集合
d.對特徵點進行相應的過濾,例如顏色過濾,面積過濾等
API:Ptr<smpleBlobDetector>create(simpleBlobDetector::params 參數集合)
參數集合裏面包括 minthreshold 低閾值 maxthreshold 高閾值 thresholdStep 閾值步進 minDistanceBetweenBlob blob分塊最小距離 filterColor 顏色過濾 filterArea 面積過濾
filterByCircularrty 圓度過濾 還有兩個是邊界長度過濾和凸度過濾,這五種過濾方式任選且只能選一種,默認使用黑色顏色過濾
具體使用代碼以下
int main(int argc,char* argv[]) { Mat srcImage = imread("F:\\opencv\\OpenCVImage\\FeatureDetectSrc1.jpg"); Mat srcGrayImage; if (srcImage.channels() == 3) { cvtColor(srcImage,srcGrayImage,CV_RGB2GRAY); } else { srcImage.copyTo(srcGrayImage); } vector<KeyPoint>detectKeyPoint; Mat keyPointImage1,keyPointImage2; SimpleBlobDetector::Params params; params.minArea = 10; params.maxArea = 1000; params.filterByCircularity = true; Ptr<SimpleBlobDetector> sbd = SimpleBlobDetector::create(params); sbd->detect(srcGrayImage,detectKeyPoint); drawKeypoints(srcImage,detectKeyPoint,keyPointImage1,Scalar(0,0,255),DrawMatchesFlags::DRAW_RICH_KEYPOINTS); drawKeypoints(srcImage,detectKeyPoint,keyPointImage2,Scalar(0,0,255),DrawMatchesFlags::DEFAULT); imshow("src image",srcImage); imshow("keyPoint image1",keyPointImage1); imshow("keyPoint image2",keyPointImage2); imwrite("F:\\opencv\\OpenCVImage\\FeatureDetectSrc1SimpleBlobDetectorKeyPointImageDefault.jpg",keyPointImage2); waitKey(0); return 0; }