Harris角點檢測的實現(cv::Mat && c++)
阿新 • • 發佈:2019-02-02
原文連結或Google “A COMBINED CORNER AND EDGE DETECTOR”可以找到Harris角點檢測的論文。
簡單的概括一下,Harris角點檢測的原理為,通過計算論文中的R來判斷某一個畫素點是否為角點,通常情況下,當R為正數且較大時,該點為角點。若R為負數且絕對值較大時,該點為邊緣點。若R的絕對值較小,則該點通常位於光滑區域。
計算R需要兩個基本量,一個為dx,另一個為dy,通常情況下,我們會計算畫素點所在的視窗內(我的程式碼中採用了2*2的區域)所有畫素點的梯度,然後進行第二步的計算。在程式碼中,x方向的梯度為dx[4],y方向的梯度為dy[4]。
得到梯度後,我們需要計算論文中的A,B,C
至此我們將得到論文中的
下面我們將計算R,根據線性代數的基本公式,我們可以得到
,其中,k的取值通常為0.04~0.06(k越小,Harris運算元越敏感)。得到R之後,我們便可以找到角點。然後通過非極大值抑制(Non-maximal Suppression)的方法,避免角點過於密集的出現。
程式碼為Harris角點響應值計算
double Harris(const cv::Mat& image, int x, int y) { int A, B, C; int dx[4]; // 0 1 // 2 3 dx[0] = (int)image.at<uchar>(y, x + 1) - image.at<uchar>(y, x - 1); dx[1] = (int)image.at<uchar>(y, x + 2) - image.at<uchar>(y, x); dx[2] = (int)image.at<uchar>(y + 1, x + 1) - image.at<uchar>(y + 1, x - 1); dx[3] = (int)image.at<uchar>(y + 1, x + 2) - image.at<uchar>(y + 1, x); int dy[4]; dy[0] = (int)image.at<uchar>(y + 1, x) - image.at<uchar>(y - 1, x); dy[1] = (int)image.at<uchar>(y + 1, x + 1) - image.at<uchar>(y - 1, x + 1); dy[2] = (int)image.at<uchar>(y + 2, x) - image.at<uchar>(y, x); dy[3] = (int)image.at<uchar>(y + 2, x + 1) - image.at<uchar>(y, x + 1); A = dx[0] * dx[0] + dx[1] * dx[1] + dx[2] * dx[2] + dx[3] * dx[3]; B = dy[0] * dy[0] + dy[1] * dy[1] + dy[2] * dy[2] + dy[3] * dy[3]; C = dx[0] * dy[0] + dx[1] * dy[1] + dx[2] * dy[2] + dx[3] * dy[3]; return A * B - C * C -0.04 * (A + B) * (A + B); }
非極大值抑制的可以採用只保留某一個視窗內Harris響應值最大的點進行處理,在此不貼程式碼了。
注:萬不可偷懶只求一個點的dx和dy,否則得到的值恆為負數,因為=0