如何使用PIL的GaussianBlur模糊四边形内边缘并调整透明度
四边形图像内边缘模糊实现方案
原有代码问题
你对参数的判断是正确的:PIL.ImageFilter.GaussianBlur(80)中传入的80是高斯模糊半径,和透明度无关。
原有逻辑直接对整份alpha通道做全量高斯模糊,大模糊半径下模糊效果会自然渗透到图像中心区域,无法实现仅模糊内边缘的效果。
原有错误实现代码:
alpha = img_rotated_rgba.split()[-1] newalpha = numpy.array(alpha.filter(PIL.ImageFilter.GaussianBlur(80))) newalpha[numpy.array(alpha)==0] = 0 img_rotated_rgba.putalpha(PIL.Image.fromarray(newalpha))
修正思路
要实现仅模糊四边形内边缘、不影响中心清晰度,同时支持自定义透明度,核心逻辑是拆分蒙版分层处理:
- 先提取四边形的二值化alpha蒙版,区分完全透明区域、实体区域
- 通过蒙版腐蚀(向内收缩)+ 差集计算,单独提取出四边形的内边缘窄带区域
- 仅对边缘窄带做高斯模糊,中心区域始终保持完全不透明
- 单独给边缘区域配置透明度参数,实现自定义效果
可直接运行的修正代码
from PIL import Image, ImageFilter import numpy # ========== 自定义参数区 ========== blur_radius = 20 # 高斯模糊半径,数值越大边缘过渡越柔和 edge_width = 40 # 内边缘模糊带宽度,数值越大模糊覆盖的边缘范围越宽 edge_opacity = 0.3 # 边缘最外侧透明度,取值范围0~1,数值越小边缘越淡 # ================================= # 提取原始alpha通道 alpha = img_rotated_rgba.split()[-1] alpha_np = numpy.array(alpha) # 生成二值化四边形蒙版(非透明区值为255,透明区值为0) binary_mask = numpy.where(alpha_np > 0, 255, 0).astype(numpy.uint8) binary_mask_img = Image.fromarray(binary_mask) # 生成向内收缩后的蒙版,用于定位需要保留清晰效果的中心区域 eroded_mask = binary_mask_img.filter(ImageFilter.MinFilter(edge_width)) eroded_mask_np = numpy.array(eroded_mask) # 原始蒙版和收缩后蒙版做差集,得到仅包含内边缘的窄带蒙版 edge_mask_np = binary_mask - eroded_mask_np edge_mask_img = Image.fromarray(edge_mask_np) # 仅对边缘窄带做高斯模糊 blurred_edge_np = numpy.array(edge_mask_img.filter(ImageFilter.GaussianBlur(blur_radius))) # 合成最终alpha通道 new_alpha_np = numpy.zeros_like(alpha_np) # 中心区域保持完全不透明 new_alpha_np[eroded_mask_np > 0] = 255 # 边缘区域应用模糊+自定义透明度 edge_zone = edge_mask_np > 0 new_alpha_np[edge_zone] = (blurred_edge_np[edge_zone] * edge_opacity).astype(numpy.uint8) # 原始图像外的透明区域保持完全透明 new_alpha_np[alpha_np == 0] = 0 # 将新alpha通道应用回原图 img_rotated_rgba.putalpha(Image.fromarray(new_alpha_np))
参数调整指南
- 若模糊效果侵入中心清晰区域:调小edge_width参数,确保收缩后的蒙版完全覆盖需要保留清晰度的中心范围
- 若边缘过渡太生硬:调大blur_radius参数,拉长模糊过渡距离
- 若边缘颜色过深/过浅:调整edge_opacity参数,数值越低边缘越通透,数值越高边缘越接近原图不透明度
内容的提问来源于stack exchange,提问作者Kara
相关产品推荐
相关产品推荐

