背景
这个主题 r/deepfakes 在reddit上已经爆红一个多月了,可以百度下 ‘AI算法把女星面部嫁接到成人电影上:效果以假乱真’这篇文章有详细的介绍。
昨天主题的管理者在github上开源了自己的代码,并在reddit上新建了项目讨论,下面我们就来深入的解读一下。
deepfake采用的是face swap技术,从算法而言没有特殊之处,所以这个事情在学术上没有特别的价值。但是这个哥们从一个大众十分关注的点进行切入把技术做成应用并且爆红,说明他知道大家到都需要什么。有人会问,这样使用别人的图像做这种视频和图像不会被人告吗?这是一个很现实的例子,我给你一把锋利的菜刀,你是用他成为五星级厨神,还是连环杀人犯,跟这把刀没有一毛钱的关系,关键在于用刀的人。目前好像没有任何法律来限制这样的行为,在这里我们只学技术。
下面说正事
包
Keras、tensorflow、opencv-python、scikit-image 这几个都不用介绍了,大家都知道
face_recognition 这个包是python的用来找到面部的区域的,也就是说所有的替换和计算都是通过这个包找到了面布区域,然后在针对这个区域进行的操作
代码详解
模型也很简单66行搞定,位置在 lib/model.py,今天刚要发布这篇文章的时候发现源代码又更新了,增加了插件机制,主要代码也被放在了plugin目录。但是这篇文章还是以前版本为准,因为上一版本的代码好理解
#引入需要的包
from keras.models importModel
from keras.layers importInput,Dense,Flatten,Reshape
from keras.layers.advanced_activations importLeakyReLU
from keras.layers.convolutional importConv2D
from keras.optimizers importAdam
from.PixelShufflerimportPixelShuffler
# 这个PixelShuffler 层,完成图片高分辨率输出,用于将低分辨率的图片转化成高分辨率的图片,通俗的讲就是去马赛克。
# 相关理论和论文可以搜pixel shuffle自行寻找,这里用的是人写好了keras的PixelShuffler layer 代码在gist也有
optimizer =Adam(lr=5e-5, beta_1=0.5, beta_2=0.999) #优化器
IMAGE_SHAPE =(64,64,3)
ENCODER_DIM =1024
#卷积操作封装,一个2D的卷积后面跟一个LeakyReLU
def conv(filters):
def block(x):
x =Conv2D(filters, kernel_size=5, strides=2, padding='same')(x)
x =LeakyReLU(0.1)(x)
return x
return block
# 反卷积,所以用到了 PixelShuffler
def upscale(filters):
def block(x):
x =Conv2D(filters *4, kernel_size=3, padding='same')(x)
x =LeakyReLU(0.1)(x)
x =PixelShuffler()(x)
return x
return block
# 因为用了keras,所以每层之间的关系看起来就十分简单了,这里就不详述了
# 最后的操作肯定也是要压扁后送到全连接层在输出模型
# 这里不需要pooling和dropout,因为我们做的不是分类,所以不能丢失信息
# 编码器
defEncoder():
input_ =Input(shape=IMAGE_SHAPE)
x = input_
x = conv(128)(x)
x = conv(256)(x)
x = conv(512)(x)
x = conv(1024)(x)
x =Dense(ENCODER_DIM)(Flatten()(x))
x =Dense(4*4*1024)(x)
x =Reshape((4,4,1024))(x)
x = upscale(512)(x)
returnModel(input_, x)
# 解码器
defDecoder():
input_ =Input(shape=(8,8,512))
x = input_
x = upscale(256)(x)
x = upscale(128)(x)
x = upscale(64)(x)
x =Conv2D(3, kernel_size=5, padding='same', activation='sigmoid')(x)
returnModel(input_, x)
encoder =Encoder()
decoder_A =Decoder()
decoder_B =Decoder()
x =Input(shape=IMAGE_SHAPE)
#A和B是两个模型,分别是原型和替换
autoencoder_A =Model(x, decoder_A(encoder(x)))
autoencoder_B =Model(x, decoder_B(encoder(x)))
autoencoder_A.compile(optimizer=optimizer, loss='mean_absolute_error')
autoencoder_B.compile(optimizer=optimizer, loss='mean_absolute_error')
成果
效果跟训练数据有关,数据越丰富,效果越好。替换了一个杨幂做测试,我这个没多少照片,但是看着也有点意思了
参考
项目地址 :https://github.com/deepfakes/faceswap
PixelShuffler源码 :https://gist.github.com/t-ae/6e1016cc188104d123676ccef3264981
B站的UP也做过类似的视频 将神奇女侠替换成了杨幂: https://www.bilibili.com/video/av18366816/