基于hough在图像中检测直线和图像旋转

一、hough变换检测直线

利用hough变换能够检测出图像中存在的直线,有利于对图像特征进行分析。hough变换是利用图像空间与参数空间之间的“点-线”对偶性,通过把图像空间转换到参数空间,对参数空间处理来检测出直线。运用直线的极坐标公式:ρ=хcos(θ)+уsin(θ),ρ,θ就是一对参数,通过对图像中的像素点运用这个公式处理就可以等到二维的ρ,θ参数空间,在参数空间会形成峰值,从而利用峰值就可以检测出直线。

下面模拟hough变换:

这是一幅简单的8位灰度图像,则可以通过下面代码实现:定义int p[1400][180]表示参数空间

for(i=0;i<height;i++)
    {
        for(j=0;j<width;j++)
        {
            if(*(p_Data+width*i+j)==0)
            {
                for(k=0;k<180;k++)
                {
                    pr=(int)(i*sin(k*3.141592/180)+j*cos(k*3.141592/180));
                    if((pr>0)&&(pr<1400))   //1400是我定义的数组最大标号
                        p[pr][k]++;
                }
            }
        }
    }

得出的p[][]的二维值,通过:

int a=0,q1=0;

for(i=0;i<1400;i++)
    {
        for(j=0;j<180;j++)
        {
            if(p[i][j]>a)
            {
                a=p[i][j];
                q1=j;
            }
        }
    }

得到的q1就是直线的倾斜角,从而可以判断直线。


二、得到了直线的倾斜角后就可以对图像进行旋转校正

BYTE * CDIB::Rotate(double rotaleangle)
{
    long OffBits,SrcBufSize,DstBufSize,DstLineBytes,SrcLineBytes;

    BYTE *tempptr,*lpptr,*lpsrc,*temp;

    double srcx1,srcy1,srcx2,srcy2;
    double srcx3,srcy3,srcx4,srcy4;
    double dstx1,dsty1,dstx2,dsty2;
    double dstx3,dsty3,dstx4,dsty4;

    long wold,hold,wnew,hnew;

    long x0,y0,x1,y1;
    double cosa,sina;
    double num1,num2;
//角度到弧度转换

//#define PI 3.1415926535
//#define RADIAN(angle) ((angle)*PI/180.0)
    rotaleangle=(double)RADIAN(rotaleangle);
    cosa=(double)cos((double)rotaleangle);
    sina=(double)sin((double)rotaleangle);
    CString s;
    //s.Format("%lf",rotaleangle);
//    AfxMessageBox(s);

    lpsrc=GetData();

    wold=GetWidth();
    hold=GetHeight();

    SrcLineBytes = WIDTHBYTES(wold * 8);
//原坐标点
    srcx1=(double)(-0.5*(wold-1));
    srcy1=(double)(0.5*(hold-1));
    srcx2=(double)(0.5*(wold-1));
    srcy2=(double)(0.5*(hold-1));
    srcx3=(double)(-0.5*(wold-1));
    srcy3=(double)(-0.5*(hold-1));
    srcx4=(double)(0.5*(wold-1));
    srcy4=(double)(-0.5*(hold-1));
   //新坐标点
    dstx1=cosa*srcx1+sina*srcy1;
    dsty1=-sina*srcx1+cosa*srcy1;
    dstx2=cosa*srcx2+sina*srcy2;
    dsty2=-sina*srcx2+cosa*srcy2;
    dstx3=cosa*srcx3+sina*srcy3;
    dsty3=-sina*srcx3+cosa*srcy3;
    dstx4=cosa*srcx4+sina*srcy4;
    dsty4=-sina*srcx4+cosa*srcy4;
    wnew=(DWORD)(max(fabs(dstx4-dstx1),fabs(dstx3-dstx2))+0.5);
    hnew=(DWORD)(max(fabs(dsty4-dsty1),fabs(dsty3-dsty2))+0.5);
    DstLineBytes = WIDTHBYTES(wnew * 8);
//    s.Format("%ld:%ld",wnew,DstLineBytes);
//    AfxMessageBox(s);
    num1=(double)(-0.5*(wnew-1)*cosa-0.5*(hnew-1)*sina+0.5*(wold-1));
    num2=(double)(0.5*(wnew-1)*sina-0.5*(hnew-1)*cosa+0.5*(hold-1));
    DstBufSize=wnew*hnew;
    tempptr=new BYTE[wnew*hnew];
    memset(tempptr,(BYTE)255,wnew*hnew);
    temp=tempptr;
    x0=y0=0;
    long x=0,y=0;
    for(y1=0;y1<hnew;y1++)
    {
        for(x1=0;x1<wnew;x1++)
        {
            tempptr = temp + DstLineBytes * (hnew - 1 - y1) + x1;           
            // 计算该象素在源DIB中的坐标
            x=(long)(1.0f*x1*cosa+y1*sina+num1+0.5);
            x0=(long)(1.0f*x1*cosa+y1*sina+num1);
            y0=(long)(-1.0f*x1*sina+y1*cosa+num2);
            y=(long)(-1.0f*x1*sina+y1*cosa+num2+0.5);
            // 判断是否在源图范围内
            if( (x0 >= 0) && (x0 < wold) && (y0 >= 0) && (y0 < hold))
            {
                // 指向源DIB第y0行,第x0个象素的指针
                lpptr = lpsrc + SrcLineBytes * (hold - 1 - y0) + x0;               
                // 复制象素
                *tempptr=*lpptr;
            }
        }
    }
    this->m_pBitmapInfoHeader->biWidth=wnew;
    this->m_pBitmapInfoHeader->biHeight=hnew;
    this->m_pData=temp;
    return tempptr;

}



你可能感兴趣的:(byte)