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

再次把灰度图,转成二值图像,用于比较。。。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
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)            (((a) > (b)) ? (a) : (b))
#define min(a,b)            (((a) < (b)) ? (a) : (b))
 
//BMP图像结构
struct BMP_img
{
    //{BMP头
    BYTE  bfType[2];//类型,判断是否为‘B’,‘M’
    DWORD size;//文件尺寸
    DWORD reser;//保留,为0
    DWORD header_length;//头部长度,也就是数据起始位置
    //}BMP头长度,14字节
 
    //{信息头40字节
    DWORD infoheader_length;//信息头长度,40
    DWORD width;//图像宽度
    DWORD height;//图像高度
    WORD  biplanes;//颜色平面数,为1
    WORD  bmp_type;/* 8bit 24bit; */
    DWORD compres;//0表示不压缩
    DWORD datasize;//数据长度,size-54
    DWORD bixpm;//水平分辩率
    DWORD biypm;//垂直分辩率
    DWORD clrused;//为0所有颜色,其它的为索引数
    DWORD relclrused;//0表示都重要
    //}信息头结束
 
    //其它信息
    BYTE *image;//指向一块内存,保存BMP的内容
    DWORD lineBytes;//一行占多少字节
};
 
//从源BMP图中,剪切车牌所在区域的新结构
struct Bmp1{
    DWORD width;
    DWORD height;
    BYTE *image;
    int left[10];//保存车牌中7个字的左右列
    int right[10];
    int top[10];//保存车牌上下位置
    int bottom[10];
    int up;
    int down;
    byte strr[7][1024];
    byte string[7];//反回已找到的车牌下标
    float ang;//倾斜角度
};
 
//蓝色车牌
struct HSV{
  float H;//H值范围:190 ~ 245
  float S;//S值范围: 0.35 ~ 1,我理解为黑白灰度
  int V;//V值范围: 0.3 ~ 1
};
 
