- 操作系统:手机安装 Termux ,Termux 内安装 ubuntu
- Termux 0.119.0-beta.3
- 内嵌 ubuntu 24.04
- 编译器:GNU g++ 14.2.0
- 编辑器:Emacs 29.3
- OpenCV:4.13.0
目标
- 什么是图像直方图以及为什么它有用
- 使用 OpenCV 函数 cv::equalizeHist 均衡图像的直方图
理论
什么是图像直方图
- 它是图像强度分布的图形表示。
- 它量化了所考虑的每个强度值的像素数

什么是均衡直方图
- 这是一种提高图像对比度的方法,以扩大强度范围
- 为了更清楚起见,从上图中,您可以看到像素似乎聚集在可用强度范围的中间。直方图均衡的作用是扩大这个范围。看看下图:绿色圆圈表示人口不足的强度。应用均衡后,我们得到一个直方图,如中心的图形。生成的图像如右图所示:

它是如何工作的
- 均衡意味着将一个分布(给定的直方图)映射到另一个分布(更广泛、更均匀的强度值分布),以便强度值分布在整个范围内
- 为了实现均衡效果,重映射应该是累积分布函数(cdf)。对于直方图 H(i)H(i)H(i) ,其累积分布 H′(i)H^{'}(i)H′(i) 是:
H′(i)=∑0≤j<iH(j)
H^{'}(i) = \sum_{0 \le j < i} H(j)
H′(i)=0≤j<i∑H(j) - 最后,我们使用简单的重映射过程来获取均衡图像的强度值:
equalized(x,y)=H′(src(x,y))
equalized( x, y ) = H^{'}( src(x,y) )
equalized(x,y)=H′(src(x,y))
源代码
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
CommandLineParser parser( argc, argv, "{@input | lena.jpg | input image}" );
Mat src = imread( samples::findFile( parser.get<String>( "@input" ) ), IMREAD_COLOR );
if( src.empty() )
{
cout << "Could not open or find the image!\n" << endl;
cout << "Usage: " << argv[0] << " <Input image>" << endl;
return -1;
}
cvtColor( src, src, COLOR_BGR2GRAY );
Mat dst;
equalizeHist( src, dst );
imshow( "Source image", src );
imshow( "Equalized Image", dst );
waitKey();
return 0;
}
解释说明
- 加载图像
``cpp
CommandLineParser parser( argc, argv, “{@input | lena.jpg | input image}” );
Mat src = imread( samples::findFile( parser.get( “@input” ) ), IMREAD_COLOR );
if( src.empty() )
{
cout << “Could not open or find the image!\n” << endl;
cout << “Usage: " << argv[0] << " ” << endl;
return -1;
}
- 将其转换为灰度
cvtColor( src, src, COLOR_BGR2GRAY );
- 使用函数 cv::equalizeHist 应用直方图均衡:
Mat dst;
equalizeHist( src, dst );
- 显示原始图像和均衡图像
imshow( "Source image", src );
imshow( "Equalized Image", dst );
- 等待用户退出程序
waitKey();
结果
- 对比度不高的原图:

- 使用上面的程序后:
