备注:关于LSD的原版论文可点击此处,这一篇是原课题组又添加了一点改进的版本。

概要

LSD是一个线性时间的线段检测器,提供亚像素的精确结果。它被设计成可以在任何数字图像上工作而不需要调整参数。它可以控制自己的错误检测数量:平均而言,每幅图像允许有一个false alarm。

源码

关于这篇论文的代码和展示页,请点击这里

介绍

这一小节主要是引入了几个概念,下面就进行说明。

A.梯度和水平线

LSD的目的是检测图像上的局部直线轮廓(原文为straight contours)。这就是我们所说的线段。Contours就是图像中灰度等级变化足够快的区域,从暗到亮或相反。因此,图像的梯度和水平线level lines是关键概念。

B.线支持区域和对齐点

算法首先计算每个像素的水平线角度,以产生一个水平线场,即一个单位矢量场,使所有矢量都与穿过其基点的水平线相切。然后,根据一定的公差τ,这个场被分割成像素的连接区域,这些像素共享相同的水平线角度。 这些连接区域被称为线支持区域
说完上面这几个基本概念就举一个例子:
每个线段支持区域(图中间黑色的像素部分)都是一个线段的候选者。相应的几何对象(本例中为矩形)必须与之相关联。线条支持区域的主惯性轴被用作矩形的主要方向;矩形的大小要覆盖整个区域。对于矩形中的像素点,如果它的水平线的角度与矩形的角度在一个公差τ之内,被称为对齐点(aligned points)。

C.线段验证

每个矩形都要经过一个验证程序。在线段支持区域中的所有像素点个数为n,对齐点的个数为k,这两个数值用于验证这个矩形是否要作为一条检测到的线段。
下面就来解释一下这个验证的方法,方法是基于contrario方法(下文简称为相反性原理)和Desolneux, Moisan和Morel提出的亥姆霍兹原理(Helmholtz principle)。
亥姆霍兹原理指出,在有噪声的图像上无法进行感知(或检测)。
相反性原理是为了定义一个噪声,或者一个相反模型(contrario model),这个相反性模型不存在期望的结构。如果在相反模型中,与被观测到的这个事件一样好的事件的预期数量较少,则这个事件就被验证。换句话说,结构化事件被定义为在逆向模型中是罕见的。说人话:结构化事件(structured events)在逆向模型中是罕见的。

那么,怎么把这个原理应用到前面的对齐点等概念中呢?
在相反性模型中,一条线段上的对齐点数量应该和被观测到的线段上的一样多,或者更多。用公式表示就是
Ntest∗PH0[k(r,I)]≥k(r,i)](1)N_{test} * P_{H_0}[k(r,I)] \geq k(r,i)] \ \ \ \ \ \ \ \ \ \ \ (1)Ntest​∗PH0​​[k(r,I)]≥k(r,i)]           (1)
NtestN_{test}Ntest​是可能被考虑的矩形的总数; PH0P_{H_0}PH0​​是相反性模型H0H_0H0​的概率,I是满足相反性模型的一张随机图片;H0H_0H0​随机模型固定了对齐点的数量分布k(r, I),它只取决于与I相关的水平线场的分布。因此, H0H_0H0​是图像梯度方向的噪声模型,而不是图像的噪声模型。 注意:k(r, I)中大写的I不是指某一张图片,而是对应H0H_0H0​模型的水平线场,只取决于梯度方向。

用于LSD的相反性模型H0H_0H0​被定义为一个水平线场的随机模型,它满足下面的性质:

  • {LLA(j)}j∈Pixels\{ LLA(j) \}_{j \in Pixels}{LLA(j)}j∈Pixels​ 由独立随机变量组成的
  • LLA(j)LLA(j)LLA(j) 在[0,2π][0, 2\pi][0,2π]上均匀分布

关于相反性原理这一块具体定理以及证明,如有需要,请自行查看这一小节最后的内容。

算法流程

总的流程见下图,LSD算法将灰度图像作为输入,并返回一个检测到的线段列表。该算法实际上取决于几个决定其性能的数字;它们的值是经过精心设计的,适用于所有图像。它们是LSD设计的内部参数,而不由用户选择。改变它们的值就相当于定义了算法的新变体。
可变体的部分:梯度算子,或者在区域生长过程中的n邻域(比如从8换到4)。
下文将描述该算法的每一步,以及设置六个内部参数的设计标准。S, Σ, ρ, τ, D, 和ε。

A.图像缩放

第一步是把图像缩放为原来大小的64%,即长和宽分别都缩放80%。作用是解决aliasing和quantization artifacts(尤其是阶梯效应,看图6)的问题。对图像进行模糊处理其实也可以有同样的效果,但在相反性模型中会影响图像的统计,也就是有些结构在检测时会引入模糊处理的白噪声。注意:逆向验证适用于缩放后的图像,NFA计算中使用的N×M图像大小对应于1.25N×1.25M大小的输入图像。
缩放是通过高斯下采样进行的:

  • 图像用高斯核进行滤波,以避免混叠。高斯核的标准偏差由σ = Σ/S决定,其中S是缩放系数。Σ的值被设定为0.6,这在避免混叠和避免图像模糊之间取得了良好的平衡。
  • 然后进行下采样。
    这里是经过缩放后的LSD的结果,可以看到图二显示出了结果,而图一虽然还是断开的,但比之前好了很多。

B.梯度计算

计算梯度的时候用的是2*2的Mask,用这么小的尺寸是为了减少计算出的梯度值的依赖性(因此,在噪声图像的情况下,接近理论上的独立)。除此之外,梯度和水平线的角度还编码了边缘的方向,举例子:从暗到亮和从亮到暗是不同的,相应的梯度角或水平线角之间有180度的差异。这意味着LSD检测到的结果线段是有方向性的,其起点和终点的顺序不是任意的。如果图像的对比度被还原(将黑色改为白色,将白色改为黑色),LSD的结果将是相同的,但每个线段的起点和终点将被交换。
先写出常用的梯度计算过程,小写的i对应那一个像素点的灰度值。注意,计算出的值对应于坐标(x+0.5,y+0.5)处的图像梯度,而不是(x,y)。这个半像素的偏移量然后被添加到输出的矩形坐标中,以产生一致的结果。
水平线角度以及梯度大小分别为:

在一个相反的模型中,水平线场是由每个像素的独立随机变量组成的。但实际上,即使图像是白噪声,计算出的水平线场也不完全独立。事实上,相邻的像素值被用来计算梯度,因此梯度是(轻微)依赖的。但是仍然可以使用相反性方法(推导出的阈值也能控制错误检测的数量)。

C.梯度逆排序

为什么要逆排序:
LSD是一种贪婪算法,像素的处理顺序对结果有影响。具有高梯度的像素对应于对比度较大的边缘。在一个边缘中,中心像素通常具有最高的梯度。因此,从具有最高梯度的像素开始寻找线段。排序算法通常需要O(nlogn)操作来对n个值进行排序。但对简单的像素伪排序在线性时间内可以。
具体方法:
创建了1024 bins,对应于图像上零到最大观测值之间的相等梯度区间。像素根据其梯度大小被分类到bin内。LSD首先使用梯度最大的bin中的种子像素;然后从大到小依次类推,直到所有bins都用完。当灰度值范围是[0,255]时,1024 bins足以对梯度值进行几乎严格的分类。

D.梯度阈值

在LSD中,梯度大小小于ρ的像素(对应于平坦区域或缓慢的梯度)被拒绝,不用于构建线支持区域或矩形。假设有一个量化噪声n和一个理想图像i,有下面的式子,其中q是对|∇n|的一个约束,是量化效应导致的梯度值的可能误差的界限,|angle error|要满足 ≤ τ(用在区域增长中的角度误差)的条件。
而且,我们得到阈值为ρ=q/sinτρ = q / sinτρ=q/sinτ
通常,像素值为{0, 1, … …,255}中的整数值。 因此,梯度中的最大可能误差是1(当相邻像素的量化误差为0.5时,不能进行补偿)。由于经验上的原因,我们倾向于一个更保守的界限,我们设定q = 2。但是,如果图像强度范围与[0,255]区间相差很大,这个值就不会有好的结果。

E.区域生长

从未使用的像素的有序列表中的一个像素(种子)开始,用区域生长算法来形成一个线支持区域
递归地,测试已经在区域中的像素的未使用的邻居,并将那些水平线角度等于区域角度θregionθ_{region}θregion​的像素加入到区域中,但前提是不能超过公差τ。初始区域角度θregionθ_{region}θregion​是种子点的水平线角度,当每次有像素被添加到区域中,区域角度值都会被更新为:
过程不断重复,直到没有其他像素可以被添加到该区域。(个人理解:其实就可以理解为对不同的线支持区域进行聚类的过程)
这里使用的是八领域,而且取公差τ为22.5度或π/8弧度,τ的值只影响区域生长的结果,不影响“验证过程”的结果。从下面这个图中可以看出不同的方差对结果的影响。

F.矩形近似

在评估一个线段支持区域之前,必须找到能框住它的矩形。
像素的区域被视作一个刚体,每个像素的梯度大小被用作该点的 “质量”。然后,该区域的质量中心被选为矩形的中心,矩形的主方向被设置为该区域的第一惯性轴。最后,矩形的宽度和长度被设置为使矩形能够覆盖整个线型支撑区域的最小值。矩形的中心(cx, cy)被设置为
其中G(j)是像素j的梯度大小,主矩形的角度被设置为与矩阵的最小特征值相关的特征向量的角度

G. NFA计算

什么是NFA?
NFA就是the number of false alarms (NFA)的缩写,也就是误报的次数;这里我们要计算的是每个矩形的NFA值,如果他小于等于阈值ε,就可以当成检测结果。

这里再次引入一个概念:p-aligned points, 含义是:在方差为pπp\pipπ范围内,矩形中水平线角度和矩形主方向相同的像素点。精度p初始化为τ/π,这里一共试了γ个不同的p。

怎么计算NFA?
NFA(r)=(NM)5/2γ∗B(n,k,p)NFA(r) = (NM)^{5/2}\gamma*B(n,k,p)NFA(r)=(NM)5/2γ∗B(n,k,p)
式子中的n和k在前面提到过,线段支持区域中的所有像素点个数为n,对齐点的个数为k;N和M就是缩放之后,图片的列数和行数;B(n,k,p)是二项式,即
B(n,k,p)=∑j=kn(nj)pj(1−p)n−jB(n,k,p) = \sum_{j=k}^n\binom{n}{j}p^j(1-p)^{n-j}B(n,k,p)=j=k∑n​(jn​)pj(1−p)n−j

关于NFA的阈值ε
用实验结果来看,LSD中,ε取不同值时,结果仍然具有稳定性的这一点。图中只有很少的线段消失了。

H.利用对齐点(分割细化矩形)

区域增长的方法中可能会有个问题:当图像中存在两条直边,而它们之间形成的角度又小于公差τ时,一个矩形就会把两条不同的线段都框进去。解决方式也符合直觉,应该先检测出这个有问题的线支持区域,然后把它合理的切割成两个更小的区域。

当这个问题不存在时,矩形很好地适应了线型支撑区域,而且对齐的点的密度会很高。另一方面,当这个问题存在时,如前图所示,对齐点的密度很低。
另外,当一条略微弯曲的边缘被一连串的直线边缘局部逼近时,逼近的程度(多少线段被用来覆盖部分曲线)与对齐点的密度有关;因此,对齐点的密度也与曲线被线段逼近的精度有关。
计算公式: 很简单,就是k个对齐点数量与矩形面积的比值。这个d必须要大于阈值D=0.7。取这个数值既可以一定程度解决上面的“角度问题”,又不至于发生过度切割。
d=klength(r)∗width(r)d = \frac{k}{length(r) * width(r)}d=length(r)∗width(r)k​

论文中介绍了两种方法来分割矩形。

a.减少角度公差

