霍夫变换可以用于直线检测,圆检测等。我需要解决的问题是二维点云线特征提取,相关文献上说霍夫变换可以提取,决定深入学习一下。
先上两张图:直线的表达式采用极坐标表示ρ=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 _accum, _sort_buf; 5 cv::AutoBuffer_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 accumulator42 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 maximums55 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 value66 icvHoughSortDescent32s( sort_buf, total, accum );//快速排序
67 68 // stage 4. store the first min(total,linesMax) lines to the output buffer69 linesMax = MIN(linesMax, total);70 scale = 1./(numrho+2);71 for( i = 0; i < linesMax; i++ )//从数组中取前linesMax条线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 }
接下来需要思考如何用于霍夫变换进行二维激光点云的线特征提取。另外一个问题是三维点云的线特征如何提取?