一丶图像存储格式分类
分类 | 特点 | 举例 |
---|---|---|
黑白图像 | 二值图像只有黑白两种颜色,一个像素仅占1,0表示黑,1表示白,或相反 | ![]() |
8位索引图像 | 8位灰度索引图像中map也就是颜色表红、绿、蓝分量值相等 8位伪彩色索引图像,颜色表红、绿、蓝分量值不全相等 | ![]() |
24位真彩图 | .RGB图像也就是每个像素点3个8位的分量 | ![]() |
二丶图像存储格式转换
- 伪彩色彩 → 灰度 :直接改该索引表,将三个分量改成与索引号一致的
- 灰度 → 伪彩色彩:不好变,每个分量可能需要人为指定
- 灰度图与RGB图像转换:任何颜色都有红、绿、蓝三原色组成,假如原来某点的颜色为RGB(R,G,B),那么,我们可以通过下面几种方法,将其转换为灰度:
1.浮点算法:Gray = R * 0.3+G * 0.59+B * 0.11
2.整数方法:Gray = (R * 30+G * 59+B * 11) / 100
3.移位方法:Gray = (R * 76+G * 151+B * 28) >> 8;
4.平均值法:Gray = (R+G+B) / 3;
5.仅取绿色:Gray=G;
通过上述任一种方法求得Gray后,将原来的RGB(R,G,B)中的R,G,B统一用Gray替换,形成新的颜RGB(Gray,Gray,Gray),用它替换原来的RGB(R,G,B)就是灰度图了。
所以RGB可以转化为灰度图,RGB的红色、绿色、蓝色三个通道的缩览图都是以灰度显示的
三丶C++ bmp 转灰度实例
1. bmp文件组成
重要的有(上面的名字都是标准的)
- bfType:可以用来判断当前图片是否为bmp图像,若读出来是“BM”那就是
- biBitCount 每个像素所需要的位数,比如单色位图需要1位,8位索引图像需要8位,真彩色就是24位
- 调色板 就是红绿蓝和保留字
2. bmp读取与灰度转换(C++)
重要函数:
- int fread(void *ptr, int size, int nitems, FILE *stream);
从一个流中读数据,从所给的输入流stream中读取的nitems项数据,每一项数据长度为size字节,到由ptr所指的块中,读出的数据在流中会消失 - int fwrite(void *ptr, int size, int nitems, FILE *stream);
从ptr所指的块中读数据读取的nitems项数据,每一项数据长度为size字节,输入到由流stream
3. FILE *fopen(const char *filename, const char *mode)
使用给定的模式 mode 打开 filename 所指向的文件
w:以“写入”方式打开文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么清空文件内容(相当于删除原文件,再创建一个新文件)。
r:只读方式打开,将文件指针指向文件头。
b :字符用来告诉函数库以二进制模式打开文件
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include <iostream>
using namespace std;
/*
位图头结构
*/
#pragma pack(1)
typedef struct tagBITMAPFILEHEADER
{
unsigned char bfType[2];//文件格式
unsigned long bfSize;//文件大小
unsigned short bfReserved1;//保留
unsigned short bfReserved2;
unsigned long bfOffBits; //DIB数据在文件中的偏移量
}fileHeader;
#pragma pack()
/*
位图数据信息结构
*/
#pragma pack(1)
typedef struct tagBITMAPINFOHEADER
{
unsigned long biSize;//该结构的大小
long biWidth;//文件宽度
long biHeight;//文件高度
unsigned short biPlanes;//平面数
unsigned short biBitCount;//颜色位数
unsigned long biCompression;//压缩类型
unsigned long biSizeImage;//DIB数据区大小
long biXPixPerMeter;
long biYPixPerMeter;
unsigned long biClrUsed;//多少颜色索引表
unsigned long biClrImporant;//多少重要颜色
}fileInfo;
#pragma pack()
/*
调色板结构
*/
#pragma pack(1)
typedef struct tagRGBQUAD
{
unsigned char rgbBlue; //蓝色分量亮度
unsigned char rgbGreen;//绿色分量亮度
unsigned char rgbRed;//红色分量亮度
unsigned char rgbReserved;
}rgbq;
#pragma pack()
//显示位图文件头信息
void showBmpHead(fileHeader pBmpHead) {
cout << "位图文件头:" << endl;
cout << "文件大小:" << pBmpHead.bfSize << endl;
cout << "保留字_1:" << pBmpHead.bfReserved1 << endl;
cout << "保留字_2:" << pBmpHead.bfReserved2 << endl;
cout << "实际位图数据的偏移字节数:" << pBmpHead.bfOffBits << endl << endl;
}
void showBmpInfoHead(fileInfo pBmpInforHead) {
cout << "位图信息头---------" << endl;
cout << "结构体的长度:" << pBmpInforHead.biSize << endl;
cout << "位图宽:" << pBmpInforHead.biWidth << endl;
cout << "位图高:" << pBmpInforHead.biHeight << endl;
cout << "biPlanes平面数:" << pBmpInforHead.biPlanes << endl;
cout << "biBitCount采用颜色位数:" << pBmpInforHead.biBitCount << endl;
cout << "压缩方式:" << pBmpInforHead.biCompression << endl;
cout << "biSizeImage实际位图数据占用的字节数:" << pBmpInforHead.biSizeImage << endl;
cout << "X方向分辨率:" << pBmpInforHead.biXPixPerMeter << endl;
cout << "Y方向分辨率:" << pBmpInforHead.biYPixPerMeter << endl;
cout << "使用的颜色数:" << pBmpInforHead.biClrUsed << endl;
cout << "重要颜色数:" << pBmpInforHead.biClrImporant << endl;
}
#define PI 3.141592653
#pragma once
int main()
{
int i, j, k;
FILE* fpBMP, * fpGray;
fileHeader* fh;
fileInfo* fi;
rgbq* fq;
if ((fpBMP = fopen("C:\\Users\\Administrator\\Desktop\\real.bmp", "rb")) == NULL)
{
printf("打开文件失败");
exit(0);
}
if ((fpGray = fopen("C:\\Users\\Administrator\\Desktop\\22.bmp", "wb")) == NULL)
{
printf("创建文件失败");
exit(0);
}
fh = (fileHeader*)malloc(sizeof(fileHeader));
fi = (fileInfo*)malloc(sizeof(fileInfo));
//读取位图头结构和信息头
fread(fh, sizeof(fileHeader), 1, fpBMP);
showBmpHead(*fh);
cout << fh->bfType[0] << fh->bfType[1] << endl;
fread(fi, sizeof(fileInfo), 1, fpBMP);
showBmpInfoHead(*fi);
//修改头信息
fi->biBitCount = 8;
fi->biSizeImage = ((fi->biWidth * 3 + 3) / 4) * 4 * fi->biHeight;
//fi->biClrUsed=256;
fh->bfOffBits = sizeof(fileHeader) + sizeof(fileInfo) + 256 * sizeof(rgbq);
fh->bfSize = fh->bfOffBits + fi->biSizeImage;
//创建调色版
fq = (rgbq*)malloc(256 * sizeof(rgbq));
for (i = 0; i < 256; i++)
{
fq[i].rgbBlue = fq[i].rgbGreen = fq[i].rgbRed = i;
//fq[i].rgbReserved=0;
}
//将头信息写入
fwrite(fh, sizeof(fileHeader), 1, fpGray);
fwrite(fi, sizeof(fileInfo), 1, fpGray);
fwrite(fq, sizeof(rgbq), 256, fpGray);
/*存储RGB图像的一行像素点*/
unsigned char ImgData[3000][3];
/*将灰度图的像素存到一个一维数组中*/
unsigned char* data;
int h = fi->biHeight;
int w = (fi->biWidth + 3) / 4 * 4;
data = (unsigned char*)malloc(h*w);
//读取RGB图像素并转换为灰度值
for (i = 0; i <h; i++)
{
for (j = 0; j < w; j++)
{
for (k = 0; k < 3; k++) {
fread(&ImgData[j][k], 1, 1, fpBMP);
*(data + i *w + j) = int((float)ImgData[j][0] * 0.114 +
(float)ImgData[j][1] * 0.587 +
(float)ImgData[j][2] * 0.299);
}
}
fwrite(data, sizeof(unsigned char), h*w, fpGray);
free(fh);
free(fi);
free(fq);
fclose(fpBMP);
fclose(fpGray);
printf("success\n");
return 0;
}
四丶Python 灰度图转
python代码
程序的实现
from PIL import Image
img = Image.open('lena.png')
gray_img = img.convert('L')
模式“L”为灰色图像公式:L = R * 299/1000 + G * 587/1000+ B * 114/1000