<commit_before>---
layout:     post
title:      Hello World
subtitle:   国际惯例，第一篇哈喽沃德
date:       2019-4-23
author:     ZHT
header-img: img/post-bg-miui6.jpg
catalog: true
tags:
    - 人工智能
    - 深度学习
    - 换脸
---


### 前言
从车牌识别、人脸识别、语音识别、智能问答、推荐系统到自动驾驶，人们在日常生活中都可能有意无意地使用到了人工智能技术（Artificial Intelligence）。

最近这几年，得益于数据的增多、计算能力的增强、学习算法的成熟以及应用场景的丰富，越来越多的人开始关注这一个“崭新”的研究领域：**深度学习**。从根源来讲，深度学习是机器学习的一个分支，是指一类问题以及解决这类问题的方法。

深度学习：人工智能的一个子领域，一类机器学习问题，主要解决**贡献度分配问题**。以神经网络为主要模型，越来越多地用来解决一些通用人工智能问题，比如推理、决策等。

神经网络：一种以（人工）神经元为基本单元的模型

不足：虽然深度学习取得了很大的成功，但是深度学习还不是一种可以解决一系列复杂问题的通用智能技术，而是解决单个问题的一系列技术。比如可以打败人类的AlphaGo只能下围棋，而不会一个简单的算术运算。

#### 神经网络与深度学习技术的基本原理
 
> 一个人在不接触对方的情况下，通过一种特殊的方式，和对方进行一系列的问答。如果在相当长时间内，他无法根据这些问题判断对方是人还是计算机，那么就可以认为这个计算机是智能的。
> 
>     — 阿兰·图灵 [1950]，《Computing Machinery and Intelligence 》

1. 深度学习问题是一个**机器学习**问题，指从有限样例中，通过算法总结出一般性的规律，并可以应用到新的未知数据上。比如，我们可以从一些历史病例的集合，总结出症状和疾病之间的规律。这样当有新的病人时，我们可以利用总结出来的规律，来判断这个病人得了什么疾病。

2. 和传统的机器学习不同，深度学习采用的模型一般比较复杂，指样本的原始输入到输出目标之间的数据流经过多个线性或非线性的**组件**（components）。因为每个组件都会对信息进行加工，并进而影响后续的组件。当我们最后得到输出结果时，我们并不清楚其中每个组件的贡献是多少。这个问题叫做**贡献度分配问题**。在深度学习中， 贡献度分配问题也经常翻译为信用分配问题或功劳分配问题。贡献度分配问题是一个很关键的问题，这关系到如何学习每个组件中的参数。

