2. 黑电平校正算法实现
任务目标
RAW图像传感器在无光照条件下仍会输出非零像素值,该偏移由暗电流引起,称为黑电平。本案例实现黑电平校正:从RAW图像中减去每个通道的黑电平值,并将结果重新映射到有效位深范围,以消除暗电流影响、提升动态范围。
实现方案
采用全局黑电平校正方法:对每个像素通道减去对应黑电平偏移量,负值截断为0,随后将数据线性拉伸至原始位深范围以恢复满量程动态范围。该方法适用于Bayer RAW或单通道RAW数据,无需额外依赖库,仅使用Python标准库与NumPy。
代码实现
import numpy as np
def black_level_correction(raw_img: np.ndarray, black_level: int, bit_depth: int = 12) -> np.ndarray:
"""
对RAW图像执行黑电平校正。
参数:
raw_img: 输入RAW图像,uint16类型,形状为(H, W)或(H, W, C)
black_level: 传感器黑电平偏移值(每个通道相同或已按通道给定)
bit_depth: RAW图像位深,默认12bit
返回:
校正后的图像,uint16类型,像素范围[0, 2^bit_depth - 1]
"""
# 确保输入为uint16
raw = raw_img.astype(np.uint16)
# 减去黑电平,负值截断为0
corrected = raw.astype(np.int32) - black_level
corrected = np.clip(corrected, 0, None).astype(np.uint16)
# 线性拉伸至满量程,恢复动态范围
max_val = (1 << bit_depth) - 1
gain = max_val / (max_val - black_level)
corrected = np.clip(corrected * gain, 0, max_val).astype(np.uint16)
return corrected
if __name__ == "__main__":
# 模拟12bit RAW数据:8x8单通道,含暗电流偏移
np.random.seed(42)
raw_data = np.random.randint(0, 4096, (8, 8), dtype=np.uint16)
# 设定黑电平为512(12bit传感器典型值)
bl = 512
# 执行校正
result = black_level_correction(raw_data, bl, bit_depth=12)
# 验证:校正后最小像素值应接近0(原黑电平附近像素被压缩至低值)
print("原始最小像素值:", raw_data.min())
print("校正后最小像素值:", result.min())
print("校正后最大像素值:", result.max())
print("校正后像素均值:", result.mean())
运行方式
- 安装依赖:
pip install numpy - 将上述代码保存为
black_level_correction.py - 运行:
python black_level_correction.py
验证方法
程序输出校正前后的像素统计值。通过以下条件判定校正生效:
- 校正后最小像素值应显著低于原始最小值,且接近0(因黑电平被减去)
- 校正后最大像素值应接近4095(12bit满量程),表明动态范围被重新拉伸
- 校正后均值较原始均值下降约
black_level × gain的偏移量,但整体对比度保持
若需验证真实RAW文件,将raw_data替换为从RAW文件读取的numpy数组,并确保black_level与传感器规格一致即可。
关键说明
本实现假设黑电平为全局常量。若传感器各通道黑电平不同(如RGGB Bayer),需将black_level改为长度为通道数的数组,并按通道索引分别减去对应值。拉伸增益计算中,分母使用max_val - black_level,确保校正后满量程白点仍映射至最大值,避免高光细节丢失。