Python对带光晕的图像进行去黑底黑色背景操作(附源码)

由于计算机图像一开始使用的颜色系统,是不包含透明度通道的,因此一些比较老的游戏里面的发光特效依然沿用基于线性减淡的图层混合方法来实现。对,说的就是你,DNF。在下发链接中大佬对此进行了科普。

去黑底和线性减淡的区别。,沃特碧们的Colg,DNF地下城与勇士 - COLG社区

我之前看了上述链接很久,还是感觉对于本小白来说,如何通过RGB通道滤色确定透明度的方法没有讲明白,因此今天有空专门研究了一下。

前置知识:

设实际显示的颜色为C=(r,g,b),前景色A、背景色B。

若前景色带Alpha通道(透明度通道),则C=αA+(1-α)B,0≤α≤1。

实例:先找两个特效,一明一暗,如下 ,都是来自俄罗斯手绘特效大师Dmitry Sarkisov的作品。

下面的他主页地址,会科学上网的可以去观摩下。
https://www.artstation.com/dmitrysarkisovicon-default.png?t=M85Bhttps://www.artstation.com/dmitrysarkisov

   

 假设背景是黑色的,处理流程如下:

1、分解gif,导入图片,指定模式为RGBA,将图片转为numpy数组;

2、对于每个像素点,求RGB三个通道的最大值,该值越大,说明像素的颜色越亮。则对应的透明度应该越低,这里直接用该值作为该像素的透明度;

3、希望最后生成的带透明度的图片A,在放在黑色背景B上时,实际显示的图片C与原图片一致。即C=αA+(1-α)B,B=(0,0,0);因此A=C/α。将原图的每个像素点的RGB值除以该像素点的透明度。

效果如下:

左边为透明通道+黑色背景。右边为原图。基本达到预期,该方法甚至没有黑边。

 

from PIL import Image
import numpy as np
from PIL import Image
import os

def RemoveBlackBackground(input_path:str,file_name:str,output_path:str):
    target_im = Image.open(os.path.join(input_path,file_name))
    target_im = target_im.convert('RGBA')
    target_img_array = np.array(target_im)
    #透明度
    target_img_Alpha = np.max(target_img_array[:,:,:3],axis=2)
    target_img_array[:,:,3] = target_img_Alpha
    #保证在黑色背景上时与原图一致
    target_img_Alpha = target_img_Alpha/255            
    target_img_array[:,:,:3]/target_img_Alpha.reshape([target_img_array.shape[0],-1,1])
    
    res_img = Image.fromarray(target_img_array)
    if not file.endswith(".png"):
        res_img.save(os.path.join(output_path,file_name[:-4]+".png"))
    else:
        res_img.save(os.path.join(output_path,file_name))

 之前的链接去黑底和线性减淡的区别。,沃特碧们的Colg,DNF地下城与勇士 - COLG社区

 中,提到的需要通过Gamma变换的去黑底方式这里也放出来一下

from PIL import Image
import numpy as np
from PIL import Image
import os

def RemoveBlackBackground2(input_path:str,file_name:str,output_path:str):
    target_im = Image.open(os.path.join(input_path,file_name))
    target_im = target_im.convert('RGBA')
    target_img_array = np.array(target_im)
    #透明度
    target_img_Alpha = np.max(target_img_array[:,:,:3],axis=2)
    #gamma变换
    target_img_dis = np.power((target_img_dis/255),3)*255
    target_img_array[:,:,3] = target_img_Alpha

    
    res_img = Image.fromarray(target_img_array)
    if not file.endswith(".png"):
        res_img.save(os.path.join(output_path,file_name[:-4]+".png"))
    else:
        res_img.save(os.path.join(output_path,file_name))

效果如下:

前者的饱和度和光晕会保留得更完整,且后者会有黑边

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值