1. 程式人生 > >【OpenCV3經典程式設計100例】(24)2D特徵:Harris角點檢測cornerHarris()

【OpenCV3經典程式設計100例】(24)2D特徵:Harris角點檢測cornerHarris()

一、2d特徵相關知識

Learn about how to use the feature points detectors, descriptors and matching inside OpenCV.

1 什麼是特徵

在計算機視覺中,通常我們需要找到不同幀(影象)之間的匹配點。 為什麼? 如果我們知道兩個影象如何相互關聯,我們可以使用這兩個影象來提取資訊。當我們說匹配點時,我們一般指的是場景中可以輕易識別的特徵。它具有唯一可識別性。

2 影象特徵的型別

    a)       邊緣

    b)       角點(也稱為感興趣點)

    c)       斑點(也稱為感興趣區域)

3 角點

角點是兩條邊緣的交點

,所以它表示這兩條邊的方向改變的點。 因此,影象的梯度(在兩個方向上)具有很高的變化,這可用來進行角點檢測。

角點沒有明確的數學定義,但人們普遍認為角點是二維影象亮度變化劇烈的點或影象邊緣曲線上曲率極大值的點。

角點是影象很重要的特徵,對影象圖形的理解和分析有很重要的作用。角點在保留影象圖形重要特徵的同時,可以有效地減少資訊的資料量,使其資訊的含量很高,有效地提高了計算的速度,有利於影象的可靠匹配,使得實時處理成為可能。

角點在三維場景重建、運動估計、目標跟蹤、目標識別、影象配準與匹配等計算機視覺領域起著非常重要的作用。

4 角點檢測

角點檢測演算法可歸納為3類:

    a)       基於灰度影象的角點檢測

        1)       基於梯度

        2)       基於模板

        3)       基於模板梯度組合

    b)       基於二值影象的角點檢測

    c)       基於輪廓曲線的角點檢測

其中基於模板的方法主要考慮畫素鄰域點的灰度變化,即影象亮度的變化,將與鄰點亮度對比足夠大的點定義為角點。常見的基於模板的角點檢測演算法有Kitchen-Rosenfeld角點檢測演算法,Harris角點檢測演算法、KLT角點檢測演算法及SUSAN角點檢測演算法。和其他角點檢測演算法相比,SUSAN角點檢測演算法具有演算法簡單、位置準確、抗噪聲能力強等特點。

5 Harris角點檢測演算法

Harris角點檢測演算法是一種基於灰度影象的角點檢測演算法。

二、opencv函式原型和引數解析

void cornerHarris(
	InputArray src,//輸入影象,單通道8位或浮點影象
	OutputArray dst,//輸出影象型別CV_32FC1,大小同原影象
	int blockSize,//鄰域的大小
	int ksize,//Sobel運算元的孔徑大小
	double k,//Harris引數
	int borderType = BORDER_DEFAULT);//邊界模式

三、c++示例程式碼

//包含標頭檔案
#include <opencv2/opencv.hpp>
//名稱空間
using namespace cv;
using namespace std;
//全域性函式宣告部分

//主函式
int main()
{
	//【1】載入影象
	Mat srcImage = imread("G:\\opencvtest\\testImage\\house.jpg");
	//【2】檢查是否載入成功
	if (srcImage.empty())
	{
		printf("讀取圖片錯誤,請確認目錄下是否有imread函式指定圖片存在! \n ");
		return 0;
	}
	//【3】影象灰度化
	Mat grayImage;
	cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
	//【4】角點檢測
	Mat dstImage = Mat::zeros(srcImage.size(), CV_32FC1);
	cornerHarris(grayImage, dstImage, 2, 3, 0.04);
	//【5】歸一化與轉換8UC1
	Mat normImage, scaledImage;
	normalize(dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
	convertScaleAbs(normImage, scaledImage);
	//【6】繪製角點
	for (int i = 0; i < normImage.rows; i++)
	{
		for (int j = 0; j < normImage.cols; j++) 
		{
			if ((int)normImage.at<float>(i, j) > 150)
			{
				circle(srcImage, Point(j, i), 5, Scalar(0, 0, 255), 2);
				circle(scaledImage, Point(j, i), 5, Scalar(0), 2);
			}
		}
	}
	//【7】顯示影象
	imshow("24-彩色原圖", srcImage);
	imshow("24-角點檢測", scaledImage);
	//【8】保持視窗顯示
	waitKey(0);
	return 0;
}

四、執行截圖

1 彩色原圖,檢測到的角點畫圓圈


2 亮度高於閾值的畫素點畫圓圈