直线段检测算法LSD:a Line Segment Detector

直线段检测算法LSD:a Line Segment Detector

微信公众号:幼儿园的学霸

目录

简介

影像中的直线特征是视觉感知的重要线索和解释图像的基本依据,相比于点特征,直线段特征对视角和光照变化具有很好的鲁棒性。常用的直线检测有Hough直线检测和LSD等.Hough直线检测将直线检测映射为参数空间中点的检测,而LSD通过查找近似矩形区域来获得直线。LSD是由Rafael Grompone von Gioi等人在2012年提出的一种局部直线快速提取的算法, 它能在线性时间内得出亚像素级精度的检测结果,LSD算法较为稳定且存在错误控制, 可以在无人工调节任何参数的情况下快速得到满意的线特征提取结果.

流程

LSD的核心是像素合并与误差控制。

整体流程大致可以分为如下几个步骤:
1、将输入图像通过高斯核采样,缩放到0.8;
2、计算图像梯度强度,以及每个像素点的梯度角: a t a n 2 ( g x , − g y ) atan2(gx,-gy) atan2(gx,gy),其中 g x 、 g y gx、gy gxgy分别为水平和垂直方向梯度;
3、设置图像梯度强度范围到[0, 1023] (大于1023的梯度强度,强制设置为1023);
4、创建1024个链表,遍历整个梯度图,根据梯度强度,相同梯度值像素坐标放入同一张链表中;
5、将1024个链表,按从大到小顺序,合成一张大链表(首部为1023链表,尾部为0);
6、取出链表头部存储图像坐标位置,作为种子像素,根据梯度角方向相似,进行区域扩散。(每扩散一个像素,将该像素坐标从链表中删除,并且做标记,之后新的区域扩散,无法再扩散到该像素);
7、将扩散区域进行矩形拟合;
8、检测拟合矩形内梯度角,根据对应NFA公式(来自论文),计算出该拟合矩形精度误差,如果不满足,则丢弃;如果满足要求,则将该矩形记录存储,表示为一条检测到的直线;
9、继续回到第6步,从链表中,找到下一个种子点,从剩下图像进行区域扩散,至到遍历完全图,得到所有检测到的直线。

详细步骤

1.尺度缩放:

按照原文,这一步可选择跳过(s =1.0),算法的默认选择是s=0.8。目的是为了消除数字离散图像的锯齿效应。缩放完毕之后用高斯下采样的方式对输入图像进行操作,计算时,先进行高斯滤波,然后进行下采样。
其中高斯核的标准差为 σ = ζ / s \sigma =\zeta / s σ=ζ/s,其中 ζ = 0.6 \zeta=0.6 ζ=0.6以此来保持锯齿效应和图像模糊之间的平衡。高斯滤波核的半径为 h = c e i l ( σ ∗ 2 ∗ 3 ∗ l n ( 10 ) ) h=ceil(\sigma * \sqrt{2*3*ln(10)}) h=ceil(σ23ln(10) ),那么高斯滤波核的窗口大小为 w = 1 + 2 ∗ h w = 1+2*h w=1+2h.
举例说明,如果 s = 0.8 s=0.8 s=0.8,那么 σ = 0.75 , h = c e i l ( 2.787 ) = 3 , w = 7 \sigma = 0.75,h=ceil(2.787)=3,w=7 σ=0.75,h=ceil(2.787)=3,w=7

2.梯度和方向计算:

梯度计算中论文用到的是2*2的模板。主要是为了用contrario model的时候保证相邻点方向分布的独立性,减少梯度计算过程中的彼此依赖,同时小模板时计算相对较快.

G x = 1 2 [ − 1 1 − 1 1 ] G y = 1 2 [ − 1 − 1 1 1 ] (1) \begin{aligned} G_x = \frac{1}{2}\left[ \begin{array}{cc} -1 & 1 \\ -1 & 1 \end{array} \right] \quad G_y = \frac{1}{2}\left[ \begin{array}{cc} -1 & -1 \\ 1 & 1 \end{array} \right] \end{aligned} \quad \text{(1)} Gx=21[1111]Gy=21[1111](1)

