在之前的兩篇 GAN 系列文章--[GAN學習系列1]初識GAN以及[GAN學習系列2] GAN的起源中簡單介紹了 GAN 的基本思想和原理,這次就介紹利用 GAN 來做一個圖片修復的應用,主要採用的也是 GAN 在網路結構上的升級版--DCGAN,最初始的 GAN 採用的還是神經網路,即全連線網路,而 DCGAN 則是換成卷積神經網路(CNNs)了,這可以很好利用 CNN 強大的特徵提取能力,更好的生成質量更好的圖片。
原文是:
由於原文比較長,所以會分為 3 篇來介紹。
這篇文章的目錄如下:
- 介紹
- 第一步:將影象解釋為概率分佈中的樣本
- 如何填充缺失的資訊?
- 對於圖片在哪裡適配這些統計資料?
- 我們如何修復圖片呢?
- 第二步:快速生成假的圖片
- 從未知的概率分佈中學習生成新的樣本
- [ML-Heavy] 建立 GAN 模型
- 採用 G(z) 生成假的圖片
- [ML-Heavy] 訓練 DCGAN
- 目前的 GAN 和 DCGAN 實現
- [ML-Heavy] TensorFlow 實現 DCGAN
- 在你的資料集上執行 DCGAN 模型
- 第三步:為影象修復尋找最佳的假圖片
- 利用 DCGANs 實現影象修復
- [ML-Heavy] 損失函式
- [ML-Heavy] TensorFlow 實現 DCGANs 模型來實現影象修復
- 修復你的圖片
- 結論
- 對本文/專案的引用
- 供進一步閱讀的部分參考書目
- 一些未實現的對於 TensorFlow 和 Torch 的想法
本文會先講述背景和第一步的工作內容。
介紹
設計師和攝像師習慣使用一個非常強有力的工具--內容感知填充,來修復圖片中不需要或者缺失的部分。影象修復是指用於修復影象中缺失或者毀壞的部分割槽域。實現影象的修復有很多種方法。在本文中,介紹的是在 2016年7月26日發表在 arXiv 上的論文“Semantic Image Inpainting with Perceptual and Contextual Losses”,這篇論文介紹如何採用 DCGAN 來實現影象修復。這篇文章會即兼顧非機器學習背景和有機器學習背景的讀者,帶有 [ML-Heavy] 標籤的標題內容表示可以跳過這部分細節內容。我們只考慮有限制的修復帶有缺失畫素的人臉圖片的例子。TensorFlow 實現的原始碼可以在下面的 Github 地址上檢視:
我們將從以下三個步驟來完成圖片修復工作:
- 首先將影象解釋為概率分佈中的樣本
- 這樣的解釋步驟可以讓我們學習如何生成假的圖片
- 為修復圖片尋找最佳的生成圖片
下面是兩張修復前和修復後的圖片例子:
下面是本文將用到的帶有缺失區域的人臉例子:
第一步:將影象解釋為概率分佈中的樣本
如何填充缺失的資訊?
對於上述幾張圖片例子,假設你正在設計一個系列來填充這些缺失的區域,你會選擇如何做?你認為人腦會怎麼處理它呢?你需要使用哪些資訊來實現這個修復工作呢?
本文會主要關注下面兩種資訊:
- 上下文資訊(Contextual information):利用缺失畫素區域周圍畫素提供的資訊來填充
- 感知資訊(Perceptual information):將填充的部分解釋為“正常”,如同現實生活或者其他圖片中看到的一樣。
這兩種資訊都非常重要。沒有上下文資訊,你怎麼知道填充什麼資訊呢?沒有感知資訊,對於一個上下文來說會有很多種有效的填充方式。比如一些對於機器學習系統來說看上去是“正常”的填充資訊,但對於我們人類來說其實就是非常奇怪的填充內容。
因此,有一個即精確又直觀的捕獲這兩種屬性,並且可以解釋說明如何一步步實現影象修復的演算法是再好不過了。創造出這樣的演算法可能只會適用於特殊的例子,但通常都沒有人知道如何創造這樣的演算法。現在最佳的做法是使用統計資料和機器學習方法來實現一種近似的技術。
對於圖片在哪裡適配這些統計資料?
為了解釋這個問題,首先介紹一個非常好理解而且能簡明表示的概率分佈:正態分佈。下面是一個正態分佈的概率密度函式(probability density function, PDF)的圖示。你可以這麼理解 PDF,它是水平方向表示輸入空間的數值,在垂直方向上表示默寫數值發生的概率。
上面這張圖的繪製程式碼如下:
# !/usr/bin/env python3
import numpy as np
from scipy.stats import norm
import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt
plt.style.use('bmh')
import matplotlib.mlab as mlab
np.random.seed(0)
### 繪製一個正態分佈的概率密度函式圖###
# 生成資料 X範圍是(-3,3),步進為0.001, Y的範圍是(0,1)
X = np.arange(-3, 3, 0.001)
Y = norm.pdf(X, 0, 1)
# 繪製
fig = plt.figure()
plt.plot(X, Y)
plt.tight_layout()
plt.savefig("./images/normal-pdf.png")
複製程式碼
接著可以從上述分佈中取樣得到一些樣本資料,如下圖所示:
繪製程式碼如下:
### 繪製從正態分佈取樣的 1D 散點圖例子 ###
nSamples = 35
# np.random.normal 是從正態分佈中隨機取樣指定數量的樣本,這裡指定 35個
X = np.random.normal(0, 1, nSamples)
Y = np.zeros(nSamples)
fig = plt.figure(figsize=(7, 3))
# 繪製散點圖
plt.scatter(X, Y, color='k')
plt.xlim((-3, 3))
frame = plt.gca()
frame.axes.get_yaxis().set_visible(False)
plt.savefig("./images/normal-samples.png")
複製程式碼
這是 1 維概率分佈的例子,因為輸入資料就只是一維資料,我們也可以實現二維的例子,如下圖所示:
繪製程式碼如下:
### 繪製從正態分佈取樣的 2D 散點圖例子###
delta = 0.025
# 設定 X,Y 的數值範圍和步長值,分別生成 240個數
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-3.0, 3.0, delta)
print('x shape', x.shape)
# 根據座標向量來生成座標矩陣
X, Y = np.meshgrid(x, y) # X, Y shape: (240, 240)
print('X shape', X.shape)
print('Y shape', Y.shape)
# Bivariate Gaussian distribution for equal shape *X*, *Y*
# 等形狀的雙變數高斯分佈
Z = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) # Z shape (240, 240)
print('Z shape', Z.shape)
plt.figure()
# 繪製環形圖輪廓
CS = plt.contour(X, Y, Z)
plt.clabel(CS, inline=1, fontsize=10)
nSamples = 200
mean = [0, 0]
cov = [[1, 0], [0, 1]]
# 從多元正態分佈中取樣,得到結果圖中的黑點例子
X, Y = np.random.multivariate_normal(mean, cov, nSamples).T
plt.scatter(X, Y, color='k')
plt.savefig("./images/normal-2d.png")
複製程式碼
繪製上述三張圖的完整程式碼如下所示,程式碼地址為:
圖片和統計學之間的關鍵關係就是我們可以將圖片解釋為高維概率分佈的樣本。概率分佈就體現在圖片的畫素上。假設你正採用你的相機進行拍照,照片的畫素數量是有限的,當你用相機拍下一張照片的時候,就相當於從這個複雜的概率分佈中進行取樣的操作。而這個分佈也是我們用來定義一張圖片是否正常。和正態分佈不同的是,只有圖片,我們是不知道真實的概率分佈,只是在收集樣本而已。
在本文中,我們採用 RGB 顏色模型表示的彩色圖片。我們採用的是寬和高都是 64 畫素的圖片,所以概率分佈的維度應該是 64×64×3≈12k。
我們如何修復圖片呢?
首先為了更加直觀,我們先考慮之前介紹的多元正態分佈。給定x=1
時,y
最有可能的取值是什麼呢?這可以通過固定x=1
,然後最大化 PDF 的值來找到所有可能的y
的取值。如下圖所示:
上圖中垂直的黑色直線經過的黑點就是符合要求的y
值。
這個概念可以延伸到我們的影象概率分佈中,當我們知道某些數值,然後想填補完成缺失的數值的時候。只需要將它當做尋找所有可能缺失數值的最大問題,那麼找到的結果就是最有可能的圖片。
從視覺上觀察由正態分佈取樣得到的樣本,僅憑它們就找到概率密度函式是一件似乎很合理的事情。我們只需要選擇最喜歡的統計模型並將其與資料相適應即可。
然而,我們並不會應用這個方法。雖然從簡單分佈中恢復概率密度函式是很簡單,但這對於影象的複雜分佈是非常困難和棘手的事情。其複雜性一定程度上是來自於複雜的條件獨立性:影象中的每個畫素值之間都是相互依賴的。因此,最大化一個通用的概率密度函式是一個極其困難而且往往難以解決的非凸優化問題。
小結
第一篇主要介紹了影象修復的簡單背景,然後就是開始實現的第一步,也是比較偏理論,將我們待處理的圖片資料作為一個概率分佈的樣本,並簡單用程式碼實現了一維和二維的正態分佈函式圖。
在下一篇將介紹第二步內容,也就是快速生成假資料的工作。
歡迎關注我的微信公眾號--機器學習與計算機視覺,或者掃描下方的二維碼,在後臺留言,和我分享你的建議和看法,指正文章中可能存在的錯誤,大家一起交流,學習和進步!
我的個人部落格:
CSDN 部落格: