使用C语言实现BMP图像B分量直方图均衡化

本文将介绍如何使用C语言编写代码,对大小为256×256的24位真彩BMP格式图像进行B分量直方图均衡化。

首先,我们需要定义BMP文件头和图像数据的结构体,并编写读取和写入BMP文件的函数。

#include <stdio.h>
#include <stdlib.h>

typedef struct tagBITMAPFILEHEADER {
    unsigned short bfType;
    unsigned int bfSize;
    unsigned short bfReserved1;
    unsigned short bfReserved2;
    unsigned int bfOffBits;
} BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER {
    unsigned int biSize;
    int biWidth;
    int biHeight;
    unsigned short biPlanes;
    unsigned short biBitCount;
    unsigned int biCompression;
    unsigned int biSizeImage;
    int biXPelsPerMeter;
    int biYPelsPerMeter;
    unsigned int biClrUsed;
    unsigned int biClrImportant;
} BITMAPINFOHEADER;

void read_bmp(char *filename, unsigned char *image_data, BITMAPFILEHEADER *file_header, BITMAPINFOHEADER *info_header) {
    FILE *fp = fopen(filename, "rb");
    if (fp == NULL) {
        printf("Error: cannot open file %s\n", filename);
        return;
    }

    fread(file_header, sizeof(BITMAPFILEHEADER), 1, fp);
    fread(info_header, sizeof(BITMAPINFOHEADER), 1, fp);

    int width = info_header->biWidth;
    int height = info_header->biHeight;
    int row_size = (width * 3 + 3) / 4 * 4;
    unsigned char *temp_data = (unsigned char *)malloc(row_size);

    for (int i = 0; i < height; i++) {
        fread(temp_data, row_size, 1, fp);
        for (int j = 0; j < width; j++) {
            image_data[(i * width + j) * 3] = temp_data[j * 3 + 2];
            image_data[(i * width + j) * 3 + 1] = temp_data[j * 3 + 1];
            image_data[(i * width + j) * 3 + 2] = temp_data[j * 3];
        }
    }

    free(temp_data);
    fclose(fp);
}

void write_bmp(char *filename, unsigned char *image_data, BITMAPFILEHEADER *file_header, BITMAPINFOHEADER *info_header) {
    FILE *fp = fopen(filename, "wb");
    if (fp == NULL) {
        printf("Error: cannot create file %s\n", filename);
        return;
    }

    fwrite(file_header, sizeof(BITMAPFILEHEADER), 1, fp);
    fwrite(info_header, sizeof(BITMAPINFOHEADER), 1, fp);

    int width = info_header->biWidth;
    int height = info_header->biHeight;
    int row_size = (width * 3 + 3) / 4 * 4;
    unsigned char *temp_data = (unsigned char *)malloc(row_size);

    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            temp_data[j * 3 + 2] = image_data[(i * width + j) * 3];
            temp_data[j * 3 + 1] = image_data[(i * width + j) * 3 + 1];
            temp_data[j * 3] = image_data[(i * width + j) * 3 + 2];
        }
        fwrite(temp_data, row_size, 1, fp);
    }

    free(temp_data);
    fclose(fp);
}

接下来,我们开始进行B分量直方图均衡化。

  1. 计算B分量的直方图
int hist[256] = {0};
for (int i = 0; i < width * height; i++) {
    hist[image_data[i * 3]]++;
}
  1. 计算B分量的累积直方图
int cum_hist[256] = {0};
for (int i = 0; i < 256; i++) {
    cum_hist[i] = (i == 0) ? hist[i] : cum_hist[i - 1] + hist[i];
}
  1. 计算B分量的直方图均衡化映射表
int map[256] = {0};
for (int i = 0; i < 256; i++) {
    map[i] = (int)(255.0 * cum_hist[i] / (width * height) + 0.5);
}
  1. 根据映射表对B分量进行直方图均衡化
for (int i = 0; i < width * height; i++) {
    image_data[i * 3] = map[image_data[i * 3]];
}

完整的代码如下:

