Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

直方图

定义

直方图是图像处理中的一个基本工具,它提供了图像中强度值的统计摘要。它是一个量化像素强度分布的离散函数。

对于一个具有 LL 个可能强度级别(例如,对于8位灰度图像,L=256L=256)的图像,直方图 h(i)h(i) 定义为:

h(i)=nih(i) = n_i

其中 ii 是在 [0,L1][0, L-1] 范围内的强度级别,而 nin_i 是图像中具有该强度的像素数量。

在视觉上,直方图通常表示为条形图,其中每个条的高度对应于特定强度 ii 的像素计数 nin_i。出于可视化目的,特别是对于高位深图像,强度通常被分组为一组称为**箱子(bins)**的离散区间。箱子的数量是用户选择的参数;较少的箱子提供了分布的更概括的概览,而更多的箱子则提供了更丰富的细节。

下面的代码显示了一幅图像及由其计算出的两个直方图,分别使用了128和16个箱子。直方图清晰地显示了图像在[0, 255]范围内的像素强度分布。

import numpy as np
import skimage.io as io
import matplotlib.pyplot as plt

# Load the image
img = io.imread("../_static/figs/daisy.png", as_gray=True) * 255

# Display the image
fig, ax = plt.subplots(1, 1, figsize=(5,5))
ax.imshow(img, cmap="gray")
plt.show()

# Prepare the figure for the histograms
fig, axs = plt.subplots(1, 2, figsize=(12,4))

# Plot the first histogram
axs[0].hist(
    img.ravel(),           # The image must be flattened to use function hist
    bins=range(0,256,2)    # Define 128 bins (of width 2) between 0 and 255
)
axs[0].set_xlabel("Intensities")
axs[0].set_ylabel("Number")

# Plot the second histogram
axs[1].hist(
    img.ravel(),           # The image must be flattened to use function hist
    bins=range(0,256,16)   # Define 16 bins (of width 16) between 0 and 255
)
axs[1].set_xlabel("Intensities")
axs[1].set_ylabel("Number")

# Show the figure
plt.show()
<Figure size 360x360 with 1 Axes>
<Figure size 864x288 with 2 Axes>

解读直方图

直方图的形状为了解图像的色调特征提供了宝贵的见解。一个具有明显峰值或模式的直方图表明,图像由具有主导强度范围的区域组成。

在上面的例子中,直方图明显是双峰的

  • 第一个峰值,中心强度约在75左右,对应于构成图像背景的较暗像素。

  • 第二个峰值,中心强度约在180左右,对应于花瓣和花蕊的较亮像素。

这种模式特征是一个关键特性,可以在各种图像处理任务中加以利用,最著名的是图像分割。

直方图的性质

  • 归一化直方图作为概率分布: 如果将每个箱的值 h(i)h(i) 除以图像的总像素数 M×NM \times N,直方图就变为归一化直方图,记为 p(i)p(i)

    p(i)=niM×Np(i) = \frac{n_i}{M \times N}

    归一化直方图满足 i=0L1p(i)=1\sum_{i=0}^{L-1} p(i) = 1。因此可以将其解释为离散的概率质量函数(PMF),其中 p(i)p(i) 表示随机选取一个像素其强度为 ii 的概率。

  • 空间信息的丢失: 直方图的一个关键性质是它仅包含强度分布的统计信息,舍弃了所有空间信息。这意味着两幅在视觉上明显不同的图像也可能拥有完全相同的直方图,如 Figure 1 所示。

这两幅图像具有相同的直方图。右图是通过按强度值对左图的像素进行排序得到的。

Figure 1:这两幅图像具有相同的直方图。右图是通过按强度值对左图的像素进行排序得到的。

直方图变换

直方图变换,也称为点处理点算子,是一种通过对每个像素的强度值应用映射函数来修改图像的函数,该过程与其邻域无关。这些变换主要用于对比度增强,是图像预处理的基础。

变换 TT 将原始图像中的输入强度 ii 映射到一个新的输出强度 jj

j=T(i)j = T(i)

此操作会改变图像的直方图。在以下示例中,我们将假定像素强度已被归一化到范围 [0,1][0, 1]

