本节将介绍如何根据图像的直方图对图像的亮度进行调整。也就是均衡化。
通过图像直方图,我们可以判断图像是否过暗或过亮,当图像直方图过多的集中在灰度值较小的区域时,那么它所表示的是图像存在过暗的情况,反之过亮。就会导致图像中的纹理信息没办法很好的显示。
例如我想拉大较小值的灰度值区域,那么我们可以将较小值的灰度值区域斜率调大(改变x与y的映射关系,比如幂函数的形式)。
vodi cv::equalizeHist(InputArray src,
OutputArray dst
)
·src:需要直方图均衡化的CV_8UC1图像(只有处理单通道图像才涉及到均衡化,若是彩色图像,要先转化为灰度图像)。
·dst:直方图均衡化后输出图像,与src具有相同尺寸和数据类型。
#include
#include
using namespace cv; //opencv的命名空间
using namespace std;
void drawHist(Mat &hist, int type, string name)//归一化并绘制直方图函数
{
int hist_w = 512;
int hist_h = 400;
int width = 2;
Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);
normalize(hist, hist, 1, 0, type, -1, Mat());
for (int i = 1; i <= hist.rows; i++)
{
rectangle(histImage, Point(width * (i - 1), hist_h - 1),
Point(width * i - 1, hist_h - cvRound(hist_h * hist.at(i - 1)) - 1),
Scalar(255, 255, 255), -1);
}
imshow(name, histImage);
}
//主函数
int main()
{
Mat img = imread("E:/opencv/opencv-4.6.0-vc14_vc15/opencv/xyp.jpg");
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
Mat gray,hist,hist2;
cvtColor(img, gray, COLOR_BGR2GRAY); //转为灰度图像,只有一个通道
Mat equalimg;
equalizeHist(gray, equalimg);//将图像直方图均衡化
const int channels[1] = { 0 };
float inRanges[2] = { 0,255 };
const float* ranges[1] = { inRanges };
const int bins[1] = { 256 };
calcHist(&gray, 1, channels, Mat(), hist, 1, bins, ranges);//计算原图像直方图
calcHist(&equalimg, 1, channels, Mat(), hist2, 1, bins, ranges);//计算均衡化后图像直方图
//绘制直方图
drawHist(hist, NORM_INF, "hist");
drawHist(hist2, NORM_INF, "hist2");
imshow("原图", gray);
imshow("均衡化后的图像",equalimg);
waitKey(0);//等待函数用于显示图像
return 0;
}
均衡化后的图像能够较为清晰的看到原先图像中所不能看清的纹理,很好的提高了图像的纹理展示,也能够让我们更好的了解图像中的信息,均衡化后的直方图分布将最大值分布更多的集中在中心区域。