减少角度公差(也就是对角度的偏差范围要变得更小),用一个新公差τ’更好地适应该区域,之后再用区域生长算法,这样可能就可以把两个成钝角的线段区分开。
那么怎么来估计这个τ’:
取种子点周围的且在原来矩形宽度区域内的像素点,计算这些像素的水平线角度的标准差,标准差的两倍就是τ’。有了这个新方差后,再从相同的种子点进行区域生长算法。在此之前,原始区域上的所有像素都被设置为NOT USED,因此算法可以再次使用它们,而被丢弃的像素则可用于之后的区域。

b.减少区域半径

为什么有了a中的方式,还要有b?
当减小角度公差后,如果算出的线支持区域还是不能满足对齐点的密度要求(方法一失败了,还是分割不开),此时就求助于减少区域半径。
具体是怎么做的呢?
核心就是逐步移除距离种子点较远的像素点,直到可以满足对齐点密度的要求,或者是直到区域多余小而被舍弃。当线支持区域对应于一条曲线,并且该区域需要被缩小,直到满足密度标准,通常意味着获得一定程度的曲线近似,这种方法的效果最好
而这个种子点到区域中最远像素的距离就是区域半径。每次迭代,区域半径都变为原来的75%,半径之外的都会被删除,一直重复直到没有足够像素形成一个有意义的矩形。

I.矩形优化

LSD中的矩形优化包括下面几步:

  • 尝试更高精度,除了初始精度值p(使用了τ/π,以及其他五个数字),还使用p/2, p/4, p/8, p/16, and p/32,哪一个算出来的NFA最小就保留哪一个。
  • 减小矩形的宽度,也就是说初始值为W,之后每次减少0.5像素,W− 0.5, W− 1, W− 1.5, W− 2, and W− 2.5;保留能令NFA最小的那个值
  • 尝试减小矩形的一边,就是把矩形的边整体移动(不知道为什么特意和上一步区分开??有明白的小伙伴吗?),上面的边下移0.5像素,就相当于矩形的中心也向下移了0.25像素。测试的单边便宜量是0.5,1,1.5,2,2.5像素。保留令NFA最小的那个值。
  • 尝试减小矩形的另一边,类似上一步。
  • 尝试更更高的精度,用第一步中得到的p^\hat{p}p^​ 作为初始值,p^\hat{p}p^​/2, p^\hat{p}p^​/4,
    p^\hat{p}p^​/ 8, p^\hat{p}p^​/16, and p^\hat{p}p^​/32。保留令NFA最小的那个值。
    如果一个有意义的矩形找到了,也就是满足NFA≤ε,优化的步骤就停止了。

补充:

  • 初始精度值p = τ/π,在第一部和第三部除了初始值还有另外5个值。
  • γ=11。
  • 精度范围从初始值p = τ/π,一直到p = τ/1024π(足够我们用了),1度的精度就已足够。
  • 对于宽度的优化,有时候可以让工作更好,有时候更差。

J.计算复杂度

进行高斯子采样和计算图像梯度,都可以用与图像中的像素数成比例的操作数来完成。然后,通过分类将像素伪装成分仓,该操作可以在线性时间内完成。线性支持区域查找算法的计算时间与访问的像素数成正比,这个数字等于区域内的像素总数加上每个区域的边界像素。因此,被访问的像素数仍然与图像的总像素数成正比。其余的处理可以分为两种任务。第一种,例如对区域质量进行求和或计算对齐的点,与所有区域涉及的像素总数成正比。第二种,如计算惯性矩或从对齐的点的数量计算NFA值,与区域的数量成正比。所涉及的像素总数和区域的数量都最多等于像素的数量。总而言之,LSD的执行时间与图像中的像素数成正比。

最后论文里还有一部分的图片处理结果的例子,列举除了好的和坏的处理结果。感兴趣的自己可以再看看。

论文笔记-LSD: a Line Segment Detector线特征提取相关推荐

  1. 【转】 LSD(Line Segment Detector) 直线段检测算法学习~

    论文回顾之一 一种新的直线段检测算法---LSD:a Line Segment Detector 原文地址:http://blog.csdn.net/polly_yang/article/detail ...

  2. a Line Segment Detector

    FROM:http://blog.csdn.net/polly_yang/article/details/10085401 近来比较忙+生病,没有大段的时间学习PGM,临睡前回顾一篇论文--<L ...

  3. 直线段检测算法(LSD:a Line Segment Detector)

    直线段检测算法(LSD:a Line Segment Detector) 1 简介 LSD是一种线段检测算法,该方法能在较短的时间内获得较高精度的直线段检测结果. LSD直线检测算法首先计算图像中所有 ...

  4. 目标检测之线段检测---lsd line segment detector

    (1)线段检测应用背景 (2)线段检测原理简介 (3)线段检测实例 a line segment detector (4)hough 变换和 lsd 的区别 --------------------- ...

  5. 【文献翻译】LSD: A Fast Line Segment Detector with a False Detection Control

    前言 博主译文水平不好,为了学习,所以进行论文翻译和研究,博文以译文为主.如果有翻译不对之处,还请各位指出,便于我修改. 文献信息 引用格式:Gioi R G V, Jakubowicz J, Mor ...

  6. LSD(Line Segment Detector)直线提取算法

    LSD是2010年发表在ipol上的一篇论文提出的直线提取算法,在较短的时间内可以提取一张灰度图上所有的线段特征. (文中提到了a contrario model 和 Helmoholtz princ ...

  7. EDLines: A real-time line segment detector with a false detection control

    一.边的提取 在这篇论文中,作者提出了一种新的边缘检测算法,主要优势在于提取出来的线能够保持清晰.连续,在边的提取部分,主要是进行了四步操作: ①滤波 使用高斯滤波器进行处理,过滤噪声并且使图像能够更 ...

  8. [深度学习论文笔记DoDNet: Learning to segment multi-organ and tumors from multiple partially labeled datasets

    DoDNet: Learning to segment multi-organ and tumors from multiple partially labeled datasets DoDNet:学 ...

  9. 论文笔记:ReDet: A Rotation-equivariant Detector for Aerial Object Detection

    论文 paper:https://arxiv.org/pdf/2103.07733.pdf code:https://github.com/csuhan/ReDet 概述 之前说过,cv的论文图画的好 ...

最新文章

  1. “波士顿动力机器人”离上战场又近了一步,逆天了!
  2. 清华大佬手把手教你使用Python进行数据分析和可视化
  3. think in java笔记_Thinking in java读书笔记 PDF 下载
  4. linux 进程内存解析
  5. bin二进制文件的运行
  6. 【CyberSecurityLearning 39】逻辑卷以及格式化挂载、特殊权限(非常重要)
  7. maven依赖 spark sql_window环境运行spark-xgboost 8.1踩到的坑
  8. C#.Net工作笔记003---异步编程async await
  9. 40.leetcode17_letter_combinations_of_a_phone_number
  10. 设计模式07_建造者
  11. python函数知识七 闭包、装饰器一(入门)、装饰器二(进阶)
  12. 如何写一个NB的商业计划书
  13. JAVA 前端上传文件,后端解析文件流并写入数据库
  14. java编写一个测试类_java写一个类,并测试它
  15. 开发一个类似于 xxx 的应用有多难?
  16. 小豆社保「社保代缴」短信接口被盗刷解决方案-企业短信防火墙
  17. Docker镜像-Docker
  18. 正在被二次元改造的中国城市
  19. Revit二次开发,新手接入IExternalCommand、IExternalApplication,如何使用它们!
  20. CSDN的markdown不能正常生成lim符号怎么破?

热门文章

  1. 西门子plc支持什么时间服务器,怎样设置PLC时间
  2. matlab学习笔记(四)
  3. 论文文献引用规范和标准(国标GBT7714)@endnote国标样式@citation交叉引用编号
  4. python爬取b站评论_Python爬虫框架:scrapy抓取B站博人传评论数据
  5. python爬取推特的详细教程_如何利用 Twitter 开放者平台爬取 Twitter 数据?
  6. 一本看到技巧又能保持阳光心态励志书(来自苏鹏的推荐)
  7. nextdate函数白盒测试问题 软件测试_nextdate白盒测试用例
  8. 【面试宝典】软件测试工程师2021烫手精华版(第四章web测试篇)
  9. Unsupervised Monocular Depth Estimation From Light Field Image
  10. mysql 日期转周_Mysql 日期转换星期