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

代码解释

  1. 结构体定义:代码定义了三个结构体:BMPFileHeaderBMPInfoHeaderRGBTriple,分别用于存储BMP文件头信息、BMP信息头信息和RGB像素数据。
  2. 直方图结构体:定义了Histogram结构体,用于存储R分量直方图信息,包括每个灰度级出现的次数、概率和映射表。
  3. 读取图像数据:代码使用fread()函数读取BMP文件头信息、BMP信息头信息和像素数据。
  4. 统计R分量直方图:代码遍历每个像素点,统计每个R分量的出现次数。
  5. 计算直方图概率和累计概率:代码计算每个灰度级的出现概率,并计算累计概率。
  6. 计算直方图映射表:代码根据累计概率计算每个灰度级的映射表。
  7. 直方图均衡化:代码根据映射表对每个像素点的R分量进行均衡化处理。
  8. 写入均衡化后的图像数据:代码使用fwrite()函数将均衡化后的图像数据写入新的BMP文件中。

运行结果

运行该程序后,会在当前目录下生成一个名为4.bmp的图像文件,其中R分量已经进行了直方图均衡化处理。

总结

本文介绍了使用C语言编写代码对BMP图像进行直方图均衡化的实现过程。代码使用fread()fwrite()函数读取和写入图像数据,并详细解释了每个步骤。希望本文能够帮助读者理解BMP图像处理的基本原理和方法。

C语言实现BMP图像直方图均衡化

原文地址: https://www.cveoy.top/t/topic/jCXf 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录