霍夫变换理解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了霍夫变换理解相关的知识,希望对你有一定的参考价值。

霍夫变换可以用于直线检测,圆检测等。我需要解决的问题是二维点云线特征提取,相关文献上说霍夫变换可以提取,决定深入学习一下。

先上两张图:直线的表达式采用极坐标表示ρ=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 }

 接下来需要思考如何用于霍夫变换进行二维激光点云的线特征提取。另外一个问题是三维点云的线特征如何提取?

以上是关于霍夫变换理解的主要内容,如果未能解决你的问题,请参考以下文章

Hough变换-理解篇

使用 Matlab 进行霍夫变换

C语言中的霍夫变换有问题

opencv霍夫变换

霍夫变换和openCV

opencv之霍夫曼变换