0
雷鋒網(wǎng)按:本文作者phunter,文章來源大數(shù)據(jù)雜談。文中只要介紹了如何使用MXnet做出具有藝術(shù)風(fēng)格的照片。
Neural art:用機(jī)器模仿梵高
Neural art是個讓機(jī)器模仿已有畫作的繪畫風(fēng)格來把一張照片重新繪畫的算法,比如給一張貓的照片和一張梵高的自畫像,我們就可以得到用梵高風(fēng)格畫出來的貓,比如這個樣子(圖二為梵高在1889年的自畫像,引用自wikipedia):
Neural art算法來自于這篇論文 “A Neural Algorithm of Artistic Style” by Leon A. Gatys, Alexander S. Ecker, and Matthias Bethge,鏈接在http://arxiv.org/abs/1508.06576 有興趣的觀眾朋友們可以閱讀。
它的基本想法是,利用一個多層的卷積網(wǎng)絡(luò)(CNN)抽象出給定繪畫作品里一些高級的隱藏特征用來模仿繪畫風(fēng)格,并把這個繪畫風(fēng)格應(yīng)用到一個新的圖片上。這類的圖像生成模型是深度學(xué)習(xí)的一個方向,比如谷歌的Inception把一個羊的圖片和一個云的圖片生成羊形狀的云之類的“迷幻類”圖像也是類似模型的一種。Facebook也有類似的生成模型,他們基于這篇http://arxiv.org/abs/1406.2661由DMLC作者@antinucleon等人合作的文章。
Neural art算法模型有多種實(shí)現(xiàn)方式,比如這里和這里是兩個Lua/Torch版的實(shí)現(xiàn),這片論文的gitxiv下面也包含了五花八門的各種實(shí)現(xiàn),他們都是實(shí)現(xiàn)論文中的VGG模型并用caffe描述,下面的示例是用MXnet來實(shí)現(xiàn)。
MXnet的neural art范例在mxnet/example/neural-style/目錄下。因為這個例子需要大量的計算,推薦安裝GPU版的mxnet。安裝mxnet GPU版的教程參見前一集 http://phunter.farbox.com/post/mxnet-tutorial1 這里就不再重復(fù)。當(dāng)然了,mxnet的CPU和GPU無縫連接,如果沒有GPU可以使用CPU版本,只是需要每張圖耐心等待約40-50分鐘。
選擇安裝:mxnet可選使用cuDNN加速。對Neural art的例子,cuDNN v3和v4均可運(yùn)行,v4在我的GTX 960上比v3稍微快約2-3秒??梢院唵蔚膱?zhí)行這幾步:
如果之前沒有編譯安裝cuDNN版的mxnet,請在make/config.mk里把USE_CUDNN = 0修改為1重新編譯,并更新安裝對應(yīng)的python包。
如果你沒有安裝mxnet GPU版本的條件,也可以訪問以下這些網(wǎng)站或app玩一下Neural art。這個算法需要大量的GPU計算,以下這些免費(fèi)或收費(fèi)的實(shí)現(xiàn)都需要排隊。
Deepart:網(wǎng)址 https://deepart.io/ 用戶可以免費(fèi)提交,平均等待時間為1周左右,如果想插隊到24小時之內(nèi),可以捐款給網(wǎng)站。
Pikazo App:網(wǎng)址 http://www.pikazoapp.com/ 它相當(dāng)于把deepart這個網(wǎng)站做成app,需要收費(fèi)$2.99,也需要排隊。
AI Painter: 網(wǎng)址 https://www.instapainting.com/ai-painter 這是instapainting的一個業(yè)務(wù),免費(fèi),也是需要排隊。
觀眾朋友們?nèi)绻糜幸粋€裝了GPU版mxnet的機(jī)器的話,那我們就開始用mxnet自己動手豐衣足食,還可以幫朋友們生成有藝術(shù)感的微博頭像喲。以下例子中我用我妹 @dudulee的浪里格朗 家的美貓“破狗”的照片為例講解具體生成藝術(shù)圖的步驟。
mxnet使用的是論文中描述的VGG模型,在第一次使用的時候需要執(zhí)行download.sh下載該模型,mxnet的模型版本占約幾十MB的空間。下載模型完畢之后,可以把需要繪畫的原始圖片和模仿的圖片放到input目錄里,比如說破狗的照片和梵高的圖像,然后執(zhí)行:
耐心等待1-2分鐘,就可以看到結(jié)果保存在output目錄里,比如是這樣的:
如果給另外一張現(xiàn)代藝術(shù)油畫 'Blue Horse' Modern Equine Art Contemporary Horse Daily Oil Painting by Texas Artist Laurie Pace (鏈接https://www.pinterest.com/pin/407223991276827181/) 替代梵高的畫作讓機(jī)器學(xué)習(xí)風(fēng)格,破狗可以畫成這樣的:
run.py里有一些可以調(diào)整的參數(shù),如果想調(diào)試輸出效果可以按照如下解釋調(diào)整:
--model 指定模型。例子里暫時只有vgg這一個模型,以后可能添加前面提到的inception等其他模型。暫時先不用改。
--content-image 內(nèi)容圖片,比如上面的“破狗”的照片
--style-image 輸入的繪畫原作的路徑,比如上面的的“梵高自畫像”。
--stop-eps 模型里用eps值代表兩幅圖的風(fēng)格相似度,在訓(xùn)練的過程里會看到這個值逐漸收斂,值越小相似度越高。stop-eps參數(shù)指定的是收斂的終止值,一般越小就代表畫的越像,但如果太小了會需要很多的計算時間來收斂,默認(rèn)0.005已經(jīng)可以得到不錯的效果,可適當(dāng)減小到0.004等。
--content-weight --style-weight 內(nèi)容圖片和繪畫原作的相對權(quán)值,默認(rèn)是10:1,如果發(fā)現(xiàn)繪畫風(fēng)格過于強(qiáng)烈涂抹一片,可適當(dāng)修改為20:1或者30:1,反之改小。
--max-num-epochs 最大收斂步數(shù),默認(rèn)是1000步。不過一般畫作在200步左右就能找到差不多合適的eps風(fēng)格相似值,這個最大收斂步數(shù)不需要修改。
--max-long-edge 長邊最大邊長。程序會自動把輸入圖片按照這個值等比例縮放,比如上面的圖就是縮放到高度為512像素。程序運(yùn)行時間及內(nèi)存消耗約和圖片面積成正比,因為卷積網(wǎng)絡(luò)的計算量每個像素相關(guān),700像素的圖片差不多比500像素的圖片多一倍內(nèi)存和運(yùn)行時間。在接下來的對比測試?yán)锩婵梢钥吹剑?12像素的圖差不多需要1.4GB顯存,適合2G顯存的顯卡比如nvidia顯卡的macbook pro等娛樂一下就足夠了,4GB的顯卡差不多最高可以處理到850-900像素的圖片,要想上1080p就得有Titan X的12GB了。同樣的,計算時間也會相應(yīng)拉長,它也和顯卡的CUDA核心數(shù)約成反比?,F(xiàn)在你基本上明白了為什么上面提到的免費(fèi)版都需要排隊幾個小時到幾周不等了。
--lr logistic regression的梯度下降(SGD)學(xué)習(xí)率,用來尋找既在內(nèi)容上滿足“像破狗”又在風(fēng)格上“像梵高”的生成圖像。較大的eta收斂較快,節(jié)省計算時間但會在最小值附近跳躍。默認(rèn)值0.1,可以調(diào)整到0.2和0.3都可以。
--gpu 使用第幾個GPU,默認(rèn)是0號GPU,適合只有一塊顯卡的用戶(比如我家里的機(jī)器)。如果沒有GPU并能忍耐40分鐘左右算一張圖,--gpu -1也可以指定為純CPU計算。
--output 輸出文件名。
--save-epochs 是否保存中間結(jié)果,默認(rèn)每50步保存一下結(jié)果。
-remove-noise 降噪?yún)?shù),默認(rèn)0.2,可以降低一些為0.15,這就是高斯降噪的半徑。程序在學(xué)習(xí)模仿畫作的過程里會使用兩個白噪聲圖片逼近風(fēng)格圖和內(nèi)容圖,在最終生成的圖片里面可能殘留一些不必要的噪聲點(diǎn),程序里面可以降噪處理。
這個問題的答案在原論文里也語焉不詳,作者也沒有想解釋清楚。以下的討論均按我個人根據(jù)原文以及reddit和知乎上的相關(guān)討論在這里概述一下,更多討論詳情請參閱:reddit 知乎 這里一并感謝上述鏈接里的作者和評論者。
“繪畫風(fēng)格”是一個抽象定型的詞語,它可能和圖像的某種高階統(tǒng)計量相關(guān),但不同的繪畫風(fēng)格有不同的表示,對于一個沒有具體定義風(fēng)格的一般性問題,它很難用人工設(shè)計算法去完成。幸運(yùn)的是,我們知道卷積網(wǎng)絡(luò)CNN可以通過多層卷積提取物體的抽象特征完成物體識別(請參考Yann Lecun的深度學(xué)習(xí)教程),這一點(diǎn)“提取抽象特性”的能力被作者借用來描述“風(fēng)格”。也就是說,經(jīng)過多層CNN抽象之后的圖片丟棄了像素級的特征,而保留了高級的繪畫風(fēng)格。下圖引用自原論文圖1。在文章里,作者定義了一個5層的CNN網(wǎng)絡(luò),梵高的星空在通過第一二三層的時候保留了一些原圖的細(xì)節(jié),但是在第四第五層的時候,就變成了“看起來是梵高星空的樣子”這樣的抽象特征:
這時候作者機(jī)智的想到了,如果把一張梵高一張其他照片同時都放到這個CNN網(wǎng)絡(luò)里,經(jīng)過合適的調(diào)整讓第二張照片在第四五層接近梵高,而第一二三層保持和原來差不多,那就可以模仿梵高了!細(xì)節(jié)上,作者為了沿用了CNN的特征抽象能力使用了CNN作物體識別的VGG模型。
于是讓機(jī)器模仿繪畫風(fēng)格并生成圖片成了一個優(yōu)化問題:生成的圖像要像原內(nèi)容圖,比如我給一張貓的圖片最終還是要像貓;生成的圖像要像是由風(fēng)格圖畫的,比如我給了個梵高的圖,我生成的貓的圖片要看起來有梵高的風(fēng)格。也就是說要找到這樣一個中間結(jié)果,它的內(nèi)容表示(第一二三層CNN)接近于破狗,它的風(fēng)格的表示(第四第五層CNN)接近于梵高。在文章里,作者用一個白噪聲圖片通過梯度下降生成一個接近內(nèi)容圖的圖片,以及另一個白噪聲圖片生成一個接近繪畫圖風(fēng)格的圖片,并定義了神奇的描述紋理的gram matrix定義了這兩個圖的損失函數(shù)并加權(quán)平均當(dāng)作優(yōu)化目標(biāo)函數(shù),在mxnet的實(shí)現(xiàn)里通過梯度下降(SGD)完成收斂找到這樣一個內(nèi)容和風(fēng)格都搭配中間結(jié)果。舉例來說,“破狗”和“梵高自畫像”的生成過程的200多步的循環(huán)里,圖像的變化依次如下圖所示:
我們可以看到,在剛開始的幾十步里,圖片更像是原圖和繪畫的簡單紋理的疊加,而隨著循環(huán)步數(shù)增加,程序慢慢學(xué)習(xí)到了配色和筆觸的風(fēng)格,在150步左右基本成型,最終把破狗的照片繪畫成梵高的風(fēng)格。
事實(shí)上不是的,很多計算圖形學(xué)的論文已經(jīng)針對各種方向做出了一些成果,只是這篇文章利用了深度學(xué)習(xí)和CNN的方法,其他類似學(xué)習(xí)風(fēng)格的論文可以參考相關(guān)閱讀:
"A Parametric Texture Model Based on Joint Statistics of Complex Wavelet Coefficient" http://www.cns.nyu.edu/pub/lcv/portilla99-reprint.pdf這片文章用小波變換的方式提取了圖片紋理“風(fēng)格”所對應(yīng)的二階統(tǒng)計量,和本文提到的論文想法是一致的。
“Style Transfer for Headshot Portraits”
https://people.csail.mit.edu/yichangshih/portrait_web/ 這篇文章針對頭像照片的風(fēng)格做到了很快的風(fēng)格學(xué)習(xí),并且可以實(shí)時轉(zhuǎn)換視頻,對于這個有嚴(yán)格限制的問題,它的速度比Neural art高到不知道哪里去了。
作為深度學(xué)習(xí)和CNN的例子,Neural art確實(shí)很好玩,觀眾朋友們可以自己用MXnet給自己和朋友們生成有意思的藝術(shù)圖片,記得發(fā)到微博上加#mxnet#話題分享。值得提醒的是,如果原圖是半身人像類,建議也使用一些人像的畫作來學(xué)習(xí)風(fēng)格,比如“破狗”+“梵高”的組合;相對應(yīng)的,風(fēng)景圖片最好用風(fēng)景畫作風(fēng)格學(xué)習(xí)。因為風(fēng)景的表現(xiàn)重點(diǎn)和人像不同,強(qiáng)行把風(fēng)格畫到人像的照片上并不適合,它會看起來像是兩幅圖簡單疊加,這個即使是人類畫家也不好畫在一起。
雷鋒網(wǎng)注:本文轉(zhuǎn)自大數(shù)據(jù)雜談,如需轉(zhuǎn)載請聯(lián)系原作者。
更多:AI修圖藝術(shù):Prisma背后的奇妙算法 | 深度
雷峰網(wǎng)版權(quán)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。