Hough变换检测直线
理论
hough变换的代码写了很多遍,网络上也下载了很多,但是都是一知半解,没有具体去想原理,结果每次的代码存在的周期都很短,都没有很好的得到利用,分析原因还是自己一知半解,其实后来想想蛮简单的,可就是不明白当时就怎么蒙圈了,想想也只有自己了。
本文中的图片和理论都来源于参考,请尊重原有作者的版权。
直线的表示,在笛卡尔坐标系下,其方程可以用点斜式和两点式,但是在hough变换中,其表示方法是(r,theta),r表示为直线到原点的距离,theta表示该直线垂线与x轴夹角,如下图所示:
使用hough变换来检测直线的思想就是:为每一个点假设n个方向的直线,通常n=180,此时检测的直线的角度精度为1°,分别计算这n条直线的(r,theta)坐标,得到n个坐标点。如果要判断的点共有N个,最终得到的(r,theta)坐标有Nn个。有关这Nn个(r,theta)坐标,其中theta是离散的角度,共有180个取值。
最重要的地方来了,如果多个点在一条直线上,那么必有这多个点在theta=某个值theta_i时,这多个点的r近似相等于r_i。也就是说这多个点都在直线(r_i,theta_i)上。
如果空间中有3个点,如何判断这三个点在不在一个直线上,如果在,这条直线是的位置为?
这个例子中,对于每个点均求过该点的6条直线的(r,theta)坐标,共求了3*6个(r,theta)坐标。可以发现在theta=60时,三个点的r都近似为80.7,由此可判定这三个点都在直线(80.7,60)上。
通过 r0theta 坐标系可以更直观表示这种关系,如下图:图中三个点的(r,theta)曲线汇集在一起,该交点就是同时经过这三个点的直线。
Code
int HoughLine(vector<gclPoint> pointsIn, int height, int width, double rho, double theta, int thresh, vector<gclLine> &lineOut)
{
int error = 0;
int *score = NULL;
int *index = NULL;
gclLine *lineTemp = NULL;
if (pointsIn.size() <= 2 || rho <= 0 || theta <= 0)
{
error = GclParamParamIsnotValid;
goto End;
}
int thetaNum = ceil((180 - theta) / theta + 0.5);
int wlen = sqrt(height * height + width * width) + 1;
int rhoNum = ceil((wlen - rho) / rho + 0.5);
score = new int[thetaNum * rhoNum];
memset(score, 0, sizeof(int) * thetaNum * rhoNum);
lineTemp = new gclLine[thetaNum * rhoNum];
memset(lineTemp, 0, sizeof(gclLine) * rhoNum * thetaNum);
for (int i = 0; i < pointsIn.size(); i++)
{
for (int m = 0; m < thetaNum; m++)
{
int dex = 0;
double a = 0, b = 0, c = 0;
if (abs(m * theta - 90) < 10e-6)
{
dex = int(pointsIn[i].x / rho + 0.5);
a = 1; b = 0; c = -pointsIn[i].x;
}
else
{
a = tan(m * theta * M_PI / 180);
b = -1;
c = pointsIn[i].y - a * pointsIn[i].x;
double rhoTemp = abs(c) / sqrt(a * a + 1) / rho;
dex = int(rhoTemp + 0.5);
}
score[m * rhoNum + dex]++;
lineTemp[m * rhoNum + dex] = gclLine(a, b, c);
}
}
// 统计线信息
index = new int[rhoNum * thetaNum];
for (int i = 0; i < rhoNum * thetaNum; i++)
{
index[i] = i;
}
InsertSort(score, index, rhoNum * thetaNum);
for (int i = rhoNum * thetaNum - 1; i >= 0; i--)
{
if (score[i] > thresh)
{
lineOut.push_back(lineTemp[index[i]]);
}
}
End:
SAFE_DELETE(lineTemp);
SAFE_DELETE(score);
SAFE_DELETE(index);
return error;
}
此文章版权归snailgoers所有,如有转载,请注明來自原作者
评论

