灰度变换
2.4 图像直方图
2.4.1频数分布表与直方图
频数与相对灰度值:参考数学中的概念,一个灰度值的频数即为是该灰度值的所有像素个数之和,而相对灰度值则是用频数/所有像素个数。计算相对灰度值近和计算归一化一致。
比如一个图片共有100个像素,其中灰度值为3的像素共有45个,则它的频数为45,相对频率为0.45.
直方图特点:
①图像集中在左侧:意味着图像中大部分像素的灰度值较低,整体偏暗
②图像集中在右侧:意味着图像中大部分像素的灰度值较高,整体偏亮
③ 集中在某一狭小的范围内:意味着图像中的灰度值变化不大,整体对比度较低,特征不够清晰
④图像分布均匀:意味着图像中的灰度值在各个等级上都有较为均衡的分布,图像的细节特征较为清晰。
2.4.2分组频数直方图
把图像的灰度值按照从大到小的顺序排序后进行若干分组,随后算出每个分组中的所有像素数量之和,作为分组的频数
2.4.3累积直方图
用于计算图像中小于等于某灰度值的所有像素之和,其的函数图像单调递增。
2.4.4灰度直方图的计算
① NumPy
-
np.histogram():
此函数用于计算数据集的直方图。它接收输入数组和指定的bin数量或范围,并返回直方图的统计数据和bin的边界。 -
np.cumsum():
-
此函数用于计算数组的累积和,用其处以像素总数,可得出累积直方图。
② Scikit-image
-
exposure.histogram():
Scikit-image库中的此函数用于计算图像数组的直方图。它提供了多种参数来定制直方图的计算,例如指定bin的数量或范围。 -
exposure.cumulative_distribution():
此函数用于计算图像数组的累积直方图。它返回一个数组,其中包含了每个bin的累积频率。这对于图像增强和直方图均衡等非常有用。
③ OpenCV
- cv.calcHist():
OpenCV库中的此函数用于计算图像数组的直方图。它提供了丰富的参数来控制直方图的计算,如指定要计算直方图的图像通道、掩码的使用、bin的数量和范围等。这使得cv.calcHist()
成为一个非常灵活和强大的工具,适用于各种图像处理任务。
④ Matplotlib
- plt.hist():
此函数用于计算图像数组的直方图并将其显示出来。它接收输入数组和一系列参数来控制直方图的外观,如bin的数量、颜色、边界等。plt.hist()
非常适合在数据处理和图像分析过程中快速查看数据的分布。
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from skimage import io, exposure, color
# 读取灰度图像
img_path = 'saved_image.jpg'
img = io.imread(img_path, as_gray=True) # 使用skimage的io模块以灰度模式读取图像
img = img.astype(np.uint8) # 将图像数据类型转换为无符号8位整数
# 利用Matplotlib计算灰度直方图
hist_mpl, bin_edges_mpl, patches = plt.hist(img.ravel(), bins=256, range=(0, 256)) # 计算并返回直方图
# 利用Scikit-image计算直方图
hist_sk, bin_centers = exposure.histogram(img, nbins=256, source_range='dtype') # 计算图像的直方图
# 利用Scikit-image计算累积直方图
cdf_sk, bin_centers = exposure.cumulative_distribution(img, nbins=256) # 计算图像的累积直方图
# 利用OpenCV计算灰度直方图
hist_cv = cv.calcHist([img], [0], None, [256], [0, 256]).ravel().astype(np.uint8) # 计算图像的直方图并转换数据类型
# 利用NumPy计算直方图与累积直方图
hist_np, bin_edges = np.histogram(img, bins=256, range=(0, 256)) # 计算图像的直方图
cdf_np = np.cumsum(hist_np) / img.size # 计算累积分布函数(CDF)
# 显示直方图
plt.figure(figsize=(10, 8)) # 创建一个新图形并设置大小
plt.subplot(2, 3, 1) # 创建一个子图
plt.bar(bin_edges_mpl[:-1], hist_mpl, width=1, color='gray') # 绘制Matplotlib直方图
plt.title('Matplotlib Histogram') # 设置子图标题
plt.subplot(2, 3, 2) # 创建另一个子图
plt.bar(bin_centers, hist_cv, width=1, color='gray') # 绘制OpenCV直方图
plt.title('OpenCV Histogram') # 设置子图标题
plt.subplot(2, 3, 3) # 创建另一个子图
plt.bar(bin_edges[:-1], hist_np, width=1, color='gray') # 绘制NumPy直方图
plt.title('NumPy Histogram') # 设置子图标题
plt.subplot(2, 3, 4) # 创建另一个子图
plt.bar(bin_centers, hist_sk, width=1, color='gray') # 绘制Scikit-image直方图
plt.title('Scikit-image Histogram') # 设置子图标题
plt.tight_layout() # 自动调整子图参数,使之填充整个图像区域
plt.show() # 显示图形
# 显示累积直方图(以柱状图形式)
plt.figure(figsize=(10, 4)) # 创建一个新图形并设置大小
# 为了绘制柱状图,我们需要确保x轴的值是像素强度,y轴的值是累积频率
plt.subplot(1, 2, 1) # 创建一个子图
plt.bar(range(256), cdf_np * img.size, width=1, color='blue') # 绘制NumPy累积直方图
plt.title('NumPy Cumulative Histogram (Bar Chart)') # 设置子图标题
plt.xlabel('Pixel intensity') # 设置x轴标签
plt.ylabel('Cumulative count') # 设置y轴标签
plt.subplot(1, 2, 2) # 创建另一个子图
plt.bar(range(256), cdf_sk * img.size, width=1, color='red') # 绘制Scikit-image累积直方图
plt.title('Scikit-image Cumulative Histogram (Bar Chart)') # 设置子图标题
plt.xlabel('Pixel intensity') # 设置x轴标签
plt.ylabel('Cumulative count') # 设置y轴标签
plt.tight_layout() # 自动调整子图参数,使之填充整个图像区域
plt.show() # 显示图形
注,本人为在校学生,博客是边学边写的,主要是为了巩固知识,如有错误请积极指正。