圖像處理之角點檢測與亞像素角點定位

圖像處理之角點檢測與亞像素角點定位

 

角點是圖像中亮度變化最強地方反映了圖像的本質特徵,提取圖像中的角點可以有效提高圖像處理速度與精準度。所以對於整張圖像來說特別重要,角點檢測與提取的越準確圖像處理與分析結果就越接近真實。同時角點檢測對真實環境下的對象識別、對象匹配都起到決定性作用。Harris角點檢測是圖像處理中角點提取的經典算法之一,應用範圍廣發,在經典的SIFT特徵提取算法中Harris角點檢測起到關鍵作用。通常對角點檢測算法都有如下要求:


1. 基於灰度圖像、能夠自動調整運行穩定,檢測出角點的數目。

2. 對噪聲不敏感、有一定的噪聲抑制,有較強的角點角點檢測能力。

3. 準確性夠高,能夠正確發現角點位置

4. 算法儘可能的快與運行時間短


Harris角點檢測基本上滿足了上述四點要求,所以被廣發應用,除了Harris角點檢測,另外一種常見的角點檢測算法-Shi-Tomasi角點檢測也得到了廣發應用,OpenCV中對這兩種算法均有實現API可以調用。關於Harris角點檢測原理可以看我之前寫的博文:

http://blog.csdn.net/jia20003/article/details/16908661

關於Shi-Tomasi角點檢測,與Harris角點檢測唯一不同就是在計算角點響應值R上面。


然後根據輸入的閾值T大於該閾值的R對應像素點即爲圖像中角點位置座標。此刻座標往往都是整數出現,而在真實的世界中座標多數時候都不是整數,假設我們計算出來的角點位置P(34, 189)而實際上準確角點位置是P(34.278, 189.706)這樣帶小數的位置,而這樣的準確位置尋找過程就叫做子像素定位或者亞像素定位。這一步在SURF與SIFT算法中都有應用而且非常重要。常見的亞像素級別精準定位方法有三類:

1. 基於插值方法

2. 基於幾何矩尋找方法

3. 擬合方法 - 比較常用

擬合方法中根據使用的公式不同可以分爲高斯曲面擬合與多項式擬合等等。以高斯擬合爲例


這樣就求出了亞像素的位置。使用亞像素位置進行計算得到結果將更加準確,對圖像特徵提取、匹配結果效果顯著。OpenCV中已經對角點檢測實現了亞像素級別的API可以調用。

代碼演示

OpenCV亞像素角點檢測例子:

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

Mat src, gray_src;
int max_corners = 10;
int max_trackbar = 30;
const char* output_title = "subpxiel-result";
void GoodFeature2Track_Demo(int, void*);
int main(int argc, char** argv) {
	src = imread("D:/vcprojects/images/home.jpg");
	if (src.empty()) {
		printf("could not load image...\n");
		return -1;
	}
	cvtColor(src, gray_src, COLOR_BGR2GRAY);
	namedWindow("input", CV_WINDOW_AUTOSIZE);
	namedWindow(output_title, CV_WINDOW_AUTOSIZE);
	imshow("input", src);

	createTrackbar("Corners:", output_title, &max_corners, max_trackbar, GoodFeature2Track_Demo);
	GoodFeature2Track_Demo(0, 0);

	waitKey(0);
	return 0;
}

void GoodFeature2Track_Demo(int, void*) {
	if (max_corners < 1) {
		max_corners = 1;
	}
	vector<Point2f> corners;
	double qualityLevel = 0.01;
	double minDistance = 10;
	int blockSize = 3;
	double k = 0.04;
	goodFeaturesToTrack(gray_src, corners, max_corners, qualityLevel, minDistance, Mat(), blockSize, false, k);
	cout << "number of corners : " << corners.size() << endl;
	Mat copy = src.clone();
	for (size_t t = 0; t < corners.size(); t++) {
		circle(copy, corners[t], 4, Scalar(255, 0, 0), 2, 8, 0);
	}
	imshow(output_title, copy);

	// locate corner point on sub pixel level
	Size winSize = Size(5, 5);
	Size zerozone = Size(-1, -1);
	TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001);
	cornerSubPix(gray_src, corners, winSize, zerozone, criteria);
	for (size_t t = 0; t < corners.size(); t++) {
		cout << (t+1) << ".point[x, y]=" << corners[t].x << "," << corners[t].y << endl;
	}

	return;
}

原圖如下:


運行結果:


轉載請註明來自【jia20003】的博客!


發佈了269 篇原創文章 · 獲贊 1318 · 訪問量 365萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章