如何用Python的OpenCV实现无白色底色的模糊光斑透明叠加
解决方法
核心是通过提取光斑的渐变透明度掩码,让白色背景完全透明,只保留模糊光斑与街景图的自然混合,具体步骤如下:
1. 图像预处理
先读取两张图,确保尺寸一致(光斑图要匹配街景图的宽高):
import cv2 import numpy as np # 读取街景图(RGB格式)和光斑图(灰度模式,方便提取掩码) street = cv2.imread("kitti_street.jpg") flare_gray = cv2.imread("flare_white_bg.jpg", cv2.IMREAD_GRAYSCALE) # 统一两张图的尺寸 flare_gray = cv2.resize(flare_gray, (street.shape[1], street.shape[0]))
2. 生成渐变掩码
白色背景的灰度值是255,我们用255 - flare_gray生成掩码:白色背景对应掩码值0(完全透明),光斑区域则保留0255的渐变(光斑越亮,掩码值越高,混合时占比越大)。最后把掩码归一化到01范围,并扩展为3通道匹配街景图:
# 生成掩码,去除白色背景的影响 mask = 255 - flare_gray mask = mask / 255.0 # 归一化到0-1 mask = np.stack([mask]*3, axis=-1) # 转为3通道
3. 加权混合图像
把灰度光斑图转为彩色(如果你的光斑是彩色图,直接用彩色图即可),然后通过掩码控制混合比例,实现半透明光斑效果:
# 灰度光斑转彩色(彩色光斑可跳过此步) flare_color = cv2.cvtColor(flare_gray, cv2.COLOR_GRAY2BGR) # 加权混合:街景图保留(1-掩码)比例,光斑图保留掩码比例 result = (street * (1 - mask) + flare_color * mask).astype(np.uint8) # 保存或显示结果 cv2.imwrite("flare_street.jpg", result) cv2.imshow("Result", result) cv2.waitKey(0)
替代方案:RGBA通道叠加
如果之前尝试RGBA失败,问题大概率出在alpha通道的生成上。正确的做法是给光斑图添加渐变alpha通道,再与街景图叠加:
# 读取彩色光斑图并调整尺寸 flare_color = cv2.imread("flare_white_bg.jpg") flare_color = cv2.resize(flare_color, (street.shape[1], street.shape[0])) # 生成alpha通道:白色背景设为0,光斑区域渐变 gray_flare = cv2.cvtColor(flare_color, cv2.COLOR_BGR2GRAY) alpha = 255 - gray_flare # 合并为RGBA图像 flare_rgba = cv2.merge([flare_color[:, :, 0], flare_color[:, :, 1], flare_color[:, :, 2], alpha]) # 街景图转RGBA street_rgba = cv2.cvtColor(street, cv2.COLOR_BGR2BGRA) # 手动计算叠加(避免cv2.overlayImages的兼容性问题) alpha_norm = alpha / 255.0 result_rgba = (street_rgba[:, :, :3] * (1 - alpha_norm[:, :, None]) + flare_rgba[:, :, :3] * alpha_norm[:, :, None]).astype(np.uint8)
关键提醒
- 别直接用
cv2.addWeighted,白色背景会被当成有效像素混入,导致白色残留。 - 必须用渐变掩码,硬二值化会让光斑边缘出现锯齿,破坏模糊效果。
- 如果光斑图的白色不是纯255,用
cv2.inRange提取背景区域后再生成掩码即可。
内容的提问来源于stack exchange,提问作者Nitin Augustine
相关产品推荐
相关产品推荐

