基于First Order Motion实现人脸表情迁移

1. 项目概述

深度学习中很多技术都可以用来做一些极具趣味性的应用,比如之前全网火爆的 “蚂蚁呀嘿” 就可以使用PaddleGAN的动作迁移模型来实现。除此之外,如果给照片中的人物赋予一个规定动作,那么该模型还可以让老照片中的故人“动起来”,做出你指定的动作,帮助人们以全新的视角看看过去的照片。

本案例基于飞桨PaddleGAN实现人脸表情迁移,提供预训练模型,无需训练可直接使用,快速实现表情迁移效果。

首先用它来 “复活” 一下祖师爷——现代计算机科学的先驱人工智能之父阿兰·图灵:

faceboxes anchor 偏移_计算机视觉



同时,也支持多位故人同时 “动起来”,比如下面这张居里夫妇的照片:



faceboxes anchor 偏移_paddlepaddle_02



链接指路: awesome-DeepLearning

2. 解决方案

本项目采用PaddleGAN动作迁移模型中的人脸表情迁移模型First Order Motion来实现图像动画(Image Animation)任务,即输入一张源图片和一个驱动视频,源图片中的人物会做出驱动视频中的动作。




faceboxes anchor 偏移_faceboxes anchor 偏移_03



图片来源:https://aliaksandrsiarohin.github.io/first-order-model-website/

如上图所示,源图像(第一列图片)中包含一个主体,驱动视频(第一行图片)包含一系列动作。给定源图片和驱动视频后,通过First Order Motion模型会生成一个新的视频,其主体是源人物,新生成的视频中源人物的表情由驱动视频中的表情决定。

下图简单的展现了其中的原理:



faceboxes anchor 偏移_faceboxes anchor 偏移_04



只需准备一张图片和一段驱动视频,即可实现人脸表情迁移。

3. 数据准备

本项目提供了上图中使阿兰·图灵动起来的驱动视频和原始图片。数据保存在 work 文件夹下。驱动视频路径为 work/driving_video.MOV,原始图片路径为 work/image.jpeg。你也可使用自己准备的视频和照片。

4. 模型推理

下载PaddleGAN并安装相关包

在进行动作表情迁移前,需要先下载PaddleGAN并安装相关包。具体命令如下:

