车牌识别C语言源码 第一版

欢迎加入群105060236讨论。

2011-11-23更新

http://blog.csdn.net/liujia2100/article/details/6989712

http://blog.csdn.net/liujia2100/article/details/26989939

http://www.oschina.net/p/easypr

http://blog.csdn.net/longzaitianya1989/article/details/8159706

http://blog.csdn.net/yang_xian521/article/details/7050398

本算法主要分成这几个部分,图像采集(即图像输入)、图像预处理(粗略定位车牌位置)、图像处理(精确确定车牌位置,去噪)、车牌字符分割(上下边界,左右边界确定)和字符识别。


这是第二版的代码,包含三个文件,主要把匹配的模板从几十个图片合成一个数据库放到一个文件里面,即moban.h
把函数放到另一个文件里面,即Def.h

下图是在Linux下Eclipse工程截图

PC计算的结果是30ms。处理的这个车牌图片分辨率是640*480,如下

本算法还加入了图像矫正处理,并且具备一定的去噪功能下图

识别结果为

下面是在ARM6410上运行截图































以下是ARM9运行截图


ARM9 2440由于不支持硬浮点,处理640*480的24位bmp位图,非常吃力。平均需要6秒以上,这里还没有加入摄像头采集。
其中ARM9运行的程序,使用的匹配模板是原始的几十个20*40的bmp图片,如下图

这个库文件在后来,整合到了moban.h里面,方便移植。



在开发板上只是测试,没有完善的编程软件,由于没有汉字库,所以,不能显示汉字
上图是ARM9平台下。这里使用的是最原始的代码
当然,倾斜矫正和去噪处理加大了运算量。其中倾斜矫正运用霍夫变换的方法,有大量的浮点数据需要计算。占用总处理时间的大部分。
这是最原始的车牌识别程序,有些库没有添加!之后还有改善的,主要是把图像匹配的数据库放到程序中,本程序在arm2440Linux环境下运算需要6秒左右,在6410下需要1秒多,很多地方没有优化。仅供参考

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include "cv.h"
//#include "highgui.h"
#include "math.h"
#define pi 3.14
#define RADIAN(angle) ((angle)*3.14/180.0)

#define max(a,b)            (((a) > (b)) ? (a) : (b))
#define min(a,b)            (((a) < (b)) ? (a) : (b))

typedef unsigned long       DWORD;
typedef int                 BOOL;
typedef unsigned char       BYTE;
typedef unsigned short      WORD;
typedef float               FLOAT;
typedef unsigned char       byte;
//#define MAX(a,b,c) a>(b>c?b:c)?a:
struct BMP_img
{
    WORD  bfType;
    DWORD size;
 DWORD reser;
 DWORD header_length;
    DWORD infoheader_length;
 DWORD width;
 DWORD height;
 WORD  biplanes;
 WORD  bmp_type;        /* 8bit 24bit; */
 DWORD compres;
 DWORD datasize;
    DWORD bixpm;
 DWORD biypm;
 DWORD clrused;
 DWORD  relclrused;
    BYTE *image;
    byte *header_info;
 DWORD lineBytes;

};

struct Bmp1{
 DWORD width;
 DWORD height;
 byte strc[67][800];
 BYTE *image;
 int p1[15];//xl
 int p2[15];//xr
 int p3[15];//yu
 int p4[15];//yd
 int up;
 int down;
    byte strr[7][2500];
 byte string[7];
 float ang;//倾斜角度
};

struct HSV{
  float H;
  float S;
  int V;
};
 struct RGB{
  byte bitb;
  byte bitg;
  byte bitr;
  byte  re;
              };
void read_img(FILE *infile, struct BMP_img *img);
//void read_img(FILE *infile, struct BMP_img *img);

void displaytwo(struct Bmp1 img,byte *srcBmp,byte *dstBmp,int yuzhi);
unsigned char  myGetMedianNum(unsigned char * bArray, int iFilterLen);
void cuizhitouying(struct Bmp1 *img,byte *temp);
void sob(byte *srcBmp,int width,int height,int type);
void shuipingtouying(struct Bmp1 *img,byte *temp);
//void display(BMP_img img,byte *temp);

void grayScale(struct BMP_img img,byte *srcBmp,byte *dstBmp);
void junheng(struct BMP_img img,byte *srcBmp,byte *dstBmp);
void CutBmp(struct BMP_img img,struct Bmp1 *img1,int HL,int HH,int VL,int VH);
void CutBmp1(struct Bmp1 *img1,int HL,int HH,int VL,int VH);
void testhsv(float h,float s,float v,byte r,byte g,byte b);
void hsvzation(byte *image,struct HSV *hsv,int width,int height);
void location(byte *image,int width,int height,int yuzhi,int *HL,int *HH,int *VL,int *VH);
void huidu(struct Bmp1 img,byte *srcBmp,byte *dstBmp);
void bmptwo(struct Bmp1 img,byte *srcBmp,byte *dstBmp,byte yuzhi);
void Thiningtest(struct BMP_img img,byte *srcBmp,byte *dstBmp);
void Thining(byte *srcBmp,int width,int height);
void ThinnerRosenfeld(void *image, unsigned long lx, unsigned long ly);
void delpoint(byte *dst,int width,int height,int yuzhi);
void Erosion(byte *image,int width,int height,int type,int num);
void deljunzao(byte *dst,int width,int height,int yuzhi);
void pingjun(byte *dst,int width,int height);
void changeGray(byte *srcBmp,byte *dstBmp,int width,int height,int nWidth,int nHeight);
byte *changeRGB(byte *srcBmp,int width,int height,int *lwidth,int *lheight,float f);
void strBmp(struct Bmp1 *img,byte *temp);
void guiyi(struct Bmp1 *img);
void readstr(FILE *infile, byte *srcBmp);
char *myitoa(int num, char *str, int radix);   // 整数字符串转换。
void readmoban(char *path,struct Bmp1 *img2);
void writebmp(const char *path,const char *name,byte *temp);
int cmpstr(byte *src,byte *moban);
void Hough(struct Bmp1 *img);
void strout(struct Bmp1 *img);
void edgesob8(byte *image,int width,int height);
void edgesob4(byte *image,int width,int height);//4邻域
int hough(byte *srcBmp,int width,int height);
void Dilation(byte *image,int width,int height,int type,int num);
void RotateGray(byte *image,int width,int height, float iRotateAngle);
byte *RotateRGB(byte *image, float iRotateAngle,int width,int height,int *lwidth,int *lheight);
void xuanzhuan(struct Bmp1 *img1);
byte *myMalloc(int num,const byte *bmp,int type);
void guiyiRGB(struct Bmp1 *img1);
void outtext(struct Bmp1 img1,int x,int y);
int calstr(byte *srcBmp);

int main()
{
    while(1)
 {

 
 int HL=0,HH=0,VH=0,VL=0;
 struct BMP_img img;
 struct Bmp1 img1;
 FILE *f;
    byte *temp,*temp1;
    //char path[80]="C:\\test\\2.bmp";
    char path1[80]="C:\\test\\moban\\";
 char path[80];
    char path3[40];
    printf("Please Input Path\n");
  
    scanf("%s",path3);
    strcpy(path,path3);
    printf("the path is :%s\n",path);

   // char path1[80]="//mnt//arm1//test//moban//";
    //char path[80]="C:\\Documents and Settings\\liujia\\桌面\\test\\example06.bmp";
    //char path1[80]="C:\\Documents and Settings\\liujia\\桌面\\test\\moban\\";

 

    if((f=fopen(path,"rb"))==NULL)
 {
     printf( "\nCan not open the path: %s \n", path);
     exit(-1);
 }
 read_img(f, &img);
 fclose(f);
           temp=myMalloc(img.height*img.width*4,temp,0);//(byte *)malloc(sizeof(byte)*img.height*img.width*4);// byte *temp2=(byte *)malloc(sizeof(byte)*img.height*img.width);
           temp1=myMalloc(img.height*img.width*4,temp,0);
  location(img.image,img.width,img.height,15,&HL,&HH,&VL,&VH);
   CutBmp(img,&img1,HL,HH,VL,VH);
    Hough(&img1);
    xuanzhuan(&img1);
 location(img1.image,img1.width,img1.height,0,&HL,&HH,&VL,&VH);
 CutBmp1(&img1,HL,HH,VL,VH);
 huidu(img1,img1.image,temp);
 displaytwo(img1,temp,temp1,30);
    delpoint(temp1,img1.width,img1.height,3);
    shuipingtouying(&img1,temp1);
 delpoint(temp1,img1.width,img1.height,2);
    cuizhitouying(&img1,temp1);
    memset(temp,0,sizeof(char)*img1.width*img1.height);
 strBmp(&img1,temp1);//把车牌字符放到数组里面
    guiyi(&img1);
    readmoban(path1,&img1);
 strout(&img1);
    outtext(img1,0,600);
    free(temp1);
    free(temp);

 getch();
}
 return 0;
  }
void read_img(FILE *infile, struct BMP_img *img)
{

 DWORD i,j,l,bitcolor;
 DWORD line24;
 DWORD line8;

    struct RGB *bitmap;
 fread(&img->bfType,sizeof(WORD),1,infile);//printf("\n打开的图为 %d",img->bfType);
 fread(&img->size,sizeof(DWORD),1,infile);     //        printf("\nBMP size             :%l",img->size);
 fread(&img->reser,sizeof(DWORD),1,infile);//printf("\n保留位:");
 fread(&img->header_length,sizeof(DWORD),1,infile); //printf("\nheader length    :%l",img->header_length);
 fread(&img->infoheader_length,sizeof(DWORD),1,infile);
 fread(&img->width, sizeof(DWORD), 1, infile);
 fread(&img->height, sizeof(DWORD), 1, infile);     //printf( "\nwidth   :%l\n  height  :%l ", img->width, img->height);
 fread(&img->biplanes, sizeof(WORD), 1, infile);
 fread(&img->bmp_type, sizeof(WORD), 1, infile);  // printf("\nBMP Tpye             :%l ", img->bmp_type);
 fread(&img->compres, sizeof(DWORD), 1, infile);    //if(img->compres==0) {printf("\nbmp图片为非压缩!");}printf(" ");
 fread(&img->datasize, sizeof(DWORD), 1, infile);//printf("\nBMP Data Size        :%l ",img->datasize);
 fread(&img->bixpm, sizeof(DWORD), 1, infile);
 fread(&img->biypm, sizeof(DWORD), 1, infile);
 fread(&img->clrused, sizeof(DWORD), 1, infile);    //printf("\n实际使用颜色数=%d ",img->clrused);printf(" ");
 fread(&img->relclrused, sizeof(DWORD), 1, infile);

 img->lineBytes=(img->width*img->bmp_type+31)/32*4;
                                                                                                               //printf("\nLineBytes            :%l\n",img->lineBytes);

 line24=(img->width*24+31)/32*4;

    line8=(img->width*8+31)/32*4;
  if(img->bmp_type==1){bitcolor=2;printf("不能读取退出");exit(-1);}
  if(img->bmp_type==4){bitcolor=16;printf("不能读取退出");exit(-1);}
  if(img->bmp_type==8)
  {
   byte *temp=(BYTE*)malloc(img->height*line8*sizeof(BYTE));
   memset(temp,0x00,img->height*img->lineBytes*sizeof(BYTE));

   bitcolor=256;
   bitmap=(struct RGB *)calloc(bitcolor,sizeof(struct RGB));
   img->image=(unsigned char *)malloc(sizeof(unsigned char)*(line8*img->height));
   memset(img->image,0x00,sizeof(byte)*line8*img->height);

   if(img->image==NULL) {fprintf(stderr, "\n Allocation error for temp in read_bmp() \n");}

   fseek(infile,0x36, SEEK_SET);
   fread(bitmap,sizeof(struct RGB),bitcolor,infile);
   fseek(infile, img->header_length, SEEK_SET);
   //fread(temp, sizeof(unsigned char),lineBytes*img->height, infile);
   fread(temp, img->lineBytes*img->height,1, infile);
   if(temp==NULL)printf("\n读取失败\n");

   for(i=0;i<img->height;i++)
   {
    for(j=0;j<img->width;j++)
    {
     img->image[i*img->width+j]=(byte)(0.299*bitmap[temp[i*line8+j]].bitb+0.578*bitmap[temp[i*line8+j]].bitg+0.114*bitmap[temp[i*line8+j]].bitr);
   // putpixel(j,img->height-i,RGB(img->image[i*img->width+j],img->image[i*img->width+j],img->image[i*img->width+j]));

    }
   }
   free(temp);
   temp=NULL;
  }
  if(img->bmp_type==24)
  {
   byte *temp=(byte *)malloc(sizeof(byte)*img->height*img->lineBytes); if(temp==NULL)
    exit(-1);
   img->image=(unsigned char *)malloc(sizeof(unsigned char)*((line24)*img->height));
   if(img->image==NULL) fprintf(stderr, "\n Allocation error for temp in read_bmp() \n");
   fseek(infile, img->header_length, SEEK_SET);
   fread(temp, sizeof(unsigned char), (img->lineBytes)*img->height, infile);
     // byte *temp=(byte *)malloc(sizeof(byte)*img->lineBytes*img->height)

   for(i=0;i<img->height;i++)
   {
   l=0;
    for(j=0;j<img->width*3;j+=3)
   {
    //l=(img->height-i-1)*img->lineBytes+j;
     l=(img->height-i-1)*img->width*3+j;
                      img->image[l+2]=*(temp+i*img->lineBytes+j+2);
       img->image[l+1]=*(temp+i*img->lineBytes+j+1);
       img->image[l]=*(temp+i*img->lineBytes+j);
   }
   }

 free(temp);
 temp=NULL;
  }
}

void readstr(FILE *infile, byte *srcBmp)
{

 int width,height, headlength;
 int i,j,bitcolor,line8;
 byte *temp;
 byte temp1;
 struct RGB *bitmap;

 width=20;
 height=40;
 headlength=1078;

 line8=(width*8+31)/32*4;

 temp=(BYTE*)malloc(height*line8*sizeof(BYTE));
    memset(temp,0x00,height*line8*sizeof(BYTE));
      bitcolor=256;
    bitmap=(struct RGB *)malloc(sizeof(struct RGB)*bitcolor);
   fseek(infile,0x36, SEEK_SET);
   fread(bitmap,sizeof(struct RGB),bitcolor,infile);
   fseek(infile, headlength, SEEK_SET);
   fread(temp, line8*height,1, infile);
   if(temp==NULL){printf("\n读取失败\n"); exit(-1);}

   for(i=0;i<height;i++)
   {
    for(j=0;j<width;j++)
    {

    temp1=temp[i*line8+j];
    if(temp1>=150)
     temp1=255;
    else temp1=0;
     srcBmp[(height-i-1)*width+j]=temp1;//(byte)(0.299*bitmap[temp[i*line8+j]].bitb+0.578*bitmap[temp[i*line8+j]].bitg+0.114*bitmap[temp[i*line8+j]].bitr);

    }
   }
   free(temp);
   temp=NULL;
 }

void grayScale(struct BMP_img img,byte *srcBmp,byte *dstBmp)
{
 int i,j,temp1,n;
 float gray;
 temp1=img.width*3;
 srcBmp=img.image;
 for(i=0;i<img.height;i++)
    {
        for(j=0,n=0;j<img.width;n+=3,j++)

        {
   gray=(*(srcBmp+i*img.lineBytes+n+2)*0.299)+(*(srcBmp+i*img.lineBytes+n+1)*0.578)+(*(srcBmp+i*img.lineBytes+n)*0.114);
   dstBmp[i*img.lineBytes+n]=(byte)(gray+0.5);
   dstBmp[i*img.lineBytes+n+1]=(byte)(gray+0.5);
   dstBmp[i*img.lineBytes+n+2]=(byte)(gray+0.5);

  }
    }
}
void huidu(struct Bmp1 img,byte *srcBmp,byte *dstBmp)
{
 int i,j,n;
 float gray;
 srcBmp=img.image;
 for(i=0;i<img.height;i++)
    {
        for(j=0,n=0;j<img.width;n+=3,j++)

        {
   gray=(*(srcBmp+i*img.width*3+n+2)*0.299)+(*(srcBmp+i*img.width*3+n+1)*0.578)+(*(srcBmp+i*img.width*3+n)*0.114);
   dstBmp[i*img.width+j]=(byte)(gray+0.5);


  }
    }
}
void hsvzation(byte *image,struct HSV *hsv,int width,int height)
{
 int i,j,k;
 float min,max,delta,tmp;//h,s,v,m,n;
 //int lineBytes=(width*24+31)/32*4;
 byte r,g,b;
 for(i=0;i<height;i++)
 {
  for(k=0,j=0;j<width*3;k++,j+=3)
  {
   g=image[i*width*3+j+1];
   b=image[i*width*3+j];
   r=image[i*width*3+j+2];

   tmp=min(r,g);
   min=min(tmp,b);
   tmp=max(r,g);
   max=max(tmp,b);
   hsv[i*width+k].V=(int)max;
   delta=max-min;
   if(delta==0)
   {
    hsv[i*width+k].H=0;
    continue;
    //value=0;
    //return value;
   }
   if(max!=0)
   {

    //tmp=delta/max;
    hsv[i*width+k].S=delta/max;//tmp;
   }
   else
   {

    hsv[i*width+k].S=0;
    hsv[i*width+k].H=0;
    continue;

   }
   if(r==max)
   {
    // tmp=(g-b)/delta;
    hsv[i*width+k].H=(g-b)/delta;//tmp;
   }
   else if(g==max)
    hsv[i*width+k].H=2+(b-r);
   else
   {
    //tmp=4+(r-g)/delta;
    hsv[i*width+k].H=4+(r-g)/delta;//tmp;
   }
   hsv[i*width+k].H*=60;
   if(hsv[i*width+k].H<0)
    hsv[i*width+k].H+=360;
   //value=(int)(h+0.5);

 

  }
 }


}

