Harris 角点检测

1、角点检测相关概念;
2、API;
3、Code;

角点检测

1、角点通常被定义为两条边的交点,角点的局部邻域应该具有两个不同区域的不同方向的边界
2、在图像处理和计算机视觉领域,兴趣点(interest point),也被称作关键点(key point),特征点(feature point ),它被大量用于解决物体识别,图像识别,图像匹配,视觉跟踪,三维重建等一系列的问题;
3、图像的特征类型可分为如下3种:①边缘;②角点;③斑点(blobs);
4、角点(corner):如果某一点在任意方向的一个微小变动都会引起灰度很大的变化,那么我们把它
称为角点;角点位于两条边缘的交点处,代表了两个边缘变化的方向上的点,所以它们是可以精确定位的二维特征,甚至可以达到亚像素精度

5、关于角点的描述:

  1. 一阶导数(灰度的梯度)的局部最大所对应的像素点;
  2. 两条及两条以上边缘的交点;
  3. 图像中梯度值和梯度方向的变化速率都很高的点;
  4. 角点处的一阶导数最大,二阶导数为0,指示了物体边缘不连续的方向;

Harris角点检测算法

1、角点检测算法可以归为3类:

  • 基于灰度图像的角点检测;
  • 基于二值图像的角点检测;
  • 基于轮廓曲线的角点检测;

2、基于灰度图像的角点检测可分为 : 基于梯度、基于模板、基于模板梯度组合三类方法,其中基于模板的方法主要考虑像素邻域点的灰度变化,即亮度变化,将邻点对比度足够大的点定义为角点 ,常见的基于模板的角点检测算法有: 1、Kitchen-Rosenfeld角点检测算法;2、harris角点检测算法;3、KLT角点检测算法;4、SUSAN角点检测算法等;
3、Harris角点检测算法是直接基于灰度图像的角点提取算法,稳定性高,对L型角点检测精度高,但由于采用了高斯滤波,运算速度慢; 运算原理:

Harris API

1、cornerHarris():
k–经验常数,常取0.04-0.06

2、调用demo:

Mat normimg,scaledImg;
Mat dstimg = Mat::zeros(srcimg.size(),CV_32FC1);
//Harris 计算
cornerHarris(srcimg,dstimg,2,3,0.0001,BORDER_DEFAULT);
//归一化
normalize(dstimg,normimg,0,255,NORM_MINMAX,CV_32FC1,Mat());
//转换为正值
convertScaleAbs(normImg, scaledImage);
...(对normImg像素进行操作)

Code

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

using namespace cv;
using namespace std;

const char* input_win = "input image";
const char* output_win = "harris image";

//全局变量声明
Mat srcImage, grayImage,dst;
int thresh_v = 200;
int thresh_max = 255; //最大阈值

void on_CornerHarris(int, void*);

int main(int argc, char** argv)
{
   
	//读入图像
	srcImage = imread("C:\\Users\\hello\\Desktop\\6.jpg");
	if (srcImage.empty())
	{
   
		cout << "could not load the image..." << endl;
		return -1;
	}
	imshow(input_win, srcImage);

	cvtColor(srcImage, grayImage, CV_BGR2GRAY);
	GaussianBlur(grayImage, grayImage, Size(5, 5), 0, 0);
	namedWindow(output_win, WINDOW_AUTOSIZE);

	//创建滚动条
	createTrackbar("Threshold value: ", input_win, &thresh_v, thresh_max, on_CornerHarris);
	//调用一次回调函数,进行初始化
	on_CornerHarris(0, 0);

	waitKey(0);
	return 0;

}


void on_CornerHarris(int, void*)
{
   
	Mat dstImage;
	Mat normImage;
	Mat scaledImage; //线性变换后8位无符号整型图
	//绘图用
	Mat drawImg = srcImage.clone();

	//置0当前需要显示的两幅图,即清除上一次调用此函数时他们的值
	dstImage = Mat::zeros(srcImage.size(), CV_32FC1);
	
	//进行角点检测
	cornerHarris(grayImage, dstImage, 2, 3, 0.04, BORDER_DEFAULT);
	//归一化
	normalize(dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
	//将归一化后的图像线性变换成8位无符号整型
	convertScaleAbs(normImage, scaledImage);

	//draw
	for (int row = 0; row < scaledImage.rows; row++)
	{
   
		for (int col = 0; col < scaledImage.cols; col++)
		{
   
			if ((int)scaledImage.at<uchar>(row, col) > thresh_v)   //将大于阈值的点绘出
			{
   
				circle(drawImg, Point(col, row), 1, Scalar(0, 0, 255), 2, LINE_8, 0);				
			}
		}
	}	
	imshow(output_win, drawImg);
}

效果

Harris角点检测阈值选择很重要,选的不合适,计算时间会特别特别长;