- UID
- 2285
- 精华
- 积分
- 513
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
- #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;//一行占多少字节
- };
- //蓝色车牌
- 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);//跳过头部,也就是跳到图像位置
- fread(img->image, sizeof(byte), (img->lineBytes)*img->height, infile);//全部读到内存中
- }
- fclose(infile);
- return 1;
- }
- 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);
- 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]=255;
- }
- 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);
- }
- //把RGB数据转换成HSV空间图像数据
- //输入,图像,HSV倍象素,宽,高
- void hsvzation(byte *image,struct HSV *hsv,int width,int height)
- {
- int i,j,k;
- DWORD l,lk;
- //float min,max,delta,tmp;//h,s,v,m,n;
- int min,max,delta,tmp;
- byte r,g,b;
- for(i=0;i<height;i++)
- {
- l=i*width;
- for(k=0,j=0;j<width*3;k++,j+=3)
- {
- lk=l+k;
- g=image[l*3+j+1];
- b=image[l*3+j];
- r=image[l*3+j+2];
- tmp=min(r,g);//取3者最小值
- min=min(tmp,b);
- tmp=max(r,g);//取3者最大值
- max=max(tmp,b);
- hsv[lk].V=max;//V保存三者最大值
- delta=max-min;//保存最大值与最小值的差
- if(delta==0)//如果3值相等
- {
- hsv[lk].H=0;
- hsv[lk].S=0;//这句是我加的
- continue;
- }
- //如果三值依次是100,150,200,则.S=100/200=0.5
- //如果三值依次是0,50,100,则为1
- //如果三值依次是99,99,100,则为0.01
- //意思就是三值越接近,此值越小,越不接近,此值越大
- //应该是指颜色灰度
- hsv[lk].S=(float)delta/max;
- if(r==max)//如果红色为最大值,说明当前点的颜色偏红
- {
- //如果三值依次为200,150,100,则.H=50/100=0.5
- //如果三值依次为100,50,0,则.H还是0.5
- //如果三值依次为:100,99,99,则为0
- //如果为100,0,100,则为-1
- //可以看出,蓝色与绿色越接近,趋向0,否则为趋向+-1
- hsv[lk].H=(g-b)/(float)delta;//tmp;
- }
- else if(g==max)//如果绿色为最大值
- hsv[lk].H=2+(b-r);//没看懂,取值范围-253~255
- else//蓝为最大值
- {
- //和红色最大一样的,[-1,0],[0-1],加上4后,变成【3,5]
- hsv[lk].H=4+(r-g)/(float)delta;//
- }
- //-1~1 *60=-60~60
- //-253~257,*60=-15180~15420之间
- hsv[lk].H*=60;//(3,5)*60=[180,300]
-
- //可以看到,当其值为【-60,0)时,加上360=【300,360)区间
- //至于那个-15180多的那种结果,加上360也不管用
- if(hsv[lk].H<0)
- hsv[lk].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;
- struct HSV *hsv;//float,float,int
- byte *temp1;
- hsv=(struct HSV *)malloc(sizeof(struct HSV)*width*height);//分配HSV倍图像像素大小
- hsvzation(image,hsv,width,height);//根据RGB,计算出HSV的值
- //再分配一块内存,像素个
- temp1=(byte *)malloc(sizeof(byte)*height*width);
- for(i=0;i<height;i++)//循环高度
- {
- for(j=0,n=0;j<width;n+=3,j++)//循环宽度
- {
- if((hsv[i*width+j].H<230.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;//为白色
- }
- else//为黑色
- {
- temp1[i*width+j]=0;
- }
- }
- }//可以看到,本循环的意思就是把原始图像,黑白化,满足条件为白,否则通通为黑
-
- //写入镜像后的数据到2.bmp中
- WriteBmp1("2.bmp",temp1,width,height);
-
- free(temp1);
- temp1=NULL;
- free(hsv);
- }
- int main(int argc, char **argv)
- {
- struct BMP_img img;//定义结构
- int HL=0,HH=0,VH=0,VL=0;
- //把当前文件夹下的1.bmp文件内容,读到img结构中,并上下镜像
- if(read_img("1.bmp", &img)==0)
- {
- printf("error");
- return 0;
- }
-
- location(img.image,img.width,img.height,15,&HL,&HH,&VL,&VH);//根据蓝底找到车牌所在位置
-
- free(img.image);//释放动态分配的内存
-
- printf("请打开2.bmp进行查看\n");
- system("pause");
- return 0;
- }
复制代码
|
-
-
|