3. 目前可以比较好解决贡献度分配问题的模型是**人工神经网络**（Artificial NeuralNetwork，ANN）。人工神经网络，也简称神经网络，是一种受人脑神经系统的工作方式启发而构造的一种数学模型。
![](https://github.com/Fabsqrt/BitTigerLab/blob/master/ArtificialIntelligent/DeepFake/i/flow.png?raw=true)

#### 视频转图像
##### FFmpeg
FFmpeg提供了处理音频、视频、字幕和相关源数据的工具库。
核心的库包括：
* libavcodec提供了处理编码的能力
* libavformat实现了流协议、容器类型、基本的I/O访问
* libavutil包括哈希、解压缩等多样的功能
* libavfilter提供了链式修改音频和视频的能力
* libavdevice提供了对设备访问的抽象
* libswresample实现了混音等能力
* libswscale实现了颜色和尺度变换的能力
对外主要提供了三个工具
* ffmpeg用来处理多媒体内容
* ffplay是一个极简的播放器
* ffprobe是多媒体内容的分析工具
视频转图片的功能，可以通过以下命令来实现：
```
ffmpeg -i clipname -vf fps=framerate -qscale:v 2 "imagename.jpg"
```
把一个视频，按照固定的频率生成图片
### 人脸定位
#### 基本算法
人脸定位是一个相对成熟的领域，主要应用dlib库的相关功能。我们虽然可以定制一个人脸识别的算法，但是我们也可以使用已有的通用的人脸识别的函数库。

有两类算法，一类是HOG的脸部标记算法。
![](https://github.com/Fabsqrt/BitTigerLab/raw/master/ArtificialIntelligent/DeepFake/i/facial_landmarks1.jpg)
该算法的效果如上图。它将人脸分成了如下的区域：
* 眼睛（左/右）
* 眉毛（左/右）
* 鼻子
* 嘴
* 下巴

基于这些标记，我们不仅能够进行后续的换脸，也能检测脸的具体形态，眨眼状态等。例如，我们可以把这些点连在一起，得到更多的特征。
![](https://github.com/Fabsqrt/BitTigerLab/raw/master/ArtificialIntelligent/DeepFake/i/landmarked_face2.png)


具体较为复杂，专业术语较多没咋听懂，不过大致是通过计算每个点的亮度，然后把每个点表示为指向更黑的方向的向量，因为每个点的绝对值会受到环境的影响，但是相对值则比较稳定。因此，通过梯度变化的表示，能够准备出高质量的数据。

在新的图片上基于不同的起点和尺度寻找可行的区间，基于**非极大抑制**的方法来减少冗余和重复的，下图就是一个有冗余和去除冗余的情况，说白了就是**找一个最大概率的矩阵去覆盖掉和它过于重合的矩阵**，并且不断重复这个过程
![](https://github.com/Fabsqrt/BitTigerLab/raw/master/ArtificialIntelligent/DeepFake/i/hog_object_detection_nms.jpg)


有了轮廓之后，我们可以找到脸部标记。利用已经标记好的训练集来训练一个回归树的组合，从而用来预测。
![](https://github.com/Fabsqrt/BitTigerLab/raw/master/ArtificialIntelligent/DeepFake/i/facedot.png)
在这个基础上，就能够标记出这68个点。
![](https://github.com/Fabsqrt/BitTigerLab/raw/master/ArtificialIntelligent/DeepFake/i/68.jpg)
基于人脸的68个标记的坐标，可以计算人脸的角度，从而抠出摆正后的人脸。

### 人脸转换
人脸转换的基本原理是什么？假设让你盯着一个人的视频连续看上100个小时，接着又给你看一眼另外一个人的照片，接着让你凭着记忆画出来刚才的照片，你一定画的会很像第一个人的。

使用Autoencoder模型：编码器把输入图片进行压缩，再用输出解码器把图片进行还原，这样即使我们输入的是另外一个人脸，也会被Autoencoder编码成为一个类似原来的脸。

还需要把人脸共性相关的属性和人脸特性相关的属性进行学习。因此，我们对所有的脸都用一个统一的编码器，这个编码器的目的是学习人脸共性的地方；然后，我们对每个脸有一个单独的解码器，这个解码器是为了学习人脸个性的地方。这样当你用B的脸通过编码器，再使用A的解码器的话，你会得到一个与B的表情一致，但是A的脸。


### 从图片到视频
```
ffmpeg  -f image2 -i imagename%04d.jpg -vcodec libx264 -crf 15 -pix_fmt yuv420p output_filename.mp4
```

## 上手操作




需要准备：
1. 原视频，素材视频
2. 安装FakeApp2.2，CUDA9，cudnn，VisualStudio
3. 将core库解压放在安装目录下
4. 配置英伟达cudnn的环境变量

###### 原视频的截图
![](https://s2.ax1x.com/2019/04/28/EMtmPH.png)
###### 原视频截图的人脸定位
![](https://s2.ax1x.com/2019/04/28/EMtZIe.png)
###### 模型视频的截图
![](https://s2.ax1x.com/2019/04/28/EMtVaD.png)
###### 模型视频截图的人脸定位
![](https://s2.ax1x.com/2019/04/28/EMtnGd.png)
###### 训练模型文件
![](https://s2.ax1x.com/2019/04/28/EMtEVO.png)
###### 训练结果
![](https://s2.ax1x.com/2019/04/28/EMYUu6.png)

失败总结：
1. 这个软件的运行原理是什么？
通过对视频进行逐帧分析，将AB视频中的人脸提取出来，用聚类、模糊评判、变形、逼近等算法，对两张人脸表情进行同步，同步率可以用LOSS值表示，当同步到满意效果后，将A视频的人脸用B视频中提取并处理后的人脸，进行逐帧替换，替换完成之后合成新的视频A，换脸完成。
2. 如何才能得到满意的效果？
这个软件本质上是一种拟合算法，用B的脸去拟合A，正常的拟合过程，是一个数据收敛的过程，LOSS逐步减小，当LOSS缩小到极限值时，收敛完成，拟合成功，所以要得到好的效果，需要满足以下几个条件：
* AB两个集合（人脸）的数据范围必须接近，举个反例：A视频中全是侧脸，B视频中全是正脸，拟合效果肯定比较差，因为两者的脸部数据范围不同。所以，如果想要好的效果，首先，B中能够获得与A中人脸数据同样大（或者更大）的范围
* B的数据理论上应该大于A，被拟合对象A的数据范围应该被B覆盖，覆盖越多，拟合效果越好。反例1，A切出1000张脸，B只有10张，你用B去替换A，肯定不会有好结果；反例2，A分辨率720p，B分辨率480p，也不会有好结果；反例3，A人脸是百天的，B人脸是夜晚的，同样，没有好结果

3. A的数据波动范围不能太大！举个例子：A1是一个女主播对着镜头说话，全过程中脸的角度、远近几乎没变化，脸部也没有遮挡，这种情况可以认为数据波动很小。A2是一个科幻电影的女主角，全程都在快速切换镜头，脸部有各种遮挡，这种情况可以说是数据波动很大，被拟合对象A的数据波动越大，越难建立稳定的模型，拟合就越困难

4. 所需时间太长，硬件条件达不到，目前的750Ti运行太慢，正常一个几分钟的较好的视频片段需要一个好显卡跑至少十多个小时，计算量巨大<commit_msg>Update 2019-4-28-深度学习之换脸.md<commit_after>---
layout:     post
title:      深度学习之换脸
subtitle:   记一次失败的换脸
date:       2019-4-23
author:     ZHT
header-img: img/post-bg-miui6.jpg
catalog: true
tags:
    - 人工智能
    - 深度学习
    - 换脸
---


### 前言

从车牌识别、人脸识别、语音识别、智能问答、推荐系统到自动驾驶，人们在日常生活中都可能有意无意地使用到了人工智能技术（Artificial Intelligence）。

最近这几年，得益于数据的增多、计算能力的增强、学习算法的成熟以及应用场景的丰富，越来越多的人开始关注这一个“崭新”的研究领域：**深度学习**。从根源来讲，深度学习是机器学习的一个分支，是指一类问题以及解决这类问题的方法。

深度学习：人工智能的一个子领域，一类机器学习问题，主要解决**贡献度分配问题**。以神经网络为主要模型，越来越多地用来解决一些通用人工智能问题，比如推理、决策等。

神经网络：一种以（人工）神经元为基本单元的模型

不足：虽然深度学习取得了很大的成功，但是深度学习还不是一种可以解决一系列复杂问题的通用智能技术，而是解决单个问题的一系列技术。比如可以打败人类的AlphaGo只能下围棋，而不会一个简单的算术运算。

#### 神经网络与深度学习技术的基本原理

> 一个人在不接触对方的情况下，通过一种特殊的方式，和对方进行一系列的问答。如果在相当长时间内，他无法根据这些问题判断对方是人还是计算机，那么就可以认为这个计算机是智能的。
> 
>     — 阿兰·图灵 [1950]，《Computing Machinery and Intelligence 》

1. 深度学习问题是一个**机器学习**问题，指从有限样例中，通过算法总结出一般性的规律，并可以应用到新的未知数据上。比如，我们可以从一些历史病例的集合，总结出症状和疾病之间的规律。这样当有新的病人时，我们可以利用总结出来的规律，来判断这个病人得了什么疾病。

2. 和传统的机器学习不同，深度学习采用的模型一般比较复杂，指样本的原始输入到输出目标之间的数据流经过多个线性或非线性的**组件**（components）。因为每个组件都会对信息进行加工，并进而影响后续的组件。当我们最后得到输出结果时，我们并不清楚其中每个组件的贡献是多少。这个问题叫做**贡献度分配问题**。在深度学习中， 贡献度分配问题也经常翻译为信用分配问题或功劳分配问题。贡献度分配问题是一个很关键的问题，这关系到如何学习每个组件中的参数。

3. 目前可以比较好解决贡献度分配问题的模型是**人工神经网络**（Artificial NeuralNetwork，ANN）。人工神经网络，也简称神经网络，是一种受人脑神经系统的工作方式启发而构造的一种数学模型。
![](https://github.com/Fabsqrt/BitTigerLab/blob/master/ArtificialIntelligent/DeepFake/i/flow.png?raw=true)

#### 视频转图像

##### FFmpeg

FFmpeg提供了处理音频、视频、字幕和相关源数据的工具库。
核心的库包括：
* libavcodec提供了处理编码的能力
* libavformat实现了流协议、容器类型、基本的I/O访问
* libavutil包括哈希、解压缩等多样的功能
* libavfilter提供了链式修改音频和视频的能力
* libavdevice提供了对设备访问的抽象
* libswresample实现了混音等能力
* libswscale实现了颜色和尺度变换的能力

对外主要提供了三个工具
* ffmpeg用来处理多媒体内容
* ffplay是一个极简的播放器
* ffprobe是多媒体内容的分析工具

视频转图片的功能，可以通过以下命令来实现：
```
ffmpeg -i clipname -vf fps=framerate -qscale:v 2 "imagename.jpg"
```
把一个视频，按照固定的频率生成图片

### 人脸定位

#### 基本算法

人脸定位是一个相对成熟的领域，主要应用dlib库的相关功能。我们虽然可以定制一个人脸识别的算法，但是我们也可以使用已有的通用的人脸识别的函数库。

有两类算法，一类是HOG的脸部标记算法。
![](https://github.com/Fabsqrt/BitTigerLab/raw/master/ArtificialIntelligent/DeepFake/i/facial_landmarks1.jpg)
该算法的效果如上图。它将人脸分成了如下的区域：
* 眼睛（左/右）
* 眉毛（左/右）
* 鼻子
* 嘴
* 下巴

基于这些标记，我们不仅能够进行后续的换脸，也能检测脸的具体形态，眨眼状态等。例如，我们可以把这些点连在一起，得到更多的特征。
![](https://github.com/Fabsqrt/BitTigerLab/raw/master/ArtificialIntelligent/DeepFake/i/landmarked_face2.png)


具体较为复杂，专业术语较多没咋听懂，不过大致是通过计算每个点的亮度，然后把每个点表示为指向更黑的方向的向量，因为每个点的绝对值会受到环境的影响，但是相对值则比较稳定。因此，通过梯度变化的表示，能够准备出高质量的数据。

在新的图片上基于不同的起点和尺度寻找可行的区间，基于**非极大抑制**的方法来减少冗余和重复的，下图就是一个有冗余和去除冗余的情况，说白了就是**找一个最大概率的矩阵去覆盖掉和它过于重合的矩阵**，并且不断重复这个过程
![](https://github.com/Fabsqrt/BitTigerLab/raw/master/ArtificialIntelligent/DeepFake/i/hog_object_detection_nms.jpg)


有了轮廓之后，我们可以找到脸部标记。利用已经标记好的训练集来训练一个回归树的组合，从而用来预测。
![](https://github.com/Fabsqrt/BitTigerLab/raw/master/ArtificialIntelligent/DeepFake/i/facedot.png)
在这个基础上，就能够标记出这68个点。
![](https://github.com/Fabsqrt/BitTigerLab/raw/master/ArtificialIntelligent/DeepFake/i/68.jpg)
基于人脸的68个标记的坐标，可以计算人脸的角度，从而抠出摆正后的人脸。

### 人脸转换

人脸转换的基本原理是什么？假设让你盯着一个人的视频连续看上100个小时，接着又给你看一眼另外一个人的照片，接着让你凭着记忆画出来刚才的照片，你一定画的会很像第一个人的。

使用Autoencoder模型：编码器把输入图片进行压缩，再用输出解码器把图片进行还原，这样即使我们输入的是另外一个人脸，也会被Autoencoder编码成为一个类似原来的脸。

还需要把人脸共性相关的属性和人脸特性相关的属性进行学习。因此，我们对所有的脸都用一个统一的编码器，这个编码器的目的是学习人脸共性的地方；然后，我们对每个脸有一个单独的解码器，这个解码器是为了学习人脸个性的地方。这样当你用B的脸通过编码器，再使用A的解码器的话，你会得到一个与B的表情一致，但是A的脸。


### 从图片到视频

```
ffmpeg  -f image2 -i imagename%04d.jpg -vcodec libx264 -crf 15 -pix_fmt yuv420p output_filename.mp4
```

## 上手操作

需要准备：
1. 原视频，素材视频
2. 安装FakeApp2.2，CUDA9，cudnn，VisualStudio
3. 将core库解压放在安装目录下
4. 配置英伟达cudnn的环境变量

###### 原视频的截图
![](https://s2.ax1x.com/2019/04/28/EMtmPH.png)
###### 原视频截图的人脸定位
![](https://s2.ax1x.com/2019/04/28/EMtZIe.png)
###### 模型视频的截图
![](https://s2.ax1x.com/2019/04/28/EMtVaD.png)
###### 模型视频截图的人脸定位
![](https://s2.ax1x.com/2019/04/28/EMtnGd.png)
###### 训练模型文件
![](https://s2.ax1x.com/2019/04/28/EMtEVO.png)
###### 训练结果
![](https://s2.ax1x.com/2019/04/28/EMYUu6.png)
![](https://s2.ax1x.com/2019/04/28/EQ3kvV.png)

失败总结：
1. 这个软件的运行原理是什么？
通过对视频进行逐帧分析，将AB视频中的人脸提取出来，用聚类、模糊评判、变形、逼近等算法，对两张人脸表情进行同步，同步率可以用LOSS值表示，当同步到满意效果后，将A视频的人脸用B视频中提取并处理后的人脸，进行逐帧替换，替换完成之后合成新的视频A，换脸完成。
2. 如何才能得到满意的效果？
这个软件本质上是一种拟合算法，用B的脸去拟合A，正常的拟合过程，是一个数据收敛的过程，LOSS逐步减小，当LOSS缩小到极限值时，收敛完成，拟合成功，所以要得到好的效果，需要满足以下几个条件：
* AB两个集合（人脸）的数据范围必须接近，举个反例：A视频中全是侧脸，B视频中全是正脸，拟合效果肯定比较差，因为两者的脸部数据范围不同。所以，如果想要好的效果，首先，B中能够获得与A中人脸数据同样大（或者更大）的范围
* B的数据理论上应该大于A，被拟合对象A的数据范围应该被B覆盖，覆盖越多，拟合效果越好。反例1，A切出1000张脸，B只有10张，你用B去替换A，肯定不会有好结果；反例2，A分辨率720p，B分辨率480p，也不会有好结果；反例3，A人脸是百天的，B人脸是夜晚的，同样，没有好结果

3. A的数据波动范围不能太大！举个例子：A1是一个女主播对着镜头说话，全过程中脸的角度、远近几乎没变化，脸部也没有遮挡，这种情况可以认为数据波动很小。A2是一个科幻电影的女主角，全程都在快速切换镜头，脸部有各种遮挡，这种情况可以说是数据波动很大，被拟合对象A的数据波动越大，越难建立稳定的模型，拟合就越困难

4. 所需时间太长，硬件条件达不到，目前的750Ti运行太慢，正常一个几分钟的较好的视频片段需要一个好显卡跑至少十多个小时，计算量巨大
{'fraction_non_alphanumeric': 0.13580913311022347, 'fraction_numerical': 0.030227787973658642, 'mean_word_length': 9.61168384879725, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 25, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5988768', 'n_tokens_mistral': 7723, 'n_tokens_neox': 8543, 'n_words': 286}