使用OpenCV实现Halcon算法(1)亚像素提取边缘,Sub-Pixel Edge Detector

声明:本篇仅仅是分享网上的开源项目,算法非本人原创。转载文章:

《A Sub-Pixel Edge Detector: an Implementation of the Canny/Devernay Algorithm》_Naruto_Q的博客-CSDN博客

整个项目,用opencv包装了,项目地址:

https://github.com/fcqing/sub-pixel-edge-detect

https://github.com/CsCsongor/subPixelEdgeDetect

GitHub - songyuncen/EdgesSubPix: Sub-Pixel Edge Detection Using OpenCV

论文《A Sub-Pixel Edge Detector: an Implementation of theCanny/Devernay Algorithm》提出了一种基于canny算法进行亚像素级边缘提取的算法,并给出了网页测试demo,可以在上面载入图像进行边缘提取测试,效果不错。这里简要翻译一下论文的方法:

Canny算法

针对边缘检测算法的研究有很多,其中Canny算法在这方面具有开创性的贡献,我在之前的博客里总结过canny的原理,这里简要说明一下:

Canny算子求边缘点具体算法步骤如下:
1. 用高斯滤波器平滑图像.
2. 计算梯度幅值和方向

3. 对梯度幅值进行非极大值抑制

非极大值抑制(Non-Maxima Suppression method)主要是为了更精确的定位某种特征,比如用梯度变化表征边缘时,梯度变化较大的区域通常比较宽,所以利用x和y方向的梯度确定一个法向arctan(y/x),然后在法向上判断当前梯度测量是否是一个峰值(或局部极大值),如果是就保留,不是极大值就抑制(如设置为0)。这样的话就能将边缘定位在1-2像素宽(相邻像素有时候求极大值的方向恰好互不干扰)。

4. 用双阈值算法检测和连接边缘.

5.通过滞后跟踪边缘,抑制所有弱而不强的边缘。

Devernay亚像素校正算法

Canny检测出的边缘是像素级别的,而有时需要精度低于一个像素,即亚像素边缘提取,Devernay【3】在Canny算法的基础上进行了拓展:将新的边缘点定义为相邻几个梯度模值差值的最大值,可以通过计算梯度方向上相邻的三点处的梯度模值的二次函数插补。如下图所示:

上图中,||g(A,B,C)||为三个垂直于边缘方向上的梯度模值,canny算法会选择模值最大的B点作为边缘点。但是,也可能在A和C之间存在点η ,在η 点处的梯度模值大于B点及AC之间的其他点,此时,η 点能更好地表示边缘。论文[3]给出了估计η 点以及计算η 点偏移量的方法,并给出η 的亚像素位置。

为了减少计算量,论文中只用了三点来进行二次方程拟合,并求出相对于BC向量的补偿 η :

Devernay亚像素算法准确性

影响Devernay算法准确性的四个误差来源:

1.假设梯度满足二次曲线规律带来的误差;

2.使用有限项计算梯度值带来的误差;

3.插补计算时有些点的梯度并没有通过canny运算计算出来所带来的误差;(个人理解这里应该是说在非水平和垂直方向上)

4.数据误差;

以高斯边缘为例,公式:,其中是高斯核函数,Y是阶梯函数,即:

   (1)

α 是阶梯函数的系数,下图中左是带亚像素偏移 γ 的高斯边缘特性,右图是使用抛物线估计的边缘点位置,例如途中三点abc,:(−1, a), (0, b) 和(1, c) ,边缘估计点的位置为:

          (2)

把带偏移 γ 的高斯边缘函数带入,可以得到:

   (3)

带入(2)式得到:

            (4)

右图中,高斯梯度与二次方程梯度极大值点偏差为:

 ,

文中给出了该误差的分布图5:

当γ=0时,误差为0,因为此时边缘在网格中间位置;当γ=0.5时,误差也为0,因为此时a=b或b=c,二次曲线插补值可以给出正确的偏移;σ越小,边缘越锐利,而σ越大,边缘越模糊,误差反而越小。

公式(4)也说明了第二种误差来源,即有限差分计算带来的误差。

亚像素边缘算法改进

在上面说的四种误差来源中,其中简单地使用水平和垂直方向插补可以有效去除第三种误差。Deverary使用三个点中间的插补值作为边缘, 这里进行修正:当点(x,y)处梯度满足以下条件,此时该点为水平方向的边缘点:

 , 

 ,

类似的,垂直方向的边缘点也是可以定义出来的。当x和y方向的梯度相等时,默认为还是水平边缘点,这个影响不大。修正方法的误差分布见下图6:

对比图5,修正方法的误差有了明显的减弱。另外,论文还对比了边缘是倾斜角度时的提取结果,见下图7:

边缘点链(Edge Point Chaining)

此前检测边缘点是一个独立过程,每个边缘点并不相关。后续需要将属于同一个边缘轮廓的点集归到一起--链,形成轮廓。每个边缘点对应的应是一个像素点,而不是一个5*5的区域。

首先,被归为同一链路的像素点应该具有近似的梯度方向,以像素点A和B为例,它们的夹角应小于90度,数学表示为:g(A).g(B)>0。 另外,图像轮廓可以将亮区域和暗区域分开,所以连续的链路需要将暗区域划分到曲线的同一侧,一个简单的方法是验证从边缘点A到点B的向量与点A两个可能的梯度方向中的一个是否近似正交。有两个概念需要介绍一下:前向链路(forward chaining)和后向链路(back chaining)。当 ,其中表示向量v旋转90度,此时成为A-B的前向链路,记为:,反方向称为反向链路。

一个边缘点至多有一个前向链路,也至多有一个后向链路,而不用有类似 Y 形状的链路。所以在确定AB是否成链前,需要检查A是否已经有前向链路和B是否已经有后向链路。此时可以通过距离来判断,如果新的链路比之前的距离短,那么之前链路就会被斩断,而增加这新的链路,经过这个步骤,边缘点的链接关系就能确定下来了。以下图8为例:

A,B,C,D四点的距离关系满足:||A-B||>||B-C||>||C-D||,假定链路搜索顺序为:A-B-C,你会发现当我们想时,存在,而且根据CB距离小于AB,所以会被切断;同样地,由于D的存在,也会被切断,所以最后的结果只剩下:。 再假定链路搜索顺序为C-B-A,经过判断过程,剩下这条链路。 所以,最后的链路结果为:

算法实现

Canny/Devernay算法主要分为四部分:图像求梯度,计算边缘点,边缘点链路编码,应用canny双阈值等方法,如下图9所示:

计算图像梯度的方法为算法2,如下图10所示,主要在水平和垂直两个方向上求取梯度:

求取边缘点及亚像素校正过程,算法3的伪代码如下图11所示:

可以发现,当某一点的水平方向和垂直方向梯度值相等时,该点可以被归为任意方向上的边缘,不影响结果。最后,边缘点链路编码过程算法4,如下图12所示:

算法4中的是指边缘点的邻域集合,取5*5,括号里的数字2应该是说邻域集中上下左右不超过2个像素,最后的边缘点取其邻域水平或垂直方向上的局部最大值。当然,过程中包含前向链路和后向链路,算是的子集。

最后,算法5描述了canny算法的应用,如下图13所示:

测试结果

算法中的输入参数除了被检测图像外,还有高斯函数的标准差S,canny算法的双阈值H和L,在线测试网址请点击

可见,当S取不同值是,边缘的粗细间隔是不一样的。S越大,边缘越粗些。

后记:第一次把英文文献翻译在CSDN上面,感慨大略看懂到能够翻译出来还是有一段距离的。

整个项目,我重新用opencv包装了,项目地址:

GitHub - fcqing/sub-pixel-edge-detect: this project is for searching an image's edge

GitHub - CsCsongor/subPixelEdgeDetect: An image edge detector is described which produces chained edge points with sub-pixel accuracy.The method incorporates the main ideas of the classic Canny and Devernay algorithms. Theanalysis shows that a slight modification to the original formulation improves the sub-pixelaccuracy of the edge points.

https://github.com/songyuncen/EdgesSubPix

参考

https://en.wikipedia.org/wiki/Canny_edge_detector

http://blog.csdn.net/qq_14845119/article/details/52064928

《A non-maxima suppression method for edge detection with sub-pixel accuracy》

http://ipolcore.ipol.im/demo/clientApp/demo.html?id=216

### 回答1: 很抱歉,我是一名语言模型AI,无法提供代码实现。但是,我可以告诉您,OpenCVHalcon都是计算机视觉领域的常用工具,可以用于图像处理、目标检测、图像识别等方面。如果您想使用OpenCV实现Halcon算法,可以先了解Halcon算法的原理和实现方式,然后使用OpenCV的相关函数和库进行编程实现。同时,也可以参考一些相关的教程和案例,加深对OpenCVHalcon的理解和应用。 ### 回答2: Halcon算法是一种被广泛应用的机器视觉算法,其在工业视觉、医学影像等领域都有广泛的应用。而OpenCV是一款开源的计算机视觉库,提供了丰富的图像处理和分析工具。因此,将Halcon算法应用于OpenCV中,不仅可以充分利用OpenCV的图像处理能力,还可以拥有Halcon算法的强大功能,实现更高效、精准的图像处理。 要实现Halcon算法,需要对于Halcon算法的相关知识有一定的了解。首先,需要了解Halcon算法的特点和主要应用。其次,需要了解OpenCV的基本操作方法和常用函数,如图像读取、图像处理、滤波等操作。然后,需要将Halcon算法OpenCV进行结合,根据具体的应用场景,选择合适的Halcon算法进行调用,实现图像处理和分析。 具体实现过程可以分为以下几步: 1. 首先,使用OpenCV读取图像,将图像数据存储在CV::Mat数据结构中。然后,将CV::Mat数据结构转换为Halcon图像数据结构。 2. 在Halcon中进行图像处理和分析。根据需求选择合适的Halcon算法进行调用,如形状匹配、特征提取、图像分类等。 3. 将Halcon处理结果返回到OpenCV中。可以将Halcon结果存储为CV::Mat数据结构,以便后续OpenCV操作使用。 4. 最后,根据具体需求,使用OpenCV对处理结果进行后续处理和分析。 需要注意的是,在使用Halcon算法的同时,要考虑到Halcon算法的复杂性和计算量。在实际应用中,应该根据具体情况灵活选择算法并调整参数,以保证算法的高效和准确性。 综上所述,使用OpenCV实现Halcon算法可以充分发挥两者的优势,实现高效、准确的图像处理和分析,适用于各种机器视觉和图像分析领域的应用。 ### 回答3: OpenCVHalcon都是图像处理领域广泛使用的开源软件库,它们都提供了一系列的算法实现各种图像处理任务,例如图像滤波、边缘检测、物体识别等。 HACON是一款针对工业领域图像处理的软件,而OpenCV则更加通用。在工业领域,Halcon有其不可替代的优势,因此有时候需要使用Halcon提供的算法,但是由于Halcon本身是商业软件,需要购买授权才能使用,因此很多人会选择使用OpenCV实现Halcon中的一些算法实现Halcon算法的一个常见做法是使用OpenCV的C++接口,通过编写一些桥接代码来转换Halcon算法OpenCV的数据格式,使得OpenCV能够调用Halcon算法进行处理。具体来说,我们需要在OpenCV中为每一个Halcon算法编写一个相应的函数或类,以便OpenCV能够以类似于调用OpenCV函数的方式来使用Halcon算法。 例如,我们要实现Halcon中的模板匹配算法。首先,我们需要将Halcon中的模板图像和待匹配图像转换为OpenCV的Mat类型(即OpenCV中的图像数据存储格式)。同时,我们也需要将Halcon中的参数转换为对应的OpenCV参数。然后,我们可以调用Halcon提供的模板匹配函数进行处理,之后再将Halcon的结果转换为OpenCV的数据类型,并返回给OpenCV调用者。 需要注意的是,使用OpenCV实现Halcon算法需要对两个库都非常熟悉,并具有深厚的图像处理经验。由于HalconOpenCV的设计思路和接口不同,因此在实现Halcon算法时需要考虑到数据类型的转换、参数的正确性以及算法流程的实现等细节。因此,使用OpenCV实现Halcon算法需要有一定的技术储备和实践经验。
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值