【OpenCV3】角点检测——cv::goodFeaturesToTrack()与cv::cornerSubPix()详解

49 篇文章 32 订阅
38 篇文章 16 订阅

一提到角点检测,最常用的方法莫过于Harris角点检测,opencv中也提供了Harris角点检测的接口,即cv::cornerHarris(),但是Harris角点检测存在很多缺陷(如角点是像素级别的,速度较慢等),因此我们这里将介绍opencv中的另一个功能更为强大的函数——cv::goodFeaturesToTrack(),它不仅支持Harris角点检测,也支持Shi Tomasi算法的角点检测。但是,该函数检测到的角点依然是像素级别的,若想获取更为精细的角点坐标,则需要调用cv::cornerSubPix()函数进一步细化处理,即亚像素。

1、cv::goodFeaturesToTrack()角点检测

cv::goodFeaturesToTrack()的具体调用形式如下:

	void cv::goodFeaturesToTrack(
		cv::InputArray image, // 输入图像(CV_8UC1 CV_32FC1)
		cv::OutputArray corners, // 输出角点vector
		int maxCorners, // 最大角点数目
		double qualityLevel, // 质量水平系数(小于1.0的正数,一般在0.01-0.1之间)
		double minDistance, // 最小距离,小于此距离的点忽略
		cv::InputArray mask = noArray(), // mask=0的点忽略
		int blockSize = 3, // 使用的邻域数
		bool useHarrisDetector = false, // false ='Shi Tomasi metric'
		double k = 0.04 // Harris角点检测时使用
	);


第一个参数是输入图像(8位或32位单通道图)。

第二个参数是检测到的所有角点,类型为vector或数组,由实际给定的参数类型而定。如果是vector,那么它应该是一个包含cv::Point2f的vector对象;如果类型是cv::Mat,那么它的每一行对应一个角点,点的x、y位置分别是两列。

第三个参数用于限定检测到的点数的最大值。

第四个参数表示检测到的角点的质量水平(通常是0.10到0.01之间的数值,不能大于1.0)。

第五个参数用于区分相邻两个角点的最小距离(小于这个距离得点将进行合并)。

第六个参数是mask,如果指定,它的维度必须和输入图像一致,且在mask值为0处不进行角点检测。

第七个参数是blockSize,表示在计算角点时参与运算的区域大小,常用值为3,但是如果图像的分辨率较高则可以考虑使用较大一点的值。

第八个参数用于指定角点检测的方法,如果是true则使用Harris角点检测,false则使用Shi Tomasi算法。

第九个参数是在使用Harris算法时使用,最好使用默认值0.04。


下面使用测试代码,看一下实际的检测效果。

测试代码如下:

	cv::Mat image_color = cv::imread("house.jpg", cv::IMREAD_COLOR);

	//使用灰度图像进行角点检测
	cv::Mat image_gray;
	cv::cvtColor(image_color, image_gray, cv::COLOR_BGR2GRAY);

	//设置角点检测参数
	std::vector<cv::Point2f> corners;
	int max_corners = 200;
	double quality_level = 0.01;
	double min_distance = 3.0;
	int block_size = 3;
	bool use_harris = false;
	double k = 0.04;

	//角点检测
	cv::goodFeaturesToTrack(image_gray, 
							corners, 
							max_corners, 
							quality_level, 
							min_distance, 
							cv::Mat(), 
							block_size, 
							use_harris, 
							k);

	//将检测到的角点绘制到原图上
	for (int i = 0; i < corners.size(); i++)
	{
		cv::circle(image_color, corners[i], 1, cv::Scalar(0, 0, 255), 2, 8, 0);
	}

	cv::imshow("house corner", image_color);
	cv::waitKey(0);
	return;


实际检测效果如下:




2、cv::cornerSubPix()亚像素角点检测

前面已经提及,cv::goodFeaturesToTrack()提取到的角点只能达到像素级别,在很多情况下并不能满足实际的需求,这时,我们则需要使用cv::cornerSubPix()对检测到的角点作进一步的优化计算,可使角点的精度达到亚像素级别。

具体调用形式如下:

	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_ITER 、cv::TermCriteria::EPS(可以是两者其一,或两者均选),前者表示迭代次数达到了最大次数时停止,后者表示角点位置变化的最小值已经达到最小时停止迭代。二者均使用cv::TermCriteria()构造函数进行指定。


