机器视觉入门之路(三九--A,霍夫变换(hough transform)寻找直线,c++)

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)

最后这个叫欧拉公式,可以用无穷级数来证明。(有机会整理一下)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值