# 从github/gitee上下载PaddleGAN的代码,只需在第一次运行项目时下载即可
# github下载可能速度较慢,推荐通过gitee下载
#!git clone https://github.com/PaddlePaddle/PaddleGAN
!git clone https://gitee.com/paddlepaddle/PaddleGAN.git
Cloning into 'PaddleGAN'...
remote: Enumerating objects: 326, done.[K
remote: Counting objects: 100% (326/326), done.[K
remote: Compressing objects: 100% (193/193), done.[K
remote: Total 3705 (delta 180), reused 259 (delta 125), pack-reused 3379[K
Receiving objects: 100% (3705/3705), 157.63 MiB | 20.45 MiB/s, done.
Resolving deltas: 100% (2388/2388), done.
Checking connectivity... done.
# 这里使用PaddleeGAN develop版本
# 如遇版本更新导致后续命令运行报错,可使用我们提供的PaddleaddleGAN-develop.zip文件,uncomment如下代码进行解压
# !unzip -oq /home/aistudio/PaddleGAN-develop.zip
%cd PaddleGAN
!git checkout develop
/home/aistudio/PaddleGAN
Already on 'develop'
Your branch is up-to-date with 'origin/develop'.
# 安装所需安装包
!pip install -r requirements.txt
!pip install imageio-ffmpeg
%cd applications/

表情动作迁移

运行如下命令,实现表情动作迁移。其中,各参数的具体使用说明如下:

  • driving_video: 驱动视频,视频中人物的表情动作作为待迁移的对象。本项目中驱动视频路径为 “work/driving_video.MOV”,大家可以上传自己准备的视频,更换 driving_video 参数对应的路径;
  • source_image: 原始图片,视频中人物的表情动作将迁移到该原始图片中的人物上。这里原始图片路径使用 “work/image.jpeg”,大家可以使用自己准备的图片,更换 source_image 参数对应的路径;
  • relative: 指示程序中使用视频和图片中人物关键点的相对坐标还是绝对坐标,建议使用相对坐标,若使用绝对坐标,会导致迁移后人物扭曲变形;
  • adapt_scale: 根据关键点凸包自适应运动尺度;
  • ratio: 针对多人脸,将框出来的人脸贴回原图时的区域占宽高的比例,默认为0.4,范围为【0.4,0.5】

命令运行成功后会在ouput文件夹生成名为result.mp4的视频文件,该文件即为动作迁移后的视频。

!export PYTHONPATH=$PYTHONPATH:/home/aistudio/PaddleGAN && python -u tools/first-order-demo.py  --driving_video ~/work/driving_video.MOV  --source_image ~/work/image.jpeg --ratio 0.4 --relative --adapt_scale --output  ~/work

视频配乐

可以执行如下命令为视频配乐,生成的新视频保存为 work/output.mp4

!ffmpeg -y -i /home/aistudio/work/music.mov -i /home/aistudio/work/result.mp4 -strict -2 -q:v 1 /home/aistudio/work/output.mp4
ffmpeg version 2.8.15-0ubuntu0.16.04.1 Copyright (c) 2000-2018 the FFmpeg developers
  built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.10) 20160609
  configuration: --prefix=/usr --extra-version=0ubuntu0.16.04.1 --build-suffix=-ffmpeg --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --cc=cc --cxx=g++ --enable-gpl --enable-shared --disable-stripping --disable-decoder=libopenjpeg --disable-decoder=libschroedinger --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzvbi --enable-openal --enable-opengl --enable-x11grab --enable-libdc1394 --enable-libiec61883 --enable-libzmq --enable-frei0r --enable-libx264 --enable-libopencv
  libavutil      54. 31.100 / 54. 31.100
  libavcodec     56. 60.100 / 56. 60.100
  libavformat    56. 40.101 / 56. 40.101
  libavdevice    56.  4.100 / 56.  4.100
  libavfilter     5. 40.101 /  5. 40.101
  libavresample   2.  1.  0 /  2.  1.  0
  libswscale      3.  1.101 /  3.  1.101
  libswresample   1.  2.101 /  1.  2.101
  libpostproc    53.  3.100 / 53.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/home/aistudio/work/music.mov':
  Metadata:
    major_brand     : qt  
    minor_version   : 0
    compatible_brands: qt  
    creation_time   : 2021-03-16 07:40:06
  Duration: 00:00:09.52, start: 0.036712, bitrate: 130 kb/s
    Stream #0:0(und): Audio: mp3 (.mp3 / 0x33706D2E), 44100 Hz, stereo, s16p, 127 kb/s (default)
    Metadata:
      creation_time   : 2021-03-16 07:40:06
      handler_name    : Core Media Data Handler
Input #1, mov,mp4,m4a,3gp,3g2,mj2, from '/home/aistudio/work/result.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf58.20.100
  Duration: 00:00:08.37, start: 0.000000, bitrate: 92 kb/s
    Stream #1:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 512x384, 89 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandler
[1;36m[libx264 @ 0xbff980] [0m[0;33m-qscale is ignored, -crf is recommended.
[0m[1;36m[libx264 @ 0xbff980] [0musing cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 AVX2 LZCNT BMI2
[1;36m[libx264 @ 0xbff980] [0mprofile High, level 3.0
[1;36m[libx264 @ 0xbff980] [0m264 - core 148 r2643 5c65704 - H.264/MPEG-4 AVC codec - Copyleft 2003-2015 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=12 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to '/home/aistudio/work/output.mp4':
  Metadata:
    major_brand     : qt  
    minor_version   : 0
    compatible_brands: qt  
    encoder         : Lavf56.40.101
    Stream #0:0(und): Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p, 512x384, q=-1--1, 30 fps, 15360 tbn, 30 tbc (default)
    Metadata:
      handler_name    : VideoHandler
      encoder         : Lavc56.60.100 libx264
    Stream #0:1(und): Audio: aac ([64][0][0][0] / 0x0040), 44100 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      creation_time   : 2021-03-16 07:40:06
      handler_name    : Core Media Data Handler
      encoder         : Lavc56.60.100 aac
Stream mapping:
  Stream #1:0 -> #0:0 (h264 (native) -> h264 (libx264))
  Stream #0:0 -> #0:1 (mp3 (native) -> aac (native))
Press [q] to stop, [?] for help
frame=  251 fps=0.0 q=-1.0 Lsize=     265kB time=00:00:09.58 bitrate= 226.2kbits/s    
video:99kB audio:155kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 4.074175%
[1;36m[libx264 @ 0xbff980] [0mframe I:2     Avg QP:20.07  size:  8708
[1;36m[libx264 @ 0xbff980] [0mframe P:63    Avg QP:19.45  size:   960
[1;36m[libx264 @ 0xbff980] [0mframe B:186   Avg QP:24.35  size:   124
[1;36m[libx264 @ 0xbff980] [0mconsecutive B-frames:  1.2%  0.0%  0.0% 98.8%
[1;36m[libx264 @ 0xbff980] [0mmb I  I16..4:  2.9% 93.0%  4.0%
[1;36m[libx264 @ 0xbff980] [0mmb P  I16..4:  0.0%  0.2%  0.0%  P16..4: 23.1%  6.8%  2.9%  0.0%  0.0%    skip:66.9%
[1;36m[libx264 @ 0xbff980] [0mmb B  I16..4:  0.0%  0.0%  0.0%  B16..8: 13.2%  0.0%  0.0%  direct: 0.0%  skip:86.7%  L0:35.7% L1:63.8% BI: 0.5%
[1;36m[libx264 @ 0xbff980] [0m8x8 transform intra:92.3% inter:92.3%
[1;36m[libx264 @ 0xbff980] [0mcoded y,uvDC,uvAC intra: 76.8% 36.5% 1.5% inter: 2.1% 1.0% 0.0%
[1;36m[libx264 @ 0xbff980] [0mi16 v,h,dc,p: 25% 15% 11% 49%
[1;36m[libx264 @ 0xbff980] [0mi8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 21% 17% 19%  6%  7%  8%  7%  8%  7%
[1;36m[libx264 @ 0xbff980] [0mi4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 28% 14% 10%  4% 11% 14%  7%  7%  4%
[1;36m[libx264 @ 0xbff980] [0mi8c dc,h,v,p: 66% 15% 18%  1%
[1;36m[libx264 @ 0xbff980] [0mWeighted P-Frames: Y:0.0% UV:0.0%
[1;36m[libx264 @ 0xbff980] [0mref P L0: 56.9% 18.4% 19.5%  5.3%
[1;36m[libx264 @ 0xbff980] [0mref B L0: 88.3%  9.5%  2.1%
[1;36m[libx264 @ 0xbff980] [0mref B L1: 97.4%  2.6%
[1;36m[libx264 @ 0xbff980] [0mkb/s:96.47