我们知道,bmp(bitmap picture)图像格式是目前在数字图像处理领域通用的图片格式。
它是windows系统交换图形、图像数据的一种标准格式。
下图1是文件信息头的格式。
根据上面的图表,我们实现以下两个问题:
1. 将24位真彩色图像转为8位灰度图
2. 实现图像的裁剪
实例1: 将24位真彩色图像转为8位灰度图(BMP格式)
实例分析
1) 读取24位真彩色图像
读取24位真彩色图像和8位灰度图像最大的区别有两个:a. 24位真彩色图像的图像数据为24位,分别是BGR(各8位)。b. 没有调色板(因为每BGR三个分量就表示一种颜色)
特别注意:的是RGB图像三个分量的排列方式是BGR
2) 将彩色信息转化为灰度信息
一般有以下三种转换公式:
a. RGB各占三分之一
Gray = R*0.333 + G*0.333 + B*0.333
b. 基于人类视觉对RGB三种颜色的敏感程度不同,而有以下公式:
Gray = R*0.299 + G*0.587 + B*0.114
c. 这种公式我应用在车牌识别中,因为我国车牌大多蓝底白字,所以我将蓝色分量的权值改为0,那么蓝色像素体现在灰度图像中就变黑了,而白色依然是白色,有着较好的区分效果。
Gray = R*0.5 + G*0.5
3) 保存灰度图像
a. 需要注意的是,我们读取彩色图像的文件头,是不能直接用在灰度图像中的。需要修改文件头的第2-5字节、10-13字节和28-29字节的内容。第2-5字节的内容为bmp文件的大小,其大小包括文件信息头54字节,调色板1024字节(8位灰度图,位数不同都不一样,24位真彩色没有调色板),位图数据。
举个例子:一幅640*480的8位灰度bmp格式文件的大小为
Size = 54 + 1024 + 640*480 = 308278 byte(转为16进制就是00 04 B4 36H)
一幅640*480的24位真彩色bmp格式文件的大小为
Size = 54 + 640*480*3 = 921654 byte(转为16进制就是00 0E 10 36H)
第10-13字节和28-29字节的修改在图1已经详尽说明,在此不再赘述。彩色图像转灰度图像函数代码(图像读写函数未贴出)
void ColtoGray(int Row,int Col,unsigned char *imageIn,unsigned char *imageOut,float a,float b,float c)
{
int x,y;
int n;
float sum=0;
for(y=0;y<Row;y++)
for(x=0;x<Col;x++)
{
for(n=0;n<3;n++)
{
switch(n)
{
case 0:
sum=sum+imageIn[(y*Col+x)*3]*a; break;
case 1:
sum=sum+imageIn[(y*Col+x)*3+1]*b; break;
case 2:
sum=sum+imageIn[(y*Col+x)*3+2]*c; break;
}
}
imageOut[y*Col+x]=sum;
sum=0;
}
}
实例2: 实现图像的裁剪
- 实例分析
1)图像裁剪就是在原图上抠出一个矩形区域,并将它另存为bmp图像输出。
2)重点和难点是修改文件信息头中的宽(第18-21字节)和高(22-25字节)的信息以及实例1中文件大小的修改。 - 实例代码
void imageCut(int Row,int Col,unsigned char *imageIn,unsigned char *Fheadg,int startCutX,int startCutY,int cutx,int cuty,unsigned char *imageOut,unsigned char isCol)
{
int i,j;
int x,y;
unsigned char n;
int imageSize;
if(Row<startCutY+cuty||Col<startCutX+cutx)
{
printf("超出裁剪范围");
return;
}
if(isCol == 1)
{
n = 3;
imageSize = n*cutx*cuty+54;
}
else
{
n = 1;
imageSize = n*cutx*cuty+1078;
}
//头文件宽高和文件大小修改
Fheadg[2] = imageSize%256;
Fheadg[3] = imageSize/256%256;
Fheadg[4] = imageSize/256/256%256;
Fheadg[5] = imageSize/256/256/256%256;
Fheadg[18] = cutx%256;
Fheadg[19] = cutx/256;
Fheadg[22] = cuty%256;
Fheadg[23] = cuty/256;
for(y=0,i=startCutY;i<startCutY+cuty;y++,i++)
for(x=0,j=startCutX;j<(startCutX+cutx)*n;x++,j++)
imageOut[y*cutx*n+x] = imageIn[i*Col*n+j];
}
*本文章是作者辛苦所做,如有不足望大家指出。另转载请注明出处,谢谢各位了。*