如何使用OpenCV实现图像融合算法中的饱和区域消除?
饱和区域消除相关概念及OpenCV实现指南
概念答疑
- 饱和像素:8位图像中,像素值达到存储上限255的过曝像素,这类像素已经丢失亮部纹理细节,没有有效参考价值。
- 饱和区域:由大量饱和像素组成的图像区域,若纳入融合计算会导致最终结果出现偏色、亮部细节丢失等问题,因此论文明确要求长曝光图像的饱和像素不参与融合估算过程。
- 与最大值255距离小于阈值判定逻辑:对于单个像素值
p,判定公式为255 - p < 阈值(论文默认取值10),只要满足该条件的像素都会被判定为接近饱和的无效像素,纳入过滤范围。 - 联合直方图条目重置操作:统计长、短曝光图像对应位置像素对的联合直方图时,只要任意一个像素满足上述饱和判定条件,就将对应直方图bin的计数值重置为0,即该组像素对不参与后续融合权重的统计计算。
基于Python+OpenCV的实现代码
import cv2 import numpy as np def is_saturation(pixel_val, threshold=10, max_val=255): # 判定是否为饱和/接近饱和像素 return (max_val - pixel_val) < threshold def reset_saturation_hist(long_exp_img, short_exp_img, threshold=10, max_val=255): # 三通道图像可先拆分通道分别处理,此处示例先转灰度图统计 if len(long_exp_img.shape) == 3: long_exp_gray = cv2.cvtColor(long_exp_img, cv2.COLOR_BGR2GRAY) short_exp_gray = cv2.cvtColor(short_exp_img, cv2.COLOR_BGR2GRAY) else: long_exp_gray = long_exp_img short_exp_gray = short_exp_img # 初始化256*256的联合直方图 joint_hist = np.zeros((max_val+1, max_val+1), dtype=np.int32) h, w = long_exp_gray.shape # 统计联合直方图 for i in range(h): for j in range(w): l_val = long_exp_gray[i, j] s_val = short_exp_gray[i, j] joint_hist[l_val, s_val] += 1 # 重置饱和相关的直方图条目 for l_val in range(max_val+1): for s_val in range(max_val+1): if is_saturation(l_val, threshold, max_val) or is_saturation(s_val, threshold, max_val): joint_hist[l_val, s_val] = 0 return joint_hist # 示例用法 if __name__ == "__main__": # 读取长短曝光图像 long_img = cv2.imread("long_exposure.jpg") short_img = cv2.imread("short_exposure.jpg") processed_hist = reset_saturation_hist(long_img, short_img, threshold=10)
注意事项
- 若处理的是16位图像,将
max_val参数修改为65535即可,阈值可根据实际场景的过曝程度调整。 - 三通道图像可拆分BGR三个通道分别处理,再将每个通道的直方图结果代入后续融合流程。
- 上述代码为了逻辑清晰使用循环实现,处理大尺寸图像时可通过
numpy.histogram2d生成联合直方图,再用布尔掩码批量重置饱和条目,运行效率会提升数倍。
内容的提问来源于stack exchange,提问作者Tùng Dương Quang
相关产品推荐
相关产品推荐