下面就通过一个示例看看cv::cornerSubPix()亚像素角点检测的具体效果。

	cv::Mat image_color = cv::imread("image.jpg", cv::IMREAD_COLOR);

	//用于绘制亚像素角点
	cv::Mat image_copy = image_color.clone();
	//使用灰度图像进行角点检测
	cv::Mat image_gray;
	cv::cvtColor(image_color, image_gray, cv::COLOR_BGR2GRAY);

	//设置角点检测参数
	std::vector<cv::Point2f> corners;
	int max_corners = 100;
	double quality_level = 0.01;
	double min_distance = 10;
	int block_size = 3;
	bool use_harris = false;
	double k = 0.04;

	//角点检测
	cv::goodFeaturesToTrack(image_gray,
		corners,
		max_corners,
		quality_level,
		min_distance,
		cv::Mat(),
		block_size,
		use_harris,
		k);

	//将检测到的角点绘制到原图上
	for (int i = 0; i < corners.size(); i++)
	{
		cv::circle(image_color, corners[i], 5, cv::Scalar(0, 0, 255), 2, 8, 0);
	}

	//指定亚像素计算迭代标注
	cv::TermCriteria criteria = cv::TermCriteria(
					cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS,
					40,
					0.01);

	//亚像素检测
	cv::cornerSubPix(image_gray, corners, cv::Size(5, 5), cv::Size(-1, -1), criteria);

	//将检测到的亚像素角点绘制到原图上
	for (int i = 0; i < corners.size(); i++)
	{
		cv::circle(image_copy, corners[i], 5, cv::Scalar(0, 255, 0), 2, 8, 0);
	}

	cv::imshow("corner", image_color);
	cv::imshow("sub pixel corner", image_copy);

	cv::imwrite("corner.jpg", image_color);
	cv::imwrite("corner_sub.jpg", image_copy);
	cv::waitKey(0);
	return;


直接角点检测和亚像素角点检测的结果分别如下:





从检测的效果来看,使用亚像素角点检测后角点的精细度确实得到了显著的提升。


2017.04.07

  • 33
    点赞
  • 215
    收藏
    觉得还不错? 一键收藏
  • 19
    评论
opencv-4.4.0-vc14_vc15.exe 版本:4.4.0 2020年7月 OpenCV 4.x的夏季更新已发布 :晴天: 此版本的亮点: SIFT(尺度不变特征变换)算法已移至主存储库(SIFT的专利已过期) DNN模块: 改进的图层/激活/支持更多模型: 最新的Yolo v4检测器:#17148。为[yolo]层(Yolo v3和Yolo v4)禁用了每层NMS,因为它们是不正确的-用于cv::dnn::NMSBoxes所有检测。 ONNX:添加对Resnet_backbone(Torchvision)的支持#16887 EfficientDet模型支持:#17384 新样本/演示: 添加文本识别示例:C ++ / Python FlowNet2光流:#16575 英特尔®推理引擎后端(OpenVINO™): 增加了对OpenVINO 2020.3 LTS / 2020.4版本的支持 计划在下一版本中删除对NN Builder API的支持 CUDA后端中的许多修复和优化(感谢@YashasSamaga):PR G-API模块: 在OpenCV后端引入了用于状态内核的新API :GAPI_OCV_KERNEL_ST。有状态内核在各个图执行(标准中更多)或流的视频帧之间(以流模式)保留其状态。 在G-API推出更多面向视频的操作:goodFeaturesToTrack,buildOpticalFlowPyramid,calcOpicalFlowPyrLK。 添加了更多的图像处理内核:Laplacian和双边过滤器。 修复了G-API的OpenCL后端中的潜在崩溃。 OpenCV社区的许多其他伟大贡献,包括但不限于: Obj-C / Swift绑定:#17165 (opencv_contrib)Julia绑定是正在进行的GSoC项目的一部分:#2547 (opencv_contrib)BIMEF:生物启发的多重曝光融合框架,用于弱光图像增强: #2448 为CV_16UC1图像启用Otsu阈值:#16640 为文本检测添加笔划宽度变换算法:#2464 计划在Apache 2许可证上进行下一版本OE-32的 迁移#17491

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值