直方图均衡
图像的直方图是像素强度分布的图形表示。它可以估算像素值集中的位置以及是否存在异常偏差。例如 - 考虑以下图像。比如,所有像素值都具有2位的深度并且是无符号的。因此,像素的允许值范围是0-3。
正如您在上图中所看到的,有5个像素值0,7个像素值1,9个像素值2和4个像素值3。这些信息列表如下。
例图
图像的直方图通常以图形的形式呈现。下图表示上图的直方图。
统计分布图
直方图均衡化是图像处理中常用的技术,通过均衡强度分布来增强图像的对比度。它会使暗图像(曝光不足)不那么暗,而明亮图像(曝光过度)则不那么明亮。 上图的均衡直方图应理想地如下图所示。
直方图
但实际上,很难实现这种完美的直方图均衡。 然而,有各种技术来实现接近完美的直方图均衡。 在OpenCV中,有一个内置函数来均衡直方图。
理想的直方图
使用OpenCV对灰度图像进行直方图均衡
下面是演示如何使用OpenCV内置函数均衡灰度图像直方图的示例程序。#include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main(int argc, char** argv) { //读取图像 Mat image = imread("fly-agaric.jpg"); //检测失败 if (image.empty()) { cout << "Could not open or find the image" << endl; cin.get(); //等待键盘 return -1; } //转换成灰度图 cvtColor(image, image, COLOR_BGR2GRAY); //直方图均衡化 Mat hist_equalized_image; equalizeHist(image, hist_equalized_image); //创建窗口 namedWindow("Original", WINDOW_NORMAL); namedWindow("HistogramEqualized", WINDOW_NORMAL); //显示图像 imshow("Original", image); imshow("HistogramEqualized", hist_equalized_image); waitKey(0); //等待键盘 destroyAllWindows(); //毁灭世界 return 0; }将上面的代码段复制并粘贴到IDE中并运行它。请注意必须在代码中将“fly-agaric.jpg”替换为计算机中图像的有效位置。然后你应该看到如下图所示的2张图像。
灰度图的直方图均衡化
使用OpenCV对彩色图像进行直方图均衡
在这个例子中,我将向你展示如何使用简单的OpenCV程序均衡彩色图像的直方图。#include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace std; int main(int argc, char** argv) { //读取图像 Mat image = imread("fly-agaric.jpg"); //检测失败 if (image.empty()) { cout << "Could not open or find the image" << endl; cin.get(); //等待键盘 return -1; } //从BGR转换成YCrCb颜色空间 Mat hist_equalized_image; cvtColor(image, hist_equalized_image, COLOR_BGR2YCrCb); //把图像3个通道分割出来; Y、Cr和Cb通道各别存在一个std::vector中 vector<Mat> vec_channels; split(hist_equalized_image, vec_channels); //只对Y通道进行直方图均衡化 equalizeHist(vec_channels[0], vec_channels[0]); //重新合拼图像(YCrCB) merge(vec_channels, hist_equalized_image); //转换回BGR图像 cvtColor(hist_equalized_image, hist_equalized_image, COLOR_YCrCb2BGR); //创建窗口 namedWindow("Original", WINDOW_NORMAL); namedWindow("HistogramEqualized", WINDOW_NORMAL); //显示图像 imshow("Original", image); imshow("HistogramEqualized", hist_equalized_image); waitKey(0); //等待键盘 destroyAllWindows(); //毁灭 return 0; }将上面的代码段复制并粘贴到IDE中并运行它。请注意必须在代码中将“fly-agaric.jpg”替换为计算机中图像的有效位置。然后你应该看到如下图所示的2张图像。
彩色图像的直方图均衡
说明
OpenCV使用BGR颜色空间加载彩色图像。利用该颜色空间,不可能在不影响颜色信息的情况下均衡直方图,因为所有3个通道都包含颜色信息。因此,你必须将BGR图像转换为像YCrCb这样的颜色空间。在YCrCb颜色空间中,图像的Y通道仅包含强度信息,其中Cr和Cb通道包含图像的所有颜色信息。因此,只应处理Y通道以获得直方图均衡图像而不改变任何颜色信息。处理完毕后,在调用imshow()函数之前,应将YCrCb图像转换回BGR颜色空间。Mat hist_equalized_image; cvtColor(image, hist_equalized_image, COLOR_BGR2YCrCb);加载的图像是BGR颜色空间。由于所有通道都包含颜色信息,因此无法处理此颜色空间的3个通道(蓝色,绿色和红色)以均衡直方图。因此,加载的图像应转换为YCrCb颜色空间。在该颜色空间中,Y通道仅包含强度信息,而Cr和Cb通道包含颜色信息。因此,仅需要处理Y通道以均衡直方图。
vector<Mat> vec_channels; split(hist_equalized_image, vec_channels);上述OpenCV函数将3通道图像分成3个独立的矩阵。每个矩阵都被推送到std::vector。vec_channels[0]包含Y通道,vec_channels[1]包含Cr通道,vec_channels[2]包含Cb通道。
equalizeHist(vec_channels[0], vec_channels[0]);上述函数均衡了Y通道的直方图。
merge(vec_channels, hist_equalized_image);merge是split的相反,他把存有3个通道信息的std::vector合拼成一个cv::Mat