地板图像分割后阴影丢失,如何添加人工阴影?替换L通道无效
问题描述
对带有不同纹理的地板图像进行分割后,地板上物体的阴影被去除了,请问是否有方法添加人工阴影?
尝试替换L通道的值,但似乎没有效果,代码如下:
input = cv2.imread(INPUT_IMG) input_lab = cv2.cvtColor(input , cv2.COLOR_BGR2LAB) input_L, input_A, input_B=cv2.split(input_lab) # 分割图像 seg_img = segment_img(INPUT_IMG, PATTERN, PROMPT) seg_lab = cv2.cvtColor(seg_img , cv2.COLOR_BGR2LAB) seg_L, seg_A, seg_B=cv2.split(seg_lab) merge_L_channel = cv2.addWeighted(input_L, 1 - ALPHA, seg_L, ALPHA, 0) merge_lab = cv2.merge([merge_L_channel, input_A, input_B]) output_img = cv2.cvtColor(merge_lab, cv2.COLOR_LAB2BGR)
解决方案
1. 提取原图像阴影蒙版并针对性叠加
直接全局加权L通道无效的核心原因是:你没有只针对原图像的阴影区域进行亮度融合,而是整体混合了全图的亮度通道,导致阴影特征被非阴影区域稀释。
具体步骤:
- 提取阴影蒙版:从原输入图像中分离出阴影区域,生成二值蒙版(阴影区域为白色,其余为黑色):
# 转换为灰度图,提取阴影区域 gray_input = cv2.cvtColor(input, cv2.COLOR_BGR2GRAY) # 自适应阈值分割阴影,可调整参数适配你的图像 shadow_mask = cv2.adaptiveThreshold(gray_input, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 形态学处理消除噪点,优化蒙版 kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)) shadow_mask = cv2.morphologyEx(shadow_mask, cv2.MORPH_CLOSE, kernel)
- 蒙版区域叠加阴影:仅在阴影蒙版覆盖的区域,将原图像的亮度信息与分割图的亮度融合:
# 分割图转LAB色彩空间 seg_lab = cv2.cvtColor(seg_img, cv2.COLOR_BGR2LAB) seg_L, seg_A, seg_B = cv2.split(seg_lab) # 仅在阴影区域混合原图像与分割图的L通道,权重可调整 seg_L[shadow_mask == 255] = cv2.addWeighted( seg_L[shadow_mask == 255], 0.3, input_L[shadow_mask == 255], 0.7, 0 ) # 合并通道得到带阴影的结果 merged_lab = cv2.merge([seg_L, seg_A, seg_B]) output_with_shadow = cv2.cvtColor(merged_lab, cv2.COLOR_LAB2BGR)
2. 基于物体轮廓的人工阴影生成
如果原图像阴影提取效果不佳,可根据分割出的物体轮廓,手动生成符合光照逻辑的阴影:
- 提取分割后物体的蒙版
- 根据光照方向偏移蒙版生成阴影形状
- 模糊并降低阴影亮度,叠加到分割图上
示例代码:
# 获取分割后物体的蒙版 seg_gray = cv2.cvtColor(seg_img, cv2.COLOR_BGR2GRAY) obj_mask = cv2.threshold(seg_gray, 200, 255, cv2.THRESH_BINARY_INV)[1] # 根据光照方向设置阴影偏移量(示例为右下方向) dx, dy = 10, 10 shadow_offset = np.zeros_like(obj_mask) shadow_offset[dy:, dx:] = obj_mask[:-dy, :-dx] # 模糊阴影边缘并降低亮度 shadow = cv2.GaussianBlur(shadow_offset.astype(np.float32), (15, 15), 0) shadow = (shadow * 0.5).astype(np.uint8) # 将阴影叠加到分割图的灰度通道 seg_img_gray = cv2.cvtColor(seg_img, cv2.COLOR_BGR2GRAY) seg_img_gray[shadow > 0] = cv2.addWeighted( seg_img_gray[shadow > 0], 1, shadow[shadow > 0], 1, 0 ) output_with_shadow = cv2.cvtColor(seg_img_gray, cv2.COLOR_GRAY2BGR)
3. 优化原L通道混合逻辑
若想继续使用L通道混合思路,需限制混合范围为阴影区域,而非全局操作,这样既保留分割图的纹理,又还原阴影特征。
内容的提问来源于stack exchange,提问作者Akshay Kumar
相关产品推荐
相关产品推荐

