opencv学习笔记(三十二)Harris角点检测

1.角点检测的意义

参考这篇博文:https://blog.csdn.net/pbymw8iwm/article/details/82624898

基于特征的图像配准方法是图像配准中最常见的方法之一。一类重要的点特征:角点(corner points),其定义主要有以下:

  1.  局部窗口沿各方向移动,灰度均产生明显变化的点      
  2. 图像局部曲率突变的点
  3. 典型的角点检测算法:Harris角点检测、CSS角点检测
  4. Harris角点检测基本思想
    从图像局部的小窗口观察图像特征,角点定义:窗口向任意方向的移动都导致图像灰度的明显变化

2.原理

(1)将图像窗口平移[u,v]产生灰度变化E(u,v),

(2)判断特征点是否为角点的依据:R只与M值有关,R为大数值正数时特征点为角点,R为大数值负数时为边缘,R为小数值时为平坦区:

3.相关API

void cornerHarris(InputArray src,OutputArray dst,int blockSize,int ksize,double k,int borderType=BORDER_DEFAULT)

src:输入图像

dst:输出图像

blocksize:计算2个最大最小特征值时候的矩阵的大小

ksize:移动监测时候的窗口大小

k:参数(取值0.04到0.06)

border Type:边界处理方式

返回的是像素值,所以要通过阈值进行筛选。也可以直接通过二值化,筛选出需要的点。

4.实现步骤

(1)转灰度图像,或者分割为单通道图像

(2)进行检测

(3)归一化处理

(4)负像素取绝对值

5.代码实现

#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;
Mat src, gray_src;
int thresh = 130;
int max_count = 255;
const char* output_title = "HarrisCornerDetection Result";
void Harris_Demo(int, void*);
int main(int argc, char** argv) {

	src = imread("D:/demo.jpg");
	if (src.empty()) {
		printf("could not load image...\n");
		return -1;
	}
	namedWindow("input image", CV_WINDOW_AUTOSIZE);
	imshow("input image", src);
	namedWindow(output_title, CV_WINDOW_AUTOSIZE);

	cvtColor(src, gray_src, COLOR_BGR2GRAY);//输入转为灰度图像,或者转成3通道的分割图
	createTrackbar("Threshold:", output_title, &thresh, max_count, Harris_Demo);
	Harris_Demo(0, 0);
	waitKey(0);
	return 0;
}

//滑块call的函数
void Harris_Demo(int, void*) {
	Mat dst, norm_dst, normScaleDst;
	dst = Mat::zeros(gray_src.size(), CV_32FC1);

	int blockSize = 2;
	int ksize = 3;
	double k = 0.04;
	cornerHarris(gray_src, dst, blockSize, ksize, k, BORDER_DEFAULT);//返回一些角点
	normalize(dst, norm_dst, 0, 255, NORM_MINMAX, CV_32FC1, Mat());//归一化
	convertScaleAbs(norm_dst, normScaleDst);//负数转为正数
	//画点在原图上
	Mat resultImg = src.clone();
	for (int row = 0; row < resultImg.rows; row++) {
		uchar* currentRow = normScaleDst.ptr(row);//取出点像素值
		for (int col = 0; col < resultImg.cols; col++) {
			int value = (int)*currentRow;
			if (value > thresh) { //如果值比设定的阈值大则输出,所以阈值为0时候基本全部输出,阈值为255时候一个没有
				circle(resultImg, Point(col, row), 2, Scalar(0, 0, 255), 2, 8, 0);//画一个半径为2个像素点的圆突出
			}
			currentRow++;
		}
	}

	imshow(output_title, resultImg);
}

发布了53 篇原创文章 · 获赞 9 · 访问量 3267

猜你喜欢

转载自blog.csdn.net/weixin_41039168/article/details/99424897