霍夫变换+最小二乘法 直线检测
- 格式:doc
- 大小:726.74 KB
- 文档页数:6
霍夫变换直线检测 c语言霍夫变换是一种在图像处理中广泛应用的算法,用于检测图像中的直线。
它是由霍夫于1962年提出的,被广泛应用于计算机视觉领域。
霍夫变换的基本原理是将直线表示为参数空间中的点,然后通过统计参数空间中的点的数量来确定直线。
具体而言,对于图像中的每个点,我们可以通过遍历参数空间中的所有可能的直线,来确定该点是否在直线上。
如果该点在直线上,则在参数空间中对应的直线的计数加1。
最后,我们可以根据参数空间中点的数量,来确定图像中的直线。
在C语言中实现霍夫变换的直线检测可以分为以下几个步骤:1. 图像预处理:首先,我们需要对图像进行预处理,以便更好地进行直线检测。
常见的预处理操作包括灰度化、边缘检测等。
通过将彩色图像转换为灰度图像,我们可以简化计算,并且减少噪声的影响。
边缘检测可以帮助我们找到图像中的边缘,从而更好地检测直线。
2. 参数空间的定义:在霍夫变换中,我们需要定义参数空间。
对于直线检测,常用的参数是直线的斜率和截距。
我们可以通过定义一个二维数组来表示参数空间,其中每个元素对应一个直线的斜率和截距。
3. 参数空间的计算:对于图像中的每个边缘点,我们都需要遍历参数空间中的所有可能的直线,并将对应的直线的计数加1。
这可以通过两层循环来实现,外层循环遍历所有可能的斜率,内层循环遍历所有可能的截距。
4. 直线检测:在计算完参数空间后,我们可以根据参数空间中的计数来确定图像中的直线。
通常,我们会设定一个阈值,只有当参数空间中的计数超过该阈值时,才认为该直线存在。
5. 直线绘制:最后,我们可以将检测到的直线绘制在图像上,以便查看结果。
这可以通过在图像上绘制参数空间中计数最大的直线来实现。
需要注意的是,霍夫变换的效果受到参数空间的定义和阈值的选择的影响。
如果参数空间定义得不合理,或者阈值选择不当,可能会导致直线检测的准确性下降。
因此,在实际应用中,需要根据具体情况进行调整和优化。
总结起来,霍夫变换是一种常用的直线检测算法,可以通过对图像进行预处理、定义参数空间、计算参数空间、检测直线和绘制直线等步骤来实现。
直线状目标的特征提取方法研究直线状目标的特征提取方法是图像处理和计算机视觉领域的一个重要研究方向。
在这个问题中,我们可以从多个角度来探讨直线状目标的特征提取方法。
首先,我们可以从传统的图像处理方法开始讨论。
传统的特征提取方法包括边缘检测、霍夫变换和直线拟合等。
边缘检测可以帮助我们找到图像中的边缘信息,而霍夫变换可以用来检测直线。
直线拟合则可以通过最小二乘法或者RANSAC等方法来拟合检测到的直线,从而提取直线的特征。
其次,我们可以讨论基于深度学习的特征提取方法。
随着深度学习的发展,卷积神经网络在图像特征提取方面取得了很大的成功。
可以使用卷积神经网络来提取图像中的直线特征,例如利用卷积层来提取图像中的边缘信息,再通过后续的网络结构来检测和拟合直线。
另外,我们还可以讨论基于特征描述子的方法。
例如,可以使用SIFT(尺度不变特征变换)或者SURF(加速稳健特征)等特征描述子来提取图像中的直线特征。
这些方法可以对图像中的局部特征进行描述,并且具有一定的尺度和旋转不变性,适用于直线状目标的特征提取。
此外,还可以讨论基于多传感器融合的特征提取方法。
当图像数据不够丰富或者复杂时,可以考虑融合其他传感器的数据,例如激光雷达或者红外传感器等。
通过融合多种传感器的数据,可以更准确地提取直线状目标的特征。
综上所述,直线状目标的特征提取方法涉及传统图像处理、深度学习、特征描述子以及多传感器融合等多个方面。
不同的方法各有优劣,可以根据具体的应用场景和需求来选择合适的特征提取方法。
希望以上回答能够全面地解答你关于直线状目标特征提取方法的问题。
基于最小二乘修正的随机Hough变换直线检测作者:乔寅骐肖健华黄银和尹奎英来源:《计算机应用》2015年第11期摘要:利用Hough变换进行直线检测时,由于直线在参数空间中的映射容易受到邻近目标、噪声以及本身非理想状态的干扰,算法中的投票过程较易出现无效累积,进而导致虚检、漏检及端点定位不准等问题。
针对传统方法的上述缺陷,提出了一种基于ρθ域最小二乘拟合修正的随机Hough变换的直线检测方法。
首先,在随机抽样时利用像素-长度比值对抽样的有效性进行判定,剔除不在直线上的抽样点对;然后,对邻域相关点进行ρθ域的最小二乘拟合,得到修正后的直线参数用于累加投票,投票过程中设定累加阈值,通过检测峰值点逐次检出疑似长直线;最后,通过设定断裂阈值对每条长直线进行筛选和分段,定位出直线段的端点。
仿真实验表明,所提方法在投票时有效抑制了复杂环境对局部最大值的干扰,使直线检测的准确率得到显著提升。
关键词:直线检测;随机Hough变换;投票有效性;最小二乘法;参数空间中图分类号: TP391.4文献标志码:A0引言在图像处理和计算机视觉领域,目标识别是一个重要的课题,而直线的检测又是其中最为基本的内容之一。
直线检测之前通常需要对图像进行预处理,如去噪、增强、分割、边缘检测等,将图像转换为只包含边缘信息的二值图像再进行直线检测[1-2]。
图像直线检测的难点在于,既要正确捕获直线目标,又要保证一定的宽容度以适应非理想直线的情形。
Hough变换(Hough Transform, HT)是处理直线检测问题的一种经典算法,在诸多领域得到了广泛应用[3-5]。
它的主要思想是,在参数空间的离散化网格中,利用“多对一”映射将各个像素点映射到参数空间,然后通过累加“投票”得到共线的像素点在参数空间的映射,进而得到图像中直线的参数。
这种方法为在参数域进行直线检测提供了新的思路,但实际应用中由于非理想直线和复杂场景干扰,效果不佳。
一方面图像中的潜在直线往往因为噪声的干扰而偏离理想状态,出现诸如局部弯曲或断裂的现象,参数空间峰值点不容易被检测到,导致漏检;另一方面,潜在直线周边的其他非直线目标像素的存在,使参数空间相应位置出现伪峰,导致虚检。
hough变换直线检测主要原理
霍夫变换是一种在图像空间进行几何形状检测的方法,用于检测平面上的直线。
主要原理如下:
1. 点与直线的表示:霍夫变换使用极坐标系来表示直线,每个点在图像中表示一条通过该点的直线。
直线可以用两个参数表示:r表示离原点的距离,θ表示与x轴的夹角。
2. 累加过程:对每个点,遍历所有可能的直线参数,并在霍夫空间中进行累加。
对于每个点,对应于通过该点的所有直线,累加器中相应位置的值加1。
这个累加过程可以在霍夫空间中的一个二维数组中进行。
3. 阈值检测:当累加器中的某个值超过预设的阈值时,认为该直线存在。
这个阈值可以根据应用需求进行设置。
4. 参数反算:根据累加器中的峰值,反算出对应的直线参数(r和θ),并在图像中绘制出检测到的直线。
霍夫变换的主要优点是对于存在噪声和局部遮挡的图像仍然能够有效地检测直线。
但是其缺点是计算复杂度较高,直线的参数空间较大,需要处理大量的累加器。
同时,霍夫变换对于直线的精确定位和参数估计准确性不高,对于曲线的检测效果较差。
霍夫变换(hough transform)霍夫变换(Hough Transform)霍夫变换是一种图像处理技术,用于在图像中检测直线、圆形等几何形状。
它最早由Paul Hough在1962年提出。
霍夫变换在计算机视觉和模式识别领域得到广泛应用,特别在边缘检测和形状分析中表现出色。
一、霍夫变换原理1. 直线检测霍夫变换的直线检测基于极坐标下的直线方程:ρ = xcosθ + ysinθ。
其中,ρ表示直线与原点的距离,θ为直线与x轴的夹角。
霍夫变换通过在ρ-θ空间中进行投票,找到出现频率最高的ρ和θ组合,即可以确定一条直线。
2. 圆形检测霍夫变换的圆形检测考虑到圆心坐标和半径。
以圆心坐标(xc, yc)和半径r为变量,对每个像素点进行投票。
根据累加器中出现频率最高的圆心和半径组合,即可确定一个圆。
二、霍夫变换的步骤1. 边缘检测霍夫变换需要基于边缘图像进行处理,因此首先需要对原始图像进行边缘检测。
常用的边缘检测算法有Canny边缘检测和Sobel算子等。
2. 构建累加器对于直线检测,构建一个二维累加器数组,用于记录直线参数的出现频率。
对于圆形检测,构建一个三维累加器数组,用于记录圆心和半径的出现频率。
3. 参数空间搜索遍历边缘图像上的每个像素点,对于每个边缘像素,计算对应的ρ和θ(直线检测)或圆心坐标和半径(圆形检测)。
在累加器中相应位置加1。
4. 参数估计根据累加器中出现频率最高的位置,估计出最佳直线或圆形的参数。
可以设定一个阈值,只接受出现频率高于该阈值的参数。
5. 绘制检测结果根据参数估计的结果,在原始图像上绘制检测出的直线或圆形。
三、霍夫变换的应用1. 直线检测霍夫变换的直线检测广泛应用于计算机视觉领域。
例如,道路标线检测、物体边缘检测、图像中的几何形状检测等。
通过直线检测,可以提取出图像中的重要几何特征,为后续的图像处理和分析提供基础。
2. 圆形检测霍夫变换的圆形检测可以应用于许多领域,例如医学图像处理、目标跟踪、光学字符识别等。
c++霍夫变换检测直线通常这是⼀幅边缘图像,⽐如来⾃ Canny算⼦。
cv:: Houghlines函数的输出是cV::Vec2f向量,每个元素都是⼀对代表检测到的直线的浮点数(p,0)。
在下例中我们⾸先应⽤ Canny算⼦获取图像轮廓,然后基于霍夫变换检测直线这个函数的的表达直线的⽅式⽤的不习惯的话可以⽤下⾯这个。
HoughLinesP函数的原型为:void HoughLinesP(InputArray image,OutputArray lines, double rho, double theta, int threshold, double minLineLength=0,double maxLineGap=0 )image为输⼊图像,要求是8位单通道图像lines为输出的直线向量,每条线⽤4个元素表⽰,即直线的两个端点的4个坐标值rho和theta分别为距离和⾓度的分辨率threshold为阈值,即步骤3中的阈值minLineLength为最⼩直线长度,在步骤5中要⽤到,即如果⼩于该值,则不被认为是⼀条直线maxLineGap为最⼤直线间隙,在步骤4中要⽤到,即如果有两条线段是在⼀条直线上,但它们之间因为有间隙,所以被认为是两个线段,如果这个间隙⼤于该值,则被认为是两条线段,否则是⼀条。
int main(){Mat img = imread("D:\\pdf2jpg\\nn\\00010.jpg");//GetRedComponet(img);Mat contours,res;Canny(img,contours,125,350);cvtColor( contours, res, CV_GRAY2BGR );vector<Vec4i> lines;HoughLinesP(contours, lines, 1, CV_PI/180, 80, 30, 10 );for( size_t i = 0; i < lines.size(); i++ ){Vec4i l = lines[i];line(res, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 2);}imwrite("D:\\dst1.jpg",res);}统计概论霍夫直线检测houghlinesP是⼀个改进,不仅执⾏效率较⾼,⽽且能检测到直线的两个端点。
OpenCV实现霍夫变换直线检测霍夫变换(Hough Transform)是图像处理中检测是否存在直线的重要算法,该算法是由Paul Hough在1962年⾸次提出,最开始只能检测图像中的直线,但是霍夫变换经过不断的扩展和完善已经可以检测多种规则形状,例如圆形、椭圆等。
霍夫变换通过将图像中的像素在⼀个空间坐标系中变换到另⼀个坐标空间坐标系中,使得在原空间中具有形同特性的曲线或者直线映射到另⼀个空间中形成峰值,从⽽把检测任意形状的问题转化为统计峰值的问题。
霍夫变换通过构建检测形状的数学解析式将图像中像素点映射到参数空间中,例如我们想检测两个像素点所在的直线,需要构建直线的数学解析式。
在图像空间x-y直⾓坐标系中,对于直线可以⽤式(7.1)所⽰的解析式来表⽰。
其中k是直线的斜率,b是直线的截距。
假设图像中存在⼀像素点A(x0,y0),所有经过这个像素点直线可以⽤式表⽰。
在图像空间x-y直⾓坐标系中,由于变量是x和y,因此式表⽰的是经过点像素点A(x0,y0)的直线,但是经过⼀点的直线有⽆数条,因此式中的和具有⽆数个可以选择的值,如果将x0和y0看作是变量, k和 b表⽰定值,那么式可以表⽰在k-b空间的⼀条直线,映射过程⽰意图如图所⽰。
⽤式的形式表⽰映射的结果如式所⽰,即霍夫变换将x-y直⾓坐标系中经过⼀点的所有直线映射成了k-b空间中的⼀条直线,直线上的每个点都对应着x-y直⾓坐标系中的⼀条直线。
当图像中存在另⼀个像素点B(x1,y1)时,在图像空间x-y直⾓坐标系中所有经过像素点B(x1,y1)的直线也会在参数空间中映射出⼀条直线。
由于参数空间中每⼀个点都表⽰图像空间x-y直⾓坐标系中直线的斜率和截距,因此如果有⼀条直线经过像素点A(x0,y0)和像素点B(x1,y1)时,这条直线所映射在参数空间中的坐标点应该既在像素点A(x0,y0)映射的直线上⼜在像素点B(x1,y1)映射的直线上。
在平⾯内⼀个点同时在两条直线上,那么这个点⼀定是两条直线的交点,因此这条同时经过A(x0,y0)和B(x1,y1)的直线所对应的斜率和截距就是参数空间中两条直线的交点。
基于霍夫变换的直线检测技术科技信息博士·专家论坛基于霍夫变换的直线检测技术唐佳林1王镇波2张鑫鑫1(1.北京理工大学珠海学院信息学院2.中山大学智能交通研究中心)[摘要]直线检测是数字图像处理的重要内容,在道路识别,建筑物识别,医学图像分析等领域都有十分重要的应用。
通过对已经受直线中的间隙和噪声影响较小。
在Matlab获得的图像进行边缘检测,然后用Hough变换对边缘检测进行直线检测。
该方法简单,环境下对该方法进行了仿真实验,并对图像中直线目标进行了检测,结果表明用该方法对图像中直线目标进行检测是快速有效的。
[关键词]Hough变换边缘检测直线检测引言人工图像和卫星影像中,大多数物体都是由直线组成的。
在图像处理中,对直线的识别和定位就显得十分重要。
同时,工程上对直线物体或图标进行模式识别和定位是一个常见的问题。
所以寻求一种快速的直线检测方法非常重要。
Hough变换是一种用来在边缘增强处理后的圆、椭图像中,提取边缘特征的简便而有效的方法,它能够提取直线、[1-2]圆、二次曲线甚至是任意形状的边缘。
Hough变换在计算机视觉、军事防御、办公自动化等领域都得到了[3]普遍的关注和广泛的应用。
其基本思想是将原图像变换到参数空间,用大多数边界点满足某种参数形式来描述图像中的线,通过设置累加器进行累积,求得峰值对应的点所需要的信息。
Hough变换以其对局部缺损的不敏感,对随机噪声的鲁棒性以及适于并行处理等优良特性,备模式识别和计算机视觉领域学者的青睐。
Hough变换的突受图像处理、出优点就是可以将图像中较为困难的全局检测问题转换为参数空间中相对容易解决的局部峰值检测问题。
1.Hough变换原理出ρ;并将该单元的累加器(5)在参数空间中,找到ρ和α所对应得单元,加1,即Q(i,j)=Q(i,j)+1;(6)当直角坐标系中的点都经过(3)(4)两步遍历后,检验参数空间中每个累加器的值,累加器最大的单元所对应的ρ和α即为直角坐标系中的直线方程式(1-1)的参数。
霍夫直线变换原理
霍夫直线变换原理是一种在计算机视觉和图像处理领域广泛应用的技术,它通过检测图像中的直线来实现目标检测、图像分割等功能。
本文将介绍霍夫直线变换原理的基本概念、应用场景以及实现方法。
霍夫直线变换原理是由霍夫(Hough)在1962年提出的,旨在解决在图像中检测直线的问题。
其基本原理是将直线表示为参数空间中的一个点,并通过累加来检测出直线。
具体来说,对于图像中的每个像素点,如果它可能属于某条直线,就在参数空间中为该直线的参数进行累加。
最终,累加值最大的点即为检测到的直线。
在实际应用中,霍夫直线变换可以用于很多领域,如道路标线检测、边缘检测、医学图像分析等。
以道路标线检测为例,通过霍夫直线变换,可以准确地检测出道路上的直线标线,为自动驾驶系统提供关键信息。
要实现霍夫直线变换,首先需要进行边缘检测,以获取图像中的直线信息。
常用的边缘检测算法包括Sobel算子、Canny算子等。
然后,对于每个边缘点,通过霍夫变换算法计算其在参数空间中的累加值,并找出累加值最大的点,即为检测到的直线。
除了传统的霍夫直线变换算法外,还有一些改进的算法,如累计霍夫变换(Accumulator Hough Transform)、多分辨率霍夫变换(Multiscale Hough Transform)等,可以提高算法的效率和准确性。
总的来说,霍夫直线变换原理是一种强大的图像处理技术,可以在很多领域发挥重要作用。
通过检测图像中的直线,可以实现目标检测、图像分割等功能,为计算机视觉和图像处理领域带来了很大的便利。
希望本文的介绍能够帮助读者更好地了解霍夫直线变换原理,从而在实际应用中更好地应用这一技术。
霍夫变换直线检测 c语言霍夫变换是一种常用的图像处理方法,可以用于直线检测。
在计算机视觉和模式识别领域,霍夫变换被广泛应用于直线检测、圆检测和形状检测等任务中。
霍夫变换最早由霍夫于1962年提出,用于检测图像中的直线。
它的基本思想是将直线表示为参数空间中的一个点,然后通过统计参数空间中的投票数来确定图像中的直线。
在霍夫变换中,我们需要定义两个参数:极坐标中的角度和距离。
对于图像中的每个像素点,我们可以遍历所有可能的角度和距离值,并在参数空间中进行投票。
当某个参数组合得到足够多的票数时,我们认为这个参数组合对应的直线在图像中存在。
通过这种方式,我们可以找到图像中的所有直线。
在具体实现中,我们通常使用二维数组来表示参数空间。
数组的行数表示角度的离散值,列数表示距离的离散值。
对于每个像素点,我们遍历所有可能的参数组合,并在相应的数组位置上进行投票。
最后,我们在参数空间中找到投票数最多的位置,即为图像中的直线。
霍夫变换的优点是能够检测出任意角度和长度的直线,对噪声和局部变形具有一定的鲁棒性。
然而,它也存在一些缺点。
首先,计算复杂度较高,特别是对于大尺寸的图像。
其次,参数空间的离散化可能导致检测到的直线不够精确。
因此,在实际应用中,我们需要根据具体情况选择合适的参数值,以达到较好的检测效果。
除了直线检测,霍夫变换还可以用于圆检测和形状检测。
对于圆检测,我们需要定义三个参数:圆心的横坐标、纵坐标和半径。
对于形状检测,我们可以根据需要定义更多的参数。
总结来说,霍夫变换是一种常用的图像处理方法,可以用于直线检测、圆检测和形状检测等任务。
它的基本思想是通过统计参数空间中的投票数来确定图像中的目标。
尽管霍夫变换存在一些缺点,但在实际应用中,我们可以通过选择合适的参数值和优化算法来克服这些问题。
希望通过本文的介绍,读者能够对霍夫变换有一个初步的了解,进一步探索其在图像处理中的应用。
霍夫变换检测图像直线算法python实现创作不易,如果对您有帮助,帮忙点赞哦!⼀. 霍夫变换理解:可参考:⼆. 霍夫变换简介:霍夫变换,是将坐标由直⾓坐标系变换到极坐标系,然后再根据数学表达式检测某些形状(如直线和圆)的⽅法。
当 l1直线上的某些点变换到极坐标系下时,表现为某些线(和前⾯点数量⼀致),这些线交于⼀点,通过该点的坐标就能表⽰原先的 l1直线。
三. 霍夫变换⽤于检测图像直线算法实现:①提取图像边缘(可使⽤Canny算法等)[我也实现了它,前⾯Canny算法有问题可以参考我的另⼀篇⽂章:]②实现⼆值图像霍夫变换1. 求出图像对⾓线长:r_max2. 在边缘点 (x,y) 处,t 取[0,180),步长设为1,根据下式进⾏霍夫变换霍夫变换,(r_ho,t) 表⽰极坐标,(x,y) 表⽰直⾓坐标↑3. 做⼀个⼤⼩为 r_max * 180 的表,变换后⼀个值落在表内某坐标,就将该坐标表内值 + 1,简⾔之,就是在进⾏投票,统计通过哪个点的直线的数量最多(即在原图像上越趋近于⼀条直线)。
③进⾏⾮极⼤值抑制(NMS)操作,使找出的直线落在不同的地点NMS 的算法如下:1. 遍历该表,如果遍历到的像素的投票数⼤于其8近邻的像素投票值,则它不变。
2. 如果遍历到的像素的投票数⼩于其8近邻的像素投票值,则将其设置为0。
④找到20个投票数最多的点(即:直⾓坐标系下20条直线)准备进⾏输出1. np.ravel 将多维数组降为1维2. np.argsort 将数组元素从⼩到⼤排序,返回索引值3. [::-1] 数组反序 -> 得到从⼤到⼩索引值4. [:20] 前20个最⼤投票值的索引5. 根据索引得到坐标(r,t)⑤霍夫反变换后,画出原图中的20条直线,输出图像霍夫逆变换公式↑四. 纯⼿⼯实现 ——> 利⽤霍夫变换检测图像中的直线2import numpy as np3import matplotlib.pyplot as plt45# Canny算法:提取图像边缘6def Canny(img):78# Gray scale9def BGR2GRAY(img):10 b = img[:, :, 0].copy()11 g = img[:, :, 1].copy()12 r = img[:, :, 2].copy()1314# Gray scale15 out = 0.2126 * r + 0.7152 * g + 0.0722 * b16 out = out.astype(np.uint8)1718return out192021# Gaussian filter for grayscale22def gaussian_filter(img, K_size=3, sigma=1.3):2324if len(img.shape) == 3:25 H, W, C = img.shape26 gray = False27else:28 img = np.expand_dims(img, axis=-1)29 H, W, C = img.shape30 gray = True3132## Zero padding33 pad = K_size // 234 out = np.zeros([H + pad * 2, W + pad * 2, C], dtype=np.float)35 out[pad : pad + H, pad : pad + W] = img.copy().astype(np.float)3637## prepare Kernel38 K = np.zeros((K_size, K_size), dtype=np.float)39for x in range(-pad, -pad + K_size):40for y in range(-pad, -pad + K_size):41 K[y + pad, x + pad] = np.exp( - (x ** 2 + y ** 2) / (2 * sigma * sigma))42#K /= (sigma * np.sqrt(2 * np.pi))43 K /= (2 * np.pi * sigma * sigma)44 K /= K.sum()4546 tmp = out.copy()4748# filtering49for y in range(H):50for x in range(W):51for c in range(C):52 out[pad + y, pad + x, c] = np.sum(K * tmp[y : y + K_size, x : x + K_size, c]) 5354 out = np.clip(out, 0, 255)55 out = out[pad : pad + H, pad : pad + W]56 out = out.astype(np.uint8)5758if gray:59 out = out[..., 0]6061return out626364# sobel filter65def sobel_filter(img, K_size=3):66if len(img.shape) == 3:67 H, W, C = img.shape68else:69 H, W = img.shape7071# Zero padding72 pad = K_size // 273 out = np.zeros((H + pad * 2, W + pad * 2), dtype=np.float)74 out[pad : pad + H, pad : pad + W] = img.copy().astype(np.float)75 tmp = out.copy()7677 out_v = out.copy()78 out_h = out.copy()7980## Sobel vertical81 Kv = [[1., 2., 1.],[0., 0., 0.], [-1., -2., -1.]]82## Sobel horizontal83 Kh = [[1., 0., -1.],[2., 0., -2.],[1., 0., -1.]]86for y in range(H):87for x in range(W):88 out_v[pad + y, pad + x] = np.sum(Kv * (tmp[y : y + K_size, x : x + K_size]))89 out_h[pad + y, pad + x] = np.sum(Kh * (tmp[y : y + K_size, x : x + K_size]))9091 out_v = np.clip(out_v, 0, 255)92 out_h = np.clip(out_h, 0, 255)9394 out_v = out_v[pad : pad + H, pad : pad + W]95 out_v = out_v.astype(np.uint8)96 out_h = out_h[pad : pad + H, pad : pad + W]97 out_h = out_h.astype(np.uint8)9899return out_v, out_h100101102def get_edge_angle(fx, fy):103# get edge strength104 edge = np.sqrt(np.power(fx.astype(np.float32), 2) + np.power(fy.astype(np.float32), 2))105 edge = np.clip(edge, 0, 255)106107 fx = np.maximum(fx, 1e-10)108#fx[np.abs(fx) <= 1e-5] = 1e-5109110# get edge angle111 angle = np.arctan(fy / fx)112113return edge, angle114115116def angle_quantization(angle):117 angle = angle / np.pi * 180118 angle[angle < -22.5] = 180 + angle[angle < -22.5]119 _angle = np.zeros_like(angle, dtype=np.uint8)120 _angle[np.where(angle <= 22.5)] = 0121 _angle[np.where((angle > 22.5) & (angle <= 67.5))] = 45122 _angle[np.where((angle > 67.5) & (angle <= 112.5))] = 90123 _angle[np.where((angle > 112.5) & (angle <= 157.5))] = 135124125return _angle126127128def non_maximum_suppression(angle, edge):129 H, W = angle.shape130 _edge = edge.copy()131132for y in range(H):133for x in range(W):134if angle[y, x] == 0:135 dx1, dy1, dx2, dy2 = -1, 0, 1, 0136elif angle[y, x] == 45:137 dx1, dy1, dx2, dy2 = -1, 1, 1, -1138elif angle[y, x] == 90:139 dx1, dy1, dx2, dy2 = 0, -1, 0, 1140elif angle[y, x] == 135:141 dx1, dy1, dx2, dy2 = -1, -1, 1, 1142if x == 0:143 dx1 = max(dx1, 0)144 dx2 = max(dx2, 0)145if x == W-1:146 dx1 = min(dx1, 0)147 dx2 = min(dx2, 0)148if y == 0:149 dy1 = max(dy1, 0)150 dy2 = max(dy2, 0)151if y == H-1:152 dy1 = min(dy1, 0)153 dy2 = min(dy2, 0)154if max(max(edge[y, x], edge[y + dy1, x + dx1]), edge[y + dy2, x + dx2]) != edge[y, x]: 155 _edge[y, x] = 0156157return _edge158159def hysterisis(edge, HT=100, LT=30):160 H, W = edge.shape161162# Histeresis threshold163 edge[edge >= HT] = 255164 edge[edge <= LT] = 0165166 _edge = np.zeros((H + 2, W + 2), dtype=np.float32)167 _edge[1 : H + 1, 1 : W + 1] = edge169## 8 - Nearest neighbor170 nn = np.array(((1., 1., 1.), (1., 0., 1.), (1., 1., 1.)), dtype=np.float32) 171172for y in range(1, H+2):173for x in range(1, W+2):174if _edge[y, x] < LT or _edge[y, x] > HT:175continue176if np.max(_edge[y-1:y+2, x-1:x+2] * nn) >= HT:177 _edge[y, x] = 255178else:179 _edge[y, x] = 0180181 edge = _edge[1:H+1, 1:W+1]182183return edge184185# grayscale186 gray = BGR2GRAY(img)187188# gaussian filtering189 gaussian = gaussian_filter(gray, K_size=5, sigma=1.4)190191# sobel filtering192 fy, fx = sobel_filter(gaussian, K_size=3)193194# get edge strength, angle195 edge, angle = get_edge_angle(fx, fy)196197# angle quantization198 angle = angle_quantization(angle)199200# non maximum suppression201 edge = non_maximum_suppression(angle, edge)202203# hysterisis threshold204 out = hysterisis(edge, 100, 30)205206return out207208# 霍夫变换实现检测图像中的20条直线209def Hough_Line(edge, img):210## Voting211def voting(edge):212 H, W = edge.shape213214 drho = 1215 dtheta = 1216217# get rho max length218 rho_max = np.ceil(np.sqrt(H ** 2 + W ** 2)).astype(np.int)219220# hough table221 hough = np.zeros((rho_max, 180), dtype=np.int)222223# get index of edge224# ind[0] 是符合条件的纵坐标,ind[1]是符合条件的横坐标225 ind = np.where(edge == 255)226227## hough transformation228# zip函数返回元组229for y, x in zip(ind[0], ind[1]):230for theta in range(0, 180, dtheta):231# get polar coordinat4s232 t = np.pi / 180 * theta233 rho = int(x * np.cos(t) + y * np.sin(t))234235# vote236 hough[rho, theta] += 1237238 out = hough.astype(np.uint8)239240return out241242# non maximum suppression243def non_maximum_suppression(hough):244 rho_max, _ = hough.shape245246## non maximum suppression247for y in range(rho_max):248for x in range(180):249# get 8 nearest neighbor250 x1 = max(x-1, 0)251 x2 = min(x+2, 180)253 y2 = min(y+2, rho_max-1)254if np.max(hough[y1:y2, x1:x2]) == hough[y,x] and hough[y, x] != 0: 255pass256#hough[y,x] = 255257else:258 hough[y,x] = 0259260return hough261262def inverse_hough(hough, img):263 H, W, _= img.shape264 rho_max, _ = hough.shape265266 out = img.copy()267268# get x, y index of hough table269# np.ravel 将多维数组降为1维270# argsort 将数组元素从⼩到⼤排序,返回索引271# [::-1] 反序->从⼤到⼩272# [:20] 前20个273 ind_x = np.argsort(hough.ravel())[::-1][:20]274 ind_y = ind_x.copy()275 thetas = ind_x % 180276 rhos = ind_y // 180277278# each theta and rho279for theta, rho in zip(thetas, rhos):280# theta[radian] -> angle[degree]281 t = np.pi / 180. * theta282283# hough -> (x,y)284for x in range(W):285if np.sin(t) != 0:286 y = - (np.cos(t) / np.sin(t)) * x + (rho) / np.sin(t)287 y = int(y)288if y >= H or y < 0:289continue290 out[y, x] = [0,255,255]291for y in range(H):292if np.cos(t) != 0:293 x = - (np.sin(t) / np.cos(t)) * y + (rho) / np.cos(t)294 x = int(x)295if x >= W or x < 0:296continue297 out[y, x] = [0,0,255]298299 out = out.astype(np.uint8)300301return out302303304# voting305 hough = voting(edge)306307# non maximum suppression308 hough = non_maximum_suppression(hough)309310# inverse hough311 out = inverse_hough(hough, img)312313return out314315316# Read image317 img = cv2.imread("../paojie.jpg").astype(np.float32)318319# Canny320 edge = Canny(img)321322# Hough323 out = Hough_Line(edge, img)324325 out = out.astype(np.uint8)326327# Save result328 cv2.imwrite("out.jpg", out)329 cv2.imshow("result", out)330 cv2.waitKey(0)331 cv2.destroyAllWindows()View Code五. 实验结果:原图↑霍夫变换检测到的直线↑六. 参考内容:七. 版权声明:未经作者允许,请勿随意转载抄袭,抄袭情节严重者,作者将考虑追究其法律责任,创作不易,感谢您的理解和配合!。
寻找圆心算法一、背景介绍圆心是圆的几何中心,对于许多几何问题的解决都离不开对圆心的确定。
寻找圆心算法是一种用于确定给定圆的圆心坐标的计算方法。
在几何学、图像处理、计算机视觉以及机器人等领域都有广泛的应用。
二、常见的寻找圆心算法在本章节,将介绍一些常见的用于寻找圆心的算法,包括:1. 三点法三点法是最直观也是最简单的寻找圆心算法。
它利用了圆的性质:圆上任意三个点确定一个唯一的圆。
具体步骤如下: 1. 任意选择三个圆上的点。
2. 知道三点的坐标后,根据三点共线的条件判断它们是否共线。
如果共线,即可确认三点所在的直线是圆的直径,圆心为直线中点。
3. 如果不共线,则通过计算三个点的垂直平分线的交点来确定圆心。
2. 最小二乘法最小二乘法是一种基于最小二乘原理的圆心寻找算法。
该方法通过拟合圆上的点到圆心的距离最小化来确定圆心位置。
具体步骤如下: 1. 选择至少三个圆上的点,并记录它们的坐标。
2. 建立误差函数,即圆上的点到圆心的距离与拟合圆半径的差的平方和。
3. 使用数值优化算法(如梯度下降法)最小化误差函数,从而得到最佳的圆心位置。
3. 霍夫变换霍夫变换是一种基于直线检测的寻找圆心算法。
该方法将圆上的点映射到霍夫空间,通过统计霍夫空间中投票最多的圆心位置来确定圆心。
具体步骤如下: 1. 对圆上的每个点,遍历可能的圆的参数空间,在霍夫空间中进行投票。
2. 统计投票结果,找到得票最多的圆心位置。
三、应用领域寻找圆心算法在许多领域都有广泛的应用,包括但不限于以下几个方面:1. 几何学在几何学中,寻找圆心是很多几何问题的前提。
通过寻找圆心的算法,可以推导出许多圆的性质和定理,解决各种几何问题。
2. 图像处理在图像处理中,寻找圆心算法可以用于检测图像中的圆形目标。
通过分析图像中的轮廓和边缘信息,可以准确地确定圆心位置,进而实现圆形目标的检测和跟踪。
3. 计算机视觉在计算机视觉中,寻找圆心算法可以应用于物体识别和目标跟踪。
图像处理之霍夫变换(直线检测算法)_java图像处理之霍夫变换(直线检测算法)霍夫变换是图像变换中的经典手段之一,主要用来从图像中分离出具有某种相同特征的几何形状(如,直线,圆等)。
霍夫变换寻找直线与圆的方法相比与其它方法可以更好的减少噪声干扰。
经典的霍夫变换常用来检测直线,圆,椭圆等。
霍夫变换算法思想:以直线检测为例,每个像素坐标点经过变换都变成都直线特质有贡献的统一度量,一个简单的例子如下:一条直线在图像中是一系列离散点的集合,通过一个直线的离散极坐标公式,可以表达出直线的离散点几何等式如下:X *cos(theta) + y * sin(theta) = r 其中角度theta指r与X轴之间的夹角,r为到直线几何垂直距离。
任何在直线上点,x, y都可以表达,其中 r, theta是常量。
该公式图形表示如下:然而在实现的图像处理领域,图像的像素坐标P(x, y)是已知的,而r, theta则是我们要寻找的变量。
如果我们能绘制每个(r, theta)值根据像素点坐标P(x, y)值的话,那么就从图像笛卡尔坐标系统转换到极坐标霍夫空间系统,这种从点到曲线的变换称为直线的霍夫变换。
变换通过量化霍夫参数空间为有限个值间隔等分或者累加格子。
当霍夫变换算法开始,每个像素坐标点P(x, y)被转换到(r, theta)的曲线点上面,累加到对应的格子数据点,当一个波峰出现时候,说明有直线存在。
同样的原理,我们可以用来检测圆,只是对于圆的参数方程变为如下等式:(x –a ) ^2 + (y-b) ^ 2 = r^2其中(a, b)为圆的中心点坐标,r圆的半径。
这样霍夫的参数空间就变成一个三维参数空间。
给定圆半径转为二维霍夫参数空间,变换相对简单,也比较常用。
编程思路解析:1. 读取一幅带处理二值图像,最好背景为黑色。
2. 取得源像素数据3. 根据直线的霍夫变换公式完成霍夫变换,预览霍夫空间结果4. 寻找最大霍夫值,设置阈值,反变换到图像RGB值空间(程序难点之一)5. 越界处理,显示霍夫变换处理以后的图像关键代码解析:直线的变换角度为[0 ~ PI]之间,设置等份为500为PI/500,同时根据参数直线参数方程的取值范围为[-r, r]有如下霍夫参数定义:[java]view plaincopy1.// prepare for hough transform2.int centerX = width / 2;3.int centerY = height / 2;4.double hough_interval = PI_VALUE/(double)hough_space;5.6.int max = Math.max(width, height);7.int max_length = (int)(Math.sqrt(2.0D) * max);8.hough_1d = new int[2 * hough_space * max_length];实现从像素RGB空间到霍夫空间变换的代码为:[java]view plaincopy1.// start hough transform now....2.int[][] image_2d = convert1Dto2D(inPixels);3.for (int row = 0; row < height; row++) {4.for (int col = 0; col < width; col++) {5.int p = image_2d[row][col] & 0xff;6.if(p == 0) continue; // which means background color7.8.// since we does not know the theta angle and r value,9.// we have to calculate all hough space for each pixel poi nt10.// then we got the max possible theta and r pair.11.// r = x * cos(theta) + y * sin(theta)12.for(int cell=0; cell < hough_space; cell++ ) {13.max = (int)((col - centerX) * Math.cos(cell * hough_int erval) + (row - centerY) * Math.sin(cell * hough_interval));14.max += max_length; // start from zero, not (-max_length)15.if (max < 0 || (max >= 2 * max_length)) {// make sure r did not out of scope[0, 2*max_lenght]16.continue;17.}18.hough_2d[cell][max] +=1;19.}20.}21.}寻找最大霍夫值计算霍夫阈值的代码如下:[java]view plaincopy1.// find the max hough value2.int max_hough = 0;3.for(int i=0; i<hough_space; i++) {4.for(int j=0; j<2*max_length; j++) {5.hough_1d[(i + j * hough_space)] = hough_2d[i][j];6.if(hough_2d[i][j] > max_hough) {7.max_hough = hough_2d[i][j];8.}9.}10.}11.System.out.println("MAX HOUGH VALUE = " + max_h ough);12.13.// transfer back to image pixels space from hough par ameter space14.int hough_threshold = (int)(threshold * max_hough);从霍夫空间反变换回像素数据空间代码如下:[java]view plaincopy1.// transfer back to image pixels space from hough param eter space2.int hough_threshold = (int)(threshold * max_hough);3.for(int row = 0; row < hough_space; row++) {4.for(int col = 0; col < 2*max_length; col++) {5.if(hough_2d[row][col] < hough_threshold) // discard it6.continue;7.int hough_value = hough_2d[row][col];8.boolean isLine = true;9.for(int i=-1; i<2; i++) {10.for(int j=-1; j<2; j++) {11.if(i != 0 || j != 0) {12.int yf = row + i;13.int xf = col + j;14.if(xf < 0) continue;15.if(xf < 2*max_length) {16.if (yf < 0) {17.yf += hough_space;18.}19.if (yf >= hough_space) {20.yf -= hough_space;21.}22.if(hough_2d[yf][xf] <= hough_value) {23.continue;24.}25.isLine = false;26.break;27.}28.}29.}30.}31.if(!isLine) continue;32.33.// transform back to pixel data now...34.double dy = Math.sin(row * hough_interval);35.double dx = Math.cos(row * hough_interval);36.if ((row <= hough_space / 4) || (row >= 3 * hough_spa ce / 4)) {37.for (int subrow = 0; subrow < height; ++subrow) {38.int subcol = (int)((col - max_length - ((subrow - center Y) * dy)) / dx) + centerX;39.if ((subcol < width) && (subcol >= 0)) {40.image_2d[subrow][subcol] = -16776961;41.}42.}43.} else {44.for (int subcol = 0; subcol < width; ++subcol) {45.int subrow = (int)((col - max_length - ((subcol - center X) * dx)) / dy) + centerY;46.if ((subrow < height) && (subrow >= 0)) {47.image_2d[subrow][subcol] = -16776961;48.}49.}50.}51.}52.}霍夫变换源图如下:霍夫变换以后,在霍夫空间显示如下:(白色表示已经找到直线信号)最终反变换回到像素空间效果如下:一个更好的运行监测直线的结果(输入为二值图像):完整的霍夫变换源代码如下:[java]view plaincopy1.package com.gloomyfish.image.transform;2.3.import java.awt.image.BufferedImage;4.5.import com.process.blur.study.AbstractBufferedImageOp;6.7.public class HoughLineFilter extends AbstractBufferedIma geOp {8.public final static double PI_VALUE = Math.PI;9.private int hough_space = 500;10.private int[] hough_1d;11.private int[][] hough_2d;12.private int width;13.private int height;14.15.private float threshold;16.private float scale;17.private float offset;18.19.public HoughLineFilter() {20.// default hough transform parameters21.// scale = 1.0f;22.// offset = 0.0f;23.threshold = 0.5f;24.scale = 1.0f;25.offset = 0.0f;26.}27.28.public void setHoughSpace(int space) {29.this.hough_space = space;30.}31.32.public float getThreshold() {33.return threshold;34.}35.36.public void setThreshold(float threshold) {37.this.threshold = threshold;38.}39.40.public float getScale() {41.return scale;42.}43.44.public void setScale(float scale) {45.this.scale = scale;46.}47.48.public float getOffset() {49.return offset;50.}51.52.public void setOffset(float offset) {53.this.offset = offset;54.}55.56.@Override57.public BufferedImage filter(BufferedImage src, BufferedImage dest) {58.width = src.getWidth();59.height = src.getHeight();60.61.if ( dest == null )62.dest = createCompatibleDestImage( src, null );63.64.int[] inPixels = new int[width*height];65.int[] outPixels = new int[width*height];66.getRGB( src, 0, 0, width, height, inPixels );67.houghTransform(inPixels, outPixels);68.setRGB( dest, 0, 0, width, height, outPixels );69.return dest;70.}71.72.private void houghTransform(int[] inPixels, int[] outPix els) {73.// prepare for hough transform74.int centerX = width / 2;75.int centerY = height / 2;76.double hough_interval = PI_VALUE/(double)hough_sp ace;77.78.int max = Math.max(width, height);79.int max_length = (int)(Math.sqrt(2.0D) * max);80.hough_1d = new int[2 * hough_space * max_length];81.82.// define temp hough 2D array and initialize the hough 2D83.hough_2d = new int[hough_space][2*max_length];84.for(int i=0; i<hough_space; i++) {85.for(int j=0; j<2*max_length; j++) {86.hough_2d[i][j] = 0;87.}88.}89.90.// start hough transform now....91.int[][] image_2d = convert1Dto2D(inPixels);92.for (int row = 0; row < height; row++) {93.for (int col = 0; col < width; col++) {94.int p = image_2d[row][col] & 0xff;95.if(p == 0) continue; // which means background color96.97.// since we does not know the theta angle and r value,98.// we have to calculate all hough space for each pixel point99.// then we got the max possible theta and r pair.100.// r = x * cos(theta) + y * sin(theta)101.for(int cell=0; cell < hough_space; cell++ ) {102.max = (int)((col - centerX) * Math.cos(cell * hough_int erval) + (row - centerY) * Math.sin(cell * hough_interval));103.max += max_length; // start from zero, not (-max_length)104.if (max < 0 || (max >= 2 * max_length)) {// make sure r did not out of scope[0, 2*max_lenght]105.continue;106.}107.hough_2d[cell][max] +=1;108.}109.}110.}111.112.// find the max hough value113.int max_hough = 0;114.for(int i=0; i<hough_space; i++) {115.for(int j=0; j<2*max_length; j++) {116.hough_1d[(i + j * hough_space)] = hough_2d[i][j];117.if(hough_2d[i][j] > max_hough) {118.max_hough = hough_2d[i][j];119.}120.}121.}122.System.out.println("MAX HOUGH VALUE = " + max_h ough);123.124.// transfer back to image pixels space from hough par ameter space125.int hough_threshold = (int)(threshold * max_hough);126.for(int row = 0; row < hough_space; row++) {127.for(int col = 0; col < 2*max_length; col++) {128.if(hough_2d[row][col] < hough_threshold) // discard it129.continue;130.int hough_value = hough_2d[row][col];131.boolean isLine = true;132.for(int i=-1; i<2; i++) {133.for(int j=-1; j<2; j++) {134.if(i != 0 || j != 0) {135.int yf = row + i;136.int xf = col + j;137.if(xf < 0) continue;138.if(xf < 2*max_length) {139.if (yf < 0) {140.yf += hough_space;141.}142.if (yf >= hough_space) {143.yf -= hough_space;144.}145.if(hough_2d[yf][xf] <= hough_value) {146.continue;147.}148.isLine = false;149.break;150.}151.}152.}153.}154.if(!isLine) continue;155.156.// transform back to pixel data now...157.double dy = Math.sin(row * hough_interval);158.double dx = Math.cos(row * hough_interval);159.if ((row <= hough_space / 4) || (row >= 3 * hough_spa ce / 4)) {160.for (int subrow = 0; subrow < height; ++subrow) { 161.int subcol = (int)((col - max_length - ((subrow - center Y) * dy)) / dx) + centerX;162.if ((subcol < width) && (subcol >= 0)) {163.image_2d[subrow][subcol] = -16776961;164.}165.}166.} else {167.for (int subcol = 0; subcol < width; ++subcol) {168.int subrow = (int)((col - max_length - ((subcol - center X) * dx)) / dy) + centerY;169.if ((subrow < height) && (subrow >= 0)) {170.image_2d[subrow][subcol] = -16776961;171.}172.}173.}174.}175.}176.177.// convert to hough 1D and return result178.for (int i = 0; i < this.hough_1d.length; i++)179.{180.int value = clamp((int)(scale * this.hough_1d[i] + offset )); // scale always equals 1181.this.hough_1d[i] = (0xFF000000 | value + (value << 16 ) + (value << 8));182.}183.184.// convert to image 1D and return185.for (int row = 0; row < height; row++) {186.for (int col = 0; col < width; col++) {187.outPixels[(col + row * width)] = image_2d[row][col];188.}189.}191.192.public BufferedImage getHoughImage() {193.BufferedImage houghImage = new BufferedImage(ho ugh_2d[0].length, hough_space, BufferedImage.TYPE_4BYTE_AB GR);194.setRGB(houghImage, 0, 0, hough_2d[0].length, hough _space, hough_1d);195.return houghImage;196.}197.198.public static int clamp(int value) {199.if (value < 0)200.value = 0;201.else if (value > 255) {202.value = 255;203.}204.return value;205.}206.207.private int[][] convert1Dto2D(int[] pixels) {208.int[][] image_2d = new int[height][width];209.int index = 0;210.for(int row = 0; row < height; row++) {211.for(int col = 0; col < width; col++) {212.index = row * width + col;213.image_2d[row][col] = pixels[index];214.}215.}216.return image_2d;218.219.}转载文章请务必注明出自本博客!!。
霍夫变换中直线拟合的最小二乘法
ichriZ 1.基本概念
(1)霍夫变换
霍夫变换(Hough Transform) 是图像处理中从图像中识别几何形状的基本方法之一,应用很广泛,也有很多改进算法。
最基本的霍夫变换是从黑白图像中检测直线或线段。
(2)最小二乘法
曲线拟合方法的一种,通过最小化误差的平方和寻找数据的最佳函数匹配。
2.适用情况
霍夫变换是基于统计的方法,能将图像中的噪声或干扰点的影响消除,但其结果存在精度不够与直线有效区间不易控制的问题;最小二乘法是直线拟合的有效方法,但直接用于拟合时易受干扰点或噪声点影响。
在检测图像中的直线段时,先利用霍夫变换消除无效点的影响,再结合最小二乘法法进行拟合,可以提高检测效果。
3.霍夫变换原理与实现方法
(一)霍夫变换原理
在平面直角坐标系中一条直线,任取其上一点,有
表示参数平面中的一条直线。
再取上另一点则有
表示参数平面中的一条直线。
与相交于一点,对应于坐标系
中直线
即:同一直线上的不同的点在对应的参数平面中对应不同的直线,但都交于同一点,所以可以通过坐标系中的交点来寻找坐标系中的直线。
当坐标系中的直
线数量为R时,坐标系中对应R个峰值交点,它们对应于坐标系中的R 条直线。
此种方法不能够表示这类直线,实际中常将原有直线表示为参数方程
此直线上的点对应坐标系中的一族三角函数曲线,它们在有效区间内交于一点
,对应于坐标系中的。
下图是一个具体例子:
交点坐标
(二)最小二乘法原理
对于给定数据,要求在某个函数类
中寻求一个函数
,使
本文中讨论的是直线的最小二乘法,故均取一次多项式。
设具有如下格式
霍夫变换—>
其中是待定参数,求具有这种形式的最小二乘法的实
质,就是要适当的选择参数,使相应的函数
满足条件。
也就是说,点是多元函数
的极小点,从而满足方程组
因此,可以通过解此方程组(称为法方程组)来求取,以便
获得最小二乘解。
当讨论的曲线为代数多项式时,不妨取
则有
令得方程组
即
本文中模拟的是直线,使用一次多项式,则约束条件为
其中直线表达式为
(三)霍夫变换的实现方法
图像处理中的二值边缘图,一般是处理离散数据,则根据霍夫变换可按下列步骤实现直线检测:
(1)参数空间量化成m*n(m为的等分数,n为的等分数)个单元,并设置累加器矩阵;
(2)给参数空间中的每个单元分配一个累加器,并把累加器的初始值置为0;
(3)取出直角坐标系中的点
带入式,并以量化的值计算出;
(4)在参数空间中,找到和所对应的单元,并将该单元的累加器加1,即
(5)当直角坐标系中的点都经过(3)(4)两步遍历后,检测参数空间中每个累加
器的值,累加器最大的单元所对应的和即为直角坐标系中直线方程式的参数。
由上述霍夫变换过程可知,如果参数空间中的和量化过粗,则参数空间中的
凝聚效果较差,找不出直线的准确参数和;反之,和量化过细,那么计算
量将增大。
另外,当直角坐标系中的点分布在R条直线附近时,可在第5步检测累加器时,
取出累加器中前R个值最大的单元所对应的和,以和为直角坐标系中直
线方程式的参数,即可同时实现多条直线的拟合。
4.霍夫变换与最小二乘法相结合的直线拟合方法
假设采集到的数据为,s为数据集中的数据点数,M中改的数据点分布在R调直线附近,根据实验目的要求给定误差阈值为d k。
(1)霍夫变换。
将式改写成
根据式,对M作霍夫变换,可得拟合直线的参数。
(2)找出拟合直线附近的点集。
将式表示的法线式直线方程改写成斜截式
其中
计算M中的点到由式确定的直线的距离
如果
则
为符合误差阈值要求的第k条霍夫变换直线附近的点集。
(3)以点集为拟合数据,分别拟合各直线,可得直线方程式的参数。
以和为端点,可确定各直线段的区间,
即
5.简单实现
编程环境:Windows7+Qt5+OpenCV2.4.3
实验测得数据:
X坐标36 48 63 72 84 97 108 120 143
Y坐标78 88 101 109 119 130 140 150 170
原图像经过二值化处理的图像检测结果
6.参考文献
曾接贤, et al. "霍夫变换与最小二乘法相结合的直线拟合." 南昌航空工业学院学报(自然科学版) 4 (2003).
Hough, Paul VC. "Method and means for recognizing complex patterns." U.S. Patent No. 3,069,654.
18 Dec. 1962.。