图片识别(灰度化)

首先呢,这是昨天到今天晚上的学习,总结下。

发现我自己的问题

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();
}

  然后看看效果。

posted @ 2014-03-13 17:21  elroyzhang  阅读(2490)  评论(0编辑  收藏  举报