xy坐标系直线:
y=kx+b
请看图:假定红色线段上的所有样本点(100个)都满足上面的直线方程。
(a图)
也就是说,红色的点(x1,y1)(x2,y2)(x3,y3)......(x98,y98)(x99,y99)(x100,y100)带入方程,只能求出一个k值和一个b值,假定为(k1,b1)。
换一种表达,在kb坐标系,(k1,b1)只是一个点。如图(仅仅示意而已):
(b图)
这就是hough(霍夫)变换的思想。即a图和b图是一一对应的,而霍夫寻找直线,就是通过(k1,b1)寻找a图中的红色样本点。
以上是原理,下面是常用的直线hough(霍夫)表达式:p=cos(theta)*x+y*sin(theta)
之所以如此,是为了对付诸如k=tg(90)之类的问题,下面推导一下y=kx+b如何演变为p=cos(theta)*x+y*sin(theta),看图:
因为k=-ctg(theta),
b=p/sin(theta),
所以y=-ctg(theta)*x+p/sin(theta)
即y=-x*cos(theta)/sin(theta)+p/sin(theta),
两边乘以sin(theta),得
y*sin(theta)=-x*cos(theta)+p,整理得:
p=cos(theta)*x+y*sin(theta)
在这通用式中,我们是通过(p,theta)来寻找直线的。
下面是hough(霍夫)找直线的代码,抄的图像处理(左飞),一直有一个问题不能释疑,今天一并解决。vc++代码如下:
void CLineBufProcess::HoughLine(BYTE* image0, BYTE* &image1, int &w, int &h,int Gaugetype,int scale)
{//Gaugetype==1,梯度图像,Gaugetype==2,canny图像,此处直接使用canny图像;scale=1
double sinValue[360];
double cosValue[360];
int i,x,y;
int p = (int)(sqrt((double)(w*w+h*h)+1));
BYTE* tempImage=(BYTE*)malloc(sizeof(BYTE)*w*h);
CannySideGrandiant(image0, tempImage,w,h);//canny后使用hough找线
if(image1!=NULL) free(image1);
image1 = (BYTE*)malloc(sizeof(BYTE)*p*360);
memset(image1,0,(p)*360);
BYTE** HoughBuf = (BYTE**)malloc(sizeof(BYTE*)*(p));
for(int y=0; y<p; y++)
{
HoughBuf [y] = image1+y*360;
}
for(i=0; i<360 ; i++)
{
sinValue[i] = sin(i*3.1415926/180);
cosValue[i] = cos(i*3.1415926/180);
}
int tp;
//int k = 100;
for(y=0; y<h; y++)
for(x=0; x<w; x++)
{
for(i=0; i<360; i++)
{
if( tempImage[(y*w+x)] >this->m_grayThres)//
{
tp = (int)( x*sinValue[i] + y*cosValue[i]);
if (tp<0||HoughBuf[tp][i]==255) continue;
HoughBuf[tp][i] += scale;
}
}
}
w = 360;
h = p;
free(HoughBuf);
free(tempImage);
}
代码中红色的公式 tp = (int)( x*sinValue[i] + y*cosValue[i])是否与p=cos(theta)*x+y*sin(theta)不同?是的。但为什么他能找直线?并且是正确的,我试过没有千遍,但不会下50遍,当我有一天发现这个问题,大吃一惊,而且不能释怀,纠结啊!
现在释疑如下:
1,我们在visionpro toolgroup思考突破(一)中,有这样一句话,逻辑的好处是,即使你是错的,他永远在正确的错,p=sin(theta)*x+y*cos(theta)就是这种错的逻辑,但他永远在正确的错。
2,p=sin(theta)*x+y*cos(theta)与p=cos(theta)*x+y*sin(theta)是映射关系,一一对应,不会有第二种。
基于以上两点分析,这或许是我抄错了,最后发现左飞写错了(谁都有大意的时候)。若你要使用正确的(p,theta),请你更正错误,否则,不必修改。
最后,忽然联想到一个公式,p*exp(i*theta)=p*cos(theta)+P*i*sin(theta),不要和上面的公式混淆了。
坐标系中:
(x,y)---------------------(p,theta)
(x,y)=(p*cos(theta),p*sin(theta))
向量系中:
x+i*y=p*cos(theta)+p*sin(theta)*i
p*cos(theta)+p*sin(theta)*i=p*exp(i*theta)
最后这个叫欧拉公式,可以用无穷级数来证明。(有机会整理一下)