反色

反色变换反转图像的强度级别:

T(i)=1iT(i) = 1 - i

这对于增强嵌入在图像暗区的白色或灰色细节很有用。

反色变换反转了灰度级,使暗区变亮,亮区变暗。

Figure 2:反色变换反转了灰度级,使暗区变亮,亮区变暗。

伽马校正

伽马校正是一种用于控制图像整体亮度的非线性变换:

T(i)=iγT(i) = i^\gamma
  • 如果 γ<1\gamma < 1,映射会偏向更亮的输出值,从而增强暗区的细节。

  • 如果 γ>1\gamma > 1,映射会偏向更暗的输出值,增强亮区的细节。

这种变换对于显示系统至关重要,因为它有助于补偿显示器中输入电压和输出亮度之间的非线性关系。它也模拟了人类视觉的非线性响应。

伽马校正示例,\gamma=0.4,这会使图像变亮并增强阴影部分的细节。

Figure 3:伽马校正示例,γ=0.4\gamma=0.4,这会使图像变亮并增强阴影部分的细节。

对比度拉伸(归一化)

对比度拉伸,也称为归一化,是一种线性变换,它扩展图像的动态范围以填充整个可用的强度范围。

T(i)=iiminimaximinT(i) = \frac{i-i_\text{min}}{i_\text{max}-i_\text{min}}

其中 imini_\text{min}imaxi_\text{max} 是原始图像中的最小和最大强度值。这是一种简单而有效的方法,用于改善未使用全部强度谱的图像的对比度。

对比度拉伸通过将原始强度范围线性映射到完整的 [0, 1] 范围来增强对比度。

Figure 4:对比度拉伸通过将原始强度范围线性映射到完整的 [0,1][0, 1] 范围来增强对比度。

直方图均衡化

直方图均衡化是一种强大的非线性技术,它重新分配像素强度以实现更均匀的分布。其目标是生成一个具有平坦直方图的输出图像。

该变换基于图像归一化直方图的累积分布函数(CDF)。对于强度级别 ii 的变换由下式给出:

T(i)=CDF(i)=k=0ip(k)=1MNk=0inkT(i) = \text{CDF}(i) = \sum_{k=0}^i p(k) = \frac{1}{MN} \sum_{k=0}^i n_k

其中 p(k)p(k) 是归一化直方图,nkn_k 是强度为 kk 的原始直方图计数,而 MNMN 是总像素数。这种变换拉伸了像素密集的强度范围,并压缩了像素稀疏的范围。结果通常是全局对比度的显著增加,使细节更清晰可见。这是一种无需参数的全自动方法。详细的推导可以在 [Gonzalez 2010, section 3.3.1] 中找到。

直方图均衡化通过平坦化强度分布来增强全局对比度。

Figure 5:直方图均衡化通过平坦化强度分布来增强全局对比度。

直方图均衡化效果。

Figure 6:直方图均衡化效果。

直方图均衡化的概念视图。

Figure 7:直方图均衡化的概念视图。

