本博客內(nèi)容來源于網(wǎng)絡以及其他書籍,結合自己學習的心得進行重編輯,因為看了很多文章不便一一標注引用,如圖片文字等侵權,請告知刪除。
學習筆記目錄----->傳送門 <-----
斑點檢測簡介
定義斑點
首先我們來給斑點下個比一個“點”更準確的文字定義,斑點通常指與周圍有著顏色和灰度區(qū)別的區(qū)域(我們也稱這種區(qū)域叫做奇異區(qū)域)。舉個例子,一輛汽車可以是一個斑點,車身的輪胎也可以是一個斑點,輪胎上的一個螺絲釘也可以是一個斑點。只要這個區(qū)域與周圍的區(qū)域有著顏色或者灰度的區(qū)別,我們就認為它在某個觀察維度下就是一個斑點,取決于對物體分析的顆粒度。
上面我們用比較形象的語言定義了斑點,那么我們怎么用比較數(shù)學的語言去描述它呢?斑點就是被邊緣完整包圍的一塊區(qū)域。這塊區(qū)域的像素值與周圍區(qū)域有這較大的差別。(好像不是很數(shù)學。。。。。。)
斑點檢測有什么用途
斑點檢測可以幫我們分割出特定的感興趣的區(qū)域,查找興趣點,以及在形狀的檢測中,比如圓形檢測,較其他方法有很大輔助。
檢測方法
斑點檢測的思路和上面的描述差不多,就是檢測出圖像中比周圍像素值大或者比周圍區(qū)域像素值小的區(qū)域,一般來說,有兩種基本方法
- 基于求導的微分方法,即使用濾波核與圖像進行卷積,找出與濾波核具有相同特征的區(qū)域,例如LoG 算法,DoH算法,DOG算法
- 基于局部極值的分水嶺算法,例如opencv 中的 SimpleBlobDetector, 分水嶺算法的思路比較簡單, 假設我們將像素值設置為高度,像素值為0就是地面,然后整幅圖像也如一座座山峰,每個山峰的峰頂就是我們的局部極值。局部極值就和我們的斑點的描述是不是很像了,在后面我們詳細描述其操作步驟。
下面我們來描述一下這幾種算法

LoG斑點檢測詳述
LoG全稱是:Laplace of Gaussian(高斯拉普拉斯)是一種形態(tài)學處理的方法,可以用來進行斑點的檢測。
拉普拉斯感覺很熟悉,哦,對了,在之前的邊緣檢測中,我們有學習過拉普拉斯算子,它是一個二階算子,在過0點的地方可認為是邊緣。高斯拉普拉斯和拉普拉斯算子是否有關系呢?我們接下來看。
在想他們是否有關系之前我們先解釋一下,高斯拉普拉斯函數(shù)為什么能檢測斑點。
首先,我們想一個問題:一個圖像與一個二維函數(shù)進行卷積操作,直觀上的出來的解是什么含義?
我們應該知道對圖像的卷積就是使卷積模板與原圖像的像素相對應的位置先做乘法然后把相應位置得到的結果進行求和,最終把求和的結果賦給目標像素。那這實際上就是做了點積操作,點積的操作就是兩個向量相應位置相乘然后求和。點積的物理意義是兩個向量之間的相似度,推廣到二維圖像可以說成卷積模板與圖像中某一塊區(qū)域的相似度。如果卷積結果越大,說明圖像中的某位置和卷積模板類似,如果卷積結果小,說明圖像中某位置和卷積模板的相似度很小。
同理,圖像與高斯拉普拉斯函數(shù)的卷積實際就是求取圖像與高斯拉普拉斯函數(shù)的相似性。當圖像中的斑點尺寸與高斯拉普拉斯函數(shù)的形狀趨近一致時,圖像的拉普拉斯響應達到最大。
我們在邊緣檢測說,二階微分圖中極大值和極小值之間的過 0 點,被認為是邊緣。那么極大值和極小值又是什么呢?其實就是我們認為的斑點。
我們可以看一下高斯拉普拉斯的函數(shù)可視化,是不是就是一個斑點。








高斯拉普拉斯響應值達到最大或最小,也就是我們的斑點。
現(xiàn)在我們基本上解釋了,之前的我們的問題。接下來我們看一下具體的操作。
- 我們計算出在半徑范圍內(nèi)的不同的尺度因子σ(即高斯核方差)的高斯核的拉普拉斯算子
- 在圖片上進行不同尺度因子LoG
- 然后在尺度空間和圖像空間上檢測都是極值的點,確定為斑點的中心。

DOH斑點檢測
DOH 全稱:Determinant of Hessian,基本方法流程和思路與LoG一樣,區(qū)別不同的是使用了Hessian矩陣:

理論上,與LOG相比,DOH對細長結構的斑點有較好的抑制作用。
DOG斑點檢測
DOG實際上對LOG的一種近似,為什么呢?先來看看歸一化之后的LoG算子:


