从信息熵上看图像
信息量
信息量的定义源于信息论,特别是香农的信息熵理论。信息量(或自信息)衡量的是一个事件发生所带来的信息量大小。这里给出信息量公式的推导思路及其背后的逻辑。
基本假设
- 信息量与事件发生的概率成反比:如果一个事件发生的概率越大,那么它所提供的信息就越少;相反,如果一个事件发生的概率越小,那么它所提供的信息就越多。
- 独立事件的信息量可加:若有两个独立事件(A)和(B),则这两个事件同时发生所提供的总信息量应该等于各自单独发生时所提供的信息量之和。即如果 I ( A ) I(A) I(A)是事件 A A A的信息量, I ( B ) I(B) I(B)是事件 B B B的信息量,则两个事件共同提供的信息量应满足 I ( A and B ) = I ( A ) + I ( B ) I(A \text{ and } B) = I(A) + I(B) I(A and B)=I(A)+I(B)。
推导过程
根据上述两点基本假设,我们可以推导出信息量的公式:
-
概率与信息量的关系:由于信息量与事件发生的概率成反比,我们假设信息量 I ( p ) I(p) I(p)可以表示为某个函数形式 f ( p ) f(p) f(p),其中 p p p是事件发生的概率。考虑到概率 p p p越小,信息量越大,我们可以初步确定 f ( p ) f(p) f(p)应该是关于 p p p的单调递减函数。
-
独立事件信息量的累加性:对于两个独立事件(A)和(B),它们同时发生的概率是 p A × p B p_A \times p_B pA×pB。根据假设,我们需要找到一个函数 f f f,使得 f ( p A × p B ) = f ( p A ) + f ( p B ) f(p_A \times p_B) = f(p_A) + f(p_B) f(pA×pB)=f(pA)+f(pB)。这提示我们寻找一个满足这种性质的函数。
-
对数函数的引入:观察到只有对数函数能够满足乘法转加法的特性,即 log ( p A × p B ) = log ( p A ) + log ( p B ) \log(p_A \times p_B) = \log(p_A) + \log(p_B) log(pA×pB)=log(pA)+log(pB)。因此,自然地想到使用对数函数来定义信息量。但需要注意的是,对数函数的结果是负值(因为 0 < p ≤ 1 0 < p \leq 1 0<p≤1),而信息量应该是正值,所以我们取对数的相反数作为信息量的度量。此外,为了使信息量在数学上更加直观(例如,使得最高信息量对应于最小概率事件),我们通常使用对数的负值,从而得到信息量 I ( p ) = − log ( p ) I(p) = -\log(p) I(p)=−log(p)。
综上所述,基于信息量与事件发生概率的反比关系以及独立事件信息量的可加性,我们得出了信息量的基本公式为 I ( p ) = − log b ( p ) I(p) = -\log_b(p) I(p)=−logb(p),其中 b b b是对数的底数,可以根据需要选择2、 e e e或其他正数。在实际应用中,最常见的是选择 b = 2 b=2 b=2,此时信息量的单位是比特。
底数的选择:
选择不同的底数仅影响信息量的单位。以2为底数时,信息量的单位是比特(bit);以 e e e为底数时,单位是纳特(nat)。选择哪个底数取决于具体的应用场景和个人偏好。
信息量公式中使用底数2的原因主要与二进制系统和信息单位的选择有关,以下是详细的解释:
-
二进制系统的普遍性:
在计算机科学和数字通信中,信息通常以二进制形式(0和1)表示。使用底数2时,信息量的单位是比特(bit),这直接对应一个二进制位所能携带的信息量。例如,一个公平硬币抛掷的结果(概率1/2)的信息量为 log 2 ( 2 ) = 1 \log_2(2) = 1 log2(2)=1 比特,恰好对应一个二进制位的选择。 -
编码效率的直观性:
底数2的信息量公式 I = − log 2 ( P ) I = -\log_2(P) I=−log2(P) 可以直观反映表示事件所需的最小二进制位数。例如,一个八面骰子(每个面概率1/8)的信息量为 log 2 ( 8 ) = 3 \log_2(8) = 3 log2(8)=3比特,对应3位二进制编码,直接映射到实际存储或传输需求。 -
香农熵的单位一致性:
香农在信息论中定义熵时选择底数2,使得熵的单位为比特。例如,对于等概率的n个事件,熵 H = log 2 ( n ) H = \log_2(n) H=log2(n) 表示编码这些事件所需的最小平均比特数,便于实际应用中的计算和优化。 -
与其他单位的兼容性:
虽然可以使用自然对数(单位纳特,nat)或以10为底(单位哈特利,hartley),但比特更贴合工程实践。转换时仅需乘以常数(如1 nat ≈ 1.443 bit),不影响信息量的本质,但比特更符合技术标准。
总结:底数2的选择是为了使信息量以比特为单位,直接关联二进制编码的实际需求,提升计算和应用的直观性。尽管数学上允许其他底数,但底数2在信息技术中已成为标准,因其紧密对应硬件实现和数据表示的基本原理。
信息熵
信息熵是衡量随机变量不确定性的一个度量,它由克劳德·香农在其开创性的信息论工作中提出。信息熵的推导基于几个关键的原则和假设,下面我们将逐步介绍如何从这些原则出发推导出信息熵的公式。
基本假设
- 连续性:对于任何给定的概率分布,熵应该是概率分布的连续函数。
- 对称性:熵不依赖于事件的具体顺序,即如果两个事件的概率交换,则熵不变。
- 确定性:如果一个随机变量是确定的(即它的概率分布中有一个概率为1,其余均为0),那么该随机变量的熵应为0。
- 可加性:若一个选择过程可以分为两步进行,则总熵等于第一步的熵加上第二步的条件熵。
推导过程
设离散随机变量(X)具有可能的状态集合 { x 1 , x 2 , . . . , x n } \{x_1, x_2, ..., x_n\} {x1,x2,...,xn},每个状态 x i x_i xi发生的概率为 p ( x i ) p(x_i) p(xi)。我们需要找到一种方法来量化整个系统(X)的不确定性或平均信息量,这就是信息熵 H ( X ) H(X) H(X)。
1. 定义单个事件的信息量
首先,我们定义单个事件 x i x_i xi发生所带来的信息量 I ( x i ) I(x_i) I(xi)与事件发生的概率 p ( x i ) p(x_i) p(xi)的关系。根据之前讨论的信息量公式,我们知道信息量应该与概率成反比,并且满足独立事件信息量累加的性质,因此采用以下形式:
I ( x i ) = − log ( p ( x i ) ) I(x_i) = -\log(p(x_i)) I(xi)=−log(p(xi))
这里使用了负号以确保信息量为正值,并且通常选择底数为2,使得信息量的单位为比特(bit)。
2. 计算平均信息量(熵)
接下来,为了衡量整个系统的平均信息量或不确定性,我们需要计算所有可能事件的信息量的期望值。这个期望值就是信息熵 H ( X ) H(X) H(X):
H ( X ) = ∑ i = 1 n p ( x i ) ⋅ I ( x i ) H(X) = \sum_{i=1}^{n} p(x_i) \cdot I(x_i) H(X)=i=1∑np(xi)⋅I(xi)
将 I ( x i ) = − log ( p ( x i ) ) I(x_i) = -\log(p(x_i)) I(xi)=−log(p(xi))代入上述公式中,得到信息熵的表达式:
H ( X ) = − ∑ i = 1 n p ( x i ) log ( p ( x i ) ) H(X) = -\sum_{i=1}^{n} p(x_i) \log(p(x_i)) H(X)=−i=1∑np(xi)log(p(xi))
这便是信息熵的基本公式。它表示的是一个离散随机变量的平均不确定性或平均信息量。
一维熵
上面公式对应的则是一维熵,在图像上则表示为图像像素值的灰度。图像的熵是一个衡量图像信息量的指标,反映了图像中像素值分布的不确定性或复杂度。高熵意味着图像包含更多的信息或细节,而低熵则表示图像较为单一或均匀。
计算图像熵的基本步骤如下:
-
计算直方图:首先需要计算图像像素值的分布情况,即直方图。对于灰度图像,直方图显示了每个灰度级出现的频率;对于彩色图像,则可以分别计算各个颜色通道(如RGB)的直方图。
-
归一化直方图:将直方图转换为概率分布,即每个灰度级出现的概率。这通常通过将每个灰度级的计数除以总的像素数量来实现。
-
计算熵:使用以下公式计算熵:
H = − ∑ i p i log 2 ( p i ) H = -\sum_{i} p_i \log_2(p_i) H=−i∑pilog2(pi)
其中, p i p_i pi是第(i)个灰度级的概率。注意,如果某个灰度级没有出现在图像中(即 p i = 0 p_i=0 pi=0),则对应的项在求和时应被忽略,因为 0 × log 2 ( 0 ) 0 \times \log_2(0) 0×log2(0)按惯例视为0。
下面是一个使用Python和OpenCV库计算灰度图像熵的例子:
import cv2
import numpy as np
def calculate_entropy(image):
# 将图像转换为灰度图像
if len(image.shape) == 3:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 计算图像的直方图
histogram = cv2.calcHist([image], [0], None, [256], [0, 256])
# 归一化直方图以获得概率分布
histogram_prob = histogram / (image.shape[0] * image.shape[1])
# 计算熵
entropy = -np.sum(histogram_prob * np.log2(histogram_prob + (histogram_prob == 0)))
return entropy
# 加载图像
image = cv2.imread('your_image_path.jpg')
# 计算并打印图像的熵
entropy = calculate_entropy(image)
print(f"图像的熵: {entropy}")
在这个例子中,我们首先确保输入图像为灰度图像,然后计算其直方图,并将其归一化得到概率分布。最后,根据上述熵的定义计算图像的熵。注意,在计算熵时对直方图中的零元素进行了处理,避免了因取对数而导致的数值错误。此方法同样适用于彩色图像,但需要分别计算每个颜色通道的熵,或者先将彩色图像转换为灰度图像再进行计算。
二维熵(联合熵)
联合熵是用来衡量多个随机变量的不确定性。具体来说,对于两个随机变量(X)和(Y),它们的联合熵 H ( X , Y ) H(X,Y) H(X,Y)定义为这两个变量联合分布的熵,反映了同时知道(X)和(Y)的值时系统的总不确定性。
联合熵可以通过以下公式计算:
H
(
X
,
Y
)
=
−
∑
x
∈
X
∑
y
∈
Y
P
(
x
,
y
)
log
P
(
x
,
y
)
H(X,Y) = -\sum_{x \in X}\sum_{y \in Y} P(x,y) \log P(x,y)
H(X,Y)=−x∈X∑y∈Y∑P(x,y)logP(x,y)
这里,
P
(
x
,
y
)
P(x,y)
P(x,y)表示
X
=
x
X=x
X=x且
Y
=
y
Y=y
Y=y同时发生的概率。联合熵的单位通常依据对数的底来决定:如果使用以2为底的对数,则单位是比特;如果使用自然对数(以(e)为底),则单位是纳特。
联合熵有几个重要的性质:
- 非负性:联合熵总是非负的。
- 对称性: H ( X , Y ) = H ( Y , X ) H(X,Y) = H(Y,X) H(X,Y)=H(Y,X),即联合熵不依赖于随机变量的顺序。
- 与单独熵的关系:联合熵大于等于任一变量的单独熵,即 H ( X , Y ) ≥ H ( X ) H(X,Y) \geq H(X) H(X,Y)≥H(X)和 H ( X , Y ) ≥ H ( Y ) H(X,Y) \geq H(Y) H(X,Y)≥H(Y)。随着变量的增加,系统的不确定性也会提高。
二维熵在图像上的表现
二维熵意味着考虑两个变量,表现在图像则是考虑像素的灰度值和像素之间的相邻位置(空间关系),可以考虑通过滤波或者灰度共生矩阵之类的方式生成含有像素空间关系的图像。
使用OpenCV实现图像的二维熵计算,主要步骤包括生成灰度共生矩阵(GLCM)并基于此计算熵。
下面是一个示例代码计算一幅灰度图像的二维熵:
import cv2
import numpy as np
def calculate_glcm(image, distance=1, angle_deg=0):
"""
计算灰度共生矩阵(GLCM)。
参数:
- image: 输入的灰度图像。
- distance: 像素对之间的距离,默认为1。
- angle_deg: 方向的角度(以度为单位),可以是0、45、90或135度,默认为0。
返回:
- glcm: 归一化后的灰度共生矩阵。
"""
# 根据角度调整方向
if angle_deg == 0:
dy, dx = 0, distance
elif angle_deg == 45:
dy, dx = -distance, distance
elif angle_deg == 90:
dy, dx = -distance, 0
elif angle_deg == 135:
dy, dx = -distance, -distance
else:
raise ValueError("angle_deg must be one of 0, 45, 90, or 135.")
# 获取图像尺寸
rows, cols = image.shape
# 初始化GLCM
glcm = np.zeros((256, 256), dtype=np.uint32)
# 计算GLCM
for row in range(0, rows - abs(dy)):
for col in range(0, cols - abs(dx)):
i = image[row, col]
j = image[row + dy, col + dx]
glcm[i, j] += 1
# 归一化GLCM
glcm = glcm.astype(float) / float(np.sum(glcm))
return glcm
def calculate_glcm_entropy(glcm):
"""
根据给定的灰度共生矩阵计算二维熵。
参数:
- glcm: 灰度共生矩阵。
返回:
- entropy: GLCM的二维熵。
"""
# 找到非零元素的位置
non_zero_indices = np.nonzero(glcm)
# 计算这些非零概率的熵贡献
entropy = -np.sum(glcm[non_zero_indices] * np.log2(glcm[non_zero_indices]))
return entropy
# 加载图像并转换为灰度图
image = cv2.imread('your_image_path.jpg', cv2.IMREAD_GRAYSCALE)
# 计算灰度共生矩阵
glcm = calculate_glcm(image, distance=1, angle_deg=0)
# 计算二维熵
entropy = calculate_glcm_entropy(glcm)
print(f"图像的二维熵: {entropy}")
拓展
可以考虑多维信息熵,例如引入梯度、帧差。在静态背景识别上,背景处于低灰度值,对应概率高,对应的熵较低,当有物体入侵后,存在少部分高灰度值,熵会变高。