霍夫变换可以用于直线检测,圆检测等。我需要解决的问题是二维点云线特征提取,相关文献上说霍夫变换可以提取,决定深入学习一下。
先上两张图:直线的表达式采用极坐标表示ρ=xcosθ+ysinθ,关于ρ和θ的几何意义如图。证明下面的图可以说明。
因此过某一点A的极坐标方程可以表示所有过A点的直线族。 同理过某一点B的极坐标方程可以表示过有过点B的直线族。两个直线族的集合就是同时过A点和B点的直线。
霍夫变换首先将极坐标系的纵横坐标轴ρ和θ离散化,构成一个网格m*n的数组。这样对栅格图像的每一个非0点进行霍夫变换,同时对相应的数组元素进行累加。
OpenCV中的源码帮助理解一下:
1 static void icvHoughLinesStandard( const CvMat* img, float rho, float theta, 2 int threshold, CvSeq *lines, int linesMax ) 3 { 4 cv::AutoBuffer<int> _accum, _sort_buf; 5 cv::AutoBuffer<float> _tabSin, _tabCos; 6 7 const uchar* image; 8 int step, width, height; 9 int numangle, numrho; 10 int total = 0; 11 int i, j; 12 float irho = 1 / rho; 13 double scale; 14 15 CV_Assert( CV_IS_MAT(img) && CV_MAT_TYPE(img->type) == CV_8UC1 ); 16 17 image = img->data.ptr; 18 step = img->step; 19 width = img->cols; 20 height = img->rows; 21 22 numangle = cvRound(CV_PI / theta);//对角度进行等分 23 numrho = cvRound(((width + height) * 2 + 1) / rho);//对半径进行等分? 24 25 _accum.allocate((numangle+2) * (numrho+2)); 26 _sort_buf.allocate(numangle * numrho); 27 _tabSin.allocate(numangle); 28 _tabCos.allocate(numangle); 29 int *accum = _accum, *sort_buf = _sort_buf; 30 float *tabSin = _tabSin, *tabCos = _tabCos; 31 32 memset( accum, 0, sizeof(accum[0]) * (numangle+2) * (numrho+2) );//定义了一个numangle*numrho数组 33 34 float ang = 0; 35 for(int n = 0; n < numangle; ang += theta, n++ ) 36 { 37 tabSin[n] = (float)(sin((double)ang) * irho); 38 tabCos[n] = (float)(cos((double)ang) * irho); 39 } 40 41 // stage 1. fill accumulator 42 for( i = 0; i < height; i++ ) 43 for( j = 0; j < width; j++ ) 44 { 45 if( image[i * step + j] != 0 ) 46 for(int n = 0; n < numangle; n++ ) 47 { 48 int r = cvRound( j * tabCos[n] + i * tabSin[n] ); 49 r += (numrho - 1) / 2; 50 accum[(n+1) * (numrho+2) + r+1]++; 51 } 52 } 53 54 // stage 2. find local maximums 55 for(int r = 0; r < numrho; r++ ) 56 for(int n = 0; n < numangle; n++ ) 57 { 58 int base = (n+1) * (numrho+2) + r+1; 59 if( accum[base] > threshold && 60 accum[base] > accum[base - 1] && accum[base] >= accum[base + 1] && 61 accum[base] > accum[base - numrho - 2] && accum[base] >= accum[base + numrho + 2] ) 62 sort_buf[total++] = base; 63 } 64 65 // stage 3. sort the detected lines by accumulator value 66 icvHoughSortDescent32s( sort_buf, total, accum ); 67 68 // stage 4. store the first min(total,linesMax) lines to the output buffer 69 linesMax = MIN(linesMax, total); 70 scale = 1./(numrho+2); 71 for( i = 0; i < linesMax; i++ ) 72 { 73 CvLinePolar line; 74 int idx = sort_buf[i]; 75 int n = cvFloor(idx*scale) - 1; 76 int r = idx - (n+1)*(numrho+2) - 1; 77 line.rho = (r - (numrho - 1)*0.5f) * rho; 78 line.angle = n * theta; 79 cvSeqPush( lines, &line ); 80 } 81 }
接下来需要思考如何用于霍夫变换进行二维激光点云的线特征提取。另外一个问题是三维点云的线特征如何提取?
原文:http://www.cnblogs.com/yhlx125/p/5164739.html