因為k-1是常量不影響函數(shù)極值點,所以檢測歸一化的LoG在尺度空間的極值,即近似于檢測DoG空間的極值(再具體的過程大家可以自己推導一下)。
所以DoG進行斑點檢測流程:
- 首先使用不同尺度的高斯算子對圖像進行平滑
- 其次計算相鄰尺度下平滑圖像的差分圖像(DoG空間)
- 最后在DoG空間尋找極值點
LoG與DoG相比,明顯需要更多的加法運算和乘法運算。雖然DoG需要在每層金字塔多做一次高斯操作(即為了得到S+2張DoG圖需要S+3張高斯模糊圖),但通過減法取代LoG核的計算過程,顯著減少了運算次數(shù),大大節(jié)省了運算時間。
SimpleBlobDetector算法斑點檢測詳述
SimpleBlobDetector 算法并沒有什么過于復雜的數(shù)學計算,正如其名字,簡單的斑點檢測,我們來看看其大概的幾個重要的過程。
- 對一張圖片,設定一個低閾值,設定一個高閾值,在設定一個閾值步進,然后從低閾值到高閾值按照閾值步進取一系列的閾值,即對[minThreshold,maxThreshold)區(qū)間,以thresholdStep為間隔,用每一個閾值對圖像進行二值化,得到一系列圖像;
- 對每張二值圖片,使用查找這些圖像的邊,并計算每一個輪廓的中心;
- 根據(jù)2得到每一個圖片的輪廓的中心點,全部放在一起。定義一個最小距離,在這個距離區(qū)域內(nèi)的特征中心點[由theminDistBetweenBlobs控制多少才算接近]被歸為一個group,對應一個斑點特征,得到特征點集合。
- 從3得到的那些點,估計最后的斑點特征和相應半徑。
- 對特征點進行相應的過濾,例如顏色過濾,面積過濾,圓度等。
opencv 斑點檢測(SimpleBlobDetector)效果[代碼]
#include <opencv2/opencv.hpp>
#include <iostream>
cv::Mat find_blob(cv::Mat &image)
{
cv::Mat view_gray;
if(image.channels()==3){
cv::cvtColor(image,view_gray,cv::COLOR_RGB2GRAY);
}
else{
image.copyTo(view_gray);
}
cv::SimpleBlobDetector::Params params;
params.filterByArea = true;
params.minArea = 50.0f;
params.maxArea = 100000.0f;
params.filterByCircularity = true;
params.minCircularity = (float)0.5;
params.maxCircularity = std::numeric_limits<float>::max();
params.filterByConvexity = true;
params.minConvexity = (float)0.5;
params.maxConvexity = std::numeric_limits<float>::max();
params.minThreshold = 50;
params.maxThreshold = 200;
params.minDistBetweenBlobs = 0.0f;
cv::Ptr<cv::SimpleBlobDetector> blobDetector = cv::SimpleBlobDetector::create(params);
std::vector<cv::KeyPoint> keypoints;
blobDetector->detect(view_gray ,keypoints,cv::Mat());
cv::Mat keyimage;
cv::drawKeypoints(image,keypoints,keyimage,cv::Scalar(0,255,0));
cv::imshow("blob",keyimage);
cv::waitKey(0);
return keyimage;
}
int main(int argc, char *argv[])
{
cv::Mat orignal_image = cv::imread (argv[1]);
cv::Mat image_with_blob = find_blob(orignal_image);
cv::imwrite("blob_image.png",image_with_blob);
return 0;
}


僅展示SimpleBlobDetector,其他方法日后更新,可以看出來檢測的效果還是很好的,基本上蘋果和皮卡丘的眼睛嘴巴都檢測出來了。
總結
- 通過學習完斑點檢測和邊緣檢測,我們法線LOG和DOG都可以用來進行斑點和邊緣檢測,區(qū)別就是一個算極值點一個算過0點。
- 從這片文章的結構也發(fā)現(xiàn),我們大篇幅都在LOG的解釋,而其他幾種算法卻很少。這也反映出我個人的學習進度是我在LOG花了很多的時間,理解了LOG之后在去理解其他的就很簡單了,這是不是一種提高呢。不知道大家是不是這樣,所以有那么多的知識需要去學,還是不用緊張著急的。
重要的事情說三遍:
如果您看到我的文章對您有所幫助,那就點個贊唄 ( * ^ __ ^ * )
如果您看到我的文章對您有所幫助,那就點個贊唄( * ^ __ ^ * )
如果您看到我的文章對您有所幫助,那就點個贊唄( * ^ __ ^ * )
任何人或團體、機構全部轉(zhuǎn)載或者部分轉(zhuǎn)載、摘錄,請保留本博客鏈接或標注來源。博客地址:開飛機的喬巴
作者簡介:開飛機的喬巴(WeChat:zhangzheng-thu),現(xiàn)主要從事機器人抓取視覺系統(tǒng)以及三維重建等3D視覺相關方面,另外對slam以及深度學習技術也頗感興趣,歡迎加我微信或留言交流相關工作。