c/c++ 彩色图像直方图均衡 RGB->HSI 对亮度分量I进行直方图均衡后HSI->RGB 得到结果图片不正确

Ice_zerocool 2020-06-04 01:33:15

#include<iostream>
#include <Windows.h>
#define _USE_MATH_DEFINES
#include<math.h>
#include<cstring>

using namespace std;


int main()
{

FILE* stream;
fopen_s(&stream,"C:\\Users\\zero\\Desktop\\test\\color1_1_1.bmp", "rb");
if (stream == NULL)
{
cout << "文件不存在" << endl;
return 0;
}

int sizeFileHeader = sizeof(BITMAPFILEHEADER);
int sizeInfoHeader = sizeof(BITMAPINFOHEADER);

BITMAPFILEHEADER* bitmapFileHeader = new BITMAPFILEHEADER[sizeFileHeader + 1];

BITMAPINFOHEADER* bitmapInfoHeader = new BITMAPINFOHEADER[sizeInfoHeader + 1];

memset(bitmapFileHeader, 0, sizeFileHeader + 1);
memset(bitmapInfoHeader, 0, sizeInfoHeader + 1);
fread(bitmapFileHeader, sizeof(char), sizeFileHeader, stream);
fseek(stream, sizeFileHeader, 0);
fread(bitmapInfoHeader, sizeof(char), sizeInfoHeader, stream);
int srcImageLineByteCount = (((bitmapInfoHeader->biWidth * 24) + 31) / 32) * 4;
fseek(stream, sizeFileHeader + sizeInfoHeader, 0);

int width = bitmapInfoHeader->biWidth;
int height = bitmapInfoHeader->biHeight;
//读取图像数据
int count = srcImageLineByteCount - bitmapInfoHeader->biWidth * (bitmapInfoHeader->biBitCount / 8);
BYTE* tempData = new BYTE[count];
BYTE*** oldImageData = new BYTE * *[bitmapInfoHeader->biHeight];
for (int i = 0;i < bitmapInfoHeader->biHeight;i++)
{
oldImageData[i] = new BYTE * [bitmapInfoHeader->biWidth];
for (int j = 0;j < bitmapInfoHeader->biWidth;j++)
{
oldImageData[i][j] = new BYTE[3];
for (int k = 0;k < 3;k++)
{
fread(&oldImageData[i][j][k], sizeof(BYTE), 1, stream);
}
}

for (int m = 0;m < count;m++)
{
fread(&tempData[m], sizeof(BYTE), 1, stream);
}
}


fclose(stream);

//得到数据


//***********************RGB->HSI*************************
double** HSIImageData_S = new double* [height];
int** HSIImageData_I = new int* [height];
double** HSIImageData_H = new double* [height];
for (int i = 0;i < height;i++)
{
HSIImageData_S[i] = new double[width];
memset(HSIImageData_S[i], 0, width);//初始化为0

HSIImageData_H[i] = new double[width];
memset(HSIImageData_H[i], 0, width);//初始化为0

HSIImageData_I[i] = new int[width];
memset(HSIImageData_I[i], 0, width);//初始化为0
}

for (int i = 0;i < height;i++) {
for (int j = 0;j < width;j++) {
double S;
double H;
int I;

//theta
//RGB归一化
double B = (double)oldImageData[i][j][0] / 255.0;
double G = (double)oldImageData[i][j][1] / 255.0;
double R = (double)oldImageData[i][j][2] / 255.0;

double numerator = 0.5 * ((R - G) + (R - B)); //theta的分子
double denominator = sqrt((R - G) * (R - G) + (R - B) * (G - B));//theta的分母

//Hue色调
//如果分母为0,即R=G=B
if (denominator == 0) {
H = 0;
}
else {
double theta = acos(numerator / denominator);
//acos:cos的反函数,定义域为:[-1,1],值域为[0,PI]

if (B <= G) H = theta;
else H = 2 * M_PI - theta;

}

//Intensity亮度
I = (int)((R + G + B) / 3 * 255);

//Saturation饱和度
if (I == 0) {
S = 0;
}
else {
S = 1 - (3.0 * min(min(R, G), B)) / (R + G + B);
}

//将转化得到的HSI存进数组
//H
HSIImageData_H[i][j] = H;
//S
HSIImageData_S[i][j] = S;
//I
HSIImageData_I[i][j] = I;
}
}

//************************对亮度分量Intensity进行直方图均衡************************

int gray_num[256] = { 0 }; //记录每个灰度级别下的像素个数
double gray_prob[256] = { 0 }; //记录灰度分布密度
double gray_dens_accum[256] = { 0 }; //记录累计密度
int gray_after[256] = { 0 }; //均衡化后的灰度值

int gray_sum = height * width; //像素总数x
//cout << gray_sum << endl;

//统计每个像数值的个数
for (int i = 0;i < height;i++) {
for (int j = 0;j < width;j++) {
int value = HSIImageData_I[i][j];
gray_num[value]++;
}
}

//统计每个灰度的密度
for (int i = 0;i < 256;i++) {
gray_prob[i] = (double)gray_num[i] / gray_sum;
}

//统计累计密度
gray_dens_accum[0] = gray_prob[0];
for (int i = 1; i < 256;i++) {
gray_dens_accum[i] = gray_dens_accum[i - 1] + gray_prob[i];
}

//计算均衡化后的灰度值
for (int i = 0;i < 256;i++) {
gray_after[i] = (UCHAR)255 * gray_dens_accum[i];
}


//根据均衡化后的灰度值得到新的位图数据
for (int i = 0;i < height;i++) {
for (int j = 0;j < width;j++) {
HSIImageData_I[i][j] = gray_after[HSIImageData_I[i][j]];

}
}

//HSI->RGB
BYTE*** RGBImageData = new BYTE * *[bitmapInfoHeader->biHeight];
for (int i = 0;i < height;i++) {
RGBImageData[i] = new BYTE * [bitmapInfoHeader->biWidth];
for (int j = 0;j < width;j++) {
RGBImageData[i][j] = new BYTE[3];
double Hue = HSIImageData_H[i][j];
double Saturation = HSIImageData_S[i][j];
int Intensity = HSIImageData_I[i][j];

//0<Hue<=120
if (Hue >= 0 && Hue <= 2 * M_PI / 3) {
//B=I(1-S)
RGBImageData[i][j][0] = Intensity * (1 - Saturation);

//R=I[1+S*cos(H)/cos(pi/3-H)]
RGBImageData[i][j][2] = Intensity * (1 + Saturation * cos(Hue) / cos(M_PI / 3 - Hue));

//G=3I-(R+B)
RGBImageData[i][j][1] = 3 * Intensity - (RGBImageData[i][j][0] + RGBImageData[i][j][2]);

}

//120<Hue<=240
if (Hue > 2 * M_PI / 3 && Hue <= 4 * M_PI / 3) {
Hue = Hue - 2 * M_PI / 3;
//R = I(1-S)
RGBImageData[i][j][2] = Intensity * (1 - Saturation);

//G=I[1+S*cos(H)/cos(pi/3-H)]
RGBImageData[i][j][1] = Intensity * (1 + Saturation * cos(Hue) / cos(M_PI / 3 - Hue));

//B=3I-(R+G)
RGBImageData[i][j][0] = 3 * Intensity - (RGBImageData[i][j][1] + RGBImageData[i][j][2]);

}

//240<Hue<=360
if (Hue > 4 * M_PI / 3 && Hue <= 2 * M_PI) {
Hue = Hue - 4 * M_PI / 3;
//G = I(1-S)
RGBImageData[i][j][1] = Intensity * (1 - Saturation);

//B=I[1+S*cos(H)/cos(pi/3-H)]
RGBImageData[i][j][0] = Intensity * (1 + Saturation * cos(Hue) / cos(M_PI / 3 - Hue));

//R=3I-(G+B)
RGBImageData[i][j][2] = 3 * Intensity - (RGBImageData[i][j][1] + RGBImageData[i][j][0]);

}
}
}







//写数据
FILE* fileWrite;
fopen_s(&fileWrite, "C:\\Users\\zero\\Desktop\\test.bmp", "wb");
fwrite(bitmapFileHeader, sizeof(char), sizeof(BITMAPFILEHEADER), fileWrite);
fwrite(bitmapInfoHeader, sizeof(char), sizeof(BITMAPINFOHEADER), fileWrite);
for (int i = 0;i < bitmapInfoHeader->biHeight;i++)
{
for (int j = 0;j < bitmapInfoHeader->biWidth;j++)
{
for (int k = 0;k < 3;k++)
{
fwrite(&RGBImageData[i][j][k], sizeof(BYTE), 1, fileWrite);
}

}
for (int s = 0;s < count;s++)
{
fwrite(&tempData[s], sizeof(BYTE), 1, fileWrite);
}

}
fclose(fileWrite);
//delete RGBImageData;
//delete oldImageData;

cout << "success" << endl;
}


结果
...全文
106 1 打赏 收藏 举报
写回复
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
Ice_zerocool 2020-06-04
  • 打赏
  • 举报
回复
请大家帮忙看看什么问题吧?已经弄好久了,快奔溃了
发帖
其它技术问题

3880

社区成员

C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
帖子事件
创建了帖子
2020-06-04 01:33
社区公告
暂无公告