【OpenCV C++20 学习笔记】物体检测-Ballard和Guil霍夫变换

物体检测-Ballard和Guil一般化霍夫变换

Ballard一般化霍夫变换

概述

以往的霍夫变换对直线和曲线的检测都能适用,但必须要先进行二值化。而Ballard的方法能将霍夫变换推广到一般的灰度图片,所以称为一般化霍夫变换(Generalized Hough Transform)。而且Ballard的方法不仅能够识别直线、圆形、抛物线等分析曲线,还能通过这些简单的形状推广到更复杂的形状,最后做到能够识别任意的复杂形状。[1](#1)

API

在OpenCV中,要调用Ballard一般化霍夫变换,没有现成的函数,需要先创造一个GeneralizedHoughBallard对象的智能指针,然后通过该指针设置相关的参数。

GeneralizedHoughBallard指针传入一个模板,它就会在目标图中找出与模板相同的物体。

具体用法见下面的实现:

实现

这里使用的目标图片如下,即要在下图中找出我们想要识别的物体:

而模板图如下,即要找的物体:

注意:目标图片和模板图都必须转换成灰度格式才能进行检测:

cpp 复制代码
//读取目标图片
Mat image = imread("generalized_hough_mini_image.jpg");
//以灰度格式读取模板图
Mat templ = imread("generalized_hough_mini_template.jpg", IMREAD_GRAYSCALE);

//将目标图片转换成灰度图片
Mat grayImage;
cvtColor(image, grayImage, COLOR_RGB2GRAY);

创建Ballard对象指针,并设置参数,然后进行检测:

cpp 复制代码
//创建接受检测结果的向量
vector<Vec4f> positionBallard;
Mat ballardImage{ image.clone() };	//复制原图以供绘制检测结果

//======创建Ballard对象指针======
Ptr<GeneralizedHoughBallard> ballard{ createGeneralizedHoughBallard() };
//设置基础参数
ballard->setMinDist(10);			//设置检测到的物体之间的最小距离(A物体中心到B物体中心)
ballard->setLevels(360);			//R-Table水平(我也不知道是啥)
ballard->setDp(2);					//霍夫空间中的最小单元与图片像素的比例的倒数
ballard->setMaxBufferSize(1000);	//设置内部缓冲的最大容量
ballard->setVotesThreshold(40);		//votes的阈值

//设置边缘检测参数
ballard->setCannyLowThresh(30);		//Canny边缘检测的下阈值
ballard->setCannyHighThresh(110);	//Canny边缘检测的上阈值

//设置模板
ballard->setTemplate(templ);		//设置要识别的物体的模板

//进行检测
ballard->detect(grayImage,			//输入图,必须是灰度图
	positionBallard);				//输出结果,向量数组,每个向量包含4个浮点数

检测结果positionBallard中每个向量的4个浮点数中的前2个代表检测到的物体的外接矩形的中心点,第3个代表相对于模板的缩放尺寸,第4个代表旋转角度

因为返回的检测结果只是外接矩形的描述信息,所以必须要将矩形绘制出来才能将检测结果可视化:

cpp 复制代码
//绘制Ballard检测结果
for (vector<Vec4f>::iterator iter = positionBallard.begin(); iter != positionBallard.end(); ++iter) {
	//创建矩形对象
	RotatedRect rRect = RotatedRect(Point2f((*iter)[0], (*iter)[1]),
		Size2f(templ.cols * (*iter)[2], templ.rows * (*iter)[2]),
		(*iter)[3]);
	//获取矩形的四个顶点
	Point2f vertices[4];
	rRect.points(vertices);
	//在原图上绘制矩形,线条为蓝色
	for (int i = 0; i < 4; i++)
		line(ballardImage, vertices[i], vertices[(i + 1) % 4], Scalar(255, 0, 0), 6);
}

imshow("Ballard物体检测", image);
imshow("模板图", templ);
waitKey(0);

最终显示出来的检测结果如下(左图为模板图,右图为检测结果):

可以看到只有左边的钥匙被成功识别了。

Guil一般化霍夫变换

概述

Guil一般化霍夫变换不仅能够识别目标图中与模板相同的物体,还能根据模板识别以不同方向摆放、大小被缩放甚至有点变形的物体[2](#2)

因此相比于Ballard方法,它还需要另外指定物体可能的旋转角度的范围以及缩放比例的范围。比如上图中的两把钥匙外形类似,因为摆放的方向不同,而出现了相对于模板图片的旋转角度的病原体不过;另外,两把钥匙的大小也有不同,从而出现了相对于模板图片的缩放的比例的不同。

API

在OpenCV中,同样也没有专门执行Guil检测的方法,也需要先创建GeneralizedHoughGuil的智能指针,然后再设置对应的参数。
GeneralizedHoughGuil的实现与GeneralizedHoughBallard的实现只是需要设置的参数的种类多少不同,其他步骤基本没什么差别。

实现

用同样的目标图和模板进行Guil物体检测:

cpp 复制代码
//读取目标图片
Mat image = imread("generalized_hough_mini_image.jpg");
//以灰度格式读取模板图
Mat templ = imread("generalized_hough_mini_template.jpg", IMREAD_GRAYSCALE);

//将目标图片转换成灰度图片
Mat grayImage;
cvtColor(image, grayImage, COLOR_RGB2GRAY);

//创建接收检测结果的向量
vector<Vec4f>  positionGuil;
Mat guilImage{ image.clone() };

//======创建Guil对象指针
Ptr<GeneralizedHoughGuil> guil = createGeneralizedHoughGuil();
//设置基础参数
guil->setMinDist(10);
guil->setLevels(360);
guil->setDp(3);
guil->setMaxBufferSize(1000);

//设置角度参数
guil->setMinAngle(0);				//最小角度
guil->setMaxAngle(360);				//最大角度
guil->setAngleStep(1);				//每次检测步进的角度
guil->setAngleThresh(1000);			//角度的votes阈值

//设置缩放比例参数
guil->setMinScale(0.7);				//最小缩放比例
guil->setMaxScale(2.0);				//最大缩放比例
guil->setScaleStep(0.05);			//每次检测步进的缩放比例
guil->setScaleThresh(50);			//缩放比例上的votes阈值

//!!我也不知道是什么
guil->setPosThresh(10);				//位置上的votes阈值

//设置Canny边缘检测参数
guil->setCannyLowThresh(30);		//下阈值
guil->setCannyHighThresh(110);		//上阈值

//设置模板
guil->setTemplate(templ);

//进行检测
guil->detect(grayImage, positionGuil);

//绘制Guil检测结果
for (vector<Vec4f>::iterator iter = positionGuil.begin(); iter != positionGuil.end(); ++iter) {
	RotatedRect rRect = RotatedRect(Point2f((*iter)[0], (*iter)[1]),
		Size2f(templ.cols * (*iter)[2], templ.rows *(*iter)[2]),
		(*iter)[3]);
	Point2f vertices[4];
	rRect.points(vertices);
	for (int i = 0; i < 4; i++)
		line(guilImage, vertices[i], vertices[(i + 1) % 4], Scalar(0, 255, 0), 2);
}

imshow("Guil物体检测", guilImage);
imshow("模板图", templ);
waitKey();

检测结果如下:

可以看到两把钥匙都被检测出来了

挖坑

OpenCV的官方文档中对GeneralizedHoughGuilGeneralizedHoughBallard类中的方法基本没有详细的介绍,参考文献中的两篇论文又太专业了。所以这篇文章中有些地方我也没搞清楚,先mark一下,等什么时候有空了,好好啃啃这两篇论文。


  1. Dana H Ballard. Generalizing the hough transform to detect arbitrary shapes. Pattern recognition , 13(2):111--122, 1981. ↩︎

  2. N Guil, José María Gonzalez-Linares, and Emilio L Zapata. Bidimensional shape detection using an invariant approach. Pattern Recognition , 32(6):1025--1038, 1999. ↩︎

相关推荐
viperrrrrrrrrr73 小时前
大数据学习(105)-Hbase
大数据·学习·hbase
行思理5 小时前
go语言应该如何学习
开发语言·学习·golang
oceanweave6 小时前
【k8s学习之CSI】理解 LVM 存储概念和相关操作
学习·容器·kubernetes
吴梓穆8 小时前
UE5学习笔记 FPS游戏制作43 UI材质
笔记·学习·ue5
进来有惊喜8 小时前
OpenCV 表情识别
人工智能·opencv·计算机视觉
进来有惊喜8 小时前
opencv指纹匹配
人工智能·opencv·计算机视觉
学会870上岸华师8 小时前
c语言学习16——内存函数
c语言·开发语言·学习
XYN618 小时前
【嵌入式面试】
笔记·python·单片机·嵌入式硬件·学习
啊哈哈哈哈哈啊哈哈8 小时前
R3打卡——tensorflow实现RNN心脏病预测
人工智能·深度学习·学习
KangkangLoveNLP9 小时前
深度探索:策略学习与神经网络在强化学习中的应用
人工智能·深度学习·神经网络·学习·机器学习·自然语言处理