直方图均衡化
视频讲解如下:
当前系列所有demo下载地址:
https://github.com/GaoRenBao/OpenCv4-Demo
不同编程语言对应的OpenCv版本以及开发环境信息如下:
语言 | OpenCv版本 | IDE |
C# | OpenCvSharp4.4.8.0.20230708 | Visual Studio 2022 |
C++ | OpenCv-4.5.5-vc14_vc15 | Visual Studio 2022 |
Python | OpenCv-Python (4.6.0.66) | PyCharm Community Edition 2022.1.3 |
本章节给大家讲讲如何实现直方图均衡化。当前代码主体还是使用毛星云的demo,C#和Python都是在C++版本的基础上转换过来的,三个版本的效果基本一致。
首先我们需要准备一张测试图片:

三组代码运行效果都是一样的,我这里就不一一展示了,最终运行效果如下:

C#版本代码如下:
C#版本需要安装“OpenCvSharp4”、“OpenCvSharp4.runtime.win”两个库才行。不然会报错。
如果需要使用“ BitmapConverter.ToBitmap”操作,则需要追加安装“OpenCvSharp4.Extensions”库。
using OpenCvSharp;
namespace demo
{
internal class Program
{
static void Main(string[] args)
{
//【1】载入原始图
Mat srcImage = Cv2.ImRead("../../../images/Astral.jpg");
//【2】显示原始图
Cv2.CvtColor(srcImage, srcImage, ColorConversionCodes.BGR2GRAY);
Cv2.ImShow("【原始图】", srcImage);
// 【3】进行直方图均衡化
Mat dstImage = new Mat();
Cv2.EqualizeHist(srcImage, dstImage);
//【5】显示效果图
Cv2.ImShow("【C# 效果图】", dstImage);
Cv2.WaitKey(0);
}
}
}
C++版本代码如下:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
int main()
{
// 【1】加载源图像
Mat srcImage, dstImage;
srcImage = imread("../images/Astral.jpg");
if (!srcImage.data) {
printf("读取图片错误,请确定目录下是否有imread函数指定图片存在~! \n");
return false;
}
// 【2】转为灰度图并显示出来
cvtColor(srcImage, srcImage, COLOR_BGR2GRAY);
imshow("原始图", srcImage);
// 【3】进行直方图均衡化
equalizeHist(srcImage, dstImage);
// 【4】显示结果
imshow("经过直方图均衡化后的图", dstImage);
// 等待用户按键退出程序
waitKey(0);
return 0;
}
Python版本代码如下:
import cv2
import numpy as np
#【1】载入原始图
srcImage = cv2.imread("../images/Astral.jpg")
# 【2】转为灰度图并显示出来
srcImage=cv2.cvtColor(srcImage, cv2.COLOR_BGR2GRAY)
cv2.imshow("srcImage", srcImage)
#【3】进行直方图均衡化
dstImage = cv2.equalizeHist(srcImage);
#【4】显示效果图
cv2.imshow('dstImage',dstImage)
cv2.waitKey(0)
cv2.destroyAllWindows()
在python版本中,可以利用matplotlib来显示我们的直方图数据,以下demo的详细说明,请参考pdf
参考来源:OpenCV-Python-Tutorial-中文版.pdf(P130 直方图均化)
在线预览
运行效果:

import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('../images/home.jpg',0)
#flatten()
#将数组变成一维
hist,bins = np.histogram(img.flatten(),256,[0,256])
#计算累积分布图
cdf = hist.cumsum()
cdf_normalized = cdf * hist.max()/ cdf.max()
plt.plot(cdf_normalized, color = 'b')
plt.hist(img.flatten(),256,[0,256], color = 'r')
plt.xlim([0,256])
plt.legend(('cdf','histogram'), loc = 'upper left')
plt.show()
直方图均衡化经常用来使所有的图片具有相同的亮度条件的参考工具。这在很多情况下都很有用。例如,脸部识别,在训练分类器前,训练集的所有图片都要先进行直方图均衡化从而使它们达到相同的亮度条件。

import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('../images/home.jpg', 0)
# flatten() 将数组变成一维
hist, bins = np.histogram(img.flatten(), 256, [0, 256])
# 计算累积分布图
cdf = hist.cumsum()
##
# 构建 Numpy 掩模数组 cdf 为原数组 当数组元素为 0 时 掩盖(计算时被忽略
cdf_m = np.ma.masked_equal(cdf, 0)
cdf_m = (cdf_m - cdf_m.min()) * 255 / (cdf_m.max() - cdf_m.min())
# 对被掩盖的元素赋值,赋值为 0
cdf = np.ma.filled(cdf_m, 0).astype('uint8')
img2 = cdf[img]
# cv2.imshow("img2",img2)
# cv2.waitKey(0)
##
# flatten() 将数组变成一维
hist, bins = np.histogram(img2.flatten(), 256, [0, 256])
# 计算累积分布图
cdf = hist.cumsum()
cdf_normalized = cdf * hist.max() / cdf.max()
plt.plot(cdf_normalized, color='b')
plt.hist(img.flatten(), 256, [0, 256], color='r')
plt.xlim([0, 256])
plt.legend(('cdf', 'histogram'), loc='upper left')
plt.show()