本期将使用图像直方图的相关知识来提高图像对比度,对图像进行优化,从而提高图像清晰度。
完成本期内容,你可以:
- 了解图像直方图的定义和计算方法
- 了解直方图均衡化的原理
- 学会使用直方图均衡化优化图像
若要运行案例代码,你需要有:
-
操作系统:Ubuntu 16 以上 或者 Windows10
-
工具软件:VScode 或者其他源码编辑器
-
硬件环境:无特殊要求
-
核心库:python 3.6.13, opencv-contrib-python 3.4.11.39,opencv-python 3.4.2.16
图像直方图
图像直方图是用一表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数。可以借助观察该直方图了解需要如何调整亮度分布的直方图。这种直方图中,横坐标的左侧为纯黑、较暗的区域,而右侧为较亮、纯白的区域。因此,一张较暗图片的图像直方图中的数据多集中于左侧和中间部分,而整体明亮、只有少量阴影的图像则相反。计算机视觉邻域常借助图像直方图来实现图像的二值化。
灰度直方图是一幅图像中个像素灰度值出现次数或频数的统计结果,它只反映该图像中灰度值出现的频率,而未反映某一灰度值像素所在的位置。也就是说,它只包含了该图像中某个灰度值的像素出现的概率,而丢失了其所在的位置的信息。
任一幅图像,都能唯一地算出一幅与它对应的直方图。但不同的图像,可能有相同的直方图。即图像与直方图之间是多对一的映射关系。
直方图意义:
- 直方图是图像中像素强度分布的图形表达方式。
- 直方图统计了每一个强度值所具有的像素个数。
直方图广泛应用于许多计算机视觉应用中。通过标记帧和帧之间显著的边缘和颜色的统计变化,来检测视频中场景的变换。通过在每个兴趣点设置一个有相近特征的直方图所构成的标签,用以确定图像中的兴趣点。边缘、色彩、角度等直方图构成了可以被传递给目标识别分类器的一个通用特征类型。色彩和边缘的直方图还可以用来识别网络视频是否被复制等。直方图是计算机视觉中最经典的工具之一,也是一个很好的图像特征表示手段。
OpenCV中提供了cv2.calcHist()函数可以通过计算图像的统计直方图,其语法格式如下:
函数原型:hist = cv2.calcHist( images, channels, mask, histSize, ranges, accumulate )
contours为返回的轮廓。hierarchy为返回的图像的拓扑信息(轮廓层次)。
参数描述如下:
- hist:返回的统计直方图,是一个一维数组,数组内是各个灰度级的像素个数。
- images:原始图像,图像需要使用“[ ]”括起来使用。
- channels:指定通道编号。
- mask:掩码图像。
- histSize:BINS的数量,该值需要用中括号括起来。
- ranges:像素值范围RANGE。
- accumulate:累计(累积、叠加)标识,默认值为False。
图像直方图均衡化
直方图均衡化是通过拉伸像素强度的分布范围,使得在0~255灰阶上的分布更加均衡,提高了图像的对比度,达到改善图像主观视觉效果的目的。对比度较低的图像适合使用直方图均衡化方法来增强图像细节。
OpenCV中提供了cv2.equalizeHist()函数来实现直方图均衡化。
函数原型:dst = cv2.equalizeHist(src)
dst为直方图均衡化处理结果
参数描述如下:
- src:8位单通道原始图像
具体步骤
步骤一:创建项目结构
创建项目名为使用直方图提高图像对比度
,项目根目录下新建code
文件夹储存代码,新建dataset
文件夹储存数据,项目结构如下:
使用直方图提高图像对比度 # 项目名称
├── code # 储存代码文件
├── dataset # 储存数据文件
注:如项目结构已存在,无需再创建。
步骤二:读取图像绘制图像直方图
- 在
code
文件夹下,新建contrast.py
文件; - 导入所需模块:OpenCV、matplotlib ;
- 读取
dataset
文件夹下的doll.png
图片; - 依次计算
B G R
三个通道的图像直方图; - 将三个通道的直方图绘制到一张画布中;
代码实现
# 导入所需模块 OpenCV、matplotlib
import cv2
import matplotlib.pyplot as plt
# 读取图片
img = cv2.imread("../dataset/doll.png")
# 统计整幅图像B G R 三个通道的直方图,BINS值为256,像素值范围为[0,255]
histb = cv2.calcHist([img],[0],None,[256],[0,255])
histg = cv2.calcHist([img],[1],None,[256],[0,255])
histr = cv2.calcHist([img],[2],None,[256],[0,255])
plt.figure()
plt.plot(histb,color='b')
plt.plot(histg,color='g')
plt.plot(histr,color='r')
plt.show()
效果展示:
步骤三:直方图均衡化
- 拆分图像通道;
- 分别对三个通道进行直方图均衡化;
- 将三通道按照
B G R
的顺序合成; - 显示直方图均衡化后的图像;
代码实现
# 进行直方图均衡化
# 通道分解
(b, g, r) = cv2.split(img)
b = cv2.equalizeHist(b)
g = cv2.equalizeHist(g)
r = cv2.equalizeHist(r)
# 通道合成
result = cv2.merge((b, g, r))
# 显示图片
cv2.imshow("origin image", img)
cv2.imshow("histogram equalization", result)
cv2.waitKey(0)
效果展示:
步骤四:绘制均衡化后图像直方图
- 依次计算结果图像
B G R
三个通道的图像直方图; - 将三个通道的直方图绘制到一张画布中;
代码实现
# 统计整幅图像B G R 三个通道的直方图,BINS值为256,像素值范围为[0,255]
histb = cv2.calcHist([result],[0],None,[256],[0,255])
histg = cv2.calcHist([result],[1],None,[256],[0,255])
histr = cv2.calcHist([result],[2],None,[256],[0,255])
plt.figure()
plt.plot(histb,color='b')
plt.plot(histg,color='g')
plt.plot(histr,color='r')
plt.show()
图像进行直方图均衡化以后,图像中像素分布更均匀,图像的对比度提高,从而清晰度也就提高了。