图片的直方图均衡化
程序员文章站
2022-04-30 13:52:40
...
功能,实现图片的直方图均衡化
左上为原图灰度化,右上为原图的直方图
左下为均衡化后的图,右下为均衡化后的直方图
总结:感觉聊过不怎么样。。。
int main()
{
int *arr = new int[256]();
Mat image = imread("D:/Code/C++/Practice/Pronucination/test/123.jpg");
Mat shuzu1,shuzu2;
cout << image.channels() << endl;
cout << "row = " << image.rows << ";col = " << image.cols << endl;
image = gray_image(image);
Histogram_array(image, arr);
shuzu1 = drawHist(image, arr);
Mat image2 = Equalization(image, arr);
Histogram_array(image2, arr);
shuzu2 = drawHist(image2, arr);
Mat img = Merge_image(image, shuzu1, image2, shuzu2);
img = Change_Size(img, 540, 960);
imshow("图像", img);
waitKey();
return 0;
}
//输入灰度图原图像
//输出一个直方图数组
void Histogram_array(Mat img,int* pixel_value)
{
int i, j;
uchar* data;
int value1;
//int *pixel_value = new int[256]();
if (img.channels() == 1)
{
for (i = 0; i < img.rows; ++i)
{
data = img.ptr<uchar>(i);
for (j = 0; j < img.cols; ++j)
{
value1 = data[j];
pixel_value[value1]++;//记录每个像素值的个数
}
}
}
}
//输入:一张图片,主要是获取图像的行列
//输出:一个直方图
Mat drawHist(Mat img,int *arr)
{
int i,j,k;
int value = 0;
uchar* data;
int row = img.rows,col = img.cols;
Mat picture(row, col, CV_8UC1); // 新建画布
int MaxCount = Max_Number(arr,256);//寻找在处于某一灰度级中个数最多的像素个数
double yscaleRate = double(row) / MaxCount;//y缩放比例
double xscaleRate = col / 256;//x缩放比例
int yAxis[256];
for (int i = 0; i < 256; i++)
yAxis[i] = int(arr[i] * yscaleRate);
//绘制直方图
for (i = 0; i < picture.rows; ++i)
{
data = picture.ptr<uchar>(i);
for (j = 0; j < 256; ++j)
{
if (yAxis[j] > 0)
{
for (k = 0; k < xscaleRate; ++k)
{
value = value = j * xscaleRate + k;
data[value] = 255;
}
yAxis[j]--;
}
else
{
for (k = 0; k < xscaleRate; ++k)
{
value = value = j * xscaleRate + k;
data[value] = 0;
}
}
}
}
return picture;
}
//直方图均衡化
//输入:原图像,直方图数组
//输出:均衡化后的图像
Mat Equalization(Mat img, int* arr)
{
int row = img.rows;
int col = img.cols;
int i,j,sum = 0;
int t1 = 0, t2 = 0;
float error1 = 0, error2 = 0;
int t = 0;
uchar* data;
float *ret = new float[256]();
//计算概率并累计概率
for (i = 0; i < 256; ++i)
{
if (arr[i] > 0)
sum++;
ret[i] = (arr[i] * 1.0) / (row * col * 1.0);
if (i == 0)
continue;
else
ret[i] = ret[i] + ret[i - 1];
}
//乘上灰度个数
for (i = 0; i < 256; ++i)
{
t1 = (int)(ret[i] * sum);//下取整
t2 = t1+1;//上取整
error1 = ret[i] * sum - t1;
error2 = t2 - ret[i] * sum;
if (error1 > error2)
ret[i] = t2;
else
ret[i] = t1;
}
//更改原图像
for (i = 0; i < row; ++i)
{
data = img.ptr<uchar>(i);
for (j = 0; j < col; ++j)
{
t = data[j];
t = ret[t];
data[j] = t;
}
}
return img;
}
//输入各个尺寸的图像
//输出,将4个图像拼接起来
Mat Merge_image(Mat img, Mat img1, Mat img2, Mat img3)
{
int row = img.rows, col = img.cols;
Mat result(row, col, CV_8UC1);
//改变每个图片的尺寸
img = Change_Size(img, row / 2, col / 2);
img1 = Change_Size(img1, row / 2, col / 2);
img2 = Change_Size(img2, row / 2, col / 2);
img3 = Change_Size(img3, row / 2, col / 2);
//把每个改变尺寸后的图像拼接起来
int i, j;
int t = 0;
uchar* ret;
uchar* data, * data1, * data2, * data3;
for (i = 0; i < row; ++i)
{
ret = result.ptr<uchar>(i);
for(j = 0;j < col; ++j)
{
//上
if(i < row/2)
{
//左
if (j < col/2)
{
data = img.ptr<uchar>(i);
ret[j] = data[j];
}
//右
else
{
data1 = img1.ptr<uchar>(i);
ret[j] = data1[j - col/2];
}
}
//下
else
{
t = i - row/2;
//左
if (j < col / 2)
{
data2 = img2.ptr<uchar>(t);
ret[j] = data2[j];
}
//右
else
{
data3 = img3.ptr<uchar>(t);
ret[j] = data3[j - col/2];
}
}
}
}
return result;
}
参考博客:https://blog.csdn.net/schwein_van/article/details/84336633
推荐阅读