图片用的是冈萨雷斯的《数字图像处理》里面的花粉图片,方便和标准答案对照。直方图均衡化全是用C语言实现的,画直方图用到了easyX,用了一点C++。
原花粉图和其灰度直方图:
均衡化后的图像和灰度直方图:
代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <math.h>
#include <graphics.h>
#include <conio.h>
#define _CRT_SECURE_NO_WARNINGS
#define width 500
#define height 500
int main()
{
BITMAPFILEHEADER bmpFileHeader;
BITMAPINFOHEADER bmpInfoHeader;
RGBQUAD bmpColorTable[256];
BYTE bmpValue[width * height];
FILE* fp;
//打开图像文件
fp = fopen("pollen.bmp", "rb");
if (fp == NULL)
{
printf("打开失败!\n");
return 0;
}
//读取图像信息
fread(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
fread(&bmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
fread(bmpColorTable, sizeof(RGBQUAD), 256, fp);
fread(bmpValue, 1, width * height, fp);
//将图像灰度值存入数组中
int grayValue[width * height] = { 0 };
for (int i = 0; i < width * height; i++)
{
grayValue[i] = bmpColorTable[bmpValue[i]].rgbBlue;
}
fclose(fp);
//统计直方图
int grayCount[256] = { 0 }; //灰度数量
double grayFrequency[256] = { 0.0 }; //灰度数量对应的频率
double graySum[256] = { 0.0 }; //灰度数量累计分布
int s[256] = { 0 };
for (int i = 0; i <width*height; i++)
{
grayCount[grayValue[i]]++;
}
for (int i = 0; i < 256; i++)
{
if (grayCount[i])
{
grayFrequency[i] = grayCount[i] / (500.0 * 500.0); //每个像素的累计概率
}
graySum[0] = grayFrequency[0]; //各灰度级累积分布
if (i != 0)
{
graySum[i] = graySum[i - 1] + grayFrequency[i];
}
printf("灰度值%3d 频数为%6d 频率为%f 累计频率为%f\n", i, grayCount[i], grayFrequency[i], graySum[i]);
}
//绘制原直方图,画布坐标与广义坐标是反的
initgraph(256, 256);
line(255, 0, 0, 0); //x轴
line(0, 255, 0, 0); //y轴
for (int i = 0; i < 256; i++)
{
line(i, 256 - grayCount[i] / 100, i,255 );
}
getch();
closegraph();
//均衡化之后的值
for (int i = 0; i < 256; i++)
{
s[i] = (int)(round((double)((256 - 1) * graySum[i])));
}
//映射
for (int i = 0; i < width * height; i++)
{
grayValue[i] = s[grayValue[i]];
}
//写入新图像
fp = fopen("output.bmp", "wb");
if (fp == NULL)
{
return 0;
}
fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
fwrite(&bmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
fwrite(bmpColorTable, sizeof(RGBQUAD), 256, fp);
for (int i = 0; i < width * height; i++)
{
fwrite(&grayValue[i], 1, 1, fp);
}
fclose(fp);
//画新图像的直方图
fp = fopen("output.bmp", "rb");
fread(bmpColorTable, sizeof(RGBQUAD), 256, fp);
fread(bmpValue, 1, width * height, fp);
for (int i = 0; i < width * height; i++)
{
grayValue[i] = 0;
}
for (int i = 0; i < 256; i++)
{
grayCount[i] = 0;
}
for (int i = 0; i < width * height; i++)
{
grayValue[i] = bmpColorTable[bmpValue[i]].rgbBlue;
}
fclose(fp);
for (int i = 0; i < width * height; i++)
{
grayCount[grayValue[i]]++;
}
initgraph(256, 256);
line(255, 0, 0, 0); //x轴
line(0, 255, 0, 0); //y轴
for (int i = 0; i < 256; i++)
{
line(i, 256 - grayCount[i] / 100, i, 255);
}
getch();
closegraph();
return 0;
}