直方图均衡化的分步计算

  1. 定义强度范围和级别:

    • 对于8位灰度图像,强度在 [0,L1][0, L-1] 范围内,其中 L=256L = 256

    • 设图像尺寸为 M×NM \times Ni{0,,L1}i \in \{0, \dots, L-1\} 表示一个灰度级。

  2. 计算直方图 h(i)h(i):强度为 ii 的像素数。

  3. 归一化为概率质量函数 (pmf):

    p(i)=h(i)MN.p(i) = \frac{h(i)}{MN}.
  4. 计算累积分布函数 (cdf):

    c(i)=k=0ip(k).c(i) = \sum_{k=0}^{i} p(k).

    cdf 是非递减的,且 c(L1)=1c(L-1)=1

  5. 构建均衡化映射(查找表):

    T(i)=(L1)c(i)T(i) = \left\lfloor (L-1)\, c(i) \right\rfloor

    (或使用四舍五入)。TT 将输入灰度级映射到 [0,L1][0, L-1] 范围内的输出灰度级。

  6. 将映射应用于图像:对于每个值为 ii 的像素,设置 j=T(i)j = T(i)

  7. (可选,彩色图像)转换到亮度空间(例如 YCbCr/HSVY'C_bC_r/HSV),仅对亮度(Y/VY/V)进行均衡化,然后转换回 RGB 以避免色相偏移。

注释和实用技巧:

  • 如果图像仅使用狭窄的强度范围,均衡化会将其拉伸以占据更多的 [0,L1][0, L-1] 范围,从而增加全局对比度。

  • 对于非常小的图像或稀疏的直方图,优先使用四舍五入而非向下取整,以减少条带效应。

  • 均衡化可能会过度放大平坦区域的噪声;对比度受限的自适应直方图均衡化(CLAHE)是一种常见的替代方法。

计算示例(3位, 64×64)

一个3位图像(L=8, M \times N=4096)的设置,具有给定的直方图。

Figure 8:一个3位图像(L=8,M×N=4096L=8, M \times N=4096)的设置,具有给定的直方图。

分步均衡化 (L1=7L-1 = 7):

  1. 计数和 pmf p(rk)p(r_k):

    • n=[790,1023,850,656,329,245,122,81]n = [790, 1023, 850, 656, 329, 245, 122, 81]

    • p=[0.19,0.25,0.21,0.16,0.08,0.06,0.03,0.02]p = [0.19, 0.25, 0.21, 0.16, 0.08, 0.06, 0.03, 0.02]

  2. Cdf c(rk)c(r_k) = pp 的累积和:

    • c=[0.19,0.44,0.65,0.81,0.89,0.95,0.98,1.00]c = [0.19, 0.44, 0.65, 0.81, 0.89, 0.95, 0.98, 1.00]

  3. 缩放: sk=(L1)c(rk)=7c(rk)s_k = (L-1) c(r_k) = 7 c(r_k):

    • ss (实数) =[1.33,3.08,4.55,5.67,6.23,6.65,6.86,7.00]= [1.33, 3.08, 4.55, 5.67, 6.23, 6.65, 6.86, 7.00]

  4. 使用四舍五入进行映射: T(rk)=round(sk)T(r_k) = \mathrm{round}(s_k):

    • T=[1,3,5,6,6,7,7,7]T = [1, 3, 5, 6, 6, 7, 7, 7]

计算的紧凑视图:

kkrkr_knkn_kp(rk)p(r_k)c(rk)c(r_k)sk=7c(rk)s_k = 7 \cdot c(r_k)T(rk)T(r_k)
007900.190.191.331
1110230.250.443.083
228500.210.654.555
336560.160.815.676
443290.080.896.236
552450.060.956.657
661220.030.986.867
77810.021.007.007

按输出级别 jj 的均衡化直方图质量:

  • j=1j=1: 0.19 (来自 r=0r=0)

  • j=3j=3: 0.25 (来自 r=1r=1)

  • j=5j=5: 0.21 (来自 r=2r=2)

  • j=6j=6: 0.16+0.08=0.240.16+0.08 = 0.24 (来自 r=3,4r=3,4)

  • j=7j=7: 0.06+0.03+0.02=0.110.06+0.03+0.02 = 0.11 (来自 r=5,6,7r=5,6,7)

  • j{0,2,4}j \in \{0,2,4\}: 0

3位示例的计算步骤和结果。

Figure 9:3位示例的计算步骤和结果。

直方图规定化

与直方图均衡化类似,直方图规定化(或称直方图匹配)也是对图像进行变换,使其直方图与一个指定参考直方图相匹配(均衡化是参考直方图为均匀分布的特例)。

直方图规定化的概念视图。

Figure 10:直方图规定化的概念视图。

直方图规定化的分步计算

  1. 定义强度范围和数据集:

    • 强度范围为 [0,L1][0, L-1];对于8位图像,L=256L = 256

    • 设源图像尺寸为 M×NM \times N,灰度级为 i{0,,L1}i \in \{0, \dots, L-1\}

    • 设参考图像(或目标直方图)定义了所需的灰度级统计数据。

  2. 计算源和参考的直方图:

    • 源计数:hs(i)h_s(i) = 源中值为 ii 的像素数。

    • 参考计数:hr(j)h_r(j) = 参考中值为 jj 的像素数(或提供的目标直方图)。

  3. 归一化为pmf:

    ps(i)=hs(i)MN,pr(j)=hr(j)MrNr.p_s(i) = \frac{h_s(i)}{MN}, \qquad p_r(j) = \frac{h_r(j)}{M_r N_r}.
  4. 计算累积分布函数(cdf):

    cs(i)=k=0ips(k),cr(j)=k=0jpr(k).c_s(i) = \sum_{k=0}^{i} p_s(k), \qquad c_r(j) = \sum_{k=0}^{j} p_r(k).

    两个cdf在[0,L1][0, L-1]上都是非递减的,并以1结束。

  5. 构建规定化映射(查找表):

    • 概念上,将每个源级别 ii 映射到其cdf值最接近的参考级别 jj

      T(i)=argminj{0,,L1}cs(i)cr(j).T(i) = \arg\min_{j \in \{0,\dots,L-1\}} \big| c_s(i) - c_r(j) \big|.
    • 等价地,使用逆cdf视图(如果需要,可进行插值):

      T(i)=cr1(cs(i)).T(i) = c_r^{-1}\big(c_s(i)\big).
  6. 将映射应用于源图像:对每个像素值 ii,设置 j=T(i)j = T(i)

  7. (可选,彩色图像)转换为亮度空间(例如YCbCr/HSVY'C_bC_r/HSV),仅对亮度通道进行规定化,然后转换回RGB以保持色相。

注释和实用技巧:

  • crc_r有平坦区域或离散跳跃时,对cr1c_r^{-1}使用插值以减少条带效应。

  • 确保TT是非递减的(单调的)以避免伪影;对LUT强制执行单调性可以帮助解决此问题。

  • 对每个通道进行多通道规定化可能会改变颜色;仅亮度或联合方法可以缓解此问题。

  • 像scikit-image这样的库提供了match_histograms来实现这些步骤。

直方图规定化(匹配)示例。

Figure 11:直方图规定化(匹配)示例。

计算示例(3位, 64×64)

源直方图(与均衡化示例相同):

源3位直方图(L=8, M \times N=4096)。

Figure 12:源3位直方图(L=8,M×N=4096L=8, M \times N=4096)。

目标直方图(给定):

目标3位直方图。

Figure 13:目标3位直方图。

分步规定化 (L1=7L-1 = 7):

  1. 源 pmf psp_s 和 cdf csc_s:

    • ps=[0.19,0.25,0.21,0.16,0.08,0.06,0.03,0.02]p_s = [0.19, 0.25, 0.21, 0.16, 0.08, 0.06, 0.03, 0.02]

    • cs=[0.19,0.44,0.65,0.81,0.89,0.95,0.98,1.00]c_s = [0.19, 0.44, 0.65, 0.81, 0.89, 0.95, 0.98, 1.00]

  2. 从给定表格得到目标 pmf prp_r 和 cdf crc_r:

    • pr=[0.00,0.00,0.00,0.15,0.20,0.30,0.20,0.15]p_r = [0.00, 0.00, 0.00, 0.15, 0.20, 0.30, 0.20, 0.15]

    • cr=[0.00,0.00,0.00,0.15,0.35,0.65,0.85,1.00]c_r = [0.00, 0.00, 0.00, 0.15, 0.35, 0.65, 0.85, 1.00]

  3. 通过最近cdf(逆cdf)匹配构建映射:

    • 对于每个 ii,选择最小化 cs(i)cr(j)|c_s(i) - c_r(j)|jj

计算的紧凑视图:

kkrkr_kcs(rk)c_s(r_k)最近的 cr(j)c_r(j)jj备注
000.190.15 (j=3) vs 0.35 (j=4) → 0.153$
110.440.35 (j=4) vs 0.65 (j=5) → 0.354$
220.650.65 (j=5)5完全匹配
330.810.85 (j=6) vs 0.65 (j=5) → 0.856$
440.890.85 (j=6) vs 1.00 (j=7) → 0.856$
550.951.00 (j=7) vs 0.85 (j=6) → 1.007$
660.981.00 (j=7)7
771.001.00 (j=7)7

因此,规定化查找表为 T=[3,4,5,6,6,7,7,7]T = [3, 4, 5, 6, 6, 7, 7, 7]

按输出级别 jj 的结果质量(将映射到 jj 的源概率分组):

  • j=3j=3: 0.19 (来自 r=0r=0)

  • j=4j=4: 0.25 (来自 r=1r=1)

  • j=5j=5: 0.21 (来自 r=2r=2)

  • j=6j=6: 0.16+0.08=0.240.16+0.08 = 0.24 (来自 r=3,4r=3,4)

  • j=7j=7: 0.06+0.03+0.02=0.110.06+0.03+0.02 = 0.11 (来自 r=5,6,7r=5,6,7)

3位规定化示例的计算步骤和结果。

Figure 14:3位规定化示例的计算步骤和结果。

计算示例(离散匹配)

我们通过将源3位直方图与目标3位直方图匹配来说明规定化(L=8L=8)。

源(原始)离散直方图。

Figure 15:源(原始)离散直方图。

目标(参考)离散直方图。

Figure 16:目标(参考)离散直方图。

步骤 (L1=7L-1 = 7):

  1. 读取源计数 nsn_s 并归一化为 psp_s;读取目标计数 nrn_r 并归一化为 prp_r

  2. 累积分布:

    • cs(i)=kips(k)c_s(i) = \sum_{k \le i} p_s(k)

    • cr(j)=kjpr(j)c_r(j) = \sum_{k \le j} p_r(j)

  3. 通过最近cdf匹配构建映射TT

    • T(i)=argminjcs(i)cr(j)T(i) = \text{argmin}_j | c_s(i) - c_r(j) |

  4. 将LUT TT应用于图像。

数值映射(本例):

  • ps=[0.19,0.25,0.21,0.16,0.08,0.06,0.03,0.02]p_s = [0.19, 0.25, 0.21, 0.16, 0.08, 0.06, 0.03, 0.02]

  • cs=[0.19,0.44,0.65,0.81,0.89,0.95,0.98,1.00]c_s = [0.19, 0.44, 0.65, 0.81, 0.89, 0.95, 0.98, 1.00]

  • pr=[0.00,0.00,0.00,0.15,0.20,0.30,0.20,0.15]p_r = [0.00, 0.00, 0.00, 0.15, 0.20, 0.30, 0.20, 0.15]

  • cr=[0.00,0.00,0.00,0.15,0.35,0.65,0.85,1.00]c_r = [0.00, 0.00, 0.00, 0.15, 0.35, 0.65, 0.85, 1.00]

iics(i)c_s(i)j=T(i)j^* = T(i) 通过最近 cdf累加到输出箱
00.1930.19 → 箱 3
10.4440.25 → 箱 4
20.6550.21 → 箱 5
30.8160.16 → 箱 6
40.8960.08 → 箱 6
50.9570.06 → 箱 7
60.9870.03 → 箱 7
71.0070.02 → 箱 7

LUT: T=[3,4,5,6,6,7,7,7]T = [3, 4, 5, 6, 6, 7, 7, 7]

输出质量总计: j=3:0.19;j=4:0.25;j=5:0.21;j=6:0.24;j=7:0.11j=3: 0.19; j=4: 0.25; j=5: 0.21; j=6: 0.24; j=7: 0.11.

离散匹配示例的计算步骤和结果。

Figure 17:离散匹配示例的计算步骤和结果。

阈值处理

直方图有时对于将图像分割成两个类别非常有用, 即根据灰度级区分图像中的对象。 实际上,如果直方图清晰地显示出两种模式(即两个“峰”), 可以在这两种模式之间定义一个阈值 TT,然后对像素应用阈值处理,使得:

  • 如果像素级别低于 TT,则该像素属于类别0(在 Figure 18 中显示为黑色),

  • 否则,该像素属于类别1(在 Figure 18 中显示为白色)。

阈值为0.45的阈值处理。

Figure 18:阈值为0.45的阈值处理。

这样的阈值处理会产生一个二值图像,其像素只有两个值。 有几种方法可以自动计算阈值,例如Otsu方法

🤖