直方图均衡化优势:
增强图像对比度,使对比度较低的局部区域获得高对比度。当图像非常暗或者非常亮,并且背景和前景之间的差异非常小时,此方法非常有效,能够解决暴露过度或暴露不足的问题。
直方图均衡化缺陷:
背景噪声增强、有用信息减少,同时在增加图像对比度时,直方图会发生变化和扩散。
代码:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
class QuickDemo
{
public:
void hist_cal_equalize(Mat &image);
Mat norm(Mat &image);
};
Mat QuickDemo::norm(Mat &image)
{
vector<Mat> bgr_planes;
// 将三通道图像划分成单通道图像
split(image, bgr_planes);
int histSize = 256;
float range[] = { 0, 256 };
const float *histRanges = { range };
Mat b_hist, g_hist, r_hist;
// 统计单通道图像直方图
calcHist(&bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRanges, true, false);
calcHist(&bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRanges, true, false);
calcHist(&bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRanges, true, false);
// 直方图高和宽
int hist_h = 400;
int hist_w = 512;
int bin_w = hist_w / histSize;
Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));
normalize(b_hist, b_hist, 0, hist_h, NORM_MINMAX, -1, Mat()); // 归一化到(0, hist_h)
normalize(g_hist, g_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
normalize(r_hist, r_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
// 绘制直方图
for (int i = 1; i < histSize; i++)
{
line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(b_hist.at<float>(i - 1))),
Point((i)*bin_w, hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 1, LINE_AA);
line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(g_hist.at<float>(i - 1))),
Point((i)*bin_w, hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 1, LINE_AA);
line(histImage, Point((i - 1) * bin_w, hist_h - cvRound(r_hist.at<float>(i - 1))),
Point((i)*bin_w, hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 1, LINE_AA);
}
return histImage;
}
void QuickDemo::hist_cal_equalize(Mat &image)
{
imshow("input", image);
Mat hist_src, hist_dst;
hist_src = norm(image);
imshow("hist_src", hist_src);
Mat img;
image.copyTo(img);
cvtColor(img, img, COLOR_BGR2YCrCb);
vector<Mat> channel;
split(img, channel);
// 直方图均衡化,该函数只能处理单通道图像
equalizeHist(channel[0], channel[0]);
merge(channel, img);
cvtColor(img, img, COLOR_YCrCb2BGR);
imshow("output", img);
hist_dst = norm(img);
imshow("hist_dst", hist_dst);
}
int main()
{
Mat image = imread("D:\\c++_opencv\\images\\0--Parade_0_Parade_marchingband_1_20.jpg", IMREAD_ANYCOLOR);
QuickDemo qd;
qd.hist_cal_equalize(image);
waitKey(0);
destroyAllWindows();
return 0;
}
结果: