Opencv特征提取与检测学习01

我的未来我决定 提交于 2020-01-13 14:31:40

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);
}




阈值不同,检测的效果也不同。
在这里插入图片描述
在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!