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); }