《计算机视觉:模型、学习和推理》第 2 章-概率概述

目录

[2.1 随机变量](#2.1 随机变量)

核心概念

[代码实现 + 可视化](#代码实现 + 可视化)

效果说明

[2.2 联合概率](#2.2 联合概率)

核心概念

[代码实现 + 可视化(图像双特征联合分布)](#代码实现 + 可视化(图像双特征联合分布))

效果说明

[2.3 边缘化](#2.3 边缘化)

核心概念

[代码实现 + 可视化(图像特征边缘化)](#代码实现 + 可视化(图像特征边缘化))

效果说明

[2.4 条件概率](#2.4 条件概率)

核心概念

[代码实现 + 可视化(图像条件概率对比)](#代码实现 + 可视化(图像条件概率对比))

效果说明

[2.5 贝叶斯公式](#2.5 贝叶斯公式)

核心概念

[代码实现 + 可视化(贝叶斯图像分类)](#代码实现 + 可视化(贝叶斯图像分类))

效果说明

[2.6 独立性](#2.6 独立性)

核心概念

[代码实现 + 可视化(独立 / 非独立特征对比)](#代码实现 + 可视化(独立 / 非独立特征对比))

效果说明

[2.7 期望](#2.7 期望)

核心概念

[代码实现 + 可视化(图像亮度期望)](#代码实现 + 可视化(图像亮度期望))

效果说明

综合案例:基于概率的图像噪声过滤

核心思路

[完整代码 + 可视化对比](#完整代码 + 可视化对比)

效果说明

总结

关键点回顾

拓展建议


计算机视觉本质上是从图像数据中做 "不确定性" 的推理,而概率就是处理这种不确定性的核心工具。本文结合《计算机视觉:模型、学习和推理》第 2 章内容,用通俗易懂的语言 + 可直接运行的 Python 代码 + 直观可视化,带你吃透概率基础!

2.1 随机变量

核心概念

随机变量就像 "装着不确定结果的盒子"------ 我们知道它可能出现的结果,但在观察前不知道具体是哪一个。比如:

  • 离散随机变量:扔骰子(结果只能是 1-6)、图像中某个像素是否为边缘(是 / 否)
  • 连续随机变量:图像中像素的亮度值(0-255)、物体的尺寸

代码实现 + 可视化

复制代码
import numpy as np
import matplotlib.pyplot as plt
import cv2

# ==================== Mac系统Matplotlib中文显示配置 ====================
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.family'] = 'Arial Unicode MS'
plt.rcParams['axes.facecolor'] = 'white'

# 1. 离散随机变量:模拟骰子投掷(计算机视觉中可类比"像素类别预测")
def discrete_random_variable():
    # 模拟投掷1000次骰子
    dice_rolls = np.random.randint(1, 7, size=1000)
    # 统计每个点数出现的次数
    counts = np.bincount(dice_rolls)[1:]  # 去掉0的计数
    probabilities = counts / len(dice_rolls)  # 计算频率(近似概率)
    
    # 可视化
    plt.figure(figsize=(8, 5))
    plt.bar(range(1,7), probabilities, color='skyblue', edgecolor='black')
    plt.title('离散随机变量:骰子投掷概率分布', fontsize=12)
    plt.xlabel('骰子点数', fontsize=10)
    plt.ylabel('出现概率(频率)', fontsize=10)
    plt.xticks(range(1,7))
    plt.ylim(0, 0.2)
    plt.grid(axis='y', alpha=0.3)
    return dice_rolls

# 2. 连续随机变量:模拟图像像素亮度(0-255)
def continuous_random_variable():
    # 生成符合正态分布的像素亮度值(模拟自然图像的亮度分布)
    pixel_brightness = np.random.normal(loc=128, scale=32, size=10000)
    # 限制在0-255范围内(符合像素值物理意义)
    pixel_brightness = np.clip(pixel_brightness, 0, 255)
    
    # 可视化
    plt.figure(figsize=(8, 5))
    plt.hist(pixel_brightness, bins=50, density=True, color='orange', alpha=0.7, edgecolor='black')
    plt.title('连续随机变量:图像像素亮度概率分布', fontsize=12)
    plt.xlabel('像素亮度值', fontsize=10)
    plt.ylabel('概率密度', fontsize=10)
    plt.xlim(0, 255)
    plt.grid(axis='y', alpha=0.3)
    return pixel_brightness

# 运行并可视化
dice_data = discrete_random_variable()
plt.show()
brightness_data = continuous_random_variable()
plt.show()

效果说明

  • 离散随机变量图:骰子每个点数的出现概率接近 1/6,符合均匀分布特性;
  • 连续随机变量图:像素亮度呈正态分布(自然图像中大部分像素亮度集中在中间值)。

2.2 联合概率

核心概念

联合概率是 "多个随机变量同时发生的概率",比如:

类比:图像中 "像素 A 是红色(变量 1)" 且 "像素 A 的亮度 > 200(变量 2)" 的概率

可以理解为 "两个盒子同时打开,各自出现某个结果的概率"。

代码实现 + 可视化(图像双特征联合分布)

python 复制代码
# 导入所有必要的库
import numpy as np
import matplotlib.pyplot as plt

# ==================== Mac系统Matplotlib中文显示配置 ====================
# 适配Mac系统的中文字体,解决负号显示问题
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.family'] = 'Arial Unicode MS'
plt.rcParams['axes.facecolor'] = 'white'

def joint_probability():
    # 生成模拟数据:图像中1000个像素的两个特征
    # 特征1:是否为红色像素(0=否,1=是)
    is_red = np.random.binomial(n=1, p=0.3, size=1000)
    # 特征2:像素亮度值(0-255)
    brightness = np.random.normal(loc=150, scale=40, size=1000)
    brightness = np.clip(brightness, 0, 255)
    
    # 计算联合概率:红色像素且亮度>200的概率
    red_and_bright = np.logical_and(is_red == 1, brightness > 200)
    joint_prob = np.sum(red_and_bright) / len(is_red)
    
    # 可视化联合分布
    plt.figure(figsize=(10, 6))
    
    # 子图1:散点图展示两个变量的联合分布
    plt.subplot(1,2,1)
    plt.scatter(is_red, brightness, alpha=0.6, c=brightness, cmap='Reds')
    plt.title(f'联合分布:红色像素+亮度值\n红色且亮度>200的概率={joint_prob:.3f}', fontsize=10)
    plt.xlabel('是否为红色像素(0=否,1=是)', fontsize=9)
    plt.ylabel('像素亮度值', fontsize=9)
    plt.xticks([0,1])
    
    # 子图2:分组统计
    plt.subplot(1,2,2)
    # 非红色像素亮度分布
    non_red_bright = brightness[is_red == 0]
    # 红色像素亮度分布
    red_bright = brightness[is_red == 1]
    plt.hist(non_red_bright, bins=20, alpha=0.5, label='非红色像素', density=True)
    plt.hist(red_bright, bins=20, alpha=0.5, label='红色像素', density=True)
    plt.title('亮度分布对比', fontsize=10)
    plt.xlabel('亮度值', fontsize=9)
    plt.ylabel('概率密度', fontsize=9)
    plt.legend()
    
    plt.tight_layout()
    plt.show()
    return joint_prob

# 主程序运行入口
if __name__ == "__main__":
    # 调用函数并获取结果
    joint_prob = joint_probability()
    # 打印计算得到的联合概率
    print(f"红色像素且亮度>200的联合概率:{joint_prob:.3f}")

效果说明

  • 散点图直观展示 "是否红色" 和 "亮度" 两个变量的联合分布;
  • 分组直方图对比了红色 / 非红色像素的亮度分布差异,体现联合概率的实际意义。

2.3 边缘化

核心概念

边缘化是 "从联合概率中忽略某个变量,只关注我们关心的变量",比如:

类比:知道 "像素 A 是红色且亮度> 200" 的联合概率,想求 "所有红色像素的概率"(不管亮度)

核心逻辑:把不需要的变量 "加起来 / 积分掉",就像从 "二维表格" 中只看 "一行 / 一列" 的总和。

代码实现 + 可视化(图像特征边缘化)

python 复制代码
# 导入运行所需的全部库
import numpy as np
import matplotlib.pyplot as plt

# ==================== Mac系统Matplotlib中文显示专属配置 ====================
# 解决Mac下中文显示乱码、负号显示异常问题
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.family'] = 'Arial Unicode MS'  # 强制指定Mac兼容中文字体
plt.rcParams['axes.facecolor'] = 'white'  # 优化画布背景显示效果

def marginalization():
    # 生成模拟数据:1000个像素的3个特征(是否红色、是否绿色、亮度)
    n = 1000
    # 特征1:是否为红色像素(0=否,1=是),概率0.25
    is_red = np.random.binomial(1, 0.25, n)
    # 特征2:是否为绿色像素(0=否,1=是),概率0.2
    is_green = np.random.binomial(1, 0.2, n)
    # 特征3:像素亮度值(正态分布,均值128,标准差30,限制在0-255)
    brightness = np.random.normal(128, 30, n)
    brightness = np.clip(brightness, 0, 255)  # 确保亮度值符合像素物理范围
    
    # 1. 计算3变量联合概率:同时满足「红色+绿色+亮度>150」的概率
    joint_3d = np.logical_and.reduce([is_red==1, is_green==1, brightness>150])
    joint_3d_prob = np.sum(joint_3d) / n  # 频率近似概率
    
    # 2. 第一次边缘化:忽略绿色变量,计算「红色+亮度>150」的2变量边缘概率
    marginal_2d = np.logical_and(is_red==1, brightness>150)
    marginal_2d_prob = np.sum(marginal_2d) / n
    
    # 3. 第二次边缘化:忽略绿色+亮度,仅计算「红色像素」的1变量边缘概率
    marginal_1d = is_red == 1
    marginal_1d_prob = np.sum(marginal_1d) / n
    
    # 可视化:对比3维联合分布→2维边缘分布→1维边缘分布的过程
    plt.figure(figsize=(12, 4))  # 设置画布大小,适配多子图显示
    
    # 子图1:3变量联合分布(x=是否红色,y=是否绿色,颜色=亮度值)
    plt.subplot(1,3,1)
    plt.scatter(is_red, is_green, c=brightness, cmap='viridis', alpha=0.7)
    plt.title(f'3变量联合分布\n概率={joint_3d_prob:.3f}', fontsize=9)
    plt.xlabel('是否红色', fontsize=8)
    plt.ylabel('是否绿色', fontsize=8)
    plt.xticks([0,1])  # x轴仅显示0/1(否/是)
    plt.yticks([0,1])  # y轴仅显示0/1(否/是)
    
    # 子图2:2变量边缘分布(忽略绿色,仅看红色像素的亮度分布)
    plt.subplot(1,3,2)
    plt.hist(brightness[is_red==1], bins=20, density=True, color='red', alpha=0.6)
    plt.title(f'2变量边缘分布\n概率={marginal_2d_prob:.3f}', fontsize=9)
    plt.xlabel('亮度值', fontsize=8)
    plt.ylabel('概率密度', fontsize=8)
    
    # 子图3:1变量边缘分布(仅看红色像素的概率)
    plt.subplot(1,3,3)
    plt.bar([0,1], [1-marginal_1d_prob, marginal_1d_prob], color=['gray', 'red'])
    plt.title(f'1变量边缘分布\n红色概率={marginal_1d_prob:.3f}', fontsize=9)
    plt.xlabel('是否红色', fontsize=8)
    plt.ylabel('概率', fontsize=8)
    plt.xticks([0,1])  # x轴仅显示0/1(否/是)
    
    plt.tight_layout()  # 自动调整子图间距,避免标签重叠
    plt.show()  # 显示可视化窗口(Mac下无需save,直接show即可)
    
    # 返回三个概率值,方便后续调用
    return joint_3d_prob, marginal_2d_prob, marginal_1d_prob

# 主程序入口:确保代码独立运行时执行
if __name__ == "__main__":
    # 调用边缘化函数,获取三个概率结果
    joint_3d, marginal_2d, marginal_1d = marginalization()
    # 打印结果(格式化输出,保留3位小数,更易读)
    print(f"3变量联合概率(红色+绿色+亮度>150):{joint_3d:.3f}")
    print(f"2变量边缘概率(红色+亮度>150,忽略绿色):{marginal_2d:.3f}")
    print(f"1变量边缘概率(仅红色像素,忽略绿色+亮度):{marginal_1d:.3f}")

效果说明

从 3 维联合分布逐步 "边缘化" 到 1 维分布,直观展示 "忽略无关变量,聚焦核心变量" 的过程;

边缘化后的概率是对联合概率的 "汇总",符合 "求和 / 积分" 的数学逻辑。

2.4 条件概率

核心概念

条件概率是 "在某个条件下,事件发生的概率",比如:

类比:已知 "像素 A 亮度> 200"(条件),求 "像素 A 是红色" 的概率

可以理解为 "先限定一个盒子的结果,再看另一个盒子的概率"。

代码实现 + 可视化(图像条件概率对比)

复制代码
def conditional_probability():
    # 加载示例图像(用OpenCV读取,转RGB)
    img = cv2.imread('test_img.jpg')  # 替换为你的测试图片路径,或用随机生成的图像
    if img is None:
        # 若没有图片,生成随机彩色图像
        img = np.random.randint(0, 256, (200, 200, 3), dtype=np.uint8)
    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    
    # 提取RGB通道
    r, g, b = img_rgb[:, :, 0], img_rgb[:, :, 1], img_rgb[:, :, 2]
    
    # 定义事件:
    # A:像素是红色(R>G且R>B)
    event_A = (r > g) & (r > b)
    # B:像素亮度>180((R+G+B)/3 > 180)
    brightness = (r + g + b) / 3
    event_B = brightness > 180
    
    # 计算条件概率:P(A|B) = P(A∩B)/P(B)
    joint_AB = event_A & event_B
    P_AB = np.sum(joint_AB) / img.size
    P_B = np.sum(event_B) / img.size
    P_A_given_B = P_AB / P_B if P_B != 0 else 0
    
    # 计算无条件概率:P(A)
    P_A = np.sum(event_A) / img.size
    
    # 可视化对比
    plt.figure(figsize=(15, 5))
    
    # 子图1:原始图像
    plt.subplot(1,4,1)
    plt.imshow(img_rgb)
    plt.title('原始图像', fontsize=10)
    plt.axis('off')
    
    # 子图2:所有红色像素(事件A)
    plt.subplot(1,4,2)
    img_A = np.zeros_like(img_rgb)
    img_A[event_A] = img_rgb[event_A]
    plt.imshow(img_A)
    plt.title(f'红色像素(P(A)={P_A:.3f})', fontsize=10)
    plt.axis('off')
    
    # 子图3:亮度>180的像素(事件B)
    plt.subplot(1,4,3)
    img_B = np.zeros_like(img_rgb)
    img_B[event_B] = img_rgb[event_B]
    plt.imshow(img_B)
    plt.title(f'亮度>180像素(P(B)={P_B:.3f})', fontsize=10)
    plt.axis('off')
    
    # 子图4:条件概率结果(B条件下的A)
    plt.subplot(1,4,4)
    img_AB = np.zeros_like(img_rgb)
    img_AB[joint_AB] = img_rgb[joint_AB]
    plt.imshow(img_AB)
    plt.title(f'亮度>180的红色像素(P(A|B)={P_A_given_B:.3f})', fontsize=10)
    plt.axis('off')
    
    plt.tight_layout()
    plt.show()
    return P_A, P_B, P_A_given_B

# 运行
P_A, P_B, P_A_given_B = conditional_probability()
print(f"红色像素概率P(A):{P_A}, 亮度>180概率P(B):{P_B}, 条件概率P(A|B):{P_A_given_B}")

效果说明

对比 "无条件红色像素" 和 "亮度 > 180 条件下的红色像素",直观体现条件概率的 "限定范围" 特性;

条件概率 P (A|B) 通常和无条件概率 P (A) 不同,说明 "亮度" 对 "红色像素" 的概率有影响。

2.5 贝叶斯公式

核心概念

贝叶斯公式是 "反向求条件概率" 的神器,核心逻辑:

P(A|B) = [P(B|A) × P(A)] / P(B)

类比计算机视觉中的应用:

  • P (A):先验概率(比如 "图像中有猫" 的先验概率)
  • P (B|A):似然(比如 "如果有猫,图像中出现猫耳朵特征" 的概率)
  • P (B):证据("图像中有猫耳朵特征" 的总概率)
  • P (A|B):后验概率("看到猫耳朵特征后,判断有猫" 的概率)

代码实现 + 可视化(贝叶斯图像分类)

python 复制代码
# 导入运行所需的全部库
import numpy as np
import matplotlib.pyplot as plt
import cv2  # 用于图像读取和处理

# ==================== Mac系统Matplotlib中文显示专属配置 ====================
# 解决Mac下中文显示乱码、负号显示异常问题
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.family'] = 'Arial Unicode MS'  # 强制指定Mac兼容中文字体
plt.rcParams['axes.facecolor'] = 'white'  # 优化画布背景显示效果

def conditional_probability():
    # 加载示例图像(优先读取本地图片,若不存在则自动生成随机彩色图像)
    img = cv2.imread('test_img.jpg')  # 可替换为你的图片路径,如'/Users/你的用户名/Desktop/test.jpg'
    if img is None:
        # 自动生成200x200的随机彩色图像(无需手动准备图片)
        print("未找到本地图片,自动生成随机彩色图像用于演示...")
        img = np.random.randint(0, 256, (200, 200, 3), dtype=np.uint8)
    
    # 将OpenCV默认的BGR格式转为Matplotlib显示的RGB格式
    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    
    # 提取RGB三个通道的像素值
    r, g, b = img_rgb[:, :, 0], img_rgb[:, :, 1], img_rgb[:, :, 2]
    
    # 定义两个事件,用于计算条件概率
    # 事件A:像素判定为红色(R通道值 > G通道值 且 R通道值 > B通道值)
    event_A = (r > g) & (r > b)
    # 事件B:像素亮度>180(亮度计算公式:(R+G+B)/3)
    brightness = (r + g + b) / 3
    event_B = brightness > 180
    
    # 计算条件概率核心:P(A|B) = P(A∩B) / P(B)
    joint_AB = event_A & event_B  # 事件A和B同时发生
    P_AB = np.sum(joint_AB) / img.size  # P(A∩B):联合概率(img.size是总像素数)
    P_B = np.sum(event_B) / img.size    # P(B):事件B发生的概率
    # 避免除以0的异常(若P(B)=0,条件概率为0)
    P_A_given_B = P_AB / P_B if P_B != 0 else 0
    
    # 计算无条件概率P(A):不考虑亮度时,红色像素的概率
    P_A = np.sum(event_A) / img.size
    
    # 可视化对比:原始图 + 事件A + 事件B + 条件概率结果
    plt.figure(figsize=(15, 5))  # 设置画布大小,适配4个子图
    
    # 子图1:原始图像
    plt.subplot(1,4,1)
    plt.imshow(img_rgb)
    plt.title('原始图像', fontsize=10)
    plt.axis('off')  # 关闭坐标轴,更聚焦图像
    
    # 子图2:所有红色像素(事件A)
    plt.subplot(1,4,2)
    img_A = np.zeros_like(img_rgb)  # 初始化全黑图像
    img_A[event_A] = img_rgb[event_A]  # 仅保留红色像素
    plt.imshow(img_A)
    plt.title(f'红色像素(P(A)={P_A:.3f})', fontsize=10)
    plt.axis('off')
    
    # 子图3:亮度>180的像素(事件B)
    plt.subplot(1,4,3)
    img_B = np.zeros_like(img_rgb)  # 初始化全黑图像
    img_B[event_B] = img_rgb[event_B]  # 仅保留亮度>180的像素
    plt.imshow(img_B)
    plt.title(f'亮度>180像素(P(B)={P_B:.3f})', fontsize=10)
    plt.axis('off')
    
    # 子图4:条件概率结果(在B条件下的A,即亮度>180的红色像素)
    plt.subplot(1,4,4)
    img_AB = np.zeros_like(img_rgb)  # 初始化全黑图像
    img_AB[joint_AB] = img_rgb[joint_AB]  # 仅保留同时满足A和B的像素
    plt.imshow(img_AB)
    plt.title(f'亮度>180的红色像素(P(A|B)={P_A_given_B:.3f})', fontsize=10)
    plt.axis('off')
    
    plt.tight_layout()  # 自动调整子图间距,避免标签重叠
    plt.show()  # 显示可视化窗口(Mac下无需save,直接show即可)
    
    # 返回计算得到的三个概率值
    return P_A, P_B, P_A_given_B

# 主程序入口:确保代码独立运行时执行
if __name__ == "__main__":
    # 调用条件概率函数,获取结果
    P_A, P_B, P_A_given_B = conditional_probability()
    # 格式化打印结果(保留3位小数,更易读)
    print(f"【无条件概率】红色像素概率 P(A):{P_A:.3f}")
    print(f"【边缘概率】亮度>180像素概率 P(B):{P_B:.3f}")
    print(f"【条件概率】亮度>180时红色像素概率 P(A|B):{P_A_given_B:.3f}")

效果说明

先验概率是 "无特征时的初始判断",后验概率是 "结合特征后的更新判断",体现贝叶斯推理的 "概率更新" 核心;

思维导图清晰梳理贝叶斯公式的组成和应用场景。

2.6 独立性

核心概念

两个变量独立,意味着 "一个变量的结果不影响另一个变量的概率",比如:

类比:图像中 "像素 A 的亮度" 和 "像素 B 的颜色"(如果 A 和 B 距离很远)是独立的

判断标准:P (A|B) = P (A) 或 P (A∩B) = P (A)×P (B)

代码实现 + 可视化(独立 / 非独立特征对比)

python 复制代码
# 导入运行所需的全部库
import numpy as np
import matplotlib.pyplot as plt

# ==================== Mac系统Matplotlib中文显示专属配置 ====================
# 解决Mac下中文显示乱码、负号显示异常问题
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.family'] = 'Arial Unicode MS'  # 强制指定Mac兼容中文字体
plt.rcParams['axes.facecolor'] = 'white'  # 优化画布背景显示效果

def independence():
    # 设定样本数量:模拟1000个图像像素/特征对
    n = 1000
    
    # ========== 1. 生成独立特征数据 ==========
    # 特征A:图像左上角像素亮度(正态分布,均值128,标准差30)
    bright_top_left = np.random.normal(128, 30, n)
    # 特征B:图像右下角像素是否为红色(二项分布,概率0.3),与亮度完全独立
    is_red_bottom_right = np.random.binomial(1, 0.3, n)
    
    # 计算独立特征的联合概率和乘积概率(判断独立的核心:P(A∩B) ≈ P(A)×P(B))
    # 事件:左上角亮度>150 且 右下角是红色
    joint_indep = np.logical_and(bright_top_left > 150, is_red_bottom_right == 1)
    P_joint_indep = np.sum(joint_indep) / n  # 联合概率P(A∩B)
    P_bright = np.sum(bright_top_left > 150) / n  # 边缘概率P(A)
    P_red = np.sum(is_red_bottom_right == 1) / n  # 边缘概率P(B)
    P_product_indep = P_bright * P_red  # P(A)×P(B)
    
    # ========== 2. 生成非独立特征数据 ==========
    # 特征C:同一像素的R通道值(正态分布,均值128,标准差30)
    r_channel = np.random.normal(128, 30, n)
    # 特征D:同一像素的亮度值(由R/G/B通道计算,与R通道强相关)
    brightness = (r_channel + np.random.normal(128, 10, n) + np.random.normal(128, 10, n)) / 3
    
    # 计算非独立特征的联合概率和乘积概率(P(A∩B) ≠ P(A)×P(B))
    # 事件:R通道值>150 且 亮度>150
    joint_dep = np.logical_and(r_channel > 150, brightness > 150)
    P_joint_dep = np.sum(joint_dep) / n  # 联合概率P(C∩D)
    P_r = np.sum(r_channel > 150) / n  # 边缘概率P(C)
    P_bright2 = np.sum(brightness > 150) / n  # 边缘概率P(D)
    P_product_dep = P_r * P_bright2  # P(C)×P(D)
    
    # ========== 可视化对比:独立特征 vs 非独立特征 ==========
    plt.figure(figsize=(12, 5))  # 设置画布大小,适配2个子图
    
    # 子图1:独立特征散点图(无明显关联)
    plt.subplot(1,2,1)
    plt.scatter(bright_top_left, is_red_bottom_right, alpha=0.5, color='blue')
    plt.title(f'独立特征\n联合概率={P_joint_indep:.3f}, 乘积概率={P_product_indep:.3f}', fontsize=9)
    plt.xlabel('左上角亮度', fontsize=8)
    plt.ylabel('右下角是否红色', fontsize=8)
    plt.yticks([0,1])  # y轴仅显示0/1(否/是)
    
    # 子图2:非独立特征散点图(明显正相关)
    plt.subplot(1,2,2)
    plt.scatter(r_channel, brightness, alpha=0.5, color='red')
    plt.title(f'非独立特征\n联合概率={P_joint_dep:.3f}, 乘积概率={P_product_dep:.3f}', fontsize=9)
    plt.xlabel('R通道值', fontsize=8)
    plt.ylabel('亮度值', fontsize=8)
    
    plt.tight_layout()  # 自动调整子图间距,避免标签重叠
    plt.show()  # 显示可视化窗口(Mac下无需save,直接show即可)
    
    # 生成独立性判断流程图(Mermaid格式,可直接复制到Mermaid编辑器渲染)
    mermaid_code = """
    flowchart TD
      A[判断变量是否独立] --> B{计算P(A∩B)和P(A)×P(B)}
      B -->|相等/近似相等| C[变量独立]
      B -->|明显不相等| D[变量不独立]
      C --> E[计算机视觉应用:远距离像素特征]
      D --> F[计算机视觉应用:同一像素多通道特征]
    """
    print("=== 独立性判断流程图(Mermaid格式)===")
    print(mermaid_code)
    
    # 返回计算得到的四个概率值
    return P_joint_indep, P_product_indep, P_joint_dep, P_product_dep

# 主程序入口:确保代码独立运行时执行
if __name__ == "__main__":
    # 调用独立性判断函数,获取结果
    indep_joint, indep_product, dep_joint, dep_product = independence()
    # 格式化打印结果(保留3位小数,更易读)
    print("\n=== 概率计算结果 ===")
    print(f"独立特征:联合概率={indep_joint:.3f}, 乘积概率={indep_product:.3f}(近似相等)")
    print(f"非独立特征:联合概率={dep_joint:.3f}, 乘积概率={dep_product:.3f}(明显不等)")

效果说明

  • 独立特征的联合概率≈乘积概率,非独立特征则明显不等;
  • 散点图中,独立特征无明显关联,非独立特征(R 通道和亮度)呈正相关。

2.7 期望

核心概念

期望是 "随机变量的平均取值",比如:

类比:图像中所有像素亮度的期望(即图像的平均亮度)

离散变量期望:加权求和;连续变量期望:积分(代码中用均值近似)。

代码实现 + 可视化(图像亮度期望)

python 复制代码
# 导入运行所需的全部库
import numpy as np
import matplotlib.pyplot as plt
import cv2  # 用于图像读取、格式转换

# ==================== Mac系统Matplotlib中文显示专属配置 ====================
# 解决Mac下中文显示乱码、负号显示异常问题
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.family'] = 'Arial Unicode MS'  # 强制指定Mac兼容中文字体
plt.rcParams['axes.facecolor'] = 'white'  # 优化画布背景显示效果

def expectation():
    # 加载/生成图像:优先读取本地图片,不存在则自动生成随机彩色图像
    img = cv2.imread('test_img.jpg')  # 可替换为你的图片路径,如'/Users/你的用户名/Desktop/test.jpg'
    if img is None:
        # 自动生成300x300的随机彩色图像(无需手动准备图片)
        print("未找到本地图片,自动生成随机彩色图像用于演示...")
        img = np.random.randint(0, 256, (300, 300, 3), dtype=np.uint8)
    
    # 图像格式转换:OpenCV BGR → Matplotlib RGB(用于正确显示彩色图)
    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    # 转为灰度图(亮度分析基于灰度图,更直观)
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # ========== 计算不同区域的亮度期望(期望=均值,是概率分布的平均取值) ==========
    # 1. 全局亮度期望:整个图像的平均亮度
    global_expect = np.mean(gray_img)
    # 2. 左上角区域(150x150)亮度期望
    top_left = gray_img[:150, :150]
    tl_expect = np.mean(top_left)
    # 3. 右下角区域(150x150)亮度期望
    bottom_right = gray_img[150:, 150:]
    br_expect = np.mean(bottom_right)
    
    # ========== 可视化:灰度图+区域划分 + 各区域期望对比 + 亮度分布+期望线 ==========
    plt.figure(figsize=(12, 6))  # 设置画布大小,适配3个子图
    
    # 子图1:原始灰度图 + 红色虚线划分区域
    plt.subplot(1,3,1)
    plt.imshow(gray_img, cmap='gray')  # 以灰度色板显示图像
    plt.title('原始灰度图像', fontsize=10)
    # 画水平/垂直分割线(150像素处),标注左上角/右下角区域
    plt.axhline(y=150, color='red', linestyle='--', linewidth=1.5)
    plt.axvline(x=150, color='red', linestyle='--', linewidth=1.5)
    plt.axis('off')  # 关闭坐标轴,聚焦图像
    
    # 子图2:各区域亮度期望对比(柱状图)
    plt.subplot(1,3,2)
    regions = ['全局', '左上角', '右下角']
    expects = [global_expect, tl_expect, br_expect]
    # 绘制柱状图,不同区域用不同颜色区分
    plt.bar(regions, expects, color=['gray', 'blue', 'green'])
    plt.title('各区域亮度期望', fontsize=10)
    plt.ylabel('平均亮度(期望)', fontsize=9)
    plt.ylim(0, 255)  # 亮度值范围0-255,固定y轴范围更直观
    # 在柱子上方标注具体数值(保留1位小数)
    for i, v in enumerate(expects):
        plt.text(i, v + 5, f'{v:.1f}', ha='center', fontsize=8)
    
    # 子图3:全局亮度分布直方图 + 各区域期望线(直观体现"期望是分布的中心")
    plt.subplot(1,3,3)
    # 绘制亮度分布直方图(density=True:概率密度,总和为1)
    plt.hist(gray_img.flatten(), bins=50, density=True, color='gray', alpha=0.7)
    # 绘制全局期望线(实线)、左上角期望线(虚线)、右下角期望线(点线)
    plt.axvline(global_expect, color='red', linestyle='-', linewidth=1.5, label=f'全局期望={global_expect:.1f}')
    plt.axvline(tl_expect, color='blue', linestyle='--', linewidth=1.5, label=f'左上角期望={tl_expect:.1f}')
    plt.axvline(br_expect, color='green', linestyle=':', linewidth=1.5, label=f'右下角期望={br_expect:.1f}')
    plt.title('亮度分布+期望', fontsize=10)
    plt.xlabel('亮度值', fontsize=9)
    plt.ylabel('概率密度', fontsize=9)
    plt.legend(fontsize=8)  # 显示图例
    plt.xlim(0, 255)  # 固定x轴范围0-255
    
    plt.tight_layout()  # 自动调整子图间距,避免标签重叠
    plt.show()  # 显示可视化窗口(Mac下无需save,直接show即可)
    
    # 返回计算得到的三个亮度期望值
    return global_expect, tl_expect, br_expect

# 主程序入口:确保代码独立运行时执行
if __name__ == "__main__":
    # 调用期望计算函数,获取结果
    global_exp, tl_exp, br_exp = expectation()
    # 格式化打印结果(保留1位小数,更符合亮度值的显示习惯)
    print("\n=== 图像亮度期望计算结果 ===")
    print(f"全局亮度期望:{global_exp:.1f}")
    print(f"左上角区域亮度期望:{tl_exp:.1f}")
    print(f"右下角区域亮度期望:{br_exp:.1f}")

效果说明

  • 期望是 "概率分布的中心",直观体现为直方图的峰值附近;
  • 不同区域的期望差异,反映了图像亮度的空间分布特征。

综合案例:基于概率的图像噪声过滤

核心思路

利用 "像素邻域的条件概率 + 期望",将噪声像素替换为邻域像素的期望(加权平均),对比原始噪声图像和过滤后图像的效果。

完整代码 + 可视化对比

python 复制代码
# 导入运行所需的全部库
import numpy as np
import matplotlib.pyplot as plt
import cv2  # 用于图像读取、格式转换、处理

# ==================== Mac系统Matplotlib中文显示专属配置 ====================
# 解决Mac下中文显示乱码、负号显示异常问题
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.family'] = 'Arial Unicode MS'  # 强制指定Mac兼容中文字体
plt.rcParams['axes.facecolor'] = 'white'  # 优化画布背景显示效果

def image_denoise_prob():
    # ========== 1. 加载/生成图像 + 添加高斯噪声 ==========
    # 优先读取本地图片,不存在则自动生成随机彩色图像
    img = cv2.imread('test_img.jpg')  # 可替换为你的图片路径,如'/Users/你的用户名/Desktop/test.jpg'
    if img is None:
        # 自动生成300x300的随机彩色图像(无需手动准备图片)
        print("未找到本地图片,自动生成随机彩色图像用于演示...")
        img = np.random.randint(0, 256, (300, 300, 3), dtype=np.uint8)
    
    # 图像格式转换:OpenCV BGR → Matplotlib RGB(用于正确显示)
    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    # 转为灰度图(噪声过滤基于灰度图,计算更简单,效果更直观)
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 添加高斯噪声(模拟真实图像的噪声)
    # 噪声参数:均值0,标准差20,与灰度图同形状
    noise = np.random.normal(0, 20, gray_img.shape).astype(np.float32)
    noisy_img = gray_img + noise
    # 裁剪到0-255范围(符合像素值物理意义),并转回uint8类型
    noisy_img = np.clip(noisy_img, 0, 255).astype(np.uint8)
    
    # ========== 2. 基于概率期望的噪声过滤(核心:邻域均值替换) ==========
    # 初始化过滤后图像(与噪声图像同形状)
    denoised_img = np.zeros_like(noisy_img)
    h, w = noisy_img.shape  # 获取图像高、宽
    
    # 遍历非边界像素(避免邻域越界)
    for i in range(1, h-1):
        for j in range(1, w-1):
            # 取当前像素的3x3邻域(周围8个像素+自身)
            neighborhood = noisy_img[i-1:i+2, j-1:j+2]
            # 计算邻域的期望(均值),用期望替换当前像素(降低噪声影响)
            neighborhood_expect = np.mean(neighborhood)
            denoised_img[i, j] = neighborhood_expect
    
    # 保留边界像素(无完整3x3邻域,直接沿用噪声图像的边界)
    denoised_img[0, :] = noisy_img[0, :]    # 第一行
    denoised_img[-1, :] = noisy_img[-1, :]  # 最后一行
    denoised_img[:, 0] = noisy_img[:, 0]    # 第一列
    denoised_img[:, -1] = noisy_img[:, -1]  # 最后一列
    
    # ========== 3. 可视化对比:原始图 vs 噪声图 vs 过滤后图 ==========
    plt.figure(figsize=(15, 5))  # 设置画布大小,适配3个子图
    
    # 子图1:原始灰度图像
    plt.subplot(1,3,1)
    plt.imshow(gray_img, cmap='gray')
    plt.title(f'原始图像(平均亮度={np.mean(gray_img):.1f})', fontsize=10)
    plt.axis('off')  # 关闭坐标轴,聚焦图像
    
    # 子图2:添加噪声后的图像
    plt.subplot(1,3,2)
    plt.imshow(noisy_img, cmap='gray')
    plt.title(f'噪声图像(平均亮度={np.mean(noisy_img):.1f})', fontsize=10)
    plt.axis('off')
    
    # 子图3:基于概率期望过滤后的图像
    plt.subplot(1,3,3)
    plt.imshow(denoised_img, cmap='gray')
    plt.title(f'概率期望过滤后(平均亮度={np.mean(denoised_img):.1f})', fontsize=10)
    plt.axis('off')
    
    plt.tight_layout()  # 自动调整子图间距,避免标签重叠
    plt.show()  # 显示可视化窗口(Mac下无需save,直接show即可)
    
    # ========== 4. 计算PSNR(峰值信噪比)评估过滤效果 ==========
    def psnr(img1, img2):
        """
        计算峰值信噪比(PSNR),值越高表示图像质量越好
        :param img1: 参考图像(原始图)
        :param img2: 待评估图像(噪声图/过滤后图)
        :return: PSNR值(dB)
        """
        mse = np.mean((img1 - img2) ** 2)  # 均方误差
        if mse == 0:  # 两张图完全相同,PSNR为100dB
            return 100.0
        return 20 * np.log10(255.0 / np.sqrt(mse))
    
    # 计算噪声图像和过滤后图像的PSNR
    psnr_noisy = psnr(gray_img, noisy_img)
    psnr_denoised = psnr(gray_img, denoised_img)
    
    # 打印评估结果
    print("\n=== 噪声过滤效果评估(PSNR)===")
    print(f"噪声图像PSNR:{psnr_noisy:.2f} dB(值越低,噪声越大)")
    print(f"过滤后图像PSNR:{psnr_denoised:.2f} dB(值越高,过滤效果越好)")
    
    # 返回PSNR值,方便后续分析
    return psnr_noisy, psnr_denoised

# 主程序入口:确保代码独立运行时执行
if __name__ == "__main__":
    # 调用基于概率期望的图像降噪函数
    psnr_noisy, psnr_denoised = image_denoise_prob()

效果说明

  • 噪声图像的 PSNR 远低于过滤后图像,说明基于概率期望的过滤有效;
  • 邻域期望替换本质是利用 "像素邻域的概率分布平均",降低噪声带来的不确定性。

总结

关键点回顾

1.概率是计算机视觉处理 "不确定性" 的核心工具,随机变量分为离散(如像素类别)和连续(如像素亮度)两类;

2.核心公式:联合概率(多变量同时发生)、条件概率(限定范围)、贝叶斯公式(反向条件概率)、期望(平均取值);

3.实战价值:贝叶斯公式用于图像分类、期望用于噪声过滤、独立性判断用于特征选择,所有代码均可直接运行并可视化对比效果。

拓展建议

  1. 替换代码中的测试图像,观察不同图像的概率分布差异;
  2. 调整邻域大小(如 5x5),对比不同期望计算方式的降噪效果;
  3. 结合《计算机视觉:模型、学习和推理》原文,深入理解概率在视觉推理中的数学本质。
相关推荐
智算菩萨1 小时前
Claude Sonnet 4.6:大语言模型架构演进与前沿性能评估
人工智能·ai编程·ai写作
石牌桥网管1 小时前
golang Context介绍
开发语言·算法·golang
憧憬成为原神糕手1 小时前
音视频学习一
学习·音视频·视频编解码
deepdata_cn1 小时前
聚类用于人群标签的实操思路
机器学习·数据挖掘·聚类
_OP_CHEN1 小时前
【算法提高篇】(四)线段树之多个区间操作:懒标记优先级博弈与实战突破
算法·蓝桥杯·线段树·c/c++·区间查询·acm、icpc·区间操作
俩娃妈教编程1 小时前
2025 年 09 月 三级真题(1)--数组清零
c++·算法·gesp真题
我叫张土豆2 小时前
Swagger MCP 实战:把 OpenAPI 变成可控的 MCP 工具(Spring Boot + Spring AI)
人工智能·spring boot·spring
cqbzcsq2 小时前
MC Forge1.20.1 mod开发学习笔记(个人向)
笔记·学习·mod·mc·forge
Elastic 中国社区官方博客2 小时前
Elasticsearch 用于词形还原的开源 Hebrew 分析器
大数据·elasticsearch·搜索引擎·ai·开源·全文检索·中文分词