直方图均衡化
如果一个图像的直方图都集中在一个区域,那么整体图像的对比度偏小,不便于图像中纹理的识别。通过映射关系,将图像中的灰度值范围扩大,增加原来两个灰度值之间的差值,就可以提高图像的对比度,进而将图像中的纹理显现出来,这个过程称为图像直方图均衡化。
equalizeHist()函数原型
void cv::equalizeHist(InputArray src, OutputArray dst)
函数功能:对单通道的灰度图进行直方图均衡化。
参数说明:
src:输入的CV_8UC1图像
dst:直方图均衡化后的输出图像
函数原理
直方图均衡化(Histogram Equalization) 又称直方图平坦化,实质上是对图像进行非线性拉伸,重新分配图像象元值,使一定灰度范围内象元值的数量大致相等。这样,原来直方图中间的峰顶部分对比度得到增强,而两侧的谷底部分对比度降低,输出图像的直方图是一个较平的分段直方图:如果输出数据分段值较小的话,会产生粗略分类的视觉效果。
示例程序
该示例程序为OpenCV 4书中的源码,该程序对一个对比度小的齿轮图片进行直方图均衡化,输出了一个对比度提高的图片。
程序代码
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
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<float>(i - 1)) - 1),
Scalar(255, 255, 255), -1);
}
imshow(name, histImage);
}
int main()
{
Mat img = imread("E:/Image/gearwheel.png");
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("原图", img);
imshow("均衡化后的图像", equalImg);
waitKey(0);
return 0;
}
运行结果
声明
本文为学习笔记,内容来源于网络和课本。