一、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;
}