計算機視覺中,我們經常要匹配兩幅圖像。匹配的的方式就是通過比較兩幅圖像中的公共特征,比如邊,角,以及圖像塊(blob)等,來對兩幅圖像進行匹配。
相對於邊,角更適合描述圖像特征,比如下面的圖像中,大概有6種特征,我們用A、B、C、D、E、F來描述,其中A, B是平的區域,在圖像中很難精確定位,C,D是邊,比A,B好些,但是圖像中的邊也很多,定位到某個邊也比較困難,相比來說E,F的角更適合描述當前的圖像的特征,也更好檢測,因為你不論怎么移動圖像,這些角的特征都和圖像其它部分不同。所以在計算機視覺中,我們通常用角來描述圖像特征。
E,F中的角我們通常稱作角點(corner points),他們具有以下特征:
–局部窗口沿各方向移動,均產生明顯變化的點
–圖像局部曲率突變的點
在這篇教程中,我們來學習如何在圖像中檢測harrs特征角,harris特征角最早在paper A Combined Corner and Edge Detector中被Chris Harris & Mike Stephens提出。
Harris角點檢測的基本思想:從圖像局部的小窗口觀察圖像特征,在各個方向移動都會導致圖像灰度的明顯變化,也就是說圖像的梯度在各個方向有很大變化。
下面我們看看harris角的計算方法:
對於灰度圖像 ,我們在窗口
內,用x方向的偏移u和y方向的偏移v,掃過所有像素,得到一個圖像灰度值的變化和。
由於我們要在一個窗口內查找harris特征角,所以我們必須找到變化最大的窗口,這個窗口內肯定存在特征角,所以我們定義下面的方程,並用泰勒級數展開式子:
-
表示成矩陣乘法形式:
-
假設
-
則有:
-
對每一個窗口計算得到一個分數R,根據R的大小來判定窗口內是否存在harris特征角。分數R根據下面公式計算得到:
這里:(
是矩陣M的2個特征值,k是一個指定值,這是一個經驗參數,需要實驗確定它的合適大小,通常它的值在0.05和0.5之間)。
在opencv中,我們可以通過函數cv::cornerHarris 計算特征角,
C++: void cornerHarris(InputArray src, OutputArray dst, int blockSize, int ksize, double k, intborderType=BORDER_DEFAULT )
Parameters:
- src – 單通道8位或者浮點圖像。
- dst – 存儲 Harris 角的結果圖像,它的格式為:CV_32FC1,圖像大小和源圖像一致。
- blockSize – 就是掃描時候窗口的大小。
- ksize – Sobel() 算子使用的值。
- k – 上面介紹的計算R時候的k參數值。
- borderType –像素插值方法。
下面的代碼顯示一副圖像的harris角檢測結果:
// 讀入輸入圖像
cv::Mat image= cv::imread("../church01.jpg",0);
if (!image.data)
return 0;
// 顯示圖像
cv::namedWindow("Original Image");
cv::imshow("Original Image",image);
// 檢測 Harris Corners
cv::Mat cornerStrength;
cv::cornerHarris(image,cornerStrength,
3, // neighborhood size
3, // aperture size
0.01); // Harris parameter
//二值化harris角的檢測結果
cv::Mat harrisCorners;
double threshold= 0.0001;
cv::threshold(cornerStrength,harrisCorners,
threshold,255,cv::THRESH_BINARY_INV);
// 顯示結果
cv::namedWindow("Harris Corner Map");
cv::imshow("Harris Corner Map",harrisCorners);
下面是程序的運行結果:
程序代碼:參考工程文件FirstOpenCV48