Opencv特征提取与检测学习01:Harris角点检测
1.什么是harris角点检测
harris角点检测是harris于1998年提出的检测图片角点位置的一个理论。
具体理论(我的理解)
如上图,W是我们定义的图像窗口,W(x,y)是窗口一个像素值,后面的一串是像素梯度。
当采取近似计算时,E(u,v) 约等于下面的这个式子。
Ix2,Iy2是图像像素点在x、y方向的二阶梯度,Ix,Iy则是一阶梯度,k是响应系数;我们是可以通过索贝尔算子,拉普拉斯算子等计算以上的梯度值。
矩阵M=
所以,R = +
其中,,
是矩阵M的特征检测值,用来计算角度响应值R,根据我们自己设定的一个阈值t,若R>t,我们就认为在W这个窗口大小的像素中,包含了角点
关于,
在图片的不同区域,得到的值是不同的。
角点处:两个特征值都很大,而且各个方向像素梯度变化明显!
平滑区:两个特征值较小,像素梯度基本不变
边缘地带:两个特征值,一个 远大于另外一个。
2.API介绍
void cornerHarris(InputArray src,
OutputArrays dst ,
int blocksize,
int ksize ,
double k,
int borderType=BORDER_DEFAULT)
参数详解:
1.src是输入图像,一般要求是灰度图,RGB三通道分割后的单通道图也行
2.dst是计算了角度响应值后的输出图片,由于计算得到的像素角度响应值可能是浮点型,所以这里的dst要求是32位浮点型,如CV_32FC1等。
3.blocksize矩阵M的大小
4.ksize 窗口W的大小
5.相应系数k,一般取0.04~0.06
6.是边缘类型,默认为4,即BORDER_DEFAULT
3.代码演示
// Opencv 文件.cpp :
#include "pch.h"
#include<opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
//Harris角点检测
double k = 0.04;
int blocksize = 3;
int ksize = 3;
int thresh=130;//阈值
int max_thresh=255;
void Callback_demo(int, void*);
Mat gray;
Mat src1;
char OUTPUT_WIN[] = "corner_harris_demo";
RNG rng;
int main()
{
src1 = imread("E:\\360downloads\\home.jpg");
if (!src1.data) {//!src.data与src.empty()一样;
printf("failure to load the image1 ");
return -1;
}
namedWindow(OUTPUT_WIN, WINDOW_AUTOSIZE);
imshow("src1", src1);
cvtColor(src1,gray, COLOR_BGR2GRAY);
createTrackbar("thresholds", OUTPUT_WIN, &thresh, max_thresh, Callback_demo);
Callback_demo(0, 0);
waitKey(0);
return 0;
}
void Callback_demo(int, void*) {
//1.是定义一张结果图片,必须是浮点类型
Mat dst = Mat::zeros(src1.size(), CV_32FC1);
cornerHarris(gray, dst, blocksize, ksize, k);
//归一化处理,防止像素值为负数,或过大
normalize(dst, dst, 0, 255, NORM_MINMAX);
convertScaleAbs(dst, dst);
//根据阈值画出对应的角点
Mat resultImage = src1.clone();
for (int row = 0; row < src1.rows; row++) {
//由于计算量较大,获取一行像素的指针比较快;
uchar *correntrow = dst.ptr(row);
for (int col = 0; col < src1.cols; col++) {
//先获得像素角点响应;
int Value = (int)*correntrow;
if (thresh < Value) {
//满足,就画出这个点,这里我用随机数产生各种颜色点
circle(resultImage, Point(row, col),2,Scalar(rng.uniform(0,255), rng.uniform(0, 255), rng.uniform(0, 255)), 2, 8);
}
correntrow++;//指针位置移动
}
}
imshow(OUTPUT_WIN, resultImage);
}
阈值不同,检测的效果也不同。
来源:CSDN
作者:雨夜※繁华
链接:https://blog.csdn.net/qq_44861675/article/details/103955480