//Harris角点检测的基本思想:从图像局部的小窗口观察图像特征,在各个方向移动都会导致图像灰度的明显变化,也就是说图像的梯度在各个方向有很大变化。平坦区和边缘灰度基本不变。
//如何判定该区域是否存在角点,需要一个函数
//w(x,y)是搜索窗口,高斯滤波器
//u,v:窗口移动范围
// [I(x + u, y + v) " I(x, y)]2:搜索范围
//1.将I(x + u, y + v)泰勒展开–》
//Ix是该点像素值在x方向的梯度
//M(x,y)实对称阵,可以将其对角化写成特征向量矩阵,与特征值矩阵之积。
//w(x,y)高斯滤波器与像素梯度的卷积可以写成先对高斯滤波器做x/y方向的梯度,再与像素做卷积,这样效率更高
//上述讲到M(x,y)是对称阵,可以对角化,解出特征值和特征向量。特征向量r1,r2可以确定该区域特征点的角度与分布及范围,可以构成一个椭圆的形式
//判别角点:
1.当r1,r2很小时,即为平坦区,r2>>r1为边缘,,r1,r2都很大是角点。
2.公式
//alpha是经验值0.4-0.6
//|θ|很小为平坦区
θ<0为边缘
θ>>0角点
//harris角点有旋转和平移不变性,但w(x,y)高斯滤波不具有尺度不变性
//尺度不变性是SIFT角点,下面我会讲到
//harris角点检测步骤
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
void Harris_Demo(int, void*);
int thresold =254;
Mat gray_src,src,dst;
int main()
{
int max_count = 500;
//1998
src = imread("C:\\Users\\Administrator\\Pictures\\Saved Pictures\\timg6ZAGKYHR.jpg");
if (src.empty())
{
printf("ould not find image \n");
return -1;
}
imshow("input", src);
cvtColor(src, gray_src, COLOR_BGR2GRAY);
//BORDER_DEFAULT边缘像素处理
namedWindow("output",WINDOW_AUTOSIZE);
createTrackbar("Threshold", "output", &thresold, max_count, Harris_Demo);
//imshow("output", gray_src);
Harris_Demo(0, 0);
waitKey(0);
return 1;
}
void Harris_Demo(int, void*)
{
Mat dst,norm_dst,normScaledst;
//dst保存存放harris检测的运行结果,需要进行归一化,dst得到的是sita的值,sita>>0为角点,sita很小为平坦区,sita<0为边缘
dst = Mat::zeros(gray_src.size(), CV_32FC1);
int blockSize = 3;//窗口大小
int ksize = 3;//Soble算子边缘检测,为进行边缘检测时的模板大小为ksize*ksize
double k = 0.04;//alpha系数0.04-0.06
//BORDER_DEFAULT边缘像素处理
cornerHarris(gray_src, dst, blockSize, ksize, k,BORDER_DEFAULT);
//归一化,将像素值约束到0--255
normalize(dst, norm_dst, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
convertScaleAbs(norm_dst, normScaledst);
Mat resultImg = src.clone();
for (int i = 0; i < resultImg.rows; i++)
{
//拿出整个一行的数据
uchar* currentRow = dst.ptr(i);
for (int j = 0; j < resultImg.cols; j++)
{
int value = (int)*currentRow;
if (value > thresold)
{
circle(resultImg, Point(j, i), 2, Scalar(0, 0, 255), 2, 8, 0);
}
//行指针+1,对一整行的像素值取值采样
currentRow ++;
}
}
imshow("output", resultImg);
}
//本文代码使用的API
createTrackbar(滑块名称,滑块显示窗口,初始值,最大值,回调函数);
//回调函数原型void Harris_Demo(int, void*);注意系数
//cornerHarris(单通道输入值, 角点值输出, 滤波器的大小, Soble角点检测, M(x,y)alpha系数,BORDER_DEFAULT边缘检测默认值);
//在回调函数中,遍历原图像像素值,用ptr()访问每行像素的角点值,设置阈值t,当像素E(x,y)函数输出值大于阈值t,则用circle(图像,绘图坐标Point(col,row),半径,颜色,粗细,线型,默认值0),圈出作为角点