void location(byte *image,int width,int height,int yuzhi,int *HL,int *HH,int *VL,int *VH)
{
    int i,j,n,maxnum,flag=0;
 struct HSV *hsv;
 int temp[2000]={0};
 byte *temp1;
    hsv=(struct HSV *)malloc(sizeof(struct HSV)*width*height);
    hsvzation(image,hsv,width,height);

 temp1=(byte *)malloc(sizeof(byte)*height*width);

 //int lineBytes=(width*24+31)/32*4;
     for(i=0;i<height;i++)
     {
      for(j=0,n=0;j<width;n+=3,j++)
    {
       if((hsv[i*width+j].H<220.0)&&(hsv[i*width+j].H>180.0)&&(hsv[i*width+j].V<250)&&(hsv[i*width+j].S>0.6))
       {

        temp1[i*width+j]=255;
        //putpixel(j,i,RGB(255,255,255));
       }
       else
       {
        temp1[i*width+j]=0;
        //putpixel(j,i,RGB(0,0,0));
       }
      }
     }
     for(i=0;i<height;i++)
     {
      for(j=0;j<width;j++)
      {
       if(temp1[i*width+j]==255)
       {
       temp[i]++;

       }
      }
     }
       edgesob8(temp1,width,height);

     maxnum=temp[0];
     for(i=1;i<height;i++)
     {

      if(temp[i]>maxnum)
       maxnum=temp[i];
     }
     maxnum=maxnum/3;
     for(i=0;i<height;i++)
     {
      if(flag==0)
      {
                 if(temp[i]>maxnum)
     {
      *HL=i-yuzhi;

       flag=1;
     }
      }
      if(flag==1)
      {

       if(temp[i]==0)
       {
        *HH=i+yuzhi;

        break;
       }
      }
     }


           memset(temp,0x00,sizeof(int)*width);
     for(i=0;i<width;i++)
     {
      for(j=0;j<height;j++)
      {
       if(temp1[j*width+i]==255)
       {
        temp[i]++;

       }
      }
     }
     flag=0;
     maxnum=temp[0];

 

     for(i=1;i<width;i++)
     {

      if(temp[i]>maxnum)
       maxnum=temp[i];
     }
     maxnum=maxnum/3;
     for(i=0;i<width;i++)
     {
      if(temp[i]>maxnum)
       {
        *VL=i-yuzhi;

       break;
       }
     }

     for(i=width;i>*VL;i--)
     {
       if(temp[i]>maxnum)
       {
        *VH=i+yuzhi;

        break;
       }

     }
     free(temp1);
     temp1=NULL;
     free(hsv);
}
void Hough(struct Bmp1 *img)
{
    int i,j,n;
 float ang;
 byte *temp1;
 //int temp[2000]={0};
    struct HSV *hsv=(struct HSV *)malloc(sizeof(struct HSV)*img->width*img->height);
    hsvzation(img->image,hsv,img->width,img->height);
 temp1=(byte *)malloc(sizeof(byte)*img->height*img->width);


     for(i=0;i<img->height;i++)
     {
      for(j=0,n=0;j<img->width;n+=3,j++)
    {
       if((hsv[i*img->width+j].H<220.0)&&(hsv[i*img->width+j].H>180.0)&&(hsv[i*img->width+j].V<250)&&(hsv[i*img->width+j].S>0.6))
       {
          temp1[i*img->width+j]=255;


       }
       else
       {
        temp1[i*img->width+j]=0;

       }
      }
     }


     Dilation(temp1,img->width,img->height,1,5);
     sob(temp1,img->width,img->height,0);
     ang=hough(temp1,img->width,img->height);
    if((ang<=8)&&(ang>=1))
      ang=ang-1;
     if(ang>90)
     {
      ang=ang-180;

     }
     img->ang=ang;

 

}
void bmptwo(struct Bmp1 img,byte *srcBmp,byte *dstBmp,byte yuzhi)
{
 int i,j;
 for(i=0;i<img.height;i++)
 {
  for(j=0;j<img.width;j++)
  {
   if(srcBmp[i*img.width+j]>=yuzhi)
   {
    dstBmp[i*img.width+j]=255;
   }
   else
   {
    dstBmp[i*img.width+j]=0;


   }
  }
  }
}
void displaytwo(struct Bmp1 img,byte *srcBmp,byte *dstBmp,int yuzhi)
{
    //int i,j,T,n,k,t,l;
 //int m;
 int totalPixels = img.width * img.height;
 int bestT = 0;


  int i,j;

 int histogramArray[256]={0};
 double densityArray[256]={0};
  double u0 = 0;
  double u1 = 0;
   double w0 = 0;
  double w1 = 0;
   double bestDeviation = 0;


 for(i=0;i<img.height;i++)
 {
  for(j=0;j<img.width;j++)
  {
    histogramArray[srcBmp[i*img.width+j]]++;
  }
  }
 for(i=0;i<256;i++)
 {
 densityArray[i] = histogramArray[i] * 1.0 / totalPixels;
 }
 for (i = 0; i < 256; i++)
  {
  w0 = 0;
  w1 = 0;
  for (j = 0; j <= i; j++) {
   w0 += densityArray[j];
  }
  for (j = i + 1; j < 256; j++) {
   w1 += densityArray[j];
  }
  u0 = 0;
  u1 = 0;
  for (j = 0; j <= i; j++) {
   u0 += j * densityArray[j];
  }
  for (j = i + 1; j < 256; j++) {
   u1 += j * densityArray[j];
  }
  u0 = u0 / w0;
  u1 = u1 / w1;
  if (w0 * w1 * (u0 - u1) * (u0 - u1) > bestDeviation) {
   bestT = i;
   bestDeviation = w0 * w1 * (u0 - u1) * (u0 - u1);
  }
 }
 for (i = 0; i < 256; i++) {
  histogramArray[i] = 0;
  }
 bestT=bestT+yuzhi;
 if(bestT<0)
  bestT=0;
 if(bestT>255)
  bestT=255;
 for(i=0;i<img.height;i++)
 {
  for(j=0;j<img.width;j++)
  {
   if(srcBmp[i*img.width+j]>bestT)
   {
    dstBmp[i*img.width+j]=255;

   }
   else
   {
    dstBmp[i*img.width+j]=0;


   }
  }
  }


 }

/*************************************************************************
*
* 函数名称:
*   MedianFilter()
*
* 参数:
*   LPSTR lpDIBBits  - 指向源DIB图像指针
*   LONG  lWidth   - 源图像宽度(象素数)
*   LONG  lHeight   - 源图像高度(象素数)
*   int   iFilterH   - 滤波器的高度
*   int   iFilterW   - 滤波器的宽度
*   int   iFilterMX  - 滤波器的中心元素X坐标
*   int   iFilterMY  - 滤波器的中心元素Y坐标
*
* 返回值:
*   BOOL     - 成功返回TRUE,否则返回FALSE。
*
* 说明:
*   该函数对DIB图像进行中值滤波。
*
************************************************************************/
int myMedianFilter(struct Bmp1 img,byte *temp,int iFilterH,int iFilterW,int iFilterMX,int iFilterMY)
{


 unsigned char* lpSrc;
 unsigned char* lpDst;
 int lHeight=img.height;
 int lWidth=img.width;
    unsigned char *aValue;
 byte   *hArray;

 // 循环变量
 int i,j,l,k;

 byte *lpNewDIBBits=(byte *)malloc(sizeof(byte)*img.height*img.width);
 if(lpNewDIBBits==NULL)
  exit(-1);


 memcpy(lpNewDIBBits,temp, img.width * lHeight);

 hArray=(byte *)malloc(sizeof(byte)*iFilterH*iFilterW);
 aValue=(byte *)malloc(sizeof(byte)*iFilterH*iFilterW);

 for(i = iFilterMY; i < lHeight - iFilterH + iFilterMY + 1; i++)
 {
  // 列(除去边缘几列)
  for(j = iFilterMX; j < lWidth - iFilterW + iFilterMX + 1; j++)
  {
   // 指向新DIB第i行,第j个象素的指针
   lpDst = (unsigned char*)lpNewDIBBits + img.width * (lHeight - 1 - i) + j;

   // 读取滤波器数组
   for (k = 0; k < iFilterH; k++)
   {
    for (l = 0; l < iFilterW; l++)
    {
     // 指向DIB第i - iFilterMY + k行,第j - iFilterMX + l个象素的指针
     lpSrc = (unsigned char*)temp + img.width * (lHeight - 1 - i + iFilterMY - k) + j - iFilterMX + l;

     // 保存象素值
     aValue[k * iFilterW + l] = *lpSrc;
    }
   }

   // 获取中值
   * lpDst = myGetMedianNum(aValue, iFilterH * iFilterW);
  }
 }

   memcpy(temp, lpNewDIBBits, img.width * img.height);
 // 释放内存
 free(lpNewDIBBits);
 lpNewDIBBits=NULL;
    free(hArray);
 hArray=NULL;

 // 返回
 return 1;
}
/*************************************************************************
*
* 函数名称:
*   GetMedianNum()
*
* 参数:
*   unsigned char * bpArray - 指向要获取中值的数组指针
*   int   iFilterLen   - 数组长度
*
* 返回值:
*   unsigned char      - 返回指定数组的中值。
*
* 说明:
*   该函数用冒泡法对一维数组进行排序,并返回数组元素的中值。
*
************************************************************************/

unsigned char  myGetMedianNum(unsigned char * bArray, int iFilterLen)
{
 // 循环变量
 int  i;
 int  j;

 // 中间变量
 unsigned char bTemp;

 // 用冒泡法对数组进行排序
 for (j = 0; j < iFilterLen - 1; j ++)
 {
  for (i = 0; i < iFilterLen - j - 1; i ++)
  {
   if (bArray[i] > bArray[i + 1])
   {
    // 互换
    bTemp = bArray[i];
    bArray[i] = bArray[i + 1];
    bArray[i + 1] = bTemp;
   }
  }
 }

 // 计算中值
 if ((iFilterLen & 1) > 0)
 {
  // 数组有奇数个元素,返回中间一个元素
  bTemp = bArray[(iFilterLen + 1) / 2];
 }
 else
 {
  // 数组有偶数个元素,返回中间两个元素平均值
  bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2;
 }

 // 返回中值
 return bTemp;
}
void shuipingtouying(struct Bmp1 *img,byte *dst)//得到车牌的上下边缘
{

 byte temp;
    int i,j;
  //int *p=(int *)malloc(sizeof(int)*img.height);
 int p[500]={0};
  memset(p,0,img->height*sizeof(int));

  for(i=0;i<img->width;i++)
 {
       if((dst[i]>=200)||(dst[img->width+i]>=200))
        for(j=0;j<img->height;j++)
  {
   if(dst[j*img->width+i]>=200)
                dst[j*img->width+i]=0;
   else break;
  }
 }
 for(i=0;i<img->width;i++)
 {
  if((dst[img->width*(img->height-1)+i]>=200)||(dst[img->width*(img->height-2)+i]>=200))
   for(j=img->height-1;j>0;j--)
   {
    if(dst[j*img->width+i]>=200)
     dst[j*img->width+i]=0;
    else break;
   }
 }

  for(i=2;i<img->height-2;i++)
 {

  for(j=0;j<img->width;j++)
  {
   if(dst[i*img->width+j]>=200)
    p[i]++;

  }
 }

  temp=0;
  for(i=0;i<img->height;i++)
  {
        if(p[i]>temp)
  {
    temp=p[i];

  }

  }

   j=temp/5;
   for(i=img->height;i>img->up;i--)
   {
    if(p[i]>j)
    {
     img->down=i;
     break;
    }
    if(i<img->height/2)
     exit(-1);
   }


    j=temp/3;
   for(i=0;i<img->down;i++)
   {

               if(p[i]>j)
      {
       img->up=i;
       break;
      }
      if(i>img->height/2)
       exit(-1);

   }

 for(i=0;i<img->up-1;i++)
  {
   for(j=0;j<img->width;j++)
     {
   dst[i*img->width+j]=0;

     }

  }
  for(i=img->height;i>img->down+1;i--)
  {
   for(j=0;j<img->width;j++)
     {
   dst[i*img->width+j]=0;

     }

  }

}
void sob(byte *srcBmp,int width,int height,int type)     //sob算子边缘检测;取出边界;
{
 int i,j,l,x,y;
// int px[6]={0};
 //int py[6]={0};
 int p1[4]={0};
 //double result;
 byte *tempy;
 byte *tempx;
 tempx=(byte *)malloc(sizeof(byte)*width*width);
 if(tempx==NULL)
  exit(-1);
 tempy=(byte *)malloc(sizeof(byte)*width*width);
 if(tempy==NULL)
  exit(-1);
  for(i =1; i<height-1; i++)
  {
   for(j=1;j<width-1;j++)//由于使用3×3的模板,为防止越界,所以不处理最下边和最右边的两列像素
   {

      if(i==height-1)
       x=0,y=0;
      else if(j==width-1)
       x=0,y=0;

      else{

       p1[0] = (byte)*(srcBmp+i*width+j);
       p1[1] = (byte)*(srcBmp+i*width+j+1);
       p1[2] = (byte)*(srcBmp+(i+1)*width+j);
       p1[3] = (byte)*(srcBmp+(i+1)*width+j+1);

 

       x=abs(p1[0]-p1[2]); //sqrt(( p1[1] - p1[2] )*( p1[1] - p1[2] ));
       y=abs(p1[0]-p1[1]);
       if(x>0)
        x=255;
       else
        x=0;
       if(y>0)
        y=255;
       else
         y=0;

      }


   tempx[i*width+j]=(byte)x;
   tempy[i*width+j]=(byte)y;
   }
  }
 for (i = 0; i < width; i++)
 {
  tempx[i] = 0;
  tempy[i] = 0;
  tempx[width*(height-1)+i] = 0;
  tempy[width*(height-1)+i] = 0;
 }
 for (i = 0; i < height; i++)
 {
  tempx[i*width] = 0;
  tempy[i*width] = 0;
  tempx[i*width+width-1] = 0;
  tempy[i*width+width-1] = 0;
 }
    if(type==0)
       memcpy(srcBmp,tempx,sizeof(byte)*width*height);
    if(type==1)
       memcpy(srcBmp,tempy,sizeof(byte)*width*height);
    if(type==2)
 {
      for(i=0;i<height;i++)
    for(j=0;j<width;j++)
    {
     l=tempx[i*width+j]+tempy[i*height+j];
     if(l>255)
      l=255;
     tempx[i*width+j]=l;
    }
       memcpy(srcBmp,tempx,sizeof(byte)*width*height);
 }
   free(tempx);
   free(tempy);
   tempx=NULL;
   tempy=NULL;

}
void cuizhitouying(struct Bmp1 *img,byte *temp)
{


 int p3[15]={0};
    int i,j,k=0,m,num,flag;
 //img.p1[15]={0};
 //img.p2[15]={0};

      int up=0;
   int down=0;
    int p[500]={0};

     for(i=0;i<img->width;i++)
 {

  for(j=0;j<img->height;j++)
  {
   if(temp[j*img->width+i]==255)
   { p[i]++;}

  }
 }

  for(i=1;i<img->width;i++)//除燥
  {
   if(p[i]>0)
   {
    if((p[i-1]==0)&&(p[i+1]==0))
     if(p[i]<5)
     p[i]=0;

   }
  }
  flag=0,m=0;
  for(i=0;i<img->width;i++)
  {
   if(p[i]>0)
   {
     flag=1;
     m++;
   }
   if((p[i]==0)&&(flag==1))
    break;
  }


      while(1)
   {
   num=0;
   flag=0;

     for(i=0;i<img->width;i++)
  {
       if(p[i]>1)
    {
            if(flag==0)
   {
      img->p1[num]=i;
      flag=1;
   }

   }
      else if(p[i]==0)
   {
     if(flag==1)
     {
      img->p2[num]=i-1;
      flag=0;
      j=img->p2[num]-img->p1[num];
      if(j<m/3)
      {
       if(p[i-1]<(img->down-img->up)/2)
       continue;
      }
      num++;
     }
  }
    if((flag==1)&&(i==img->width-1))
    {
     img->p2[num]=i;
     num++;
     break;
    }

   }
      if(num==7)
    break;
   else if(num==8)
   {


    j=100;
    for(i=0;i<num;i++)
   {
           p3[i]=img->p2[i]-img->p1[i];
    if(p3[i]<j)
             {
     j=p3[i];
     k=i;
    }
   }
    for(i=k;i<=num-k;i++)
    {
     img->p1[i]=img->p1[i+1];
     img->p2[i]=img->p2[i+1];
    }
    num--;
    break;
   }
    else //(num<7)
    {
   for(i=0;i<img->width;i++)
           {
      if(p[i]>0)
       p[i]--;
     }
    }
   }
   flag=0;
    up=0;
    down=0;
   up=img->up-3;
   if(up<0)
    up=img->up;
   down=img->down+4;
   if(down>img->height)
    down=img->down;

  for(k=0;k<7;k++)
   {
    for(i=up;i<=down;i++)
    {
     for(j=img->p1[k];j<=img->p2[k];j++)
     {
      if(temp[i*img->width+j]==255)
      {
                     img->p3[k]=i;
      flag=1;
      break;
      }
     }
     if(flag==1)
     {
      flag=0;
      break;
     }
    }
    for(i=down;i>=up;i--)
    {
     for(j=img->p1[k];j<=img->p2[k];j++)
     {
      if(temp[i*img->width+j]==255)
      {
       img->p4[k]=i;
       flag=1;
       break;
      }
     }
     if(flag==1)
     {
      flag=0;
      break;
     }
    }
   }
 }

 

 

 

 

void junheng(struct BMP_img img,byte *srcBmp,byte *dstBmp)
{
  int n[256]={0};
  double p[256]={0};
     double c[256]={0};
  int height=img.height;
  int width=img.width;
     int totalPixels = width * height;
//  double gray=0;
     int i,j,max,min,l;
  for(i=0;i<img.height;i++)
  {
   for(j=0,l=0;j<img.width;l+=3,j++)

   {
    //gray=(*(srcBmp+i*img.lineBytes+l+2)*0.299)+(*(srcBmp+i*img.lineBytes+l+1)*0.578)+(*(srcBmp+i*img.lineBytes+l)*0.114);

    srcBmp[i*img.width+j]=*(srcBmp+i*img.lineBytes+l);
   }
    }
  for(i=0;i<img.height;i++)
  {
   for(j=0;j<img.width;j++)

   {

    n[srcBmp[i*width+j]]++;
   }
  }
  for(i=0;i<256;i++){
   p[i] = n[i]*1.0/totalPixels;
  }

  for(i=0;i<256;i++){
   for(j=0;j<=i;j++){
    c[i]+=p[j]; //累计直方图
   }
  }

  max=min=srcBmp[0];

  for(i=0;i<img.height;i++)
  {
   for(j=0;j<img.width;j++)

   {
    n[srcBmp[i*width+j]]++;
   }
  }
  for(i=0;i<height;i++)
  {
   for(j=0;j<width;j++)
   {
    if(max<srcBmp[i*width+j])
    {max=srcBmp[i*width+j];}
    else if(min>srcBmp[i*width+j]){min=srcBmp[i*width+j];}
   }
  }

  for(i=0;i<height;i++){
   for(j=0;j<width;j++){
    dstBmp[i*img.lineBytes+j*3]=(byte)(c[srcBmp[i*width+j]]*(max-min)+min+0.5);
    dstBmp[i*img.lineBytes+j*3+1]=(byte)(c[srcBmp[i*width+j]]*(max-min)+min+0.5);
    dstBmp[i*img.lineBytes+j*3+2]=(byte)(c[srcBmp[i*width+j]]*(max-min)+min+0.5);
   }
  }
  //display(img,temp1);

}

void CutBmp(struct BMP_img img,struct Bmp1 *img1,int HL,int HH,int VL,int VH)
{
   int i,j,n;
   //float gray;
   int x=0,y=0;
   img1->width=VH-VL;
   img1->height=HH-HL;
   img1->image=myMalloc(img1->height*img1->width*3,0,0);//(byte *)malloc(sizeof(byte)*img1->height*img1->width*3);

   for(x=0,i=HL;i<HH;x++,i++)
   {
    for(y=0,n=0,j=VL*3;j<VH*3;n++,j+=3,y+=3)

    {

      img1->image[x*img1->width*3+y]=img.image[i*img.width*3+j];
      img1->image[x*img1->width*3+y+1]=img.image[i*img.width*3+j+1];
      img1->image[x*img1->width*3+y+2]=img.image[i*img.width*3+j+2];


    }

    }

}
void CutBmp1(struct Bmp1 *img1,int HL,int HH,int VL,int VH)
{
 int i,j,n;
 //float gray;
 int x=0,y=0;
 int width,height;
 width=img1->width;
 height=img1->height;

 //myMalloc(img1->width*img1->height*3,p,0);

 img1->width=VH-VL;
    img1->height=HH-HL;

 for(x=0,i=HL;i<HH;x++,i++)
 {
  for(y=0,n=0,j=VL*3;j<VH*3;n++,j+=3,y+=3)

    {


   img1->image[x*img1->width*3+y]=img1->image[i*width*3+j];
   img1->image[x*img1->width*3+y+1]=img1->image[i*width*3+j+1];
   img1->image[x*img1->width*3+y+2]=img1->image[i*width*3+j+2];

  }

    }
}

/**************************************************
* 函数名称:
*     ThinnerRosenfeld
*
* 参数:
*   void*     image             -二值化图像矩阵前景色为1背景色为0
*   unsigned  longlx             -图像的宽度
*   unsigned  longly             -图像的高度
*
* 返回值
*       无
*
*函数功能:
*       对输入的图像进行细化,输出细化后的图像
***********************************************************/
void ThinnerRosenfeld(void *image, unsigned long lx, unsigned long ly)
{
    char *f, *g;
    char n[10];
    char a[5] = {0, -1, 1, 0, 0};
    char b[5] = {0, 0, 0, 1, -1};
    char nrnd, cond, n48, n26, n24, n46, n68, n82, n123, n345, n567, n781;
    short k, shori;
    unsigned long i, j;
    long ii, jj, kk, kk1, kk2, kk3, size;
    size = (long)lx * (long)ly;

    g = (char *)malloc(size);
    if(g==NULL)
    {
        printf("error in alocating mmeory!\n");
        return;
    }

    f = (char *)image;
    for(kk=0l; kk<size; kk++)
    {
        g[kk] = f[kk];
    }

    do
    {
        shori = 0;
        for(k=1; k<=4; k++)
        {
            for(i=1; i<lx-1; i++)
            {
                ii = i + a[k];

                for(j=1; j<ly-1; j++)
                {
                    kk = i*ly + j;

                    if(!f[kk])
                        continue;

                    jj = j + b[k];
                    kk1 = ii*ly + jj;

                    if(f[kk1])
                        continue;

                    kk1 = kk - ly -1;
                    kk2 = kk1 + 1;
                    kk3 = kk2 + 1;
                    n[3] = f[kk1];
                    n[2] = f[kk2];
                    n[1] = f[kk3];
                    kk1 = kk - 1;
                    kk3 = kk + 1;
                    n[4] = f[kk1];
                    n[8] = f[kk3];
                    kk1 = kk + ly - 1;
                    kk2 = kk1 + 1;
                    kk3 = kk2 + 1;
                    n[5] = f[kk1];
                    n[6] = f[kk2];
                    n[7] = f[kk3];

                    nrnd = n[1] + n[2] + n[3] + n[4]
                        +n[5] + n[6] + n[7] + n[8];
                    if(nrnd<=1)
                        continue;

                    cond = 0;
                    n48 = n[4] + n[8];
                    n26 = n[2] + n[6];
                    n24 = n[2] + n[4];
                    n46 = n[4] + n[6];
                    n68 = n[6] + n[8];
                    n82 = n[8] + n[2];
                    n123 = n[1] + n[2] + n[3];
                    n345 = n[3] + n[4] + n[5];
                    n567 = n[5] + n[6] + n[7];
                    n781 = n[7] + n[8] + n[1];

                    if(n[2]==1 && n48==0 && n567>0)
                    {
                        if(!cond)
                            continue;
                        g[kk] = 0;
                        shori = 1;
                        continue;
                    }

                    if(n[6]==1 && n48==0 && n123>0)
                    {
                        if(!cond)
                            continue;
                        g[kk] = 0;
                        shori = 1;
                        continue;
                    }

                    if(n[8]==1 && n26==0 && n345>0)
                    {
                        if(!cond)
                            continue;
                        g[kk] = 0;
                        shori = 1;
                        continue;
                    }

                    if(n[4]==1 && n26==0 && n781>0)
                    {
                        if(!cond)
                            continue;
                        g[kk] = 0;
                        shori = 1;
                        continue;
                    }

                    if(n[5]==1 && n46==0)
                    {
                        if(!cond)
                            continue;
                        g[kk] = 0;
                        shori = 1;
                        continue;
                    }

                    if(n[7]==1 && n68==0)
                    {
                        if(!cond)
                            continue;
                        g[kk] = 0;
                        shori = 1;
                        continue;
                    }

                    if(n[1]==1 && n82==0)
                    {
                        if(!cond)
                            continue;
                        g[kk] = 0;
                        shori = 1;
                        continue;
                    }

                    if(n[3]==1 && n24==0)
                    {
                        if(!cond)
                            continue;
                        g[kk] = 0;
                        shori = 1;
                        continue;
                    }

                    cond = 1;
                    if(!cond)
                        continue;
                    g[kk] = 0;
                    shori = 1;
                }
            }

            for(i=0; i<lx; i++)
            {
                for(j=0; j<ly; j++)
                {
                    kk = i*ly + j;
                    f[kk] = g[kk];
                }
            }
        }
    }while(shori);

    free(g);
}

void Thining(byte *srcBmp,int width,int height)
{

 //循环变量
    int i,j;
    int lWidth=width,lHeight=height;
    //建立存储区存放2值矩阵
 BYTE *image = (BYTE*)malloc(lWidth*lHeight*sizeof(BYTE));
    //DWORD lineBytes=(img.width*24+31)/32*4;
 //float gray;
 //给2值矩阵赋值

 for(i=0;i<lHeight;i++)
 {
  for(j=0;j<lWidth;j++)
  {

   if(srcBmp[i*width+j]==0)
    image[i*lWidth+j]=0;

   else
    image[i*lWidth+j]=1;
   //putpixel(j,i,RGB(srcBmp[i*img.width+j],srcBmp[i*img.width+j],srcBmp[i*img.width+j]));

  }
 }

 //调用函数进行细化,两种函数可以选择

 ThinnerRosenfeld(image,height,width);

 //ThinnerHilditch(image,lHeight,lWidth);

 

 //将结果赋值到原图像中

 for(i=0;i<lHeight;i++)
 {
  for(j=0;j<lWidth;j++)
  {
   if(image[i*lWidth+j]==1)
    srcBmp[i*width+j]=(BYTE)255;
   else
    srcBmp[i*width+j]=(BYTE)0;
   }

 }

}

void Thiningtest(struct BMP_img img,byte *srcBmp,byte *dstBmp)
{

 //循环变量
    int i,j,n;
    int lWidth=img.width,lHeight=img.height;
    //建立存储区存放2值矩阵
 BYTE *image = (BYTE*)malloc(lWidth*lHeight*sizeof(BYTE));
    DWORD lineBytes=(img.width*24+31)/32*4;
 float gray;
 //给2值矩阵赋值
 for(i=0;i<img.height;i++)
 {
  for(j=0,n=0;j<img.width;n+=3,j++)

  {

   gray= 0.299*(float)(img.image[lineBytes*i+n+2])+0.578*(float)(*(img.image+lineBytes*i+n+1))+0.114*(float)(*(img.image+lineBytes*i+n));
   if(gray>120.0)
    srcBmp[i*img.width+j]=255;
   else srcBmp[i*img.width+j]=0;//(byte)gray;
        }
    }
 for(i=0;i<lHeight;i++)
 {
     for(j=0;j<lWidth;j++)
  {

       if(srcBmp[i*img.width+j]==0)
       image[i*lWidth+j]=1;

    else
         image[i*lWidth+j]=0;
  }
 }

   //调用函数进行细化,两种函数可以选择

   ThinnerRosenfeld(image,img.height,img.width);

 

 

   //将结果赋值到原图像中

   for(i=0;i<lHeight;i++)
   {
     for(j=0;j<lWidth;j++)
  {
    if(image[i*lWidth+j]==1)
     dstBmp[i*img.width+j]=(BYTE)0;
    else
        dstBmp[i*img.width+j]=(BYTE)255;
  }

   }

}
void delpoint(byte *dst,int width,int height,int yuzhi)
{
 int i,j,num=0,num1;
 byte *src=(byte *)malloc(sizeof(byte)*width*height);
 memset(src,0x00,sizeof(byte)*width*height);
 for(i=1;i<height-1;i++)//消除孤立噪点
 {
  for(j=1;j<width-1;j++)
  {
   if(dst[i*width+j]>200)
   {
    num1=dst[i*width+j-1]+dst[i*width+j+1]+dst[(i-1)*width+j-1]+dst[(i-1)*width+j]+dst[(i-1)*width+j+1]+dst[(i+1)*width+j-1]+dst[(i+1)*width+j]+dst[(i+1)*width+j+1]+255;
    num=num1/255;
    if(num>=yuzhi)
     //if((dst[i*width+j-1]==0)&&(dst[i*width+j-1]==0)&&(dst[(i-1)*width+j+1]==0)&&(dst[(i-1)*width+j]==0)&&(dst[(i-1)*width+j+1]==0)&&(dst[(i+1)*width+j-1]==0)&&(dst[(i+1)*width+j]==0)&&(dst[(i+1)*width+j+1]==0))
     src[i*width+j]=255;
    else src[i*width+j]=0;
   }
  }
 }
 memcpy(dst,src,sizeof(byte)*width*height);
}
void deljunzao(byte *dst,int width,int height,int yuzhi)
{
 int i,j,num=0,num1;

 byte *src=(byte *)malloc(sizeof(byte)*width*height);
 memset(src,0x00,sizeof(byte)*width*height);
 for(i=1;i<height-1;i++)//消除孤立噪点
 {
  for(j=1;j<width-1;j++)
  {
    num1=dst[i*width+j-1]+dst[i*width+j+1]+dst[(i-1)*width+j-1]+
     dst[(i-1)*width+j]+dst[(i-1)*width+j+1]+dst[(i+1)*width+j-1]+
     dst[(i+1)*width+j]+dst[(i+1)*width+j+1]+dst[i*width+j];
    num=num1/255;
    if(num>=yuzhi)
    //if((dst[i*width+j-1]==0)&&(dst[i*width+j-1]==0)&&(dst[(i-1)*width+j+1]==0)&&(dst[(i-1)*width+j]==0)&&(dst[(i-1)*width+j+1]==0)&&(dst[(i+1)*width+j-1]==0)&&(dst[(i+1)*width+j]==0)&&(dst[(i+1)*width+j+1]==0))
     src[i*width+j]=255;
    else src[i*width+j]=0;

  }
 }
 for(i=1;i<height-1;i++)//消除孤立噪点
 {
  for(j=1;j<width-1;j++)
  {
   if(dst[i*width+j]>200)
   {
    num=dst[i*width+j-1]+dst[i*width+j+1]+dst[(i-1)*width+j-1]+dst[(i-1)*width+j]+dst[(i-1)*width+j+1]+dst[(i+1)*width+j-1]+dst[(i+1)*width+j]+dst[(i+1)*width+j+1]+255;
    num=num/255;
    if(num>=2)
     //if((dst[i*width+j-1]==0)&&(dst[i*width+j-1]==0)&&(dst[(i-1)*width+j+1]==0)&&(dst[(i-1)*width+j]==0)&&(dst[(i-1)*width+j+1]==0)&&(dst[(i+1)*width+j-1]==0)&&(dst[(i+1)*width+j]==0)&&(dst[(i+1)*width+j+1]==0))
     src[i*width+j]=255;
    else src[i*width+j]=0;
   }
  }
 }
 memcpy(dst,src,sizeof(byte)*width*height);
}
void pingjun(byte *dst,int width,int height)
{
 int i,j,num=0;
 float num1;

 byte *src=(byte *)malloc(sizeof(byte)*width*height);
 memset(src,0x00,sizeof(byte)*width*height);
 for(i=1;i<height-1;i++)//消除孤立噪点
 {
  for(j=1;j<width-1;j++)
  {
   num1=dst[i*width+j-1]+dst[i*width+j+1]+dst[(i-1)*width+j-1]+
    dst[(i-1)*width+j]+dst[(i-1)*width+j+1]+dst[(i+1)*width+j-1]+
    dst[(i+1)*width+j]+dst[(i+1)*width+j+1]+dst[i*width+j];
   num=(int)(num1/9+0.5);

      src[i*width+j]=num;

  }
 }

 memcpy(dst,src,sizeof(byte)*width*height);
}
void Dilation(byte *image,int width,int height,int type,int num)
{
 int dwWidth=width;
 int dwHeight=height;

 int i=0;
 int j=0;
 //int n=0;

 BYTE g=0;

 //double avg=0;
 BYTE *temp;
 int k=0;

 


 temp=(BYTE*)malloc(dwHeight*dwWidth*sizeof(BYTE));
 memcpy(temp,image,dwHeight*dwWidth*sizeof(byte));


 memset(temp,0,dwWidth*dwHeight*sizeof(BYTE));

 


 if(type==0)
 {
  //水平方向
  for(i=0;i<dwHeight;i++)
  {
   for(j=(num-1)/2;j<dwWidth-(num-1)/2;j++)
   {
    for(k=-(num-1)/2;k<=(num-1)/2;k++)
    {
     g=*(image+dwWidth*i+j+k);
     if(g==255)
     {
      *(temp+dwWidth*i+j)=255;
      break;
     }
    }
   }
  }
 }
 else
 {
  //垂直方向
  for(i=(num-1)/2;i<dwHeight-(num-1)/2;i++)
  {
   for(j=0;j<dwWidth;j++)
   {
    for(k=-(num-1)/2;k<=(num-1)/2;k++)
    {
     g=*(image+dwWidth*(i+k)+j);
     if(g==255)
     {
      *(temp+dwWidth*i+j)=255;
      break;
     }
    }
   }
  }
 }
 memcpy(image,temp,sizeof(byte)*width*height);
 free(temp);
 temp=NULL;
}

void Erosion(byte *image,int width,int height,int type,int num)
{
 int dwWidth=width;
 int dwHeight=height;
 int i=0;
 int j=0;
 //int n=0;
 BYTE g=0;
 //double avg=0;
 BYTE *temp;
 int k=0;
 temp=(BYTE*)malloc(dwHeight*dwWidth*sizeof(BYTE));
 memset(temp,0,dwWidth*dwHeight*sizeof(BYTE));
 if(type==0)
 {
  //水平方向
  for(i=0;i<dwHeight;i++)
  {
   for(j=(num-1)/2;j<dwWidth-(num-1)/2;j++)
   {
    for(k=-(num-1)/2;k<=(num-1)/2;k++)
    {
     g=*(image+width*i+j+k);
     if(g==0)
     {
      *(temp+width*i+j)=0;
      break;
     }
    }
   }
  }
 }
 else
 {
  //垂直方向
  for(i=(num-1)/2;i<dwHeight-(num-1)/2;i++)
  {
   for(j=0;j<dwWidth;j++)
   {
    for(k=-(num-1)/2;k<=(num-1)/2;k++)
    {
     g=*(image+width*(i+k)+j);
     if(g==0)
     {
      *(temp+width*i+j)=0;
      break;
     }
    }
   }
  }
  }
 memcpy(image,temp,sizeof(byte)*width*height);
 free(temp);
 temp=NULL;
}

 

void changeGray(byte *srcBmp,byte *dstBmp,int width,int height,int nWidth,int nHeight)
{

  int i=0,j=0,i0,j0;
  float xx;float yy;
  xx=(float)nWidth/width;
  yy=(float)nHeight/height;

  //memset(srcBmp,0x00,nHeight*nWidth*sizeof(byte));
  memset(dstBmp,0x00,nHeight*nWidth*sizeof(byte));
 for(i = 0; i <nHeight; i++)
 {
 for(j = 0; j <nWidth; j++)
 {
   //i0 = (int) ((float)i/yy+0.5);
   //j0 = (int) ((float)j/xx+0.5);
   i0 = (int) ((float)i/yy);
   j0 = (int) ((float)j/xx);
   if((j0>=0)&&(j0<width)&&(i0>=0)&&(i0<height))
  // {
   dstBmp[i*nWidth+j]=srcBmp[i0*width+j0];
   //}
   //else
   //{
  // dstBmp[i*nWidth+j]=255;
   //}
  }
 }

}
void strBmp(struct Bmp1 *img,byte *temp)
{
  int i,j,k,m,n,o;
  //int width=20,height=20;
  for(i=0;i<7;i++)
  {
   o=img->p2[i]-img->p1[i]+1;
   for(m=0,j=img->p3[i];j<=img->p4[i];j++,m++)
   {

    for(n=0,k=img->p1[i];k<=img->p2[i];k++,n++)
    {
           img->strr[i][m*o+n]=temp[j*img->width+k];
    }
   }
  }
}
void guiyi(struct Bmp1 *img)
{
 int xxx;
 int i;
 //xxx=img->p2[0]-img->p1[0]+1;
 int yyy;
 //
 byte *temp=(byte *)malloc(sizeof(byte)*800);
 //strBmp(&img1,temp1);
 for(i=0;i<7;i++)
 {
  xxx=img->p2[i]-img->p1[i]+1;
  yyy=img->p4[i]-img->p3[i]+1;

     changeGray(img->strr[i],temp,xxx,yyy,20,40);

  memcpy(img->strr[i],temp,sizeof(byte)*800);
 }
}

void readmoban(char *path,struct Bmp1 *img2)
{
 FILE *f[72];
 int i;
  char str2[]=".bmp";
  char str[80];
  char str1[10];
 for(i=0;i<=66;i++)
 {
  //char str[80];
  strcpy(str,path);
     //char str1[10];
  myitoa(i,str1,10);
  strcat(str1,str2);
  strcat(str,str1);
  f[i]=fopen(str,"rb");
  if(f[i]==NULL)
   exit(-1);
  readstr(f[i],img2->strc[i]);
  fclose(f[i]);

 }

 

 

}

char *myitoa(int num,char *str,int radix)
{

char index[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";/* 索引表 */
unsigned unum; /* 中间变量 */
int i=0,j,k;/* 确定unum的值 */

 if(radix==10&&num<0) /* 十进制负数 */
 {
  unum=(unsigned)-num;
  str[i++]='-';
 }
 else unum=(unsigned)num; /* 其他情况 */
 /* 逆序 */
 do
 {
 str[i++]=index[unum%(unsigned)radix];
 unum/=radix;
 }while(unum);
 str[i]='\0';
 /* 转换 */
 if(str[0]=='-') k=1; /* 十进制负数 */
 else k=0;
 /* 将原来的“/2”改为“/2.0”,保证当num在16~255之间,radix等于16时,也能得到正确结果 */
 for(j=k;j<(i-1)/2.0+k;j++)
 {
 num=str[j];
    str[j]=str[i-j-1+k];
 str[i-j-1+k]=num;
 }
 return str;
}

void writebmp(const char *path,const char *name,byte *temp)
{

    FILE *f1,*f2;
    int i,j;
 byte temp1;
 char path1[40];
 char path2[40];
 char *p1="header.txt";
 char p4[5]=".bmp";
 char p2[1078];
 char p3[800];
 strcpy(path1,path);
 strcat(path1,p1);
 strcpy(path2,path);
 strcat(path2,name);
 strcat(path2,p4);
 if((f1=fopen(path1,"rb"))==NULL)
 {
  printf( "\n 不能打开  \n");
  exit(-1);
 }
 fread(p2,1078,1,f1);

 for(i=0;i<40;i++)
 {
  for(j=0;j<20;j++)
  {

   temp1=temp[i*20+j];
   if(temp1==0)
    temp1=0;
   else temp1=255;
   p3[(40-i-1)*20+j]=temp1;
  }
   }

 if((f2=fopen(path2,"wb"))==NULL)
    {
        printf("\n不能创建%s图\n",path1);
        exit(-1);
    }
 if(fwrite(p2,1078*sizeof(BYTE),1,f2)!=1)
    {
        printf("不能写入%s图\n",path2);
        fclose(f2);

    }
    fseek(f2,1078,SEEK_SET);

    if(fwrite(p3,20*40,1,f2)!=1)
    {
        printf("不能写入%s图\n",path2);
        fclose(f2);

    }
 fclose(f1);
    fclose(f2);

}
void strout(struct Bmp1 *img)
{
 int i,j,k=0,m=800,n;
 //int p[5]={0};
    for(i=36;i<67;i++)
 {
  k=cmpstr(img->strr[0],img->strc[i]);
    if(k==0)
    {
     n=i;
     break;
    }
    else
    {
          if(k<m)
    {
     m=k;
        n=i;
    }
    }
  }
    img->string[0]=n;

     for(i=1;i<7;i++)
  {
   n=0;k=0;m=800;
   for(j=0;j<36;j++)
   {
    if((img->p2[i]-img->p1[i])<4)
             {
                  n=1;
      break;

    }
    k=cmpstr(img->strr[i],img->strc[j]);
    if(k==0)
    {
     n=j;
     break;
    }
    else
    {
     if(k<m)
     {
      m=k;
      n=j;
     }
    }
   }


  if(n==27)//p&r
  {
   k=cmpstr(img->strc[27],img->strr[i]);
   j=cmpstr(img->strr[i],img->strc[25]);
   if(k<j)
    n=27;
   else n=25;
  }
  if(n==0)//0
  {
     j=cmpstr(img->strc[0],img->strr[i]);
  k=cmpstr(img->strr[i],img->strc[12]);
  if(j>k)
   n=12;
  else n=0;

  }
  if(n==26)
  {
   k=cmpstr(img->strc[26],img->strr[i]);
   j=cmpstr(img->strr[i],img->strc[0]);
   if(k<j)
    n=26;
   else n=0;
  }
 if(n==19)
  {
   k=cmpstr(img->strc[0],img->strr[i]);
   j=cmpstr(img->strr[19],img->strc[i]);
   if(k<j)
    n=0;
   else n=19;
  }
 if(n==13)
 {
  k=cmpstr(img->strc[13],img->strr[i]);
  j=cmpstr(img->strr[i],img->strc[0]);
  if(k<j)
   n=13;
  else n=0;
  }

  /*if((n==6)||(n==3))
  {
   k=cmpstr(img->strc[6],img->strr[i]);
   j=cmpstr(img->strc[3],img->strr[i]);
   if(k<j)
    n=5;
   else n=3;
  }
  if(n==12)
  {
   k=cmpstr(img->strc[0],img->strr[i]);
   j=cmpstr(img->strc[12],img->strr[i]);
   if(k<j)
    n=0;
   else n=12;
  }*/
  if(n==14)//E F
  {
   k=cmpstr(img->strc[14],img->strr[i]);
   j=cmpstr(img->strr[i],img->strc[15]);
   if(k<j)
    n=14;
   else n=15;
  }
  if(n==8)
  {
   k=cmpstr(img->strc[8],img->strr[i]);
   j=cmpstr(img->strr[i],img->strc[3]);
   if(k<j)
    n=8;
    else n=3;
  }
  img->string[i]=n;

   i=i;
  }


}
int cmpstr(byte *src,byte *moban)
{
    int i,j,k=0;
 byte temp[800]={0};
 memcpy(temp,src,800);

 for(i=0;i<40;i++)
  for(j=0;j<20;j++)
  {
    if(temp[i*20+j]==255)
    {
     if(moban[i*20+j]==255)
      temp[i*20+j]=0;

    }
  }
  delpoint(temp,40,20,4);
for(i=0;i<40;i++)
 for(j=0;j<20;j++)
  {
    if(temp[i*20+j]==255)
    {
     k++;
    }

  }

 return k;
}
int calstr(byte *srcBmp)
{
   int i,j,num=0;
 for(i=0;i<40;i++)
  for(j=0;j<20;j++)
  {
    if(srcBmp[i*20+j]==255)
    {
     num++;

    }
  }
  return num;
}

void edgesob8(byte *image,int width,int height)//8邻域
{

    //int sum1,sum2,sum;double gray;
    int i,j,logNum;
    //int p[8];
 BYTE *temp;
 temp=(byte*)malloc(sizeof(byte)*width*height);
 memset(temp,0x00,sizeof(byte)*width*height);
    for(i=3;i<height-2;i++)
  for(j=3;j<width-2;j++)
  {
   logNum=16*image[i*width+j]-image[(i-2)*width+j]-image[(i-1)*width+j-1]-2*image[(i-1)*width+j]-image[(i-1)*width+j+1]-image[i*width+j-2]-2*image[i*width+j-1]-2*image[i*width+j+1]-image[i*width+j+2]-image[(i+1)*width+j-1]-2*image[(i+1)*width+j]-image[(i+1)*width+j+1]-image[(i+2)*width+j];
   if(logNum > 0)

    temp[i*width+j]=255;

   else

    temp[i*width+j]=0;
   }
   memcpy(image,temp,width*height);
   free(temp);
   temp=NULL;

}
void edgesob4(byte *image,int width,int height)//4邻域
{

   // int sum1,sum2,sum;double gray;
    int i,j;
    int p[8];
 float result;
 BYTE *temp=(byte*)malloc(sizeof(byte)*width*height);
 memset(temp,0x00,sizeof(byte)*width*height);
 for(i =0; i<=height-1; i++)   //sob算子边缘检测;取出边界;
 {
  for(j=0;j<=width-1;j++)//由于使用2×2的模板,为防止越界,所以不处理最下边和最右边的两列像素
  {

   if(i==height-1)
    temp[i*width+j]=0;
   else if(j==width-1)
    temp[i*width+j]=0;

   else{

    p[0] = (byte)*(image+i*width+j);
    p[1] = (byte)*(image+i*width+j+1);
    p[2] = (byte)*(image+(i+1)*width+j);
    p[3] = (byte)*(image+(i+1)*width+j+1);
      result = sqrt(( p[0] - p[3] )*( p[0] - p[3] )+( p[1] - p[2] )*( p[1] - p[2] ));
    if(result<=0.0)
     result=0;
    if(result>=255.0)
     result=255;
    temp[i*width+j] = (byte)result;
   }
  }
 }
  memcpy(image,temp,width*height);
  free(temp);
  temp=NULL;

}
int hough(byte *srcBmp,int width,int height)
{
    int kmax=0;
    int pmax=0;
 int yuzhi=0;
 int i,j,k,n,p=(int)(height*cos(pi)+width*sin(pi));
 int mp= (int) (sqrt(width*width + height*height)+1);
 int ma=180;//180
 //int ap;
 int npp[180][1000];
 for(i=0;i<180;i++)
 for(j=0;j<1000;j++)
 npp[i][j]=0;
 /*ap=90*(p+mp);
 int *npp=(int *)malloc(sizeof(int)*ap);//myMalloc(ap,0,0);
 memset(npp,0x00,sizeof(int)*ap);*/
 for(i=1;i<height;i++)
  for(j=1;j<width;j++)
  {
   if(srcBmp[i*width+j]==255)
   {
    for(k=1;k<ma;k++)
    {
     p=(int)(i*cos(pi*k/180)+j*sin(pi*k/180));
     p=(int)(p/2+mp/2);
     npp[k][p]=npp[k][p]++;
     //npp[k*p+k]=npp[k*p+k]++;
    }
   }
  }
  kmax=0;
  pmax=0;
  n=0;
  for(i=1;i<ma;i++)
   for(j=1;j<mp;j++)
   {
    if(npp[i][j]>yuzhi)
   // if(npp[i*j+i]>yuzhi)
    {
     yuzhi=npp[i][j];
                  //  yuzhi=npp[i*j+i];
     kmax=i;
     pmax=j;
    }
   }

    return kmax;
}

void RotateGray(byte *image,int width,int height, float iRotateAngle)
{

 // 循环变量
    int i,j,lNewWidth,lNewHeight,i0,j0;
 // 旋转后图像的宽度和高度
    int ang;
 // 象素在源DIB中的坐标

 // 旋转角度(弧度)
 float fRotateAngle;
 // 旋转角度的正弦和余弦
 float fSina, fCosa;
 // 源图四个角的坐标(以图像中心为坐标系原点)
 float fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;
 // 旋转后四个角的坐标(以图像中心为坐标系原点)
 float fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;
 // 两个中间常量
 float f1,f2;

 byte *temp=(byte *)malloc(sizeof(byte)*lNewHeight*lNewWidth);
    if(temp==NULL)
     printf("\nerror\n");

 // 将旋转角度从度转换到弧度
 fRotateAngle = (float) RADIAN(iRotateAngle);
 // 计算旋转角度的正弦
 fSina = (float) sin((double)fRotateAngle);
 // 计算旋转角度的余弦
 fCosa = (float) cos((double)fRotateAngle);
 // 计算原图的四个角的坐标(以图像中心为坐标系原点)
 fSrcX1 = (float) (- (width  - 1) / 2);
 fSrcY1 = (float) (  (height - 1) / 2);
 fSrcX2 = (float) (  (width  - 1) / 2);
 fSrcY2 = (float) (  (height - 1) / 2);
 fSrcX3 = (float) (- (width  - 1) / 2);
 fSrcY3 = (float) (- (height - 1) / 2);
 fSrcX4 = (float) (  (width  - 1) / 2);
 fSrcY4 = (float) (- (height - 1) / 2);

 // 计算新图四个角的坐标(以图像中心为坐标系原点)
 fDstX1 =  fCosa * fSrcX1 + fSina * fSrcY1;
 fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1;
 fDstX2 =  fCosa * fSrcX2 + fSina * fSrcY2;
 fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2;
 fDstX3 =  fCosa * fSrcX3 + fSina * fSrcY3;
 fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3;
 fDstX4 =  fCosa * fSrcX4 + fSina * fSrcY4;
 fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4;
    // 计算旋转后的图像实际宽度
 lNewWidth  = (int) ( max( fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2) ) + 0.5);

 // 计算旋转后的图像高度
 lNewHeight = (int) ( max( fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2) )  + 0.5);


 // 两个常数,这样不用以后每次都计算了
 f1 = (float) (-0.5 * (lNewWidth - 1) * fCosa - 0.5 * (lNewHeight - 1) * fSina
  + 0.5 * (width  - 1));
 f2 = (float) ( 0.5 * (lNewWidth - 1) * fSina - 0.5 * (lNewHeight - 1) * fCosa
  + 0.5 * (height - 1));

    memset(temp,(byte)0,lNewHeight*lNewWidth*sizeof(byte));

 // 针对图像每行进行操作
 for(i = 0; i < lNewHeight; i++)
 {
  // 针对图像每列进行操作
  for(j = 0; j < lNewWidth; j++)
  {

   // 计算该象素在源DIB中的坐标
   i0 = (int) (-((float) j) * fSina + ((float) i) * fCosa + f2 + 0.5);
   j0 = (int) ( ((float) j) * fCosa + ((float) i) * fSina + f1 + 0.5);

   // 判断是否在源图范围内
   if( (j0 >= 0) && (j0 < width) && (i0 >= 0) && (i0 < height))
   {
    // 复制象素
      //*(temp + lNewWidth * (lNewHeight - 1 - i) + j)=*(image + width * (height - 1 - i0) + j0);
       *(temp + lNewWidth * i + j)=*(image + width * i0 + j0);
   }
   else
   {
    // 对于源图中没有的象素,直接赋值为255
    *(temp + lNewWidth * i + j) = 0;
    //*(temp + lNewWidth * (lNewHeight - 1 - i) + j);
   }
  }
 }


   ang=hough(temp,lNewWidth,lNewHeight);


    free(temp);
    temp=NULL;
}

