幻影坦克应该很多人都见过,好像下面这张真·幻影坦克一样:
把上图保存下来查看就可以看到出现了新的图案。
这类图片基本上可以用于所有的聊天软件和社交平台,只要它们对于图片的展示方式都是缩略图用白色背景展示,点击进入大图的时候就会转换成黑色背景。
主要的实现方式有两种:
1. 通过棋盘格交错显示
2. 通过对黑白背景下的图片进行计算后合成新图片
这里使用了第二种实现方法,具体原理如下:
利用 PNG 图片中的 Alpha 通道,配合上背景的颜色就可以对原有的 RGB 通道进行滤波(又是这个罪恶的词语呢就),原本图片上的像素在黑白两色的背景下就可以显示出不同的颜色。为了操作的方便通常这些图都是转换成灰阶图,所以就剩下 Alpha 和 Gray 两个通道。
一个透明图片最后显示出来的效果是下面公式所示:
$$
Gray=Gray_{Front} \times Alpha \div 255 + Gray_{Back} \times (255 – Alpha)\div 255
$$
这样子如果需要已知两种显示模式下背景分别为:
$$
\begin{cases}
Gray_{Front} &= Gray_{White} \\
Gray_{Back} &=255
\end{cases}
$$
$$
\begin{cases}
Gray_{Front} &= Gray_{Black} \\
Gray_{Back} &=0
\end{cases}
$$
带入后解方程就可以得到:
$$
\begin{cases}
Alpha &= 255 + Gray_{Black} – Gray_{White} \\
Gray &=255 \times Gray_{Black}/Alpha
\end{cases}
$$
根据上面的公式,可以对两幅图进行计算然后生成最终的结果:
from PIL import Image
import sys
import numpy as np
def main(argv):
if len(argv) != 4:
print("Error")
pass
image_white = np.array(Image.open(argv[1]).convert("L"))
image_black = np.array(Image.open(argv[2]).convert("L"))
image_black = image_black * 0.3
a = 255.0 + image_black - image_white
g = 255.0 / a * image_black
g[g == np.inf] = 255.0
g.clip(0, 255)
a.clip(0, 255)
a = np.round(a, 0).astype("ubyte")
g = np.round(g, 0).astype("ubyte")
print("amax:%d gmax%d amin:%d gmin:%d" % (a.max(), g.max(), a.min(), g.min()))
result = np.dstack([g, g, g, a])
print(result.shape)
im = Image.fromarray(result, "RGBA")
im.save(argv[3], "PNG")
im.show()
if __name__ == '__main__':
main(sys.argv)
上面有修改的地方是对黑色背景下的图片进行了降低亮度的处理,可以避免最终计算结果超出 $0-255$ 的范围然最后的结果图变成下面的样子:
合成下面两幅图:
结果如下:
貌似效果一般,还需要进行一些修改。
可能会有后续更新的 Github 项目。
Reference
https://zhuanlan.zhihu.com/p/31164700
https://tieba.baidu.com/p/5299504995
https://github.com/Aloxaf/MirageTankGo
《“幻影坦克”》 有 1 条评论
带我飞