C语言实现BMP图像直方图均衡化
C语言实现BMP图像直方图均衡化
本文将介绍使用C语言编写代码对256x256大小的24位真彩BMP图像进行直方图均衡化处理。代码使用fread()和fwrite()函数读取和写入图像数据,并详细解释了实现过程。
代码实现
#include <stdio.h>
#include <stdlib.h>
#pragma pack(2) // 设置结构体成员按2字节对齐
// BMP文件头结构体
typedef struct {
unsigned short bfType; // 文件类型,必须为0x4D42
unsigned int bfSize; // 文件大小,单位为字节
unsigned short bfReserved1; // 保留字段,必须为0
unsigned short bfReserved2; // 保留字段,必须为0
unsigned int bfOffBits; // 从文件头到像素数据的偏移量,单位为字节
} BMPFileHeader;
// BMP信息头结构体
typedef struct {
unsigned int biSize; // 信息头大小,必须为40
int biWidth; // 图像宽度,单位为像素
int biHeight; // 图像高度,单位为像素
unsigned short biPlanes; // 颜色平面数,必须为1
unsigned short biBitCount; // 每个像素的位数,必须为24
unsigned int biCompression; // 压缩方式,必须为0
unsigned int biSizeImage; // 像素数据大小,单位为字节
int biXPelsPerMeter; // 水平分辨率,单位为像素/米
int biYPelsPerMeter; // 垂直分辨率,单位为像素/米
unsigned int biClrUsed; // 颜色表中实际使用的颜色数,对于24位图像,该值为0
unsigned int biClrImportant; // 重要颜色数,对于24位图像,该值为0
} BMPInfoHeader;
// RGB三元组结构体
typedef struct {
unsigned char b; // 蓝色分量
unsigned char g; // 绿色分量
unsigned char r; // 红色分量
} RGBTriple;
// 直方图结构体
typedef struct {
int count[256]; // 每个灰度级出现的次数
float probability[256]; // 每个灰度级出现的概率
int mapping[256]; // 灰度级映射表
} Histogram;
int main() {
FILE *fpIn, *fpOut;
BMPFileHeader fileHeader;
BMPInfoHeader infoHeader;
RGBTriple **pixels;
Histogram histogram;
int i, j, k;
float sum = 0;
unsigned char r;
// 打开输入图像文件
fpIn = fopen('3.bmp', 'rb');
if (fpIn == NULL) {
printf('无法打开输入图像文件\n');
return 0;
}
// 读取文件头信息
fread(&fileHeader, sizeof(BMPFileHeader), 1, fpIn);
fread(&infoHeader, sizeof(BMPInfoHeader), 1, fpIn);
// 分配像素点内存
pixels = (RGBTriple **)malloc(infoHeader.biHeight * sizeof(RGBTriple *));
for (i = 0; i < infoHeader.biHeight; i++) {
pixels[i] = (RGBTriple *)malloc(infoHeader.biWidth * sizeof(RGBTriple));
}
// 读取像素点信息
for (i = 0; i < infoHeader.biHeight; i++) {
for (j = 0; j < infoHeader.biWidth; j++) {
fread(&pixels[i][j], sizeof(RGBTriple), 1, fpIn);
}
}
// 关闭输入图像文件
fclose(fpIn);
// 初始化直方图
for (i = 0; i < 256; i++) {
histogram.count[i] = 0;
histogram.probability[i] = 0;
histogram.mapping[i] = 0;
}
// 统计R分量直方图
for (i = 0; i < infoHeader.biHeight; i++) {
for (j = 0; j < infoHeader.biWidth; j++) {
histogram.count[pixels[i][j].r]++;
}
}
// 计算R分量直方图概率
for (i = 0; i < 256; i++) {
histogram.probability[i] = (float)histogram.count[i] / (infoHeader.biWidth * infoHeader.biHeight);
}
// 计算R分量直方图累计概率
for (i = 0; i < 256; i++) {
sum += histogram.probability[i];
histogram.probability[i] = sum;
}
// 计算R分量直方图映射表
for (i = 0; i < 256; i++) {
histogram.mapping[i] = (int)(histogram.probability[i] * 255 + 0.5);
}
// 对R分量进行直方图均衡
for (i = 0; i < infoHeader.biHeight; i++) {
for (j = 0; j < infoHeader.biWidth; j++) {
r = pixels[i][j].r;
pixels[i][j].r = histogram.mapping[r];
}
}
// 打开输出图像文件
fpOut = fopen('4.bmp', 'wb');
if (fpOut == NULL) {
printf('无法打开输出图像文件\n');
return 0;
}
// 写入文件头信息
fwrite(&fileHeader, sizeof(BMPFileHeader), 1, fpOut);
fwrite(&infoHeader, sizeof(BMPInfoHeader), 1, fpOut);
// 写入像素点信息
for (i = 0; i < infoHeader.biHeight; i++) {
for (j = 0; j < infoHeader.biWidth; j++) {
fwrite(&pixels[i][j], sizeof(RGBTriple), 1, fpOut);
}
}
// 关闭输出图像文件
fclose(fpOut);
// 释放像素点内存
for (i = 0; i < infoHeader.biHeight; i++) {
free(pixels[i]);
}
free(pixels);
return 0;
}
代码解释
- 结构体定义:代码定义了三个结构体:
BMPFileHeader、BMPInfoHeader和RGBTriple,分别用于存储BMP文件头信息、BMP信息头信息和RGB像素数据。 - 直方图结构体:定义了
Histogram结构体,用于存储R分量直方图信息,包括每个灰度级出现的次数、概率和映射表。 - 读取图像数据:代码使用
fread()函数读取BMP文件头信息、BMP信息头信息和像素数据。 - 统计R分量直方图:代码遍历每个像素点,统计每个R分量的出现次数。
- 计算直方图概率和累计概率:代码计算每个灰度级的出现概率,并计算累计概率。
- 计算直方图映射表:代码根据累计概率计算每个灰度级的映射表。
- 直方图均衡化:代码根据映射表对每个像素点的R分量进行均衡化处理。
- 写入均衡化后的图像数据:代码使用
fwrite()函数将均衡化后的图像数据写入新的BMP文件中。
运行结果
运行该程序后,会在当前目录下生成一个名为4.bmp的图像文件,其中R分量已经进行了直方图均衡化处理。
总结
本文介绍了使用C语言编写代码对BMP图像进行直方图均衡化的实现过程。代码使用fread()和fwrite()函数读取和写入图像数据,并详细解释了每个步骤。希望本文能够帮助读者理解BMP图像处理的基本原理和方法。
原文地址: https://www.cveoy.top/t/topic/jCXf 著作权归作者所有。请勿转载和采集!