- 1. 学习如何在你的电脑上配置OpenCV-Python环境!
- 1.1 开始了解OpenCV-Python
- 1.2 在 Windows 下安装 OpenCV-Python
- 1.3 在 Fedora 环境下安装 OpenCV-Python
- 1.4 在 Debian(Ubuntu)中配置 OpenCV-Python
- 1.5 在Docker中安装OpenCV-Python
- 1.6 在树莓派配置OpenCV-Python
- 2. OpenCV中的GUI功能
- 2.1 开始使用图像
- 2.2 开始使用视频
- 2.3 OpenCV 中的绘图函数
- 2.4 以鼠标为画笔
- 2.5 用滑块控制条做调色板
- 3. OpenCV中的GUI功能
- 3.1 图片基本操作
- 3.2 图像算术操作
- 3.3 性能评估与改进技巧
- 4. OpenCV中的图像处理
- 4.1 更换颜色空间
- 4.2 对图像进行几何变换
- 4.3 图像二值化处理
- 4.4 平滑图像
- 4.5 形态学转换
- 4.6 图像梯度
- 4.7 Canny边缘检测
- 4.8 图像金字塔
- 4.9.1 直方图:查找,绘制,分析
- 4.9.2 直方图均衡化
- 4.9.3 二维直方图
- 4.9.4 直方图反投影
- 4.10 OpenCV中的图像变换
- 4.10.1 傅立叶变换
- 4.11 模板匹配
- 4.12 霍夫直线变换
- 4.13 霍夫圆变换
- 4.14 基于分水岭算法的图像分割
- 4.14 使用 GrabCut 算法交互式前景提取
- 5. 特征检测和描述符
- 5.1 理解特征
- 5.2 Harris 角点检测
- 5.3 Shi-Tomasi 角点检测 & 适合用来跟踪的特征
- 5.4 介绍SIFT(尺度不变特征转换)
- 5.5 介绍SURF(加速稳健特征)
- 5.6 角点检测的FAST算法
- 5.7 BRIEF特征点描述算法
- 5.8 ORB 特征描述符(Oriented FAST and Rotated BRIEF)
- 5.9 特征匹配
- 5.10 特征匹配和使用单应性匹配来搜索物体
- 6. 视频分析
- 6.1 Meanshift和Camshift
- 6.2 光流
- 6.3 背景分割
- 7. 相机校准和3D重建
- 7.1 相机校准
- 7.2 姿势估计
- 7.3 极线几何
- 7.4 来自立体图像的深度图
- 8. 机器学习
- 8.1 K-最近邻算法
- 8.1.1 了解k-最近邻算法
- 8.1.2 使用kNN进行手写字符的OCR
- 8.2 支持向量机(SVM)
- 8.2.1 理解SVM
- 8.2.2 使用SVM的手写数据的OCR
- 8.3 K-Means聚类
- 8.3.1 理解 K-Means 聚类
- 8.3.2 OpenCV中的K-Means聚类
- 9. 计算摄影学
- 9.1 图像去噪
- 9.2 图像修复
- 9.3 高动态范围(HDR)
- 10. 目标检测
- 10.1 使用 Haar Cascades 的面部识别
- 11. OpenCV-Python 绑定
- 11.1 OpenCV-Python绑定如何工作?
4.9.2 直方图均衡化
目标
- 我们将学习直方图均衡的概念,并用它来改善我们的图片对比度。
理论基础
考虑像素值仅限于某个特定值范围的图像。例如,较亮的图像将所有像素限制在较高的值。但是一张好的图像将会具有来自图像所有区域的像素。所以你需要将这个直方图拉伸到两端,用简单的话来说,这就是直方图均衡化所能做到的。这通常会改善图像的对比度。
我建议你阅读关于直方图均衡化的维基百科页面,了解更多细节。它解释的很好而且有相当好的例子,所以在阅读完后你几乎可以理解所有有关于此的东西。在这里我们将看到它的Numpy实现。之后,我们将看到OpenCV函数。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('wiki.jpg',0)
hist,bins = np.histogram(img.flatten(),256,[0,256])
cdf = hist.cumsum()
cdf_normalized = cdf * float(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()
你可以看到直方图集中在在更明亮的区域。我们需要更为平均的直方图。为此,我们需要一个转换函数,将输入像素在较亮的区域映射到全区域的输出像素。这就是直方图均衡化。
现在我们找到最小的直方图值(不包括0),并应用wiki页面中给出的直方图均衡方程。但是我在这里使用了来自Numpy的mask数组的概念。对于mask数组,所有操作都在没有被mask掉的元素上执行。你可以从Numpy文档中的masked数组读到更多相关的知识。
cdf_m = np.ma.masked_equal(cdf,0)
cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())
cdf = np.ma.filled(cdf_m,0).astype('uint8')
现在我们有了一个查找表,它给出了关于每个输入像素值的输出像素值的信息。所以我们只是应用转换。
img2 = cdf[img]
现在我们像以前一样计算它的直方图和 cdf(你来做)。
另一个重要的特征是,即使图像是一个较暗的图像(而不是一个像我们使用的这张一样的更亮的图像),均衡后,我们将得到几乎相同的图像,就像我们现在得到这张一样。因此,这被用作“参考工具”来使所有图像具有相同的照明条件。这在许多情况下是有用的。例如,在人脸识别中,在用人脸识别数据训练模型之前,需要对人脸图像进行直方图均衡化处理,使其全部具有相同的照明条件。
OpenCV 中的直方图均衡化
OpenCV有一个函数来做到这一点,cv2.equalizeHist()
。它的输入只是灰度图像,输出是直方图均衡过的图像。
下面是一个简单的代码片段,显示了我们使用的相同图片时的处理方法:
img = cv2.imread('wiki.jpg',0)
equ = cv2.equalizeHist(img)
res = np.hstack((img,equ)) # 将图像拼起来
cv2.imwrite('res.png',res)
所以现在你可以在不同的光照条件下拍摄不同的图像,均衡它并检查结果。
当图像的直方图被限制在特定的区域时,直方图均衡是很好的。在直方图覆盖较大的区域,强度变化较大的地方,即同时存在明亮和暗淡的像素的情况下,这种方法将不会奏效。请查看更多资源中的SOF链接。
CLAHE(限制对比度的自适应直方图均衡)
我们刚刚看到了第一个直方图均衡算法,它只考虑了图像的全局对比度。在很多情况下,这不是一个好主意。
在直方图均衡之后,背景对比度已经得到改善。但是比较两幅图像中的雕像的面貌。由于亮度过高,我们丢失了大部分的信息。这是因为它的直方图并不像我们在前面的例子中看到的那样局限于特定的区域(试试看绘制出输入图像的直方图,你会了解更多)。
所以为了解决这个问题,我们要使用自适应直方图均衡。在这里,图像被分成称为“tiles”的小块(在OpenCV中tileSize默认为8x8)。然后每个块都像平常一样进行直方图均衡。所以直方图均衡会局限于一个小区域(除非有噪音)。如果有噪音,它会被放大。为了避免这种情况,需要应用对比度限制。如果任何直方图的面元超过了指定的对比度限制(在OpenCV中默认为40),那么在应用直方图均衡之前,这些像素将被裁切并均匀分配到其他面元。均衡之后,为了去除tiles边界中的伪影(artifacts),我们使用了双线性插值。
下面的代码片段显示了如何在OpenCV中应用CLAHE:
import numpy as np
import cv2
img = cv2.imread('tsukuba_l.png',0)
# 创建一个 CLAHE 对象 (参数是可选的)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(img)
cv2.imwrite('clahe_2.jpg',cl1)
更多资源
- 直方图均衡化的 维基百科页面
- Numpy 中的 Masked Arrays
还可以看看这些 Stackoverflow 上的有关对比度调整的问题:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论