pygame转cv2再转回Surface时alpha通道丢失,bloom效果出现黑边如何解决?
问题原因
- 你使用的
pygame.surfarray.array3d()仅读取Surface的RGB三色通道,直接丢弃了原有的alpha通道信息,透明区域默认被填充为黑色 - 后续的
set_colorkey((0,0,0))只能将纯黑色像素设为透明,高斯模糊后过渡区域的灰色像素无法被识别为透明,就会出现你遇到的黑边问题
修复方案
修改后的代码保留了alpha通道,全程用cv2处理不损失效率,可实现你要的白色到透明的平滑渐变效果:
import numpy as np import cv2 import pygame def Bloom(canvas: pygame.Surface): size = canvas.get_size() canvas_zero = canvas.copy() # 复制原画布避免修改原始对象 # 分别提取RGB通道和Alpha通道 rgb_arr = pygame.surfarray.array3d(canvas) alpha_arr = pygame.surfarray.array_alpha(canvas) # 合并为RGBA四通道数组,交换维度适配cv2的处理格式(pygame返回(w,h,c),cv2要求(h,w,c)) rgba_arr = np.dstack((rgb_arr, alpha_arr)).swapaxes(0,1) # 对RGB通道和Alpha通道同步做模糊,保证颜色和透明度都有平滑过渡 rgba_arr[:,:,:3] = cv2.GaussianBlur(rgba_arr[:,:,:3], ksize=(9,9), sigmaX=10, sigmaY=10) rgba_arr[:,:,:3] = cv2.blur(rgba_arr[:,:,:3], ksize=(9,9)) rgba_arr[:,:,3] = cv2.GaussianBlur(rgba_arr[:,:,3], ksize=(9,9), sigmaX=10, sigmaY=10) # 转换回pygame适配的维度格式 rgba_arr = rgba_arr.swapaxes(0,1) # 直接从四通道数组创建带完整alpha信息的Surface,不需要设置colorkey blur_surf = pygame.image.frombuffer(rgba_arr.tobytes(), size, "RGBA") # 合成最终效果 newCanvas = pygame.Surface(size, pygame.SRCALPHA) newCanvas.blit(blur_surf, (0,0)) newCanvas.blit(canvas_zero, (0,0)) return newCanvas
关键优化说明
- 全程保留alpha通道信息,没有丢弃透明数据
- 对alpha通道同步做模糊处理,天然实现了模糊区域从实色到完全透明的平滑过渡
- 处理效率和你原有cv2方案基本一致,不会出现PIL方案的帧率下跌问题
- 不需要再设置colorkey,彻底避免了黑边问题
内容的提问来源于stack exchange,提问作者Nath
相关产品推荐
相关产品推荐

