图片识别(灰度化)
首先呢,这是昨天到今天晚上的学习,总结下。
发现我自己的问题
1.c语言还是有问题,原因做的东西太少,理论知识不能结合实际,比如unsigned char 存储 一个字节和char存储一个字节的差别。
2.数学很重要啊。
3.学一个东西,一定要把这个东西学的屎出来了,再换。要么和没学没啥区别。
想要灰度化首先干什么呢?对了就是找图片。
这个是我在人人网注册栏找到的。
第二步呢?图片存储格式。
根据linux的哲学“一切皆文件”,所以这个图片一定可以用c语言的文件操作函数打开,我用的是c语言,当然用到文件操作这一节,复习复习。
第三部呢?
既然图片是文件,那就要读出来,文件操作就那么几个函数,都是字节或者二进制,然后读出来放在哪里呢?怎么操作这些数据呢?这个就先要查查图片编程方面的东西,百度“图片编程”会出现很多东西的,其中你会知道jpg和bmp两种格式的图片。
我发现,jpg是一种压缩后的图片(为了减轻网络传送数据的压力),bmp等等的图片太大了。大家写过哈夫曼的都知道,一个文件压缩后,它是直接显示不出来的,必须解压,解压后才是原始文件(jpg文件在网上传输的是压缩的文件,打开时候是对其解压),如果你直接对jpg操作就是大错特错(你懂得)。
下来就是要将jpg(网上的图片一般都是jpg)转换成bmp。linux下有个好东东
对于上面的东西,直接sudo就行。
现在的问题就明了了,是对bmp图片进行操作。
百度bmp。立马看到它的结构。
接着上面的问题,我们现在就知道从文件读出的数据放在哪里了。就是那几个结构体中。
现在就上代码吧。
#include <stdio.h> #include <stdlib.h> typedef unsigned short WORD; typedef unsigned int DWORD; typedef unsigned int LONG; typedef struct tagBITMAPFILEHEADER { WORD bfType; // 位图文件的类型,必须为BM(1-2字节) DWORD bfSize; // 位图文件的大小,以字节为单位(3-6字节) WORD bfReserved1; // 位图文件保留字,必须为0(7-8字节) WORD bfReserved2; // 位图文件保留字,必须为0(9-10字节) DWORD bfOffBits; // 位图数据的起始位置,以相对于位图(11-14字节) // 文件头的偏移量表示,以字节为单位 } BITMAPFILEHEADER; typedef struct tagBITMAPINFOHEADER{ DWORD biSize; // 本结构所占用字节数(15-18字节) LONG biWidth; // 位图的宽度,以像素为单位(19-22字节) LONG biHeight; // 位图的高度,以像素为单位(23-26字节) WORD biPlanes; // 目标设备的级别,必须为1(27-28字节) WORD biBitCount;// 每个像素所需的位数,必须是1(双色),(29-30字节) // 4(16色),8(256色)16(高彩色)或24(真彩色)之一 DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),(31-34字节) // 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 DWORD biSizeImage; // 位图的大小(其中包含了为了补齐行数是4的倍数而添加的空字节),以字节为单位(35-38字节) LONG biXPelsPerMeter; // 位图水平分辨率,每米像素数(39-42字节) LONG biYPelsPerMeter; // 位图垂直分辨率,每米像素数(43-46字节) DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数(47-50字节) DWORD biClrImportant;// 位图显示过程中重要的颜色数(51-54字节) } BITMAPINFOHEADER; typedef struct{ unsigned char b; unsigned char g; unsigned char r; }RGB; /* typedef struct tagRGBQUAD { BYTE rgbBlue;// 蓝色的亮度(值范围为0-255) BYTE rgbGreen; // 绿色的亮度(值范围为0-255) BYTE rgbRed; // 红色的亮度(值范围为0-255) BYTE rgbReserved;// 保留,必须为0 } RGBQUAD; typedef struct tagBITMAPINFO { BITMAPINFOHEADER bmiHeader; // 位图信息头 RGBQUAD bmiColors[1]; // 颜色表 } BITMAPINFO; */ void grey() { FILE *fp; FILE *fp1; char a[30]; BITMAPFILEHEADER head; BITMAPINFOHEADER head1; int trueWidth; int i; int j; int k = 0; unsigned char f = 0; printf("please input filename:"); scanf("%s", a); if((fp = fopen(a, "rb")) == NULL) { printf("file start error seek\n"); exit(1); } if((fp1 = fopen("11.bmp", "wb")) == NULL) { printf("file start error\n"); exit(1); } fread(&head, 14, 1, fp); fread(&head1, 40, 1, fp); printf("width:%d\n", head1.biWidth); printf("biHeigth:%d\n", head1.biHeight); printf("biBitCount:%d\n", head1.biBitCount); trueWidth = (head1.biWidth * head1.biBitCount/8 +3)/4*4; int p = trueWidth - trueWidth/3 * 3; RGB rgb[head1.biHeight][head1.biWidth]; unsigned char b[head1.biHeight][head1.biWidth]; for(j = 0; j < head1.biHeight; j++ ) { for(i = 0; i < head1.biWidth; i++) { fread(&rgb[j][i], 3, 1, fp); k++; } fseek(fp, p, SEEK_CUR); } for(i = 0; i < head1.biHeight; i++) for(j = 0; j < head1.biWidth; j++) { b[i][j] = (rgb[i][j].b + rgb[i][j].g + rgb[i][j].r)/3; } fwrite(&head, 14, 1, fp1); fwrite(&head1, 40, 1, fp1); for(i = 0; i < head1.biHeight; i++) { for(j = 0; j < head1.biWidth; j++) { fwrite(&b[i][j], 1, 3, fp1); } fwrite(&f, 1, p,fp1); } fclose(fp1); fclose(fp); } int main() { grey(); }
然后看看效果。