对彩色图像进行直方图均衡化c语言
时间: 2023-10-26 08:05:16 浏览: 166
以下是对彩色图像进行直方图均衡化的 C 语言代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
typedef struct {
unsigned char r;
unsigned char g;
unsigned char b;
} RGB;
RGB *readBMP(char *filename, int *width, int *height);
void writeBMP(char *filename, RGB *image, int width, int height);
int *histogram(RGB *image, int width, int height, int channel);
void cumulativeHistogram(int *hist, int size);
void equalizeHistogram(RGB *image, int width, int height, int channel, int *hist, int size, int maxVal);
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s <input file>\n", argv[0]);
return 1;
}
char *inputFile = argv[1];
char *outputFile = "output.bmp";
int width, height;
RGB *image = readBMP(inputFile, &width, &height);
int *redHist = histogram(image, width, height, 0);
int *greenHist = histogram(image, width, height, 1);
int *blueHist = histogram(image, width, height, 2);
cumulativeHistogram(redHist, 256);
cumulativeHistogram(greenHist, 256);
cumulativeHistogram(blueHist, 256);
equalizeHistogram(image, width, height, 0, redHist, 256, 255);
equalizeHistogram(image, width, height, 1, greenHist, 256, 255);
equalizeHistogram(image, width, height, 2, blueHist, 256, 255);
writeBMP(outputFile, image, width, height);
free(image);
free(redHist);
free(greenHist);
free(blueHist);
return 0;
}
RGB *readBMP(char *filename, int *width, int *height) {
FILE *file = fopen(filename, "rb");
if (file == NULL) {
printf("Error: could not open %s\n", filename);
exit(1);
}
unsigned char header[54];
fread(header, sizeof(unsigned char), 54, file);
int dataOffset = header[10] + header[11] * 256 + header[12] * 256 * 256 + header[13] * 256 * 256 * 256;
*width = header[18] + header[19] * 256 + header[20] * 256 * 256 + header[21] * 256 * 256 * 256;
*height = header[22] + header[23] * 256 + header[24] * 256 * 256 + header[25] * 256 * 256 * 256;
int padding = (*width % 4 == 0) ? 0 : 4 - (*width % 4);
int size = (*width + padding) * *height * sizeof(RGB);
RGB *image = (RGB *) malloc(size);
fseek(file, dataOffset, SEEK_SET);
fread(image, sizeof(RGB), *width * *height, file);
fclose(file);
return image;
}
void writeBMP(char *filename, RGB *image, int width, int height) {
FILE *file = fopen(filename, "wb");
if (file == NULL) {
printf("Error: could not open %s\n", filename);
exit(1);
}
unsigned char header[54] = {
0x42, 0x4d, 0x36, 0x8a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x8a, 0x01, 0x00, 0x13, 0x0b,
0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
int padding = (width % 4 == 0) ? 0 : 4 - (width % 4);
int size = (width + padding) * height * sizeof(RGB);
header[2] = (unsigned char) (size & 0xff);
header[3] = (unsigned char) ((size >> 8) & 0xff);
header[4] = (unsigned char) ((size >> 16) & 0xff);
header[5] = (unsigned char) ((size >> 24) & 0xff);
header[18] = (unsigned char) (width & 0xff);
header[19] = (unsigned char) ((width >> 8) & 0xff);
header[20] = (unsigned char) ((width >> 16) & 0xff);
header[21] = (unsigned char) ((width >> 24) & 0xff);
header[22] = (unsigned char) (height & 0xff);
header[23] = (unsigned char) ((height >> 8) & 0xff);
header[24] = (unsigned char) ((height >> 16) & 0xff);
header[25] = (unsigned char) ((height >> 24) & 0xff);
fwrite(header, sizeof(unsigned char), 54, file);
RGB *row = (RGB *) malloc(width * sizeof(RGB));
unsigned char *pad = (unsigned char *) calloc(padding, sizeof(unsigned char));
for (int i = height - 1; i >= 0; i--) {
memcpy(row, &image[i * width], width * sizeof(RGB));
fwrite(row, sizeof(RGB), width, file);
fwrite(pad, sizeof(unsigned char), padding, file);
}
free(row);
free(pad);
fclose(file);
}
int *histogram(RGB *image, int width, int height, int channel) {
int *hist = (int *) calloc(256, sizeof(int));
for (int i = 0; i < width * height; i++) {
if (channel == 0) hist[image[i].r]++;
if (channel == 1) hist[image[i].g]++;
if (channel == 2) hist[image[i].b]++;
}
return hist;
}
void cumulativeHistogram(int *hist, int size) {
for (int i = 1; i < size; i++) {
hist[i] += hist[i - 1];
}
}
void equalizeHistogram(RGB *image, int width, int height, int channel, int *hist, int size, int maxVal) {
double factor = (double) maxVal / (width * height);
for (int i = 0; i < width * height; i++) {
if (channel == 0) {
image[i].r = (unsigned char) round(hist[image[i].r] * factor);
} else if (channel == 1) {
image[i].g = (unsigned char) round(hist[image[i].g] * factor);
} else if (channel == 2) {
image[i].b = (unsigned char) round(hist[image[i].b] * factor);
}
}
}
```
代码使用了 BMP 文件格式,需要 `readBMP` 和 `writeBMP` 函数来读写 BMP 文件。`histogram` 函数计算给定通道的像素值的直方图,`cumulativeHistogram` 函数计算累积直方图,`equalizeHistogram` 函数将像素值映射到均衡化的像素值。在 `main` 函数中,首先读入 BMP 文件,然后对每个通道进行直方图均衡化,最后将均衡化后的图像写入 BMP 文件。
需要注意的是,在直方图均衡化中,我们需要使用累积直方图来计算像素值的映射,然后将像素值映射到新的像素值。由于彩色图像有三个通道,因此需要分别对三个通道进行直方图均衡化,然后将三个通道的均衡化结果合并成新的彩色图像。
阅读全文