OpenCV学习笔记基础篇(十三):霍夫变换

前言:

笔者目前在校本科大二,有志于进行计算机视觉、计算机图形学方向的研究,准备系统性地、扎实的学习一遍OpenCV的内容,故记录学习笔记,同时,由于笔者同时学习数据结构、机器学习等知识,会尽量根据自己的理解,指出OpenCV的应用,并在加上自己理解的前提下进行叙述。
若有不当之处,希望各位批评、指正。


本篇学习内容:

1.霍夫变换


注:

霍夫变换运用了很巧妙的数学方法。我揣摩很久,难以下笔,觉得很难说清楚这件事。但是学习总是要向前的,本篇我便以自身理解来对其介绍一番。

1.霍夫变换

1.1 数学理论

霍夫变换做的其实是一件统计学上的事情。要理解霍夫变换,首先要理解它是怎么做这个统计的。

接下来的理论说明会同时参考官方文档、《OpenCV3编程入门》、https://homepages.inf.ed.ac.uk/rbf/HIPR2/hough.htm。

摘自https://homepages.inf.ed.ac.uk/rbf/HIPR2/hough.htm:
The motivating idea behind the Hough technique for line detection is that each input measurement (e.g. coordinate point) indicates its contribution to a globally consistent solution (e.g. the physical line which gave rise to that image point).

这句话是说,霍夫变换的思想是:每个输入点都代表了其对总体方案的一定贡献。

我们要怎么获得这样的贡献呢?

我们知道,直线是由无穷多个点组成的。而在图像变换中,在计算机领域,我们可以这样处理:当我们发现了超过k个点属于同一条直线(k可以是我们设置的阈值),那我们就认为图像中存在这样一条直线。

那么,怎么发现两个点属于同一条直线?

霍夫变换很巧妙地运用了极坐标方法:

1.一条直线在笛卡尔坐标系可以由斜率,截距表示。(k,b)
2.一条直线在极坐标系可以由极径,极角表示。(r,θ)
3.霍夫变换采用极坐标系的表示方法来表示一条直线,即:
在这里插入图片描述
  r = x c o s θ + y s i n θ . \ r = xcosθ + ysinθ.  r=xcosθ+ysinθ.

这样做有什么好处呢?

设有点(a,b),那么由上面的表达式,
在这里插入图片描述
可以看到,一旦(a,b)给定(它们不再是变量),那么就确定了一个r关于θ的函数它代表了所有通过(a,b)的直线!换句话说,这是(a,b)对应的所有可能的r-θ值。下图中曲线上的每一个点都代表一条通过(a,b)的直线)。也就是说,笛卡尔坐标系上的每一个点都对应r-θ坐标系上的一条直线(由函数表达式来看,它正好是经过伸缩、平移变换的正弦曲线)!

在这里插入图片描述
(图片来源于《OpenCV3编程入门》)

那么,如果对不同点进行上述操作后,它们生成的正弦曲线在r-θ坐标系相交,就代表这两个点经过同一条直线。(这是必然发生的,因为在二维平面两点确定一条直线)

进一步地,如果k个点进行上述操作后,它们生成的正弦曲线在r-θ坐标系相交于同一点,就代表这k个点经过同一条直线。当k足够大时,我们便认为,图像中存在这样一条直线。

在这里插入图片描述
我们可以进一步推广这种思想。比如,检测一个圆。

一个圆在笛卡尔系中由三个参数表示:(x,y,r)分别代表圆心和半径。将其变换一下,在给定(x,y,r)的情况下,也可以得到所有可能的(r,θ,m)值(m代表半径大小)。这样,我们在统计时,就需要统计3个参数(r,θ,m)的情况,算量会相应增加。(对应的统计空间变成了三维。之前说的r-θ是一个二维统计空间)

再进一步推广,对于一般的形状,也可以通过这样的变换,来查找对应统计空间下的情况。但是,形状越复杂,算量越大。这里便不再介绍。

1.2 函数使用

这里暂且只介绍标准霍夫变换:HoughLines()和累计概率霍夫变换:HoughLinesP()

HoughLines():

void cv::HoughLines	(	
InputArray 	image,	//输入图像
OutputArray lines,	//输出结果。存储检测到的线条
double 	rho,		//距离精度。以像素为单位
double 	theta,		//角度精度。以角度为单位
int 	threshold,	//阈值。在累加空间中大于阈值的线段才可以被检测通过。
double 	srn = 0,	
double 	stn = 0,	
double 	min_theta = 0,
double 	max_theta = CV_PI 
)	

对部分参数进行进一步解释:
images:必须为8位单通道二进制图像。最好是放边缘检测之后的图像进去。
lines:储存了霍夫线变换检测到的线条的输出矢量。每一条线由(ρ,θ)表示。
srn:对于多尺度的霍夫变换,这是rho的除数。粗略的累加器进步尺寸是rho,精确的累加器进步尺寸是rho/srn。
stn:对于多尺度的霍夫变换,这是theta的除数。粗略的累加器进步尺寸是theta,精确的累加器进步尺寸是theta/stn。如果srn = stn = 0,则使用经典霍夫变换。
min_theta:对于多尺度霍夫变换,所检查线段的最小角度。必须在0到max_theta之间
max_theta:对于多尺度霍夫变换,所检查线段的最大角度。必须在min_theta到CV_PI之间

摘自博文https://blog.csdn.net/wenhao_ir/article/details/51774444:
标准霍夫变换本质上是把图像映射到它的参数空间上,它需要计算所有的M个边缘点,这样它的运算量和所需内存空间都会很大。如果在输入图像中只是处理m(m<M)个边缘点,则这m个边缘点的选取是具有一定概率性的,因此该方法被称为概率霍夫变换(Probabilistic Hough Transform)。

HoughLinesP():

void cv::HoughLinesP	(	
InputArray 	image,	//输入图像
OutputArray lines,	//输出结果。存储检测到的线条
double 	rho,		//距离精度。以像素为单位
double 	theta,		//角度精度。以角度为单位
int 	threshold,	//阈值。在累加空间中大于阈值的线段才可以被检测通过。
double 	minLineLength = 0,	//检测出来直线的最短长度
double 	maxLineGap = 0 		//检测出来直线点与点之间的最大距离。
)	

其实我觉得HoughLinesP()的参数更好懂一些。
这里偷懒照抄了一个官方文档里的示例,用的是HoughLinesP():

Mat src, dst, color_dst;
src = imread("E:/program/image/1.jpg");
Canny(src, dst, 50, 200, 3);
cvtColor(dst, color_dst, COLOR_GRAY2BGR);
vector<Vec4i> lines;
HoughLinesP(dst, lines, 1, CV_PI / 180, 80, 30, 10);
for (size_t i = 0; i < lines.size(); i++)
{
	line(color_dst, Point(lines[i][0], lines[i][1]),
		Point(lines[i][2], lines[i][3]), Scalar(0, 0, 255), 3, 8);
}
namedWindow("Source", 1);
imshow("Source", src);
namedWindow("Detected Lines", 1);
imshow("Detected Lines", color_dst);
waitKey(0);
return 0;

在这里插入图片描述
左边是原图,右边的白色线条是边缘检测图像。红色线条是霍夫变换检测出来的直线段。

参考文献:

  1. OpenCV官方文档:https://docs.opencv.org/4.x/
  2. 《OpenCV3编程入门》毛星云、冷雪飞等编著
  3. https://homepages.inf.ed.ac.uk/rbf/HIPR2/hough.htm
  4. https://blog.csdn.net/wenhao_ir/article/details/51774444
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值