用深度學習技術FCN自動生成口紅

  • 2019 年 10 月 3 日
  • 筆記

1 這個是什麼?

       基於全卷積神經網路(FCN)的自動生成口紅Python程式。


圖1 FCN生成口紅的效果(注:此兩張人臉圖來自人臉公開資料庫LFW)

2 怎麼使用了?

       首先能從這個Github (https://github.com/Kalafinaian/ai_lips_makeup) 中下載這個python項目。下載解壓後你得到這樣一個程式。


圖2 口紅Python程式

       本項目的運行環境為Python3.6,需要的深度學習包tensorflow , 臉部圖形處理包dlib,通用電腦視覺處理包cv2,以上三個python軟體包都可以通過如下pip命令按照

       pip install opencv-python
       pip instll dlib=19.16.0
       pip install tensorflow=1.12.0

       安裝好必要的python包後,就直奔主題說如何給一張人臉圖加上口紅,用pycharm打開項目運行main_predict.py。按照提示選擇口紅效果,再輸入人臉圖片的地址,最後加上口紅的照片會在test_out文件夾中存儲。


圖3 FCN口紅運行演示

       同理類似處理test_in文件夾下的002.jpg,那麼在test_out文件夾下可以獲得加上亮面口紅的人臉照片了。


圖4 FCN口紅的預測輸出

3 程式的原理

       這個基於全卷積神經網路的FCN口紅的工作原理如下 (釉面口紅為例)
       (1) 訓練集輸入為沒有口紅的人臉,訓練集輸出為有釉面口紅人臉,共170
個訓練集。(因版權原因本程式不提供完整人臉,只提供口紅照片)


圖5 沒有口紅的人臉

圖6 有釉面口紅的人臉(誠如所見,訓練集口紅都是人工PS的?)

       (2)使用dlib自帶的模型提取出人臉嘴唇,將所有嘴唇圖片resize到90×30的大小那麼訓練的輸入和輸出


圖7 訓練集原始嘴唇

圖8 訓練集對應釉面口紅輸出

       (3)構建一個三層全卷積神經網路
       (3.1)第一層輸入為30×90×3 (RGB三通道)的多維數組,所以第一層卷積輸入通道為3個,另定義輸出通道為24個,採用elu激活函數,沒有下取樣
       (3.2)根據第一層輸出通道可知第二層輸入為30×90×24的多維數組,另定義第二層輸出通道為45個,同樣採用elu激活函數,沒有下取樣
       (3.3)根據第二層輸出通道可知第三層輸入為30×90×45的多維數組,另定義第二層輸出通道為3個,同樣採用elu激活函數,沒有下取樣
       (3.4)定義損失函數為均方差損失,即loss等於第三次輸出和訓練輸出每個像素點差的平方求平均數。

       (4) 迭代訓練100詞,將模型參數保持為model文件夾中model_brightening
(詳細過程可見程式碼)

       (5) 高興的使用模型參數進行口紅生成

4 延伸閱讀(全卷積神經網路和ELU激活函數)

       簡單來說FCN將傳統CNN中的全連接層轉化成一個個的卷積層(本文中程式連pooling也省略了)。在傳統的CNN結構中,前N層是卷積層,倒數第二層是一個長度為4096的一維向量,倒數第一層是長度為1000的一維向量,對應1000個類別的概率。FCN將這3層表示為卷積層,卷積核的大小(通道數,寬,高)分別為(4096,1,1)、(4096,1,1)、(1000,1,1)。所有的層都是卷積層,故稱為全卷積網路。簡單來說FCN與CNN的區別在於FCN把CNN最後的全連接層換成卷積層,輸出一張已經label好的圖。


圖9 FCN演示圖

       關於FCN具體只是可參見UC Berkeley的Jonathan Long等人提出了Fully Convolutional Networks (FCN)[1]。

       然後再介紹一下ELU激活函數[2],這個函數長這樣的

[fleft( x right) = left{ begin{array}{l} x;;;;;;;;;;;;;;x > 0 \ alpha left( {{e^x} – 1} right);;;x le 0 \ end{array} right.,;f'left( x right) = left{ begin{array}{l} 1;;;;;;;;;;;;;;;x > 0 \ fleft( x right) + alpha ;;;x le 0 \ end{array} right.]

       在tensorflow中alpha默認取1(https://www.tensorflow.org/api_docs/
python/tf/nn/elu)。


圖10 ELU函數和其他幾個激活函數的影像

       Elu函數可以加速訓練並且可以提高分類的準確率。它有以下特徵:
       (1) elu由於其正值特性,可以像relu,lrelu,prelu一樣緩解梯度消失
       (2相比relu,elu存在負值,可以將激輸出均值往0推近,輸出均值接近0可以減少偏移效應進而使梯 度接近於自然梯度。
       (3) Lrelu和prelu雖然有負值存在,但是不能確保是一個雜訊穩定的去激活狀態。Elu在負值時是一個指數函數,對於輸入特徵只定性不定量

5 總結

       詳細過程看程式碼,具體原理讀論文。

推薦論文:

[1] Fully Convolutional Networks for Semantic Segmentation
(https://arxiv.org/abs/1411.4038)

[2] Fast and Accurate Deep Network Learning by Exponential Linear Units (ELUs)
(https://arxiv.org/abs/1511.07289v5)

推薦資源

http://vis-www.cs.umass.edu/lfw/
https://github.com/shelhamer/fcn.berkeleyvision.org