基於深度學習的圖像風格轉換


        距離上次寫博客已經好久好久好久了,真是懈怠的生活節奏,整天混吃等死玩游戲,前些日子做畢業設計時總算又學了點新東西。學了一點深度學習和卷積神經網絡的知識,附帶着詳細學習了一下前段時間我覺得比較有意思的圖像風格轉換。畢竟是初學,順便把神經網絡方面的知識也寫在前面了,便於理解。若有不對的地方的話,希望指正。

 

       主要參考的文獻有《A Neural Algorithm of Artistic Style》《Perceptual Losses for Real-Time Style Transfer and Super-Resolution》這兩篇論文,以及深度學習實踐:使用Tensorflow實現快速風格遷移等文章,代碼參考了OlavHN/fast-neural-stylehzy46/fast-neural-style-tensorflow等大神的。

 

        先說一下卷積神經網絡。卷積神經網絡(CNN)是一種前饋神經網絡,了解機器學習中人工神經網絡的話應該對這個概念不陌生。神經網絡中的感知器模型如下圖所示。

       輸入神經元與其各自權重相乘再相加得到z,利用激活函數g(z)進行變換得到神經元y。輸入層神經元與其權重相乘再相加的過程可以用矩陣相乘相乘來表示,這點在下面的卷及神經網絡里可以看到。神經網絡里輸入層和輸出層中間的是隱藏層。

       在卷積神經網絡里,網絡結構一般是由多個卷積層、非線性化層、池化層以及最后的全連接層組成。卷積層對輸入進行卷積計算,得到的結果經過非線性化層的激活函數,再經過池化層進行采樣,最后是全連接層。

       先介紹卷積操作。假設輸入圖片是二維矩陣,每個像素值都是輸入層的一個神經元,權值也用矩陣來表示,這個權值矩陣叫做卷積核,也可以成為濾波器,卷積核代表了你看這個圖像時的感受野。不過卷積核是與輸入圖片的二維矩陣滑動計算的,這里涉及到了權值共享的問題。計算的過程如下圖所示。

         圖中黃色部分為3x3卷積核,綠色的為5x5輸入矩陣。卷積核在輸入矩陣上滑動計算,每次都計算相應位置的乘積再相加,得到卷積后的矩陣中的新的元素。每次滑動的一格代表步長(stride)為1,也可以為其它值。然后再對右面矩陣的每一個得到的元素的值通過激勵函數進行非線性化處理,一般是用的ReLU函數。如下圖所示。

 

           池化層進行下采樣,目的是減小特征圖,池化規模一般為2×2。常用的池化方法之一是最大池化(Max Pooling),即取4個點的最大值,如下圖所示,非常簡單。

 

 

        卷積神經網絡通過這樣可以不斷提取圖像的不同層次的特征圖,然后用於分類問題等等。關於卷積神經網絡的詳細解釋可以參考卷積神經網絡全面解析卷積神經網絡的理解這兩篇文章,這里就不多作解釋了。下面進入正題,圖像風格轉換的原理。

 

圖像風格轉換

       

       以目前的深度學習技術,如果給定兩張圖像,完全有能力讓計算機識別出圖像具體內容。而圖像的風格是一種很抽象的東西,人眼能夠很有效地的辨別出不同畫家不同流派繪畫的風格,而在計算機的眼中,本質上就是一些像素,多層網絡的實質其實就是找出更復雜、更內在的特性(features),所以圖像的風格理論上可以通過多層網絡來提取圖像里面可能含有的一些有意思的特征。

       根據前面第一篇論文中提出的方法,風格遷移的速度非常慢的。在風格遷移過程中,把生成圖片的過程當做一個“訓練”的過程。每生成一張圖片,都相當於要訓練一次模型,這中間可能會迭代幾百幾千次。從頭訓練一個模型相對於執行一個已經訓練好的模型來說相當費時。現在根據前面第二篇論文提出的另一種模型,使得把生成圖片當做一個“執行”的過程,而不是一個“訓練”的過程。

       快速風格遷移的網絡結構包含兩個部分。一個是“生成網絡”(Image Transform Net),一個是“損失網絡”(Loss Network)。生成網絡輸入層接收一個輸入圖片,最終輸出層輸出也是一張圖片(即風格轉換后的結果)。模型總體分為兩個階段,訓練階段和執行階段。模型如圖所示。 其中左側是生成網絡,右側為損失網絡。

       訓練階段:選定一張風格圖片。訓練過程中,將數據集中的圖片輸入網絡,生成網絡生成結果圖片y,損失網絡提取圖像的特征圖,將生成圖片y分別與目標風格圖片ys和目標輸入圖片(內容圖片)yc做損失計算,根據損失值來調整生成網絡的權值,通過最小化損失值來達到目標效果。

       執行階段:給定一張圖片,將其輸入已經訓練好的生成網絡,輸出這張圖片風格轉換后的結果。

 

生成網絡

     

       對於生成網絡,本質上是一個卷積神經網絡,這里的生成網絡是一個深度殘差網絡,不用任何的池化層,取而代之的是用步幅卷積或微步幅卷積做網絡內的上采樣或者下采樣。這里的神經網絡有五個殘差塊組成。除了最末的輸出層以外,所有的非殘差卷積層都跟着一個空間性的instance-normalization,和RELU的非線性層,instance-normalization正則化是用來防止過擬合的。最末層使用一個縮放的Tanh來確保輸出圖像的像素在[0,255]之間。除開第一個和最后一個層用9x9的卷積核(kernel),其他所有卷積層都用3x3的卷積核。

 

損失網絡

       

        損失網絡φ是能定義一個內容損失(content loss)和一個風格損失(style loss),分別衡量內容和風格上的差距。對於每一張輸入的圖片x我們有一個內容目標yc一個風格目標ys,對於風格轉換,內容目標yc是輸入圖像x,輸出圖像y,應該把風格ys結合到內容x=yc上。系統為每一個目標風格訓練一個網絡。

        為了明確逐像素損失函數的缺點,並確保所用到的損失函數能更好的衡量圖片感知及語義上的差距,需要使用一個預先訓練好用於圖像分類的CNN,這個CNN已經學會感知和語義信息編碼,這正是圖像風格轉換系統的損失函數中需要做的。所以使用了一個預訓練好用於圖像分類的網絡φ,來定義系統的損失函數。之后使用同樣是深度卷積網絡的損失函數來訓練我們的深度卷積轉換網絡。

        這里的損失網絡雖然也是卷積神經網絡(CNN),但是參數不做更新,只用來做內容損失和風格損失的計算,訓練更新的是前面的生成網絡的權值參數。所以從整個網絡結構上來看輸入圖像通過生成網絡得到轉換的圖像,然后計算對應的損失,整個網絡通過最小化這個損失去不斷更新前面的生成網絡權值。

 

感知損失

     

       對於求損失的過程,不用逐像素求差構造損失函數,轉而使用感知損失函數,從預訓練好的損失網絡中提取高級特征。在訓練的過程中,感知損失函數比逐像素損失函數更適合用來衡量圖像之間的相似程度。

(1)內容損失

        上面提到的論文中設計了兩個感知損失函數,用來衡量兩張圖片之間高級的感知及語義差別。內容的損失計算用VGG計算來高級特征(內容)表示,因為VGG模型本來是用於圖像分類的,所以一個訓練好的VGG模型可以有效的提取圖像的高級特征(內容)。計算的公式如下:

 

        找到一個圖像 y使較低的層的特征損失最小,往往能產生在視覺上和y不太能區分的圖像,如果用高層來重建,內容和全局結構會被保留,但是顏色紋理和精確的形狀不復存在。用一個特征損失來訓練我們的圖像轉換網絡能讓輸出非常接近目標圖像y,但並不是讓他們做到完全的匹配

 

       (2)風格損失

       內容損失懲罰了輸出的圖像(當它偏離了目標y時),所以同樣的,我們也希望對輸出的圖像去懲罰風格上的偏離:顏色,紋理,共同的模式,等方面。為了達成這樣的效果,一些研究人員等人提出了一種風格重建的損失函數:讓φj(x)代表網絡φ的第j層,輸入是x。特征圖譜的形狀就是Cj x Hj x Wj、定義矩陣Gj(x)為Cj x Cj矩陣(特征矩陣)其中的元素來自於:

 

       如果把φj(x)理解成一個Cj維度的特征,每個特征的尺寸是Hj x Wj,那么上式左邊Gj(x)就是與Cj維的非中心的協方差成比例。每一個網格位置都可以當做一個獨立的樣本。這因此能抓住是哪個特征能帶動其他的信息。梯度矩陣可以很高效的計算,通過調整φj(x)的形狀為一個矩陣ψ,形狀為Cj x HjWj,然后Gj(x)就是ψψT/CjHjWj。風格重建的損失是定義的很好的,甚至當輸出和目標有不同的尺寸是,因為有了梯度矩陣,所以兩者會被調整到相同的形狀。

 

具體實現

       

       GitHub地址mrxlz/ImageStyleTransform,實現基本上參考了hzy的代碼,代碼從原版遷移到了python3.5,TensorFlow1.0,具體實現代碼基本沒變,加了一些注釋,添加了一個web頁面,效果如下。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM