opencv之亚像素精度级别的角点检测

概述

在现实世界中,角点对应于物体的拐角,道路的十字路口、丁字路口等。从图像分析的角度来定义角点可以有以下两种定义:

  • 角点可以是两个边缘的角点;

  • 角点是邻域内具有两个主方向的特征点;
    一提到角点检测,最常用的方法莫过于Harris角点检测,opencv中也提供了Harris角点检测的接口,即cornerHarris(),但是Harris角点检测存在很多缺陷(如角点是像素级别的,速度较慢等),opencv中有另一个功能更为强大的函数—goodFeaturesToTrack(),它不仅支持Harris角点检测,也支持Shi Tomasi算法的角点检测。但是,该函数检测到的角点依然是像素级别的,若想获取更为精细的角点坐标,有时候我们需要这种精度的角点检测(跟踪、三维重建、相机校正),则需要调用cv::cornerSubPix()函数进一步细化处理,即亚像素。

  • 插值方法

  • 基于图像矩计算

  • 曲线拟合方法(高斯曲面、多项式、椭圆曲面)


函数API

函数api

void cv::cornerSubPix(
		cv::InputArray image, // 输入图像
		cv::InputOutputArray corners, // 角点(既作为输入也作为输出)
		cv::Size winSize, // 区域大小为 NXN; N=(winSize*2+1)
		cv::Size zeroZone, // 类似于winSize,但是总具有较小的范围,Size(-1,-1)表示忽略
		cv::TermCriteria criteria // 停止优化的标准
	);

参数说明

  • 第一个参数是输入图像,和cv::goodFeaturesToTrack()中的输入图像是同一个图像。
  • 第二个参数是检测到的角点,即是输入也是输出。
  • 第三个参数是计算亚像素角点时考虑的区域的大小,大小为NXN; N=(winSize*2+1)
  • 第四个参数作用类似于winSize,但是总是具有较小的范围,通常忽略(即Size(-1, -1))。
  • 第五个参数用于表示计算亚像素时停止迭代的标准,可选的值有cv::TermCriteria::MAX_ITERcv::TermCriteria::EPS(可以是两者其一,或两者均选),前者表示迭代次数达到了最大次数时停止,后者表示角点位置变化的最小值已经达到最小时停止迭代。二者均使用cv::TermCriteria()构造函数进行指定。

代码演示

#include 
#include 
#include 
using namespace std;
using namespace cv;

#define Pic_Path "E:\\picture\\"
#define Pic_Name "harris1.jpg"

int main(void)
{
Mat src,gray_src;
	int threshold = 100;
	int threshold_max = 255;
	string pic = string(Pic_Path) + string(Pic_Name);

	cout << "图片详细信息:" << pic << endl;

	src = imread(pic);

	if (src.empty())
	{
		cout << "图片不存在" << endl;
		return -1;
	}

	namedWindow("原始图片", WINDOW_AUTOSIZE);
	imshow("原始图片", src);
	cvtColor(src, gray_src, COLOR_BGR2GRAY);
	
	Mat dst;
	vector<Point2f> corners;
	int maxCorners = 100;          //获取角点的最大数目限值
	double qualityLevel = 0.01;    //阈值 最大值的1%
	double minDistance = 10;      //角点检测最小的间距

	//获取角点
	goodFeaturesToTrack(gray_src, corners, maxCorners, qualityLevel, minDistance, Mat(), 3, false, 0.04);

	dst = src.clone();
	for (size_t i = 0; i < corners.size(); i++)
	{
		circle(dst, corners[i], 4, Scalar(0, 0, 255), 2, 8, 0);
		cout << "int[x,y]" << corners[i].x << "," << corners[i].y << endl;
	}
	namedWindow("检测图像", WINDOW_AUTOSIZE);
	imshow("检测图像", dst);

	//对获取到的角点进行亚像素反推		
	Size winSize = Size(5, 5);		// 区域大小为 NXN; N=(winSize*2+1)
	Size zeroZone = Size(-1, -1);   // 类似于winSize,但是总具有较小的范围,Size(-1,-1)表示忽略
	TermCriteria tc = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001);   //定义迭代算子 精度 次数双限制
	cornerSubPix(gray_src, corners, winSize, zeroZone, tc);
	for (size_t i = 0; i < corners.size(); i++)
	{
		cout << "float[x,y]" << corners[i].x << "," << corners[i].y << endl;
	}

	waitKey(0);
	destroyAllWindows();
	return 0;
}

运行效果

图片详细信息:E:\picture\harris1.jpg
int[x,y]22,1001
int[x,y]61,999
int[x,y]87,952
int[x,y]48,1005
。。。
int[x,y]543,557
int[x,y]557,113
int[x,y]329,519
int[x,y]359,980
int[x,y]110,886
int[x,y]391,755
float[x,y]18.7803,998.23
float[x,y]62.6927,997.423
float[x,y]88.4064,952.118
。。。
float[x,y]333.192,517.411
float[x,y]360.236,979.549
float[x,y]108.555,886.046
float[x,y]392.311,753.397

参考链接:https://blog.csdn.net/qq_30815237/article/details/87179830

你可能感兴趣的:(opencv,opencv,计算机视觉)