1.角点检测的意义
参考这篇博文:https://blog.csdn.net/pbymw8iwm/article/details/82624898
基于特征的图像配准方法是图像配准中最常见的方法之一。一类重要的点特征:角点(corner points),其定义主要有以下:
- 局部窗口沿各方向移动,灰度均产生明显变化的点
- 图像局部曲率突变的点
- 典型的角点检测算法:Harris角点检测、CSS角点检测
- 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);
}