void FFTGabor::GaborTransform(int * lpDIBBits, LONG lWidth, LONG lHeight, int Orientation, int Frequency, FFTGaborResult * result)
{
LONG i;
LONG j;
complex<double> *TD = new complex<double>[complexWidth * complexHeight];
complex<double> *FD = new complex<double>[complexWidth * complexHeight];
// 行
for(i = 0; i < lHeight; i++)
{
// 列
for(j = 0; j < lWidth; j++)
{
// 给时域赋值
TD[j + complexWidth * i] = complex<double>(lpDIBBits[j+lWidth * i], 0);
}
}
::FFT2(TD,complexWidth , complexHeight);
//::IFFT2(TD,256,256);
//在频域执行卷积
double scale = 1.0 / (complexWidth * complexHeight);
for( i=0; i<complexWidth * complexHeight; i++)
FD[i] = TD[i] * KernelFFT2[Orientation * 4 + Frequency][i] ; // * scale;
IFFT2(FD,complexWidth , complexHeight);
//计算均值、方差及结果
//计算均值并找出tmpMag中的最大最小值,以便调整到0~255,用于显示输出。
double min, max;
double Sum=0, Avg=0, Deta=0;
double tmpModulus=0;
double * tmpMag = new double[lWidth*lHeight] ;// [128][128] ;
int x ,y;
tmpModulus = sqrt(FD[(GaborHeight/2)*complexWidth+(GaborWidth/2)].real() *
FD[(GaborHeight/2)*complexWidth+(GaborWidth/2)].real() +
FD[(GaborHeight/2)*complexWidth+(GaborWidth/2)].imag() *
FD[(GaborHeight/2)*complexWidth+(GaborWidth/2)].imag());
min = max = tmpModulus;
for( y=(GaborHeight/2); y<(GaborHeight/2)+lHeight; y++){
for( x=(GaborWidth/2); x<(GaborWidth/2)+lWidth; x++)
{
tmpModulus = sqrt(FD[y*complexWidth+x].real() * FD[y*complexWidth+x].real() +
FD[y*complexWidth+x].imag() * FD[y*complexWidth+x].imag());
if(min>tmpModulus)
min = tmpModulus;
if(max<tmpModulus)
max = tmpModulus;
Sum += tmpModulus;
tmpMag[(y-(GaborHeight/2))* lWidth + (x-(GaborWidth/2))] = tmpModulus;
}
}
Avg = Sum / (lHeight * lWidth);
//计算方差
for( y=0; y < lHeight; y++){
for( x=0; x < lWidth; x++)
Deta += (tmpMag[y* lWidth + x] - Avg)*(tmpMag[y* lWidth + x] - Avg);
}
Deta = Deta / (lHeight * lWidth);
//计算magShow以及均值
scale = 255.0/(max-min);
for( y=0; y < lHeight; y++){
for( x=0; x < lWidth; x++)
{
result->magShow[y * lWidth + x] = (int)(scale*(tmpMag[y* lWidth + x]-min));
}
}
result->Avg = Avg;
result->Deta = Deta;
delete[] tmpMag;
delete[] FD;
delete[] TD;
}
void FFTGabor::intTocomplex(complex<double> * TD,int * lpDIBBits,LONG lWidth, LONG lHeight)
{
LONG i;
LONG j;
// complex<double> *TD = new complex<double>[complexWidth * complexHeight];
// 行
for(i = 0; i < lHeight; i++)
{
// 列
for(j = 0; j < lWidth; j++)
{
// 给时域赋值
TD[j + complexWidth * i] = complex<double>(lpDIBBits[j+lWidth * i], 0);
}
}
::FFT2(TD,complexWidth , complexHeight);
}
void FFTGabor::GaborTransform(complex<double> *TD, LONG lWidth, LONG lHeight, double * TransformResult)
{
// 循环变量
LONG i;
// LONG j;
int Orientation, Frequency ;
// 分配内存
complex<double> *FD = new complex<double>[complexWidth * complexHeight];
double scale = 1.0 / (complexWidth * complexHeight);
double Sum=0, Avg=0, Deta=0;
double tmpModulus=0;
double * tmpMag = new double[lWidth*lHeight] ;// [128][128] ;
int x ,y;
for( Orientation=0; Orientation<8; Orientation++){
for( Frequency=0; Frequency<4; Frequency++)
{
//在频域执行卷积
for( i=0; i<complexWidth * complexHeight; i++)
FD[i] = TD[i] * KernelFFT2[Orientation * 4 + Frequency][i] ; // * scale;
IFFT2(FD,complexWidth , complexHeight);
//计算均值、方差及结果
Sum=0, Avg=0, Deta=0;
for( y=(GaborHeight/2); y<(GaborHeight/2)+lHeight; y++){
for( x=(GaborWidth/2); x<(GaborWidth/2)+lWidth; x++)
{
tmpModulus = sqrt(FD[y*complexWidth+x].real() * FD[y*complexWidth+x].real() +
FD[y*complexWidth+x].imag() * FD[y*complexWidth+x].imag());
Sum += tmpModulus;
tmpMag[(y-(GaborHeight/2)) * lWidth + (x-(GaborWidth/2))] = tmpModulus;
}
}
Avg = Sum / (lHeight * lWidth);
//计算方差
for( y=0; y < lHeight; y++){
for( x=0; x < lWidth; x++)
Deta += (tmpMag[y* lWidth + x] - Avg)*(tmpMag[y* lWidth + x] - Avg);
}
Deta = Deta / (lHeight * lWidth);
TransformResult[(Orientation * 4 + Frequency)*2] = Avg;
TransformResult[(Orientation * 4 + Frequency)*2+1] = Deta;
}
}
delete[] tmpMag;
delete[] FD;
}
void FFTGabor::GaborTransform(complex<double> *TD, LONG lWidth, LONG lHeight, int Orientation, int Frequency, FFTGaborResult * result)
{
LONG i;
// LONG j;
complex<double> *FD = new complex<double>[complexWidth * complexHeight];
//在频域执行卷积
double scale = 1.0 / (complexWidth * complexHeight);
for( i=0; i<complexWidth * complexHeight; i++)
FD[i] = TD[i] * KernelFFT2[Orientation * 4 + Frequency][i] ; // * scale;
IFFT2(FD,complexWidth , complexHeight);
//计算均值、方差及结果
//计算均值并找出tmpMag中的最大最小值,以便调整到0~255,用于显示输出。
double min, max;
double Sum=0, Avg=0, Deta=0;
double tmpModulus=0;
double * tmpMag = new double[lWidth*lHeight] ;// [128][128] ;
int x ,y;
tmpModulus = sqrt(FD[(GaborHeight/2)*complexWidth+(GaborWidth/2)].real() *
FD[(GaborHeight/2)*complexWidth+(GaborWidth/2)].real() +
FD[(GaborHeight/2)*complexWidth+(GaborWidth/2)].imag() *
FD[(GaborHeight/2)*complexWidth+(GaborWidth/2)].imag());
min = max = tmpModulus;
for( y=(GaborHeight/2); y<(GaborHeight/2)+lHeight; y++){
for( x=(GaborWidth/2); x<(GaborWidth/2)+lWidth; x++)
{
tmpModulus = sqrt(FD[y*complexWidth+x].real() * FD[y*complexWidth+x].real() +
FD[y*complexWidth+x].imag() * FD[y*complexWidth+x].imag());
if(min>tmpModulus)
min = tmpModulus;
if(max<tmpModulus)
max = tmpModulus;
Sum += tmpModulus;
tmpMag[(y-(GaborHeight/2))* lWidth + (x-(GaborWidth/2))] = tmpModulus;
}
}
Avg = Sum / (lHeight * lWidth);
//计算方差
for( y=0; y < lHeight; y++){
for( x=0; x < lWidth; x++)
Deta += (tmpMag[y* lWidth + x] - Avg)*(tmpMag[y* lWidth + x] - Avg);
}
Deta = Deta / (lHeight * lWidth);
//计算magShow以及均值
scale = 255.0/(max-min);
for( y=0; y < lHeight; y++){
for( x=0; x < lWidth; x++)
{
result->magShow[y * lWidth + x] = (int)(scale*(tmpMag[y* lWidth + x]-min));
}
}
result->Avg = Avg;
result->Deta = Deta;
delete[] tmpMag;
delete[] FD;
}
///车牌字符分割
void CSegmentationView::PlateSegm(BYTE Rt[][MAXWIDTH],BYTE Gt[][MAXWIDTH],BYTE Bt[][MAXWIDTH],int PlateHeight,int PlateWidth)
{
CDC *pDC=GetDC();
int i,j;
BYTE TotalRGB[230][460];
memset(TotalRGB,0,sizeof(BYTE)*230*460);
int *HistH;
HistH=new int[sizeof(int)*PlateHeight];
memset(HistH,0,sizeof(int)*PlateHeight);
// 显示车牌图像并水平投影
for(i=0;i<PlateHeight;i++)
{ for(j=0;j<PlateWidth;j++)
{
pDC->SetPixel(450+j,100+i,RGB(Rt[i][j],Gt[i][j],Bt[i][j]));
TotalRGB[i][j]=Rt[i][j]+Gt[i][j]+Bt[i][j];
if(Bt[i][j]>Gt[i][j]&&Bt[i][j]>Rt[i][j]&&(Bt[i][j]/(float)TotalRGB[i][j])>0.4)
HistH[i]++;
}
pDC->MoveTo(800,100+i);
pDC->LineTo(800+HistH[i],100+i);
}
//显示宽度除以10.0的长度
pDC->MoveTo(800,50);
pDC->LineTo(800+PlateWidth/10.0,50);
//求水平边界
int flag=1;
for(i=PlateHeight/2;i>=0;i--)
{
if(HistH[i]>0)
{
if(flag)
{
flag=0;
}
else
{
PlateRect.top=i;
if(HistH[i]<PlateWidth/10.0)
break;
}
}
else if(HistH[i]==0)
break;
}
flag=1;
for(i=PlateHeight/2;i<PlateHeight;i++)
{
if(HistH[i]>0)
{
if(flag)
{
flag=0;
}
else
{
PlateRect.bottom=i;
if(HistH[i]<PlateWidth/10.0)
break;
}
}
else if(HistH[i]==0)
break;
}
delete []HistH;HistH=NULL;
// PlateHeight=bottom-top+1;
//垂直投影
int *HistV;
HistV=new int[sizeof(int)*PlateWidth];
memset(HistV,0,sizeof(int)*PlateWidth);
for(i=0;i<PlateWidth;i++)
{ for(j=PlateRect.top;j<=PlateRect.bottom;j++)
{
if(Bt[j][i]>Gt[j][i] &&Bt[j][i]>Rt[j][i]&&(Bt[j][i]/(float)TotalRGB[j][i])>0.4)
HistV[i]++;
}
pDC->MoveTo(450+i,100);
pDC->LineTo(450+i,100-HistV[i]);
}
//显示高度除以8.0的长度
// pDC->MoveTo(400,50);
// pDC->LineTo(400,50-PlateHeight/8.0);
// int left,right;
flag=1;
for(i=PlateWidth/2;i>=0;i--)
{
if(HistV[i]>0)
{
if(flag)
{
flag=0;
}
else
{
PlateRect.left=i;
}
}
else if(HistV[i]==0)
break;
}
flag=1;
for(i=PlateWidth/2;i<PlateWidth;i++)
{
if(HistV[i]>0)
{
if(flag)
{
flag=0;
}
else
{
PlateRect.right=i;
}
}
else if(HistV[i]==0)
break;
}
delete []HistV;HistV=NULL;
CString str;
pDC->TextOut(0,180,"缩小范围:");
str.Format("高=%d",PlateRect.bottom-PlateRect.top+1);
pDC->TextOut(0,200,str);
str.Format("宽=%d",PlateRect.right-PlateRect.left+1);
pDC->TextOut(0,220,str);
BYTE PlateGray[230][460];
memset(PlateGray,0,sizeof(BYTE)*230*460);
//灰度化
for(i=PlateRect.top;i<=PlateRect.bottom;i++)
for(j=PlateRect.left;j<=PlateRect.right;j++)
{
PlateGray[i][j]=(Rt[i][j]+Gt[i][j]+Bt[i][j])/3;
}
//2显示灰度图像
for(i=PlateRect.top;i<=PlateRect.bottom;i++)
for(j=PlateRect.left;j<=PlateRect.right;j++)
{
pDC->SetPixel(50+j,200+i,RGB(PlateGray[i][j],PlateGray[i][j],PlateGray[i][j]));
}
//plateThre
BYTE Data;
int Thre=OstuThroldDIB3Out(PlateGray);
for(i=PlateRect.top;i<=PlateRect.bottom;i++)
for(j=PlateRect.left;j<=PlateRect.right;j++)
{
if(PlateGray[i][j]<Thre)
{
Data=255;
}
else
{
Data=0;
}
//3显示车牌区域二值化后的图像
pDC->SetPixel(50+j,300+i,RGB(Data,Data,Data));
}
/*------------------------------------------------------
次 函数调用代码添加处
-------------------------------------------------------*/
StrongObject3Out(PlateGray);//对车牌区域直方图均衡化
Thre=OstuThroldDIB3Out(PlateGray);
for(i=PlateRect.top;i<=PlateRect.bottom;i++)
{
for(j=PlateRect.left;j<=PlateRect.right;j++)
{
//4显示直方图均衡化的图像
pDC->SetPixel(50+j,400+i,RGB(PlateGray[i][j],PlateGray[i][j],PlateGray[i][j]));
// 对直方图均衡化后的车牌区域再次二值化
if(PlateGray[i][j]<Thre)
{
PlateGray[i][j]=255;
}
else
{
PlateGray[i][j]=0;
}
//5显示二值化的图像
pDC->SetPixel(50+j,500+i,RGB(PlateGray[i][j],PlateGray[i][j],PlateGray[i][j]));
}
}
CPen GreenPen(PS_SOLID,1,RGB(0,255,0));
CPen *OldPen;
OldPen=pDC->SelectObject(&GreenPen);
pDC->SelectStockObject(NULL_BRUSH);
pDC->Rectangle(50+PlateRect.left,500+PlateRect.top,50+PlateRect.right,500+PlateRect.bottom);
/**--------------------------------------------------
调用函数PlateProjection, 对车牌区域的上下边界进行再定位,
对车牌区域进行垂直方向的投影,分割出各个单个的字符位置
-----------------------------------------------------**/
PlateProjection(PlateGray,PlateHeight,PlateWidth);
//
pDC->SelectObject(OldPen);
ReleaseDC(pDC);
}