本次實驗利用了基於局部極值的分水嶺算法來實現圓斑點的檢測。在OPENCV中提供了simpleBlobDetector特徵檢測器來實現這種斑點檢測算法,正如它的名稱,該算法使用最簡單的方式來檢測斑點類的特徵點,效果較好,設置較爲寬鬆的參數,就能取得較好的效果。
一 算法的步驟
第一步 多次二值化圖像
首先通過一系列連續的閾值把輸入的灰度圖像轉換爲一個二值圖像的集合,閾值範圍爲[T1, T2],步長爲t,則所有閾值爲:
T1,T1+t,T1+2t,T1+3t,……,T2
第二步 確定候選圓點
通過檢測每一幅二值圖像的邊緣的方式提取出每一幅二值圖像的連通區域,我們可以認爲由邊界所圍成的不同的連通區域就是該二值圖像的斑點。其中,並不是所有的二值圖像的連通區域都可以認爲是二值圖像的斑點,我們通過一些限定條件來得到更準確的斑點。這些限定條件包括顏色,面積和形狀,斑點的形狀又可以用圓度,偏心率,或凸度來表示,具體參數和計算方法查看參數部分介紹。
第三步 對圖像圓點進行分類,確定目標圓點
根據所有二值圖像斑點的中心座標對二值圖像斑點進行分類,從而形成灰度圖像的斑點,屬於一類的那些二值圖像斑點最終形成灰度圖像的斑點,具體來說就是,灰度圖像的斑點是由中心座標間的距離小於閾值的那些二值圖像斑點所組成的,即這些二值圖像斑點屬於該灰度圖像斑點;
二 參數部分
filterByColor斑點顏色。
filterByArea斑點面積。連通區域的面積太大和太小都不是斑 。所以我們需要計算連通區域的面積,只有當該面積在我們所設定的最大面積和最小面積之間時,該連通區域才作爲斑點被保留下來。
filterByCircularity 斑點圓度。任意形狀的圓度C定義爲:
其中,S和p分別表示該形狀的面積和周長,當C爲1時,表示該形狀是一個完美的圓形,而當C爲0時,表示該形狀是一個逐漸拉長的多邊形。
filterByInertia斑點慣性率。偏心率是指某一橢圓軌道與理想圓形的偏離程度,長橢圓軌道的偏心率高,而近於圓形的軌道的偏心率低。圓形的偏心率等於0,橢圓的偏心率介於0和1之間,而偏心率等於1表示的是拋物線。直接計算斑點的偏心率較爲複雜,但利用圖像矩的概念計算圖形的慣性率,再由慣性率計算偏心率較爲方便。偏心率E和慣性率I之間的關係爲:
因此圓形的慣性率等於1,慣性率越接近1,圓形的程度越高(在實際操作中並沒有用到)。
filterByConvexity 表示斑點凸度。在平面中,凸形圖指的是圖形的所有部分都在由該圖形切線所圍成的區域的內部。我們可以用凸度來表示斑點凹凸的程度,凸度V的定義爲:
其中,H表示該斑點的凸殼面積
minDistBetweenBlobs斑點距離的最小閾值,中心座標間的距離小於該值就認爲爲同一個斑點。
三 源碼
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/features2d/features2d.hpp"
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
Mat srcImage = imread("pos71_run7_img190.jpg");
Mat srcGrayImage, srcGrayImage1, srcImage1, keyPointImage11, keyPointImage21;
if (srcImage.channels() == 3)
{
cvtColor(srcImage, srcGrayImage, CV_RGB2GRAY);
}
else
{
srcImage.copyTo(srcGrayImage);
}
GaussianBlur(srcGrayImage, srcGrayImage1,Size(11,11),0,0);
vector<KeyPoint>detectKeyPoint;
Mat keyPointImage1, keyPointImage2;
SimpleBlobDetector::Params params;
params.filterByArea = true;
params.minArea = 15;
params.maxArea = 1500;
params.thresholdStep = 10; //二值化的閾值步長,即公式1的t
params.minThreshold = 50 ;
params.maxThreshold = 200;
params.filterByCircularity = true; //斑點圓度
params.minCircularity = 0.8;
params.maxCircularity = 1;
params.filterByConvexity = false; //斑點凸度
params.minConvexity = (float)0.5;
params.maxConvexity = 1;
params.filterByInertia = false; //斑點慣性率
params.minInertiaRatio = (float)0.4;
params.maxInertiaRatio = 1;
params.filterByColor = true;
params.blobColor = 255;//白色
params.minRepeatability = 2;//重複的最小次數,
params.minDistBetweenBlobs = 20; //最小的斑點距離
Ptr<SimpleBlobDetector> sbd = SimpleBlobDetector::create(params);
sbd->detect(srcGrayImage1, detectKeyPoint);
drawKeypoints(srcImage, detectKeyPoint, keyPointImage1, Scalar(0, 255, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
resize(srcImage, srcImage1, Size(srcImage.cols / 4, srcImage.rows / 4), 0, 0, INTER_LINEAR);
imshow("src image", srcImage1);
resize(keyPointImage1, keyPointImage11, Size(keyPointImage1.cols /4, keyPointImage1.rows /4), 0, 0, INTER_LINEAR);
imshow("keyPoint image1", keyPointImage11);
imwrite("spos71_run7_img190.jpg", keyPointImage1);
waitKey(0);
return 0;
}
四 實驗結果
![這裏寫圖片描述]
五 補充說明
保存特徵點,繪製特徵點,在使用中是不透明的,下面做一個簡要介紹。
1.KeyPoint特徵點類
保存特徵點各種信息的KeyPoint類在使用的主要屬性:
class KeyPoint
{
Point2f pt; //特徵點座標
float size; //特徵點鄰域直徑
float angle; //特徵點的方向,值爲0~360,負值表示不使用
float response; //特徵點的響應強度,代表了該點是特徵點的程度,可以用於後續處理中特徵點排序
int octave; //特徵點所在的圖像金字塔的組
int class_id; //用於聚類的id
}
主要包含的特徵點信息有:位置、鄰域直徑、特徵的方向、響應強度、多尺度信息和分類等。特徵點匹配的實現就是通過逐個匹配特徵點的這些信息。
2.drawKeypoints特徵點繪製
opencv提供了一個快速繪製特徵點的函數drawKeypoints,函數原型:
void drawKeypoints( const Mat& image, const vector<KeyPoint>& keypoints, CV_OUT Mat& outImage, const Scalar&color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT );
第一個參數image:原始圖像,可以使三通道或單通道圖像;
第二個參數keypoints:特徵點向量,向量內每一個元素是一個KeyPoint對象,包含了特徵點的各種屬性信息;
第三個參數outImage:特徵點繪製的畫布圖像,可以是原圖像;
第四個參數color:繪製的特徵點的顏色信息,默認繪製的是隨機彩色;
第五個參數flags:特徵點的繪製模式,其實就是設置特徵點的那些信息需要繪製,那些不需要繪製,有以下幾種模式可選:
DEFAULT:只繪製特徵點的座標點,顯示在圖像上就是一個個小圓點,每個小圓點的圓心座標都是特徵點的座標。
DRAW_OVER_OUTIMG:函數不創建輸出的圖像,而是直接在輸出圖像變量空間繪製,要求本身輸出圖像變量就 是一個初始化好了的,size與type都是已經初始化好的變量
NOT_DRAW_SINGLE_POINTS:單點的特徵點不被繪製
DRAW_RICH_KEYPOINTS:繪製特徵點的時候繪製的是一個個帶有方向的圓,這種方法同時顯示圖像的坐,size,和方向,是最能顯示特徵的一種繪製方式。
六 參考
http://blog.csdn.net/zhaocj/article/details/44886475
http://blog.csdn.net/dcrmg/article/details/52553513