一、灰度直方图
1、原理
直方图是对数据进行统计的一种方法,并且将统计值组织到一系列事先定义好的bin当中。其中,bin 为直方图中经常用到的一个概念,可以译为 “直条” 或 “组距”,其数值是从数据中计算出的特征统计量,这些数据可以是诸如梯度、方向、色彩或者其他任何特征。
注意:直方图是根据灰度图进行绘制的。
假设有一张图像的信息(灰度值0~255,已知数字的范围包含256个值),于是可以按照一定的规律将这个范围分割成子区域(也就是bins),如:
2、术语和细节
- dims:需要统计的特征数目,在上例中,dims=1,因为仅仅统计了灰度值
- bins:每个特征空间子区段的数目,可译为 “直条” 或者 “组距”,在上例中,bins=16
- range:要统计特征的取值范围,在上例中,range=[0,255]
3、直方图的意义
- 直方图是图像中像素强度分布的图形表达方式
- 他统计了每一个强度值所具有的像素个数
- 不同的图像的直方图可能是相同的
4、直方图的计算和绘制
我们使用OpenCV中的方法统计直方图,并使用matplotlib将其绘制出来。
- 注意:该API中参数都需要加中括号 "[]"
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from matplotlib import font_manager
#设置字体
my_font = font_manager.FontProperties(fname="C:/Windows/Fonts/STHUPO.TTF")
#1、以灰度方式读取图片
img = cv.imread("images/girl.jpg", 0)
#2、统计灰度图
histr = cv.calcHist([img], [0], None, [256], [0,256])
#3、绘制灰度图
plt.figure(figsize=(10,8), dpi=100)
plt.subplot(121)
plt.title("原图", fontproperties=my_font)
#cmap是colormap的简称,用于指定渐变色,默认的值为viridis, 在matplotlib中,内置了一系列的渐变色
plt.imshow(img,cmap="gray")
plt.subplot(122)
plt.title("灰度直方图", fontproperties=my_font)
plt.plot(histr)
plt.show()
二、掩膜的应用(感兴趣区域的提取)
掩膜是用选定的图像、图形或者物体,对要处理的图像进行遮挡,来控制图像处理的区域。
在数字图像处理中,我们通常使用二维矩阵数组进行掩膜。掩膜是由0和1组成的一个二进制图像,利用该掩膜图像对要处理的图像进行掩膜,其中1值的区域被处理,0值的区域被屏蔽,不会处理。
1、示例代码
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from matplotlib import font_manager
#设置字体
my_font = font_manager.FontProperties(fname="C:/Windows/Fonts/STHUPO.TTF")
#1、直接以灰度方式读取图片
img = cv.imread("images/girl.jpg", 0)
#2、创建蒙版
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:400, 0:500] = 255 #255代表白
#3、掩膜
masked_img = cv.bitwise_and(img, img, mask=mask)
#4、统计掩膜后图像的灰度图
mask_histr = cv.calcHist([img], [0], mask, [256], [0,256])
#5、图像显示
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10,8))
axes[0,0].imshow(img, cmap="gray")
axes[0,0].set_title("原图", fontproperties=my_font)
axes[0,1].imshow(mask, cmap="gray")
axes[0,1].set_title("蒙版数据", fontproperties=my_font)
axes[1,0].imshow(masked_img, cmap="gray")
axes[1,0].set_title("掩膜后的数据", fontproperties=my_font)
axes[1,1].plot(mask_histr)
axes[1,1].grid() #加入网格
axes[1,1].set_title("灰度直方图", fontproperties=my_font)
plt.show()
三、直方图均衡化
1、原理与应用
2、API介绍
3、简单使用
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from matplotlib import font_manager
#字体设置
my_font = font_manager.FontProperties(fname="C:/Windows/Fonts/STHUPO.TTF")
#1、直接以灰度图的方式读入
img = cv.imread("images/girl.jpg", 0)
#2、均衡化处理
dst = cv.equalizeHist(img)
#3、结果显示
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10,8), dpi=100)
axes[0].imshow(img, cmap="gray")
axes[0].set_title("原图", fontproperties=my_font)
axes[1].imshow(dst, cmap="gray")
axes[1].set_title("均衡化结果", fontproperties=my_font)
plt.show()
四、自适应的直方图均值化
1、直方图均值化的不足
图像进行直方图均值化后,确实改变了对比度,原本很暗的地方变亮了,清晰可见。但是也引来了不足之处,如下图中的雕像头的面部变得模糊,看不见东西,仅剩下面部轮廓。
2、自适应直方图均衡化的做法
为了解决上述直方图均值化带来的问题,需要使用自适应的直方图均值化。此时,整幅图像被分割成很多个小块,这些小块被称为 “titles”(在OpenCV中titles的大小默认是8x8),然后再对每一个小块分别进行直方图均衡化,所以在每个区域中,直方图会集中在某一个小区域中。如果有噪声的话,使噪声会被放大。为了避免这种情况的出现要使用对比度限制。对于每个小块来说,如果直方图中的bin超过对比度的话,就把其中的像素点均匀分散到其他bins中,然后再进行直方图均衡化。
3、API介绍
4、简单使用
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from matplotlib import font_manager
#设置字体
my_font = font_manager.FontProperties(fname="C:/Windows/Fonts/STHUPO.TTF")
#1、以灰度图形式打开图像
img = cv.imread("./images/girl.jpg", 0)
#2、创建一个自适应均衡化的对象,并应用于图像
clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(img)
#3、图像显示
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10,8), dpi=100)
axes[0].imshow(img, cmap="gray")
axes[0].set_title("原图", fontproperties=my_font)
axes[1].imshow(cl1, cmap="gray")
axes[1].set_title("自适应均衡化后的结果", fontproperties=my_font)
plt.show()