Harris Corner

轉載:http://blog.csdn.net/crzy_sparrow/article/details/7391511

文章目錄:
一、Harris角點檢測基本理論
二、opencv代碼實現
三、改進的Harris角點檢測
四、FAST角點檢測
五、參考文獻
六、附錄(資料和源碼)

一、Harris角點檢測基本理論(要講清楚東西太多,附錄提供文檔詳細說明)
1.1 簡略表達:

角點:最直觀的印象就是在水平、豎直兩個方向上變化均較大的點,即Ix、Iy都較大
邊緣:僅在水平、或者僅在豎直方向有較大的變化量,即Ix和Iy只有其一較大
平坦地區:在水平、豎直方向的變化量均較小,即Ix、Iy都較小

角點響應
R=det(M)-k*(trace(M)^2) (附錄資料給出k=0.04~0.06,opencv指出是0.05-0.5,浮動較大)
det(M)=λ1*λ2 trace(M)=λ1+λ2
R取決於M的特徵值,對於角點|R|很大,平坦的區域|R|很小,邊緣的R爲負值。

1.2 詳細描述:見附錄裏的ppt
1.3 算法步驟

其中,局部極大值可用先膨脹後與原圖比較的方法求得,具體見二中源碼。

二、opencv代碼實現
harris類

[cpp] view plain copy

ifndef HARRIS_H

define HARRIS_H

include “opencv2/opencv.hpp”

class harris
{
private:
cv::Mat cornerStrength; //opencv harris函數檢測結果,也就是每個像素的角點響應函數值
cv::Mat cornerTh; //cornerStrength閾值化的結果
cv::Mat localMax; //局部最大值結果
int neighbourhood; //鄰域窗口大小
int aperture;//sobel邊緣檢測窗口大小(sobel獲取各像素點x,y方向的灰度導數)
double k;
double maxStrength;//角點響應函數最大值
double threshold;//閾值除去響應小的值
int nonMaxSize;//這裏採用默認的3,就是最大值抑制的鄰域窗口大小
cv::Mat kernel;//最大值抑制的核,這裏也就是膨脹用到的核
public:
harris():neighbourhood(3),aperture(3),k(0.01),maxStrength(0.0),threshold(0.01),nonMaxSize(3){

};  

void setLocalMaxWindowsize(int nonMaxSize){  
    this->nonMaxSize = nonMaxSize;  
};  

//計算角點響應函數以及非最大值抑制  
void detect(const cv::Mat &image){  
        //opencv自帶的角點響應函數計算函數  
        cv::cornerHarris (image,cornerStrength,neighbourhood,aperture,k);  
        double minStrength;  
        //計算最大最小響應值  
        cv::minMaxLoc (cornerStrength,&minStrength,&maxStrength);  

        cv::Mat dilated;  
        //默認3*3核膨脹,膨脹之後,除了局部最大值點和原來相同,其它非局部最大值點被  
        //3*3鄰域內的最大值點取代  
        cv::dilate (cornerStrength,dilated,cv::Mat());  
        //與原圖相比,只剩下和原圖值相同的點,這些點都是局部最大值點,保存到localMax  
        cv::compare(cornerStrength,dilated,localMax,cv::CMP_EQ);  
}  

//獲取角點圖  
cv::Mat getCornerMap(double qualityLevel) {  
        cv::Mat cornerMap;  
        // 根據角點響應最大值計算閾值  
        threshold= qualityLevel*maxStrength;  
        cv::threshold(cornerStrength,cornerTh,  
        threshold,255,cv::THRESH_BINARY);  
        // 轉爲8-bit圖  
        cornerTh.convertTo(cornerMap,CV_8U);  
        // 和局部最大值圖與,剩下角點局部最大值圖,即:完成非最大值抑制  
        cv::bitwise_and(cornerMap,localMax,cornerMap);  
        return cornerMap;  
}  

void getCorners(std::vector<cv::Point> &points,  
        double qualityLevel) {  
        //獲取角點圖  
        cv::Mat cornerMap= getCornerMap(qualityLevel);  
        // 獲取角點  
        getCorners(points, cornerMap);  
}  

// 遍歷全圖,獲得角點  
void getCorners(std::vector<cv::Point> &points,  
const cv::Mat& cornerMap) {  

        for( int y = 0; y < cornerMap.rows; y++ ) {  
                const uchar* rowPtr = cornerMap.ptr<uchar>(y);  
                for( int x = 0; x < cornerMap.cols; x++ ) {  
                // 非零點就是角點  
                      if (rowPtr[x]) {  
                            points.push_back(cv::Point(x,y));  
                      }  
                 }  
            }  
      }  

//用圈圈標記角點  
void drawOnImage(cv::Mat &image,  
const std::vector<cv::Point> &points,  
        cv::Scalar color= cv::Scalar(255,255,255),  
        int radius=3, int thickness=2) {  
                std::vector<cv::Point>::const_iterator it=points.begin();  
                while (it!=points.end()) {  
                // 角點處畫圈  
                cv::circle(image,*it,radius,color,thickness);  
                ++it;  
        }  
}  

};

