天天看點

圖像處理(九):特征點檢測之Harris角點檢測

    圖像可以看做是一個WxHxC(width x height x channels)的矩陣來表示。同一個物體,在不同觀測角度、光照強度時,圖像上的像素強度會發生改變,是以考慮用特征點來對圖像進行描述。特征點指的就是能夠顯著描述圖像特征的點。

    Harris角點檢測原理可以參考部落格:https://blog.csdn.net/lwzkiller/article/details/54633670

    角點即像素無論在梯度方向和幅值上都存在較大變化的點,這些點為輪廓的交點,對于視角、光照強度等因素都具備較強魯棒性。檢測角點的基本思想為:驗證像素點灰階值是否在任意方向上都存在較大變化。

    1、灰階值變化計算:

圖像處理(九):特征點檢測之Harris角點檢測

    使用一階泰勒展開有:

圖像處理(九):特征點檢測之Harris角點檢測

    是以,灰階值的變化量為:

圖像處理(九):特征點檢測之Harris角點檢測

    2、具體計算方式:

    通常像素點梯度變化,一般考慮的是利用自身像素與所在位置的領域内像素點之間像素值的偏差來計算。是以,計算偏差時,通常會設定一個以目前像素點坐标為中心的計算區域W,即統計像素在區域W中的變化,是以計算公式就變成:

圖像處理(九):特征點檢測之Harris角點檢測

    寫成矩陣形式有:

圖像處理(九):特征點檢測之Harris角點檢測

    變化大小取決于矩陣M:

圖像處理(九):特征點檢測之Harris角點檢測

    矩陣M的特征值

圖像處理(九):特征點檢測之Harris角點檢測

表示矩陣M在對應特征向量方向V上變化大小,

圖像處理(九):特征點檢測之Harris角點檢測

越大表示變化越大。是以,通過計算矩陣M的兩個特征值,如果兩個特征值都比較大,就表示該點為角點;如果一個特征值大,一個特征小,就表示為邊緣;如果都比較小就表示為平坦區域。

    特征值的計算方式為:

圖像處理(九):特征點檢測之Harris角點檢測

     定義一個衡量角點強度函數:

圖像處理(九):特征點檢測之Harris角點檢測

    為什麼R是這個形式?這個在作者論文中有一個圖,至于怎麼得到的就不得而知了,  k為系數,一般取值為0.04~0.06,用于調節函數形狀。

3、代碼

這個代碼不是原創,是在github上面發現的一段代碼,表示代碼寫的非常簡潔明了,代碼連結位址為:https://github.com/ronnyyoung/ImageFeatures/blob/master/source/harris.cpp

#include "imgFeat.h"

void feat::detectHarrisCorners(const Mat& imgSrc, Mat& imgDst, double alpha)
{
	Mat gray;
	if (imgSrc.channels() == 3)
	{
		cvtColor(imgSrc, gray, CV_BGR2GRAY);
	}
	else
	{
		gray = imgSrc.clone();
	}
	gray.convertTo(gray, CV_64F);

	Mat xKernel = (Mat_<double>(1,3) << -1, 0, 1);
	Mat yKernel = xKernel.t();

	Mat Ix,Iy;
	filter2D(gray, Ix, CV_64F, xKernel);
	filter2D(gray, Iy, CV_64F, yKernel);

	Mat Ix2,Iy2,Ixy;
	Ix2 = Ix.mul(Ix);
	Iy2 = Iy.mul(Iy);
	Ixy = Ix.mul(Iy);

	Mat gaussKernel = getGaussianKernel(7, 1);
	filter2D(Ix2, Ix2, CV_64F, gaussKernel);
	filter2D(Iy2, Iy2, CV_64F, gaussKernel);
	filter2D(Ixy, Ixy, CV_64F, gaussKernel);
	

	Mat cornerStrength(gray.size(), gray.type());
	for (int i = 0; i < gray.rows; i++)
	{
		for (int j = 0; j < gray.cols; j++)
		{
			double det_m = Ix2.at<double>(i,j) * Iy2.at<double>(i,j) - Ixy.at<double>(i,j) * Ixy.at<double>(i,j);
			double trace_m = Ix2.at<double>(i,j) + Iy2.at<double>(i,j);
			cornerStrength.at<double>(i,j) = det_m - alpha * trace_m *trace_m;
		}
	}
	// threshold
	double maxStrength;
	minMaxLoc(cornerStrength, NULL, &maxStrength, NULL, NULL);
	Mat dilated;
	Mat localMax;
	dilate(cornerStrength, dilated, Mat());
	compare(cornerStrength, dilated, localMax, CMP_EQ);
	

	Mat cornerMap;
	double qualityLevel = 0.01;
	double thresh = qualityLevel * maxStrength;
	cornerMap = cornerStrength > thresh;
	bitwise_and(cornerMap, localMax, cornerMap);
	
	imgDst = cornerMap.clone();
	
}

           

效果如下:

圖像處理(九):特征點檢測之Harris角點檢測