http://www.cnblogs.com/smartvessel/archive/2011/10/20/2218654.html
從理論到代碼,再從代碼到理論
(1)理論之通俗理解:
1.在圖像中檢測直線的問題,其實質是找到構成直線的所有的像素點。那麼問題就是從找到直線,變成找到符合y=mx+c的所有(x,y)的點的問題。
2.進行坐標系變化y=mx+c,變成c=-xm+b。直線上的點(x1,y1),在轉換坐標系後為一條直線。這個原理應該是高中的。
3.直線上每一個點在MC坐標系中都表現為直線,而且,這些直線都相交於一個點,(m,c)。找到所有點的問題,轉變為尋找直線的問題。
4.對於圖像中的每一個點,在MC坐標系中對應著很多的直線。找到直線的交點,就對應著找到圖像中的直線。
實際在使用這一原理的時候,不是采用直線的斜率和截距公式,而是用
如何實現:
1. 將θ角在-90度到90度的范圍裡,劃分為很多區間,對所有的像素點(x,y)在所有θ角的時候,求出ρ.從而累加ρ值出現的次數。高於某個閾值的ρ就是一個直線。
2. 這個過程就類似於如下一個二維的表格,橫坐標就是θ角,ρ就是到直線的最短距離。
橫坐標θ不斷變換,對於所有的不為0的像素點,計算出ρ,找到ρ在坐標(θ,ρ)的位置累加1.
3. 上圖中局部最大的就是找到的直線的θ和ρ的值。
(2) 具體代碼片段
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 accumulatorfor( 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 maximumsfor( 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 valueicvHoughSortDescent32s( sort_buf, total, accum );// stage 4. store the first min(total,linesMax) lines to the output bufferlinesMax = 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 );}