void xuanzhuan(struct Bmp1 *img1)
{
 int lwidth=0,lheight=0;
 //int nwidth=0,nheight=0;
 //float m;

   byte *p;
   p=RotateRGB(img1->image,img1->ang,img1->width,img1->height,&lwidth,&lheight);
       img1->width=lwidth;
       img1->height=lheight;
    free(img1->image);
    img1->image=NULL;
    img1->image=p;


}
byte *myMalloc(int num,const byte *bmp,int type)
{
   byte *p=(byte *)malloc(sizeof(byte)*num);
   if(p==NULL)
    exit(-1);
   if(type==0)
    memset(p,0x00,sizeof(byte)*num);
   if(type==1)
       memset(p,255,sizeof(byte)*num);
   if(type==2)
       memcpy(p,bmp,sizeof(byte)*num);
   return p;
}
byte *changeRGB(byte *srcBmp,int width,int height,int *lwidth,int *lheight,float f)
{
 int i,j,k,i0,j0,m,n;
 int nwidth=(int)(f*width+0.5);
    int nheight=(int)(f*height+0.5);
 byte *temp;
 temp=myMalloc(nwidth*nheight,0,0);


   for(i = 0; i < nheight; i++)
 {
  for(m=0,j = 0;j < nwidth;m+=3,j++)
  {

   i0 = (unsigned int) (i/f + 0.5);
   j0 = (unsigned int) (j/f + 0.5);
   n=i0*width*3+j0*3;
   k=nwidth*i*3+m;
   if( (j0 >= 0) && (j0 < width) && (i0 >= 0) && (i0 < height))
   {

        *(temp + k+1)=*(srcBmp + n+1);
     *(temp + k+2)=*(srcBmp+ n+2);
     *(temp + k)=*(srcBmp + n);
   }
   else
   {
     *(temp + k+1)=0;
     *(temp + k+2)=0;
     *(temp + k)=0;

   }
  }
 }
   *lwidth=nwidth;
   *lheight=nheight;
   //displayRGB(temp,nwidth,nheight,0,0);
   return temp;
}
void guiyiRGB(struct Bmp1 *img1)
{
 int nwidth=0,nheight=0;
 float m;
 byte *q;
 m=1;
 if(img1->width<200)
    {
  m=(float)(200)/img1->width;
  q=changeRGB(img1->image,img1->width,img1->height,&nwidth,&nheight,m);
  img1->width=nwidth;
  img1->height=nheight;
  free(img1->image);
  img1->image=NULL;
  img1->image=q;
 }

}
void outtext(struct Bmp1 img1,int x,int y)
{
 char *table[]={"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F",\
  "G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","京",\
  "冀","津","晋","蒙","辽","吉","黑","沪","苏","浙","皖","闽","赣","鲁","豫","鄂","湘",\
  "粤","桂","琼","渝","川","贵","云",\
  "藏","陕","甘","青","宁","新"};
 int i;

    printf("\n\n\n\n\n\n\n\n");
    printf("\n        The Car Id Is\n");
    printf("\n");
 for(i=0;i<7;i++)
 {
  printf("   ");
  printf("%s",table[img1.string[i]]);
     //outtextxy(x+i*40,y,table[img1.string[i]]);

 }
    printf("\n");
 printf("\n   This is designed by liujia\n");
 printf("\n\n\n\n\n\n\n\n");


}

byte *RotateRGB(byte *image, float iRotateAngle,int width,int height,int *lwidth,int *lheight)
{
    byte *temp;
 // 循环变量
    int i,j,m,n,lNewWidth,lNewHeight,i0,j0;
 // 旋转后图像的宽度和高度

 // 象素在源DIB中的坐标

 // 旋转角度(弧度)
 float fRotateAngle;
 // 旋转角度的正弦和余弦
 float fSina, fCosa;
 // 源图四个角的坐标(以图像中心为坐标系原点)
 float fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;
 // 旋转后四个角的坐标(以图像中心为坐标系原点)
 float fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;
 // 两个中间常量
 float f1,f2;


 // 将旋转角度从度转换到弧度
 fRotateAngle = (float) RADIAN(iRotateAngle);
 // 计算旋转角度的正弦
 fSina = (float) sin((double)fRotateAngle);
 // 计算旋转角度的余弦
 fCosa = (float) cos((double)fRotateAngle);
 // 计算原图的四个角的坐标(以图像中心为坐标系原点)
 fSrcX1 = (float) (- (width  - 1) / 2);
 fSrcY1 = (float) (  (height - 1) / 2);
 fSrcX2 = (float) (  (width  - 1) / 2);
 fSrcY2 = (float) (  (height - 1) / 2);
 fSrcX3 = (float) (- (width  - 1) / 2);
 fSrcY3 = (float) (- (height - 1) / 2);
 fSrcX4 = (float) (  (width  - 1) / 2);
 fSrcY4 = (float) (- (height - 1) / 2);

 // 计算新图四个角的坐标(以图像中心为坐标系原点)
 fDstX1 =  fCosa * fSrcX1 + fSina * fSrcY1;
 fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1;
 fDstX2 =  fCosa * fSrcX2 + fSina * fSrcY2;
 fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2;
 fDstX3 =  fCosa * fSrcX3 + fSina * fSrcY3;
 fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3;
 fDstX4 =  fCosa * fSrcX4 + fSina * fSrcY4;
 fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4;
    // 计算旋转后的图像实际宽度
 lNewWidth  = (int) ( max( fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2) ) + 0.5);

 // 计算旋转后的图像高度
 lNewHeight = (int) ( max( fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2) )  + 0.5);

     temp=myMalloc(lNewHeight*lNewWidth*3,0,0);
 // 两个常数,这样不用以后每次都计算了
 f1 = (float) (-0.5 * (lNewWidth - 1) * fCosa - 0.5 * (lNewHeight - 1) * fSina
  + 0.5 * (width  - 1));
 f2 = (float) ( 0.5 * (lNewWidth - 1) * fSina - 0.5 * (lNewHeight - 1) * fCosa
  + 0.5 * (height - 1));


 for(i = 0; i < lNewHeight; i++)
 {
  // 针对图像每列进行操作
  for(m=0,j = 0;j < lNewWidth;m+=3,j++)
  {

   // 计算该象素在源DIB中的坐标
   i0 = (int) (-((float) j) * fSina + ((float) i) * fCosa + f2 + 0.5);
   j0 = (int) ( ((float) j) * fCosa + ((float) i) * fSina + f1 + 0.5);

   // 判断是否在源图范围内
   if( (j0 >= 0) && (j0 < width) && (i0 >= 0) && (i0 < height))
   {
    n=i0*width*3+j0*3;
      //*(temp + lNewWidth * (lNewHeight - 1 - i) + j)=*(image + width * (height - 1 - i0) + j0);
        *(temp + lNewWidth * i*3 + m+1)=*(image + n+1);
     *(temp + lNewWidth * i*3 + m+2)=*(image + n+2);
     *(temp + lNewWidth * i*3+ m)=*(image + n);
      //*(temp1 + n)=0;
   }
   else
   {
    // 对于源图中没有的象素,直接赋值为255
     *(temp + lNewWidth * i*3+ m+1)=0;
     *(temp + lNewWidth * i*3+ m+2)=0;
     *(temp + lNewWidth * i*3+ m)=0;
    //*(temp + lNewWidth * (lNewHeight - 1 - i) + j);
   }
  }
 }

   *lwidth=lNewWidth;
 *lheight=lNewHeight;
  return temp;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值