endif // HARRIS_H

相關測試代碼:

[cpp] view plain copy

cv::Mat image, image1 = cv::imread (“test.jpg”);
//灰度變換
cv::cvtColor (image1,image,CV_BGR2GRAY);

// 經典的harris角點方法
harris Harris;
// 計算角點
Harris.detect(image);
//獲得角點
std::vector pts;
Harris.getCorners(pts,0.01);
// 標記角點
Harris.drawOnImage(image,pts);

cv::namedWindow (“harris”);
cv::imshow (“harris”,image);
cv::waitKey (0);
return 0;
相關測試結果:

三、改進的Harris角點檢測
從經典的Harris角點檢測方法不難看出,該算法的穩定性和k有關,而k是個經驗值,不好把握,浮動也有可能較大。鑑於此,改進的Harris方法()直接計算出兩個特徵值,通過比較兩個特徵值直接分類,這樣就不用計算Harris響應函數了。
另一方面,我們不再用非極大值抑制了,而選取容忍距離:容忍距離內只有一個特徵點。
該算法首先選取一個具有最大 最小特徵值的點(即:max(min(e1,e2)),e1,e2是harris矩陣的特徵值)作爲角點,然後依次按照最大最小特徵值順序尋找餘下的角點,當然和前一角點距離在容忍距離內的新角點唄忽略。
opencv測試該算法代碼如下:

[cpp] view plain copy

cv::Mat  image, image1 = cv::imread ("test.jpg");  
//灰度變換  
cv::cvtColor (image1,image,CV_BGR2GRAY);  
// 改進的harris角點檢測方法  
std::vector<cv::Point> corners;  
cv::goodFeaturesToTrack(image,corners,  
200,  
//角點最大數目  
0.01,  
// 質量等級,這裏是0.01*max(min(e1,e2)),e1,e2是harris矩陣的特徵值  
10);  
// 兩個角點之間的距離容忍度  
harris().drawOnImage(image,corners);//標記角點  
測試結果如下:

四、FAST角點檢測
算法原理比較簡單,但實時性很強。
該算法的角點定義爲:若某像素點圓形鄰域圓周上有3/4的點和該像素點不同(編程時不超過某閾值th),則認爲該點就是候選角點。opencv更極端,選用半徑爲3的圓周上(上下左右)四個點,若超過三個點和該像素點不同,則該點爲候選角點。
和Harris算法類似,該算法需要非極大值抑制。
opencv代碼:

[cpp] view plain copy

cv::Mat image, image1 = cv::imread (“test.jpg”);
cv::cvtColor (image1,image,CV_BGR2GRAY);
//快速角點檢測
std::vector keypoints;
cv::FastFeatureDetector fast(40,true);
fast .detect (image,keypoints);
cv::drawKeypoints (image,keypoints,image,cv::Scalar::all(255),cv::DrawMatchesFlags::DRAW_OVER_OUTIMG);

測試結果如下:

五、參考文獻
【1】The classical article describing the Harris operator: C. Harris and M.J. Stephens, A combined corner and edge detector, by Alvey Vision Conference, pp. 147–152, 1988.
【2】The article by J. Shi and C. Tomasi, Good features to track, Int. Conference on Computer Vision and Pattern Recognition, pp. 593-600, 1994 which introduced these features.
【3】The article by K. Mikolajczyk and C. Schmid, Scale and Affine invariant interest point detectors, International Journal of Computer Vision, vol 60, no 1, pp. 63-86, 2004, which proposes a multi-scale and affine-invariant Harris operator.
【4】The article by E. Rosten and T. Drummond, Machine learning for high-speed corner detection, in In European Conference on Computer Vision, pp. 430-443, 2006 that describes the FAST feature algorithm in detail

六、附錄
資源鏈接,源碼和相關文檔。
http://download.csdn.net/detail/crzy_sparrow/4170311

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章