您的位置:首页 > 运维架构

opencv学习(四十四)之图像角点检测Harris

2017-04-17 10:23 253 查看

1.概述

角点是图像很重要的特征,对图像图形的理解和分析有很重要的作用,在保留图像图形重要特征的同时,可以有效减少信息的数据量,使信息的含量很高,有效提高计算速度,有利于图像的可靠匹配,使得实时处理成为可能。在物体识别、图像匹配、视觉跟踪和三维重建等方面有很重要的应用。

角点可以认为是窗口向任意方向的移动都导致图像灰度的明显变化。从图像分析的角度来定义角点可以有一下两种:

1.角点可以是两个边缘的角点

2.角点是邻域内具有两个主方向的特征点

前者往往需要对图像边缘进行编码,这在很大程度上依赖于图像的分割与边缘提取,具有相当大的难度和计算量,且一旦待检测目标局部发生变化,很可能导致操作的失败。

角点检测算法可以归纳为三类:基于灰度图像的角点检测、基于二值图像的角点检测、基于轮廓曲线的角点检测。基于灰度图像的检测又可细分为基于梯度、基于模板、基于模板梯度组合三类方法,其中基于模板的方法主要考虑像素邻域点的灰度变化,即图像亮度的变化,将与邻点亮度对比足够大的点定义为角点。常见的基于模板的角点检测算法有Kitchen-Rosenfeld角点检测,Harris角点检测算法,KLT角点检测和SUSAN角点检测。本文主要介绍Harris角点检测。

2.Harris角点检测原理

Harris角点检测原理推导靠一篇博客讲清楚不太现实,这里介绍一个比较直观的概念而不是数学推导。

Harris角点检测是一种直接基于灰度图像的角点提取算法,稳定性高,尤其对L型角点检测精度高。

人眼对角点的识别通常是在一个局部的小区域或小窗口完成的。如下图所示:



在各个方向上移动这个特征的小窗口,窗口内区域的灰度发生了较大的变化,那么久认为在窗口内遇到了角点,如果这个特定的窗口在图像各个方向上移动时,窗口内图像的灰度发生了很大变化,而在另一些方向上没有发生变化,那么窗口内的图像可能就是一条直线的线段。

3.opencv API

opencv提供cornerHarris()提取Harris角点。cornerHarris函数对每一个像素在blockSize x blockSize邻域内,计算2 x 2梯度的协方差矩阵M(x,y),,接着它计算如下公式

输出局部最大值,即为角点。

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


src:输入图像,Mat类型即可,必须为单通道8-bit或浮点型图像

dst:角点检测的输出结果,与原图像有相同的尺寸和类型

blockSize:邻域大小,可以查看cornerEigenValsAndVecs()得到更多关于blockSize的信息

ksize:表示Sobel()算子孔径大小

**k:**Harris参数,用于判断是否为角点

borderType:前面已多次介绍,为图像边界模式,有默认值BORDER_DEFAULT

4.示例代码

#include <iostream>
#include <stdlib.h>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>

using namespace std;
using namespace cv;

//定义全局变量
Mat srcImage, grayImage;
int thresh = 100;
const int threshMaxValue = 255;

//声明回调函数
void cornerHarris_detect(int, void*);

int main()
{
srcImage = imread("harris.jpg");

//判断文件是否加载成功
if (srcImage.empty())
{
cout << "图像加载失败!";
return -1;
}
else
cout << "图像加载成功..." << endl << endl;

cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
namedWindow("grayImage", WINDOW_AUTOSIZE);
imshow("grayImage", grayImage);

createTrackbar("Threshold:", "grayImage", &thresh, threshMaxValue, cornerHarris_detect);
cornerHarris_detect(thresh, 0);

waitKey(0);

return 0;
}

void cornerHarris_detect(int, void*)
{
Mat dstImage, dst_norm_image, dst_norm_scaled;
dstImage = Mat::zeros(srcImage.size(), CV_32FC1);

//检测器参数设置
int blockSize = 2;          //邻域尺寸
int apertureSize = 3;       //Sobel算子孔径
double k = 0.04;            //Harris参数

//角点检测
cornerHarris(grayImage, dstImage, blockSize, apertureSize, k, BORDER_DEFAULT);

normalize(dstImage, dst_norm_image, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
convertScaleAbs(dst_norm_image, dst_norm_scaled);   //强归一化后的图像线性变换为8位无符号整型

//绘制角点
for (int j = 0; j < dst_norm_image.rows; j++)
{
for (int i = 0; i < dst_norm_image.cols; i++)
{
if ((int)dst_norm_image.at<float>(j,i)>thresh)
{
circle(dst_norm_scaled, Point(i, j), 5, Scalar(0), 2, 8, 0);
circle(grayImage, Point(i, j), 5, Scalar(0, 0, 255), 2, 8, 0);
}
}
}
namedWindow("cornerHarris", WINDOW_AUTOSIZE);
imshow("cornerHarris", dst_norm_scaled);
namedWindow("corner_grayImage", WINDOW_AUTOSIZE);
imshow("corner_grayImage", grayImage);
}


运行结果



5.参考文献

http://www.360doc.com/content/15/1212/23/20007814_519967668.shtml
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息