OpenCV中feature2D学习——Shi-Tomasi角点检测

概述

除了之前文章所说的利用Harris进行角点检测,还可以利用Shi-Tomasi方法(相关论文)进行角点检测,该方法也可以用于初始化基于特征点的目标跟踪。

函数实现

该方法在opencv中的具体实现是在函数goodFeaturesToTrack()中,其原型为:

C++: void goodFeaturesToTrack(InputArray image, OutputArray corners, int maxCorners, double qualityLevel, double minDistance, 
InputArray mask=noArray(), int blockSize=3, bool useHarrisDetector=false, double k=0.04 )
C: void cvGoodFeaturesToTrack(const CvArr* image, CvArr* eig_image, CvArr* temp_image, CvPoint2D32f* corners, int* corner_count, 
double quality_level, double min_distance, const CvArr* mask=NULL, int block_size=3, int use_harris=0, double k=0.04 )

函数参数说明如下:

image:输入8-bit或浮点型32-bit图像,要求单通道;

eig_image和temp_image被忽略;

corners:检测到角点的输出矩阵;

maxCorners:角点个数的最大值,如果检测到的角点数目超过这个值,则取其中最显著的角点输出;

qualityLeve:用来表征可接受角点的最差质量。该参数值乘以最佳角点的质量数值得到的乘积(即最小的特征值,参考cornerMinEigenVal()函数,或者是Harris函数的响应值,参考cornerHarris()函数)是一个阈值,所有质量数值小于这个阈值的角点将被忽略。举例来说,如果最佳角点的质量数值为1500,qualityLevel设为0.01,那么所有质量数值小于15的角点都会被忽略。

minDistance:返回角点间最小的欧氏距离。

mask:可选的感兴趣区域。如果输入图像非空(此时mask必须为CV_8UC1并且大小和输入图像一致),它制定了角点被检测到的那个区域。

blockSize:在每个像素的邻域中计算导数协方差矩阵时的平均块大小(参考cornerEigenValsAndVecs()函数)。

useHarrisDetector:是否使用Harris检测算法(参考cornerHarris()函数)或者Shi-Tomasi检测算法(参考cornerMinEigenVal()函数)。

k:Harri角点检测自由参数。

函数功能

该函数在图像或选定的区域中检测最显著的角点,的功能介绍如下:

(1)该函数在输入图像的每个像素点上使用cornerHarris()函数和cornerMinEigenVal()函数计算角点质量数值。

(2)该函数使用非极大值抑制算法(non-maximumsuppression),3*3邻域内的局部极大值被保留。

(3)像上面参数解释内容所述的,角点的最小特征值如果小于

,则被忽略。

(4)步骤(3)筛选后剩下的角点按照质量数值从高到低排序。

(5)在每个检测到的角点周围minDistance的范围内,如果有更显著的角点被检测到,则这个角点被忽略。这样也是为了保证最显著的角点被保留下来。

代码示例

代码示例如下:

/**
* @使用Shi-Tomasi方法进行角点检测
* @author holybin
*/

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace cv;
using namespace std;

/// 全局变量
Mat src, srcGray;
int maxCorners = 23;	//角点个数的最大值
int maxCornersThresh = 1000;	//角点个数最大值的上限(滑动条范围0-1000)

RNG rng(12345);
char* sourceWindow = "src";

/// 角点检测函数声明
void doGoodFeaturesToTrack( int, void* );

int main( int argc, char** argv )
{
	/// 载入图像并灰度化
	src = imread( "D:\\opencv_pic\\house_small.jpg", 1 );
	cvtColor( src, srcGray, CV_BGR2GRAY );

	/// 创建显示窗口以及滑动条
	namedWindow( sourceWindow, CV_WINDOW_AUTOSIZE );
	createTrackbar( "max num:", sourceWindow, &maxCorners, maxCornersThresh, doGoodFeaturesToTrack );  
	imshow( sourceWindow, src );

	doGoodFeaturesToTrack( 0, 0 );

	waitKey(0);
	return(0);
}

/// 角点检测函数实现:标示出每个角点位置
void doGoodFeaturesToTrack( int, void* )
{
	if( maxCorners < 1 )
		maxCorners = 1;

	/// Shi-Tomasi的参数设置
	vector<Point2f> corners;
	double qualityLevel = 0.01;
	double minDistance = 10;
	int blockSize = 3;
	bool useHarrisDetector = false;	//不使用Harris检测算法
	double k = 0.04;

	/// 深度拷贝原图像用于绘制角点
	Mat srcCopy = src.clone();
	/// 应用角点检测算法
	goodFeaturesToTrack( srcGray, 
		corners,
		maxCorners,
		qualityLevel,
		minDistance,
		Mat(),	//未选择感兴趣区域
		blockSize,
		useHarrisDetector,
		k );

	/// 当maxCorners的值较小时,以下两个值基本是一样的;
	/// 当maxCorners的值较大时,实际检测到的角点数目有可能小于maxCorners,以下两个值不一样。
	cout<<"*  detected corners : "<<corners.size()<<endl;
	cout<<"** max corners: "<<maxCorners<<endl;

	/// 绘制出角点
	int r = 4;
	for( int i = 0; i < corners.size(); i++ )
		circle( srcCopy, corners[i], r, Scalar(0,255,0), -1, 8, 0 );

	/// 显示结果
	namedWindow( sourceWindow, CV_WINDOW_AUTOSIZE );
	imshow( sourceWindow, srcCopy );  
}

运行结果:




从结果可以看出当角点个数阈值太大时,检测到的角点个数固定在434,也就是最多能检测出434个角点。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值