//文件图文件到内存中
int read_img(char const *fn, struct BMP_img *img)
{
    FILE *infile;
    if((infile=fopen(fn,"rb"))==NULL)return 0;
 
    fread(&img->bfType,2,1,infile);//BM
    if(!(img->bfType[0]=='B' && img->bfType[1]=='M'))return 0;
    fread(&img->size,sizeof(DWORD),1,infile);
    printf("\nBMP size             :%d",(int)img->size);
    fread(&img->reser,sizeof(DWORD),1,infile);
    printf("\n保留位:");
    fread(&img->header_length,sizeof(DWORD),1,infile);
    printf("\nheader length    :%d",(int)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   :%d\n  height  :%d ", (int)img->width, (int)img->height);
    fread(&img->biplanes, sizeof(WORD), 1, infile);
    fread(&img->bmp_type, sizeof(WORD), 1, infile);
    printf("\nBMP Tpye             :%d ", 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        :%d ",(int)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 ",(int)img->clrused);printf(" ");
    fread(&img->relclrused, sizeof(DWORD), 1, infile);
 
    if(img->bmp_type==24)//24位色,这里只考虑24位色图,其它的不考虑
    {
        img->lineBytes=((img->width*3+3)>>2)<<2;//计算一行需要多少字节,对齐到4字节
 
        //byte *temp=(byte *)malloc(sizeof(byte) * img->height * img->lineBytes);//分配一块内存,用于读文件
        img->image=(byte *)malloc(img->lineBytes*img->height);//分配一块内存,用于保存图像数据
        if(img->image==NULL) fprintf(stderr, "\n Allocation error for temp in read_bmp() \n");
        fseek(infile, img->header_length, SEEK_SET);//跳过头部,也就是跳到图像位置
        if(img->datasize==img->width*3)
            fread(img->image, sizeof(unsigned char), (img->lineBytes)*img->height, infile);//全部读到内存中
        else
        {
            for(i=0;i<img->height;i++)
            {
                fread(&img->image[i*img->width*3], sizeof(unsigned char), img->lineBytes, infile);//全部读到内存中
            }
        }
    }
    fclose(infile);
    return 1;
}
 
//把二值图保存为24位黑白图
void WriteBmp1(char const *fn,byte *bmp,int width,int height)
{
    int w4;
    struct BMP_img img;
    //一行有多少个字节
    img.lineBytes=((width*3+3)>>2)<<2;//对齐到4字节边界
    w4=img.lineBytes*height;//图像尺寸
    img.bfType[0]='B';img.bfType[1]='M';
    img.size=w4+54;
    img.reser=0;
    img.header_length=54;
    img.infoheader_length=40;
    img.width=width;
    img.height=height;
    img.biplanes=1;
    img.bmp_type=24;
    img.compres=0;
    img.datasize=w4;
    img.bixpm=0;
    img.biypm=0;
    img.clrused=0;
    img.relclrused=0;
     
    FILE *infile;
    if((infile=fopen(fn,"wb"))==NULL)
    {
        return;
    }
    fwrite(&img.bfType,2,1,infile);//printf("\n打开的图为 %d",img->bfType);//B M
    fwrite(&img.size,sizeof(DWORD),1,infile);     //        printf("\nBMP size             :%l",img->size);
    fwrite(&img.reser,sizeof(DWORD),1,infile);//printf("\n保留位:");
    fwrite(&img.header_length,sizeof(DWORD),1,infile); //printf("\nheader length    :%l",img->header_length);
    fwrite(&img.infoheader_length,sizeof(DWORD),1,infile);
    fwrite(&img.width, sizeof(DWORD), 1, infile);
    fwrite(&img.height, sizeof(DWORD), 1, infile);     //printf( "\nwidth   :%l\n  height  :%l ", img->width, img->height);
    fwrite(&img.biplanes, sizeof(WORD), 1, infile);
    fwrite(&img.bmp_type, sizeof(WORD), 1, infile);  // printf("\nBMP Tpye             :%l ", img->bmp_type);
    fwrite(&img.compres, sizeof(DWORD), 1, infile);    //if(img->compres==0) {printf("\nbmp图片为非压缩!");}printf(" ");
    fwrite(&img.datasize, sizeof(DWORD), 1, infile);//printf("\nBMP Data Size        :%l ",img->datasize);
    fwrite(&img.bixpm, sizeof(DWORD), 1, infile);
    fwrite(&img.biypm, sizeof(DWORD), 1, infile);
    fwrite(&img.clrused, sizeof(DWORD), 1, infile);    //printf("\n实际使用颜色数=%d ",img->clrused);printf(" ");
    fwrite(&img.relclrused, sizeof(DWORD), 1, infile);
     
    byte *wbmp=(byte*)malloc(w4);//后面多加两个字节,用于4字节对齐
    for(int i=0,s,w;i<height;i++)
    {
        s=i*width;
        w=i*img.lineBytes;
        for(int j=0;j<width;j++)
        {
            if(bmp[s+j]){
                wbmp[w+j*3]=wbmp[w+j*3+1]=wbmp[w+j*3+2]=bmp[s+j];
            }
            else wbmp[w+j*3]=wbmp[w+j*3+1]=wbmp[w+j*3+2]=0;                
        }
    }
    fwrite(wbmp,img.datasize,1,infile);
    free(wbmp);
    fclose(infile);
}
 
//灰度图变成二值图
void displaytwo(byte *srcBmp,byte *dstBmp,int width,int height,int yuzhi)
{
    int totalPixels = width * height;//总像素
    int bestT = 0;
    int i,j;
 
    int histogramArray[256];
    double densityArray[256]={0};
    double u0 = 0;
    double u1 = 0;
    double w0 = 0;
    double w1 = 0;
    double bestDeviation = 0;
    double w10,u10,temp;//用于调试
 
    //清零
    for(i=0;i<256;i++)histogramArray[i]=0;
         
    for(i=0;i<height;i++)//记下各灰度颜色所出现的次数
    {
        for(j=0;j<width;j++)
        {
            histogramArray[srcBmp[i*width+j]]++;
        }
    }
     
    //各颜色出现次数所在总像素的比重,256个histogramArray相加等于totalPixels
    //各densityArray相加等于1
    for(i=0;i<256;i++)
    {
        densityArray[i] = (double)histogramArray[i] / totalPixels;
    }
     
    for (i = 0; i < 256; i++)//循环256次
    {
        w0 = 0;
        w1 = 0;
        //w0+w1=1
        for (j = 0; j <= i; j++) {//前i项的比重和
            w0 += densityArray[j];
        }
        for (j = i + 1; j < 256; j++) {//后面项的比重和
            w1 += densityArray[j];
        }
         
        u0 = 0;
        u1 = 0;
        //前i项的比重倍数和,越亮比重越大,比如颜色为100占5% 与 颜色为200的占2.5%的比重相等
        for (j = 0; j <= i; j++) {
            u0 += j * densityArray[j];
        }
        for (j = i + 1; j < 256; j++) {//后面项的比重倍数和,越亮比重越大,
            u1 += j * densityArray[j];
        }
        if(w0)u0 = u0 / w0;//前面项的 倍比和 / 比和 = 
        if(w1)u1 = u1 / w1;//
        //假设前面100项和后150项,比重各占一半,那么前面倍比和肯定小于后面的倍比和
        //
        w10=w0*w1;//取值范围是0~0.25达到峰值,再慢慢变到0
        u10=u0-u1;//两者的差距,变到最小后,反而慢慢变大
        temp = w10 * u10 * u10;//temp的值,达到峰值后,慢慢变小
        if(temp > bestDeviation){//记下temp的峰值时,的灰度值
            bestT = i;
            bestDeviation = temp;
        }
    }
     
/*  //方法二,所有颜色的平均值,简单,但效果不那么好
    DWORD sum=0;
    for(i=0;i<height;i++)//记下各灰度颜色所出现的次数
    {
        for(j=0;j<width;j++)
        {
            sum+=srcBmp[i*width+j];//所有像素和相加
        }
    }
    bestT=sum/totalPixels;//平均值*/
     
    bestT=bestT+yuzhi;
    if(bestT<0)bestT=0;//如果传入的值太小,导致灰度小于0,则必为0
    if(bestT>255)bestT=255;//保证不大于255
    for(i=0;i<height;i++)
    {
        for(j=0;j<width;j++)
        {
            if(srcBmp[i*width+j]>bestT)
            {
                dstBmp[i*width+j]=255;
            }
            else
            {
                dstBmp[i*width+j]=0;
            }
        }
     }
}
 
int main(int argc, char **argv)
{
    struct BMP_img img;//定义结构
 
    //把当前文件夹下的1.bmp文件内容,读到img结构中,并上下镜像
    if(read_img("1.bmp", &img)==0)
    {
        printf("error");
        return 0;
    }
     
    //24位灰度图转单色灰度图
    for(int i=0;i<img.height;i++)
    {
        for(int j=0;j<img.width;j++)
        {
            img.image[i*img.width+j]=img.image[i*img.lineBytes+j*3];
        }
    }
     
    byte *temp=(byte*)malloc(img.width*img.height);
    displaytwo(img.image,temp,img.width,img.height,30);
     
    //写入镜像后的数据到2.bmp中
    WriteBmp1("2.bmp",temp,img.width,img.height);
     
    free(img.image);//释放动态分配的内存
    free(temp);
     
    printf("请打开2.bmp进行查看\n");
    system("pause");
    return 0;
}

灰度图

二值图

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值