找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 2309|回复: 1

车牌识别(五)灰度图二值化

[复制链接]
发表于 2018-8-3 11:06:43 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
再次把灰度图,转成二值图像,用于比较。。。
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. typedef unsigned long       DWORD;
  5. typedef int                 BOOL;
  6. typedef unsigned char       BYTE;
  7. typedef unsigned short      WORD;
  8. typedef float               FLOAT;
  9. typedef unsigned char       byte;

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

  12. //BMP图像结构
  13. struct BMP_img
  14. {
  15.     //{BMP头
  16.     BYTE  bfType[2];//类型,判断是否为‘B’,‘M’
  17.     DWORD size;//文件尺寸
  18.     DWORD reser;//保留,为0
  19.     DWORD header_length;//头部长度,也就是数据起始位置
  20.     //}BMP头长度,14字节

  21.     //{信息头40字节
  22.     DWORD infoheader_length;//信息头长度,40
  23.     DWORD width;//图像宽度
  24.     DWORD height;//图像高度
  25.     WORD  biplanes;//颜色平面数,为1
  26.     WORD  bmp_type;/* 8bit 24bit; */
  27.     DWORD compres;//0表示不压缩
  28.     DWORD datasize;//数据长度,size-54
  29.     DWORD bixpm;//水平分辩率
  30.     DWORD biypm;//垂直分辩率
  31.     DWORD clrused;//为0所有颜色,其它的为索引数
  32.     DWORD relclrused;//0表示都重要
  33.     //}信息头结束

  34.     //其它信息
  35.     BYTE *image;//指向一块内存,保存BMP的内容
  36.     DWORD lineBytes;//一行占多少字节
  37. };

  38. //从源BMP图中,剪切车牌所在区域的新结构
  39. struct Bmp1{
  40.     DWORD width;
  41.     DWORD height;
  42.     BYTE *image;
  43.     int left[10];//保存车牌中7个字的左右列
  44.     int right[10];
  45.     int top[10];//保存车牌上下位置
  46.     int bottom[10];
  47.     int up;
  48.     int down;
  49.     byte strr[7][1024];
  50.     byte string[7];//反回已找到的车牌下标
  51.     float ang;//倾斜角度
  52. };

  53. //蓝色车牌
  54. struct HSV{
  55.   float H;//H值范围:190 ~ 245
  56.   float S;//S值范围: 0.35 ~ 1,我理解为黑白灰度
  57.   int V;//V值范围: 0.3 ~ 1
  58. };

  59. //文件图文件到内存中
  60. int read_img(char const *fn, struct BMP_img *img)
  61. {
  62.     FILE *infile;
  63.     if((infile=fopen(fn,"rb"))==NULL)return 0;

  64.     fread(&img->bfType,2,1,infile);//BM
  65.     if(!(img->bfType[0]=='B' && img->bfType[1]=='M'))return 0;
  66.     fread(&img->size,sizeof(DWORD),1,infile);
  67.     printf("\nBMP size             :%d",(int)img->size);
  68.     fread(&img->reser,sizeof(DWORD),1,infile);
  69.     printf("\n保留位:");
  70.     fread(&img->header_length,sizeof(DWORD),1,infile);
  71.     printf("\nheader length    :%d",(int)img->header_length);
  72.     fread(&img->infoheader_length,sizeof(DWORD),1,infile);
  73.     fread(&img->width, sizeof(DWORD), 1, infile);
  74.     fread(&img->height, sizeof(DWORD), 1, infile);
  75.     printf( "\nwidth   :%d\n  height  :%d ", (int)img->width, (int)img->height);
  76.     fread(&img->biplanes, sizeof(WORD), 1, infile);
  77.     fread(&img->bmp_type, sizeof(WORD), 1, infile);
  78.     printf("\nBMP Tpye             :%d ", img->bmp_type);
  79.     fread(&img->compres, sizeof(DWORD), 1, infile);
  80.     if(img->compres==0) {printf("\nbmp图片为非压缩!");}printf(" ");
  81.     fread(&img->datasize, sizeof(DWORD), 1, infile);
  82.     printf("\nBMP Data Size        :%d ",(int)img->datasize);
  83.     fread(&img->bixpm, sizeof(DWORD), 1, infile);
  84.     fread(&img->biypm, sizeof(DWORD), 1, infile);
  85.     fread(&img->clrused, sizeof(DWORD), 1, infile);
  86.     printf("\n实际使用颜色数=%d ",(int)img->clrused);printf(" ");
  87.     fread(&img->relclrused, sizeof(DWORD), 1, infile);

  88.     if(img->bmp_type==24)//24位色,这里只考虑24位色图,其它的不考虑
  89.     {
  90.         img->lineBytes=((img->width*3+3)>>2)<<2;//计算一行需要多少字节,对齐到4字节

  91.         //byte *temp=(byte *)malloc(sizeof(byte) * img->height * img->lineBytes);//分配一块内存,用于读文件
  92.         img->image=(byte *)malloc(img->lineBytes*img->height);//分配一块内存,用于保存图像数据
  93.         if(img->image==NULL) fprintf(stderr, "\n Allocation error for temp in read_bmp() \n");
  94.         fseek(infile, img->header_length, SEEK_SET);//跳过头部,也就是跳到图像位置
  95.         fread(img->image, sizeof(byte), (img->lineBytes)*img->height, infile);//全部读到内存中
  96.     }
  97.     fclose(infile);
  98.     return 1;
  99. }

  100. //把二值图保存为24位黑白图
  101. void WriteBmp1(char const *fn,byte *bmp,int width,int height)
  102. {
  103.     int w4;
  104.     struct BMP_img img;
  105.     //一行有多少个字节
  106.     img.lineBytes=((width*3+3)>>2)<<2;//对齐到4字节边界
  107.     w4=img.lineBytes*height;//图像尺寸
  108.     img.bfType[0]='B';img.bfType[1]='M';
  109.     img.size=w4+54;
  110.     img.reser=0;
  111.     img.header_length=54;
  112.     img.infoheader_length=40;
  113.     img.width=width;
  114.     img.height=height;
  115.     img.biplanes=1;
  116.     img.bmp_type=24;
  117.     img.compres=0;
  118.     img.datasize=w4;
  119.     img.bixpm=0;
  120.     img.biypm=0;
  121.     img.clrused=0;
  122.     img.relclrused=0;
  123.    
  124.     FILE *infile;
  125.     if((infile=fopen(fn,"wb"))==NULL)
  126.     {
  127.         return;
  128.     }
  129.     fwrite(&img.bfType,2,1,infile);//printf("\n打开的图为 %d",img->bfType);//B M
  130.     fwrite(&img.size,sizeof(DWORD),1,infile);     //        printf("\nBMP size             :%l",img->size);
  131.     fwrite(&img.reser,sizeof(DWORD),1,infile);//printf("\n保留位:");
  132.     fwrite(&img.header_length,sizeof(DWORD),1,infile); //printf("\nheader length    :%l",img->header_length);
  133.     fwrite(&img.infoheader_length,sizeof(DWORD),1,infile);
  134.     fwrite(&img.width, sizeof(DWORD), 1, infile);
  135.     fwrite(&img.height, sizeof(DWORD), 1, infile);     //printf( "\nwidth   :%l\n  height  :%l ", img->width, img->height);
  136.     fwrite(&img.biplanes, sizeof(WORD), 1, infile);
  137.     fwrite(&img.bmp_type, sizeof(WORD), 1, infile);  // printf("\nBMP Tpye             :%l ", img->bmp_type);
  138.     fwrite(&img.compres, sizeof(DWORD), 1, infile);    //if(img->compres==0) {printf("\nbmp图片为非压缩!");}printf(" ");
  139.     fwrite(&img.datasize, sizeof(DWORD), 1, infile);//printf("\nBMP Data Size        :%l ",img->datasize);
  140.     fwrite(&img.bixpm, sizeof(DWORD), 1, infile);
  141.     fwrite(&img.biypm, sizeof(DWORD), 1, infile);
  142.     fwrite(&img.clrused, sizeof(DWORD), 1, infile);    //printf("\n实际使用颜色数=%d ",img->clrused);printf(" ");
  143.     fwrite(&img.relclrused, sizeof(DWORD), 1, infile);
  144.    
  145.     byte *wbmp=(byte*)malloc(w4);//后面多加两个字节,用于4字节对齐
  146.     for(int i=0,s,w;i<height;i++)
  147.     {
  148.         s=i*width;
  149.         w=i*img.lineBytes;
  150.         for(int j=0;j<width;j++)
  151.         {
  152.             if(bmp[s+j]){
  153.                 wbmp[w+j*3]=wbmp[w+j*3+1]=wbmp[w+j*3+2]=bmp[s+j];
  154.             }
  155.             else wbmp[w+j*3]=wbmp[w+j*3+1]=wbmp[w+j*3+2]=0;               
  156.         }
  157.     }
  158.     fwrite(wbmp,img.datasize,1,infile);
  159.     free(wbmp);
  160.     fclose(infile);
  161. }

  162. //灰度图变成二值图
  163. void displaytwo(byte *srcBmp,byte *dstBmp,int width,int height,int yuzhi)
  164. {
  165.     int totalPixels = width * height;//总像素
  166.     int bestT = 0;
  167.     int i,j;

  168.     int histogramArray[256];
  169.     double densityArray[256]={0};
  170.     double u0 = 0;
  171.     double u1 = 0;
  172.     double w0 = 0;
  173.     double w1 = 0;
  174.     double bestDeviation = 0;
  175.         double w10,u10,temp;//用于调试

  176.     //清零
  177.     for(i=0;i<256;i++)histogramArray[i]=0;
  178.         
  179.     for(i=0;i<height;i++)//记下各灰度颜色所出现的次数
  180.     {
  181.         for(j=0;j<width;j++)
  182.         {
  183.             histogramArray[srcBmp[i*width+j]]++;
  184.         }
  185.     }
  186.    
  187.     //各颜色出现次数所在总像素的比重,256个histogramArray相加等于totalPixels
  188.     //各densityArray相加等于1
  189.     for(i=0;i<256;i++)
  190.     {
  191.         densityArray[i] = (double)histogramArray[i] / totalPixels;
  192.     }
  193.    
  194.     for (i = 0; i < 256; i++)//循环256次
  195.     {
  196.         w0 = 0;
  197.         w1 = 0;
  198.                 //w0+w1=1
  199.         for (j = 0; j <= i; j++) {//前i项的比重和
  200.             w0 += densityArray[j];
  201.         }
  202.         for (j = i + 1; j < 256; j++) {//后面项的比重和
  203.             w1 += densityArray[j];
  204.         }
  205.                
  206.         u0 = 0;
  207.         u1 = 0;
  208.         //前i项的比重倍数和,越亮比重越大,比如颜色为100占5% 与 颜色为200的占2.5%的比重相等
  209.         for (j = 0; j <= i; j++) {
  210.             u0 += j * densityArray[j];
  211.         }
  212.         for (j = i + 1; j < 256; j++) {//后面项的比重倍数和,越亮比重越大,
  213.             u1 += j * densityArray[j];
  214.         }
  215.         if(w0)u0 = u0 / w0;//前面项的 倍比和 / 比和 =
  216.         if(w1)u1 = u1 / w1;//
  217.                 //假设前面100项和后150项,比重各占一半,那么前面倍比和肯定小于后面的倍比和
  218.                 //
  219.                 w10=w0*w1;//取值范围是0~0.25达到峰值,再慢慢变到0
  220.                 u10=u0-u1;//两者的差距,变到最小后,反而慢慢变大
  221.                 temp = w10 * u10 * u10;//temp的值,达到峰值后,慢慢变小
  222.         if(temp > bestDeviation){//记下temp的峰值时,的灰度值
  223.             bestT = i;
  224.             bestDeviation = temp;
  225.         }
  226.     }
  227.    
  228. /*        //方法二,所有颜色的平均值,简单,但效果不那么好
  229.         DWORD sum=0;
  230.     for(i=0;i<height;i++)//记下各灰度颜色所出现的次数
  231.     {
  232.         for(j=0;j<width;j++)
  233.         {
  234.             sum+=srcBmp[i*width+j];//所有像素和相加
  235.         }
  236.     }
  237.         bestT=sum/totalPixels;//平均值*/
  238.        
  239.     bestT=bestT+yuzhi;
  240.     if(bestT<0)bestT=0;//如果传入的值太小,导致灰度小于0,则必为0
  241.     if(bestT>255)bestT=255;//保证不大于255
  242.     for(i=0;i<height;i++)
  243.     {
  244.         for(j=0;j<width;j++)
  245.         {
  246.             if(srcBmp[i*width+j]>bestT)
  247.             {
  248.                 dstBmp[i*width+j]=255;
  249.             }
  250.             else
  251.             {
  252.                 dstBmp[i*width+j]=0;
  253.             }
  254.         }
  255.      }
  256. }

  257. int main(int argc, char **argv)
  258. {
  259.     struct BMP_img img;//定义结构

  260.     //把当前文件夹下的1.bmp文件内容,读到img结构中,并上下镜像
  261.     if(read_img("1.bmp", &img)==0)
  262.     {
  263.         printf("error");
  264.         return 0;
  265.     }
  266.    
  267.     //24位灰度图转单色灰度图
  268.     for(int i=0;i<img.height;i++)
  269.     {
  270.         for(int j=0;j<img.width;j++)
  271.         {
  272.             img.image[i*img.width+j]=img.image[i*img.lineBytes+j*3];
  273.         }
  274.     }
  275.    
  276.     byte *temp=(byte*)malloc(img.width*img.height);
  277.     displaytwo(img.image,temp,img.width,img.height,30);
  278.    
  279.     //写入镜像后的数据到2.bmp中
  280.     WriteBmp1("2.bmp",temp,img.width,img.height);
  281.    
  282.     free(img.image);//释放动态分配的内存
  283.     free(temp);
  284.    
  285.     printf("请打开2.bmp进行查看\n");
  286.     system("pause");
  287.     return 0;
  288. }
复制代码


2.bmp
1.bmp
回复

使用道具 举报

发表于 2018-8-11 20:57:52 | 显示全部楼层

好东西,谢谢
回复 赞! 靠!

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-12-22 16:12 , Processed in 0.033929 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表