提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
目录
前言
一、读取图片
1.图片的格式
2.bmp图片
3.读取bmp的原理
4.代码
二、四分之一变色
1.原理
2.代码
各位网友大家好,我并非是一个专业的人员或者说他人口中的“大佬”,对于图像识别方面也只是一个甚至没入门的新手,对于所发表的任何一个文章都是我本人在经过老师指导后自己学习理解的,所以有些地方略显幼稚,但是这个文章是一整个系列,一直到滤波为止(这也是我目前学到的),发表其一是处于一种良性的分享,希望可以给一些和我一样迷茫的新手提供一些帮助和建议;其二是为了自己巩固掌握。
感谢!
在读取图片时遇到的第一个问题就应该是 “该导入什么格式的图片?”。
这里需要我们自己去查找各个图片的特点。
在这里小新我用的是bmp格式的图片,原因有二:
1.Bmp图片是无损的,无损压缩,图片质量是最好的。
2.c语言读取bmp格式图片,Windows规定一个扫描行所占的字节数必须是 4的倍数(即以long 为单位),不足的以0填充,而bmp是四字节对齐的。
至于其他格式的图片,就没有深入研究了。
因为是读取bmp图片,所以实际上我们要读取图片的数据,那么我们应该读取图片文件哪一个部分呢?这是我在写代码时候的疑问,那么我就要去了解bmp的结构:
bmp一般由四部分组成:文件头信息块、图片描述信息块、颜色表(在真彩色模式无颜色表和图像数据区。
由此和我们想的一样我们需要自己设置偏移量,因为我们读取图片只需要图片里面的像素,并不需要额外的东西。通过查询可知道文件头信息块为14个字节,图片描述信息块为40个字节,因此我们就可以知道偏移量了。
图片每个像素点大小的计算方法:
从属性中计算出图片的总大小,再减去位图文件头和位图信息头以及调色板(24位、32位是没有调色板的)大小。
调色板是单色、16色、256色所特有的,相对应的调色板大小为2、16和256.
调色板以4字节为单位,每4个字节存放一个颜色,图像的数据是指向调色板的索引。
256个调色板,所以大小为256*4字节。
Bmp中数据存储的方式,颜色顺序是BGR(windows)
Bmp的运行顺序和图像的显示顺序是上下颠倒的。
所以在了解完这些必要的东西之后,我们就知道代码的必要模块:打开要读取的文件、偏移量的设置、判断是不是bmp格式的图片、获取图片的尺寸。
/* 打开文件 */
unsigned char *fp_temp;
FILE *fpbmp;
FILE *fpout;
fpbmp= fopen("1.bmp", "rb");//这里图片的名称自己定义
if (fpbmp == NULL)
{
printf("Open bmp failed!!!\n");
return 1;
}
fpout= fopen("out.bmp", "wb+");
if (fpout == NULL)
{
printf("Open out.bmp failed!!!\n");
return 1;
}
要在同一个文件夹里面才可以成功打开
/*测试是不是bmp格式的图片*/
void bmpFileTest(FILE* fpbmp)
{
unsigned short bfType = 0;
fseek(fpbmp, 0L, SEEK_SET);//seek_set 起始位置
fread(&bfType, sizeof(char), 2, fpbmp);
if (BM != bfType)
{
printf("This file is not bmp file.!!!\n");
exit(1);
}
}
/*获取文件标头的偏移量*/
void bmpHeaderPartLength(FILE* fpbmp)
{
fseek(fpbmp, 10L, SEEK_SET);
fread(&OffSet, sizeof(char), 4, fpbmp);
printf("The Header Part is of length %d.\n", OffSet);
}
/* 获取图片的长度和高度 */
void BmpWidthHeight(FILE* fpbmp)
{
fseek(fpbmp, 18L, SEEK_SET);
fread(&width, sizeof(char), 4, fpbmp);
fseek(fpbmp, 22L, SEEK_SET);
fread(&height, sizeof(char), 4, fpbmp);
printf("The Width of the bmp file is %ld.\n", width);
printf("The Height of the bmp file is %ld.\n", height);
}
之后要做的就是再定义一个输出函数将图片中rgb的值读取出来
for(j=0;j
{
for(i=0;i{
pixout[i*3+2]=r[height-1-j][i];
pixout[i*3+1]=g[height-1-j][i];
pixout[i*3] =b[height-1-j][i];
}
fwrite(pixout, 1, stride, fpout);//输出 读取pixout 输出到fpout
函数理解:
Fread函数:一般用于二进制文件的输入。从一个文件流中读数据,最多读取count个元素,每个元素size字节,如果调用成功返回实际读取到的元素个数,如果不成功或读到文件末尾返回 0
Fseek函数:移动指针到函数的任意位置
1.SEEK_SET 文件开始处
2.SEEK_CUR 当前位置
3.SEEK_END 文件末尾
fseek(FILE *stream, long offset, int fromwhere)
如果执行成功,stream将指向以fromwhere为基准,偏移offse(指针偏移量)个字节的位置,函数返回0
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
(以上全都是从小新从网上搜过来的并不详细,大家可以自己去看看其他大佬的理解)
其中注意我们是四个字节进行读取所以在读取时要用到下面两个算式
stride=(24*width+31)/8
stride=stride/4*4;
并且将其赋值给上面的pixout。
那么图片读取部分大致就结束了。
将图像尺寸存储到两个变量中long width ; 和long height ;中,根据要求,将尺寸分别除以2。即可以达到1/4的效果。并用遍历所有像素点,将三个通道中除了红色外其他颜色全部置0。
(RGB:0-255 0是白色 255是最深色)
void bmpDataPart(FILE* fpbmp)
{
int i, j=0;
int stride;
unsigned char* pix=NULL;
FILE* fpr;
FILE* fpg;
FILE* fpb;
if((fpr=fopen("bmpr.txt","w+")) == NULL)//读取文件内容
{
printf("Failed to construct file bmpr.txt.!!!");
exit(1);
}
if((fpg=fopen("bmpg.txt","w+")) == NULL)
{
printf("Failed to construct file bmpg.txt.!!!");
exit(1);
}
if((fpb=fopen("bmpb.txt","w+")) == NULL)
{
printf("Failed to construct file bmpb.txt.!!!");
exit(1);
}
fseek(fpbmp, OffSet, SEEK_SET);
stride=(24*width+31)/8;
stride=stride/4*4;
pix=malloc(stride);for(j=0;j
{
fread(pix, 1, stride, fpbmp);
for(i=0;i{
r[height-1-j][i] =pix[i*3+2];
g[height-1-j][i] =pix[i*3+1];
b[height-1-j][i] =pix[i*3];
}
}
//四分之一变色
for(j=height/2;j{
fread(pix, 1, stride, fpbmp);
for(i=0;i{
r[height-1-j][i]=255;
g[height-1-j][i]=0;
b[height-1-j][i]=0;
}
}
for(i =0; i < height; i++)
{
for(j = 0; j < width-1; j++)
{
fprintf(fpb,"%4d",b[i][j]);
fprintf(fpg,"%4d",g[i][j]);
fprintf(fpr,"%4d",r[i][j]);
}
fprintf(fpb,"%4d\n",b[i][j]);
fprintf(fpg,"%4d\n",g[i][j]);
fprintf(fpr,"%4d\n",r[i][j]);
}
fclose(fpr);
fclose(fpg);
fclose(fpb);
}
在进行四分之一变色时,其实最主要的问题时如何读取bmp格式的图片,这也是图像处理的门槛,所需要的准备知识也会很多,这里更多希望给各位同学一个参考方向,也是作为一个小白的一些些经验。
部分资料来源于网络,如果给您造成困扰,请联系我。