在计算机视觉中,角点是图像比较重要的特征,对图像图形的理解和分析有很重要的作用,在保留图像图形重要特征的同时,可以代替整幅图像的处理,有效地减少信息的数据量,使其信息的含量很高,有效地提高了计算的速度,有利于图像的可靠匹配。所以角点检测也是计算机视觉中比较重要的一块,在目标识别,图像匹配,视觉跟踪,3D重建,全景图像拼接等领域都有应用。角点又称特征点或兴趣点,定义:窗口向任意方向的移动都将导致图像灰度的明显变化。具体有如下几种描述:
角点检测方法有很多种,主要分三大类:基于灰度图像的角点检测、基于二值图像的角点检测、基于轮廓曲线的角点检测。基于灰度图像的角点检测又可分为基于梯度、基于模板和基于模板梯度组合3类方法,其中基于模板的方法主要考虑像素领域点的灰度变化,即图像亮度的变化,将与邻点亮度对比足够大的点定义为角点。Harris角点检测算法就是常见的基于模板的角点检测算法的一种。
Harris 角点最初由C.Harris和J.Stephens 于1988年在A combined corner and edge detector 一文中提出,该文实际上是对Moravec 算法思想的改进。Harris角点最直观的解释是在两个相互垂直的方向,都有较大变化的点,代表图像梯度的变化。
将图像窗口平移[u,v],产生灰度变化 E[u,v]:
其中w(x,y)是窗口的位置,I(x,y)是密度,I(x+u,y+v)是窗口移动后的密度。
泰勒展开式:
代入E(u,v) 中,相减后平方展开,表示成矩阵的形式:
在这里令
所以有:
对于每一个窗口,计算一个值
即矩阵的值和矩阵的迹平方的 k 倍相减的差值。k 的经验取值为0.04-0.06。
两特征值的大小和所检测到的范围的关系如下所示:
【代码】
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> #include <stdlib.h> using namespace cv; using namespace std; Mat src, src_gray; int thresh = 100; int max_thresh = 255; char* source_window = "Source image"; char* corners_window = "Corners detected"; void cornerHarris_demo( int, void* ) { Mat dst, dst_norm, dst_norm_scaled; dst = Mat::zeros( src.size(), CV_32FC1 ); /// Detector parameters int blockSize = 2; int apertureSize = 3; double k = 0.04; /// Detecting corners cornerHarris( src_gray, dst, blockSize, apertureSize, k, BORDER_DEFAULT ); /// Normalizing normalize( dst, dst_norm, 0, 255, NORM_MINMAX, CV_32FC1, Mat() ); convertScaleAbs( dst_norm, dst_norm_scaled ); /// Drawing a circle around corners for( int j = 0; j < dst_norm.rows ; j++ ) { for( int i = 0; i < dst_norm.cols; i++ ) { if( (int) dst_norm.at<float>(j,i) > thresh ) { circle( dst_norm_scaled, Point( i, j ), 5, Scalar(0), 2, 8, 0 ); } } } namedWindow( corners_window, CV_WINDOW_AUTOSIZE ); imshow( corners_window, dst_norm_scaled ); waitKey(30); } int main( int argc, char** argv ) { src = imread( "car.png", 1 ); cvtColor( src, src_gray, CV_BGR2GRAY ); namedWindow( source_window, CV_WINDOW_AUTOSIZE ); createTrackbar( "Threshold: ", source_window, &thresh, max_thresh, cornerHarris_demo ); imshow( source_window, src ); waitKey(30); cornerHarris_demo( 0, 0 ); waitKey(0); return(0); }
运行结果图: