摘录自http://lansesky23.blog.163.com/blog/static/35724627201351811014458/
http://blog.csdn.net/abcjennifer/article/details/7448513
1,基本思想
我们知道,一条直线在直角坐标系下可以用y=kx+b表示, 霍夫变换的主要思想是将该方程的参数和变量交换,即用x,y作为已知量k,b作为变量坐标,所以直角坐标系下的直线y=kx+b在参数空间表示为点(k,b),而一个点(x1,y1)在直角坐标系下表示为一条直线y1=x1·k+b,其中(k,b)是该直线上的任意点。为了计算方便,我们将参数空间的坐标表示为极坐标下的γ和θ。因为同一条直线上的点对应的(γ,θ)是相同的,因此可以先将图片进行边缘检测,然后对图像上每一个非零像素点,在参数坐标下变换为一条直线,那么在直角坐标下属于同一条直线的点便在参数空间形成多条直线并内交于一点。因此可用该原理进行直线检测。
X--Y平面上任意一条直线y
= ax + b,对应在参数a-b平面上都有一个点
如果点(x1,y1)与点(x2,y2)共线,则这两个点在参数a-b平面上的直线将有一个交点:
这样,在参数a-b平面上相交直线对多的点,对应的x-y平面上的直线就是我们的解。利用点--正弦曲线对偶来解题
点--正弦曲线对偶利用极坐标系描述直线
这个过程就类似于如下一个二维的表格,横坐标就是θ角,ρ就是到直线的最短距离。
横坐标θ不断变换,根据直线方程公司,ρ = xcosθ + ysinθ 对于所有的不为0的像素点,计算出ρ,找到ρ在坐标(θ,ρ)的位置累加1.
for( ang = 0, n = 0; n < numangle; ang += theta, n++ ) { tabSin[ n ] = ( float )( sin( ang ) * irho); tabCos[ n ] = ( float )( cos( ang ) * irho); } // stage 1. fill accumulator for( i = 0; i < height; i++ ) for( j = 0; j < width; j++ ) { if( image[ i * step + j ] != 0 ) for( n = 0; n < numangle; n++ ) { r = cvRound( j * tabCos[n] + i * tabSin[n] ); r += (numrho - 1) / 2; accum[(n+1) * (numrho+2) + r+1]++; } } // stage 2. find local maximums for( r = 0; r < numrho; r++ ) for( n = 0; n < numangle; n++ ) { int base = (n+1) * (numrho+2) + r+1; if( accum[base] > threshold && accum[base] > accum[base - 1] && accum[base] >= accum[base + 1] && accum[base] > accum[base - numrho - 2] && accum[base] >= accum[base + numrho + 2] ) sort_buf[total++] = base; } // stage 3. sort the detected lines by accumulator value icvHoughSortDescent32s( sort_buf, total, accum ); // stage 4. store the first min(total,linesMax) lines to the output buffer linesMax = MIN(linesMax, total); scale = 1./(numrho+2); for( i = 0; i < linesMax; i++ ) { CvLinePolar line; int idx = sort_buf[i]; int n = cvFloor(idx*scale) - 1; int r = idx - (n+1)*(numrho+2) - 1; line.rho = (r - (numrho - 1)*0.5f) * rho; line.angle = n * theta; cvSeqPush( lines, &line ); }
此函数是opencv图像变换函数中的一个,主要用来访问霍夫变换的两个算法———标准霍夫变换(SHT)和累计概率霍夫变换(PPHT)。
CvSeq* cvHonghLines2( CvArr* image, void* line_storage, int mehtod, double rho, double theta, int threshold, double param1 =0, double param2 =0 );
image:输入8-比特、单通道(二值)图像,当用CV_HOUGH_PROBABILISTIC方法检测的时候其内容会被函数改变。
line_storage:检测到的线段存储仓.可以是内存存储仓 (此种情况下,一个线段序列在存储仓中被创建,并且由函数返回),或者是包含线段参数的特殊类型(见下面)的具有单行/单列的矩阵(CvMat*)。矩阵头为函数所修改,使得它的 cols/rows 将包含一组检测到的线段。如果 line_storage 是矩阵,而实际线段的数目超过矩阵尺寸,那么最大可能数目的线段被返回(线段没有按照长度、可信度或其它指标排序).
method:Hough 变换变量,是下面变量的其中之一:
CV_HOUGH_STANDARD-- 传统或标准 Hough 变换. 每一个线段由两个浮点数 (ρ, θ) 表示,其中 ρ 是直线与原点(0,0) 之间的距离,θ 线段与 x-轴之间的夹角。因此,矩阵类型必须是 CV_32FC2 type.
CV_HOUGH_PROBABILISTIC-- 概率 Hough 变换(如果图像包含一些长的线性分割,则效率更高). 它返回线段分割而不是整个线段。每个分割用起点和终点来表示,所以矩阵(或创建的序列)类型是 CV_32SC4.
CV_HOUGH_MULTI_SCALE-- 传统 Hough 变换的多尺度变种。线段的编码方式与 CV_HOUGH_STANDARD 的一致。
rho:与象素相关单位的距离精度,一般取1
theta:弧度测量的角度精度
threshold:阈值参数。如果相应的累计值大于 threshold, 则函数返回的这个线段.
param1:第一个方法相关的参数:
对传统 Hough 变换,不使用(0).
对概率 Hough 变换,它是最小线段长度.
对多尺度 Hough 变换,它是距离精度 rho 的分母 (大致的距离精度是 rho 而精确的应该是 rho / param1 ).
param2:第二个方法相关参数:
对传统 Hough 变换,不使用 (0).
对概率 Hough 变换,这个参数表示在同一条直线上进行碎线段连接的最大间隔值(gap), 即当同一条直线上的两条碎线段之间的间隔小于param2时,将其合二为一。
对多尺度 Hough 变换,它是角度精度 theta 的分母 (大致的角度精度是 theta 而精确的角度应该是 theta / param2).
我