#include <stdio.h>
#include <stdlib.h>

typedef struct tagBITMAPFILEHEADER {
    unsigned short bfType;
    unsigned int bfSize;
    unsigned short bfReserved1;
    unsigned short bfReserved2;
    unsigned int bfOffBits;
} BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER {
    unsigned int biSize;
    int biWidth;
    int biHeight;
    unsigned short biPlanes;
    unsigned short biBitCount;
    unsigned int biCompression;
    unsigned int biSizeImage;
    int biXPelsPerMeter;
    int biYPelsPerMeter;
    unsigned int biClrUsed;
    unsigned int biClrImportant;
} BITMAPINFOHEADER;

void read_bmp(char *filename, unsigned char *image_data, BITMAPFILEHEADER *file_header, BITMAPINFOHEADER *info_header) {
    FILE *fp = fopen(filename, "rb");
    if (fp == NULL) {
        printf("Error: cannot open file %s\n", filename);
        return;
    }

    fread(file_header, sizeof(BITMAPFILEHEADER), 1, fp);
    fread(info_header, sizeof(BITMAPINFOHEADER), 1, fp);

    int width = info_header->biWidth;
    int height = info_header->biHeight;
    int row_size = (width * 3 + 3) / 4 * 4;
    unsigned char *temp_data = (unsigned char *)malloc(row_size);

    for (int i = 0; i < height; i++) {
        fread(temp_data, row_size, 1, fp);
        for (int j = 0; j < width; j++) {
            image_data[(i * width + j) * 3] = temp_data[j * 3 + 2];
            image_data[(i * width + j) * 3 + 1] = temp_data[j * 3 + 1];
            image_data[(i * width + j) * 3 + 2] = temp_data[j * 3];
        }
    }

    free(temp_data);
    fclose(fp);
}

void write_bmp(char *filename, unsigned char *image_data, BITMAPFILEHEADER *file_header, BITMAPINFOHEADER *info_header) {
    FILE *fp = fopen(filename, "wb");
    if (fp == NULL) {
        printf("Error: cannot create file %s\n", filename);
        return;
    }

    fwrite(file_header, sizeof(BITMAPFILEHEADER), 1, fp);
    fwrite(info_header, sizeof(BITMAPINFOHEADER), 1, fp);

    int width = info_header->biWidth;
    int height = info_header->biHeight;
    int row_size = (width * 3 + 3) / 4 * 4;
    unsigned char *temp_data = (unsigned char *)malloc(row_size);

    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            temp_data[j * 3 + 2] = image_data[(i * width + j) * 3];
            temp_data[j * 3 + 1] = image_data[(i * width + j) * 3 + 1];
            temp_data[j * 3] = image_data[(i * width + j) * 3 + 2];
        }
        fwrite(temp_data, row_size, 1, fp);
    }

    free(temp_data);
    fclose(fp);
}

int main() {
    BITMAPFILEHEADER file_header;
    BITMAPINFOHEADER info_header;
    unsigned char image_data[256 * 256 * 3];

    read_bmp("3.bmp", image_data, &file_header, &info_header);

    int width = info_header.biWidth;
    int height = info_header.biHeight;
    int hist[256] = {0};
    for (int i = 0; i < width * height; i++) {
        hist[image_data[i * 3]]++;
    }
    int cum_hist[256] = {0};
    for (int i = 0; i < 256; i++) {
        cum_hist[i] = (i == 0) ? hist[i] : cum_hist[i - 1] + hist[i];
    }
    int map[256] = {0};
    for (int i = 0; i < 256; i++) {
        map[i] = (int)(255.0 * cum_hist[i] / (width * height) + 0.5);
    }
    for (int i = 0; i < width * height; i++) {
        image_data[i * 3] = map[image_data[i * 3]];
    }

    write_bmp("6.bmp", image_data, &file_header, &info_header);

    return 0;
}

本代码使用fread()和fwrite()函数进行文件读写,并通过对B分量的直方图均衡化,增强图像对比度,最终将均衡后的图像输出为6.bmp。

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

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

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