学习Hough变换过程中发现检测线段的算法资料不少,但实际能高效实现的不多。自己也在学习过程,水平问题只能提供思路和部分代码。
Hough变换的基本思想:
Hough变换的基本思想就是点- 线的对偶性。它是对图像进行某种形式的坐标变换,将原始图像中给定形状的曲线或直线变换成空间中的一个点,在变换空间中形成峰值点。从而使检测整体特性变成检测局部特性,使问题简化。设在原始图像空间( x, y)直线方程为:
y = kx + b;
我们将其转换为极坐标作为变换空间,即:
ρ= xcosθ+ y sinθ
其中,ρ是原点到直线的距离;θ是该直线法线与x轴的夹角。这样空间中的一个点( xi , yi )对应着极坐标中的ρ= xi cosθ+ yi sinθ是一条正弦曲线, 那么原始图像空间中的一条直线上的所有点对应着变换空间的一个曲线族,如图1和图2所示,并且过点(ρ0 ,θ0 ) ,即为参数空间的共线, 也就是图像空间的拟和参数。所以,只要找到这个公共点就可以检测出直线。
Hough变换的基本步骤:
(1)首先对图像进行前期预处理, 得到边缘点(二值化的图像)也就是特征点。
(2)设定一个累加器数组, Accumulator (ρ, θ) ,初值为0,对每一个像素点( xi , yi )遍历θ的取值,计算对应的ρ值,如果其值对应累加器数组中某个值,则该累加器值加1。
3)当遍历完所有的( x, y)点以后, 再遍历所有的累加器的值,找出累加器的峰值点,其对应的就是原是图像空间的共线点。
直线检测代码:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- static void _rtCreateSinCos(float* sinv, float* cosv)
- {
- static bool isCreate = false;
- static float sin_tab[361], cos_tab[361];
-
- float ratio = 0;
- int inc = 0;
-
- if (!isCreate)
- {
- for (inc = DEGREES; inc >= 0; inc--)
- {
- ratio = inc * POL2CART;
- sin_tab[inc] = (float)sin(ratio);
- cos_tab[inc] = (float)cos(ratio);
- }
- isCreate = true;
- }
-
- memcpy(sinv, sin_tab, sizeof(float)*361);
- memcpy(cosv, cos_tab, sizeof(float)*361);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- static void _rtImage2Hough(const RtImage* src, CRtList<RtPoint>* list)
- {
- float sin_tab[361], cos_tab[361];
-
-
- _rtCreateSinCos(sin_tab, cos_tab);
-
-
- int x = 0, y = 0, deg = 0, rad = 0, inc = 0, index = 0;
-
- int cartSize = src->height * src->width;
-
- while (inc < cartSize)
- {
- if (255 == (*(src->pData + inc)))
- {
- x = inc % src->width;
- y = inc / src->width;
-
- for (deg = 0; deg <= DEGREES; deg++)
- {
- if ( (rad = (int)(x * cos_tab[deg] + y * sin_tab[deg])) > 0)
- {
- index = rad * (DEGREES + 1) + deg;
- (list + index)->Insert_back( rtPoint(x, y) );
- }
- }
- }
- inc++;
- }
- }
线段检测思路:
1,在直线检测到基础上,在极坐标系内对靠近直线统计,使靠近直线为同一直线(滤波作用)。
2,对直线分析其连续性,统计出各线段具体数据(细化)