车牌识别(五)灰度图二值化
再次把灰度图,转成二值图像,用于比较。。。#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头
BYTEbfType;//类型,判断是否为‘B’,‘M’
DWORD size;//文件尺寸
DWORD reser;//保留,为0
DWORD header_length;//头部长度,也就是数据起始位置
//}BMP头长度,14字节
//{信息头40字节
DWORD infoheader_length;//信息头长度,40
DWORD width;//图像宽度
DWORD height;//图像高度
WORDbiplanes;//颜色平面数,为1
WORDbmp_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;//保存车牌中7个字的左右列
int right;
int top;//保存车牌上下位置
int bottom;
int up;
int down;
byte strr;
byte string;//反回已找到的车牌下标
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=='B' && img->bfType=='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\nheight:%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);//跳过头部,也就是跳到图像位置
fread(img->image, sizeof(byte), (img->lineBytes)*img->height, 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='B';img.bfType='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\nheight:%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){
wbmp=wbmp=wbmp=bmp;
}
else wbmp=wbmp=wbmp=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;
double densityArray={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=0;
for(i=0;i<height;i++)//记下各灰度颜色所出现的次数
{
for(j=0;j<width;j++)
{
histogramArray]++;
}
}
//各颜色出现次数所在总像素的比重,256个histogramArray相加等于totalPixels
//各densityArray相加等于1
for(i=0;i<256;i++)
{
densityArray = (double)histogramArray / totalPixels;
}
for (i = 0; i < 256; i++)//循环256次
{
w0 = 0;
w1 = 0;
//w0+w1=1
for (j = 0; j <= i; j++) {//前i项的比重和
w0 += densityArray;
}
for (j = i + 1; j < 256; j++) {//后面项的比重和
w1 += densityArray;
}
u0 = 0;
u1 = 0;
//前i项的比重倍数和,越亮比重越大,比如颜色为100占5% 与 颜色为200的占2.5%的比重相等
for (j = 0; j <= i; j++) {
u0 += j * densityArray;
}
for (j = i + 1; j < 256; j++) {//后面项的比重倍数和,越亮比重越大,
u1 += j * densityArray;
}
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;//所有像素和相加
}
}
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>bestT)
{
dstBmp=255;
}
else
{
dstBmp=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=img.image;
}
}
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;
}
好东西,谢谢
页:
[1]