G x ( x , y ) = 1 2 [ f ( x + 1 , y ) − f ( x , y ) + f ( x + 1 , y + 1 ) − f ( x , y + 1 ) ] G y ( x , y ) = 1 2 [ f ( x , y + 1 ) − f ( x , y ) + f ( x + 1 , y + 1 ) − f ( x + 1 , y ) ] (2) \begin{aligned} G_x(x,y) = \frac{1}{2} [f(x+1,y)-f(x,y) + f(x+1,y+1)-f(x,y+1)] \\ G_y(x,y) = \frac{1}{2} [f(x,y+1)-f(x,y) + f(x+1,y+1) - f(x+1,y)] \end{aligned} \quad \text{(2)} Gx(x,y)=21[f(x+1,y)f(x,y)+f(x+1,y+1)f(x,y+1)]Gy(x,y)=21[f(x,y+1)f(x,y)+f(x+1,y+1)f(x+1,y)](2)

代码中使用的梯度幅值和梯度幅角求解公式为:
G = G x 2 + G y 2 θ = a t a n 2 ( G x , − G y ) (3) \begin{aligned} & G = \sqrt{ {G_x^2+G_y^2}} \\ & \theta = atan2(Gx,-Gy) \end{aligned} \quad \text{(3)} G=Gx2+Gy2 θ=atan2(Gx,Gy)(3)

这种方法计算的梯度其实是 ( x + 0.5 , y + 0.5 ) (x+0.5,y+0.5) x+0.5y+0.5处的,在最后的步骤会对这里的计算偏差进行补偿。同样的,由于计算的梯度是 ( x + 0.5 , y + 0.5 ) (x+0.5,y+0.5) x+0.5y+0.5,代码中由于未对图像进行边界扩充,因此图像的最后一行及最后一列未进行梯度方向和幅值的计算。
需要注意的是,从黑到白跟从白到黑是不同的,两者在梯度上具有180°的差异。这意味着,LSD的直线分割结果是有方向的,并非起始点和终止点任意的。举例来说,当灰度图进行亮度翻转时(黑的像素变白,白的像素变黑),那么所有LSD检测到的直线是不变的,但每根直线的起始点和终止点都交换了。

3.梯度伪排序(Pseudo-Ordering):

LSD是一种贪婪算法,因此像素处理的顺序将对结果有一定的影响. 具有较高梯度幅值的像素点所在的区域通常具有较强的边缘,(而在边缘中,中间的像素一般具有最高的梯度幅值).因此,梯度值越大,越是显著的边缘点,更适合作为种子点,从其入手进行直线分割检测.

但是对梯度值进行完全排序是一个时耗性很高的工作。因此简单的将梯度值划分为1024个等级(bins),这1024个等级涵盖了梯度由0~255的变化范围,这种排序是一个线性的时耗。种子点从梯度值最高的bin开始搜索,依次往下,直至所有点标记为USED。
BINS划分原理:设求解的图像中每个点的梯度幅值为 m o d g r a d i j modgrad_{ij} modgradij,其中的梯度幅值最大值为 m a x _ g r a d max\_grad max_grad,需要划分为 b i n s bins bins个等级,那么求解等级系数为 b i n _ c o e f = b i n s − 1 m a x _ g r a d bin\_coef=\frac{bins-1}{max\_grad} bin_coef=max_gradbins1,因此每个点量化后的梯度幅值为 m o d g r a d i j ^ = b i n _ c o e f ∗ m o d g r a d i j \hat {modgrad_{ij}}=bin\_coef * modgrad_{ij} modgradij^=bin_coefmodgradij

小梯度值抑制:
小梯度值点往往出现在平滑区域,或者仅仅是噪声。不在关注的范围内,但是他们的存在往往会严重影响直线角度的计算。考虑到区域增长时有角度承受范围 [ − τ , τ ] [-\tau,\tau] [τ,τ]。因此小梯度“脏点”的最大影响角度需要小于 τ \tau τ
一个像素点梯度幅值为g与某方向一条线段夹角为 α \alpha α,则 g ∗ s i n ( α ) g*sin(\alpha) gsin(α)代表像素点在与该方向垂直的方向梯度变化量 q 0 > = 1 q_0>=1 q0>=1,才代表该点像素拥有的在该直线方向容忍度范围内level-line可以被后续区域生长接受。
ρ = q s i n τ \rho =\frac{q}{sin{\tau }} ρ=

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值