本篇內(nèi)容主要講解“利用Python實現(xiàn)圖片風格遷移”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“利用Python實現(xiàn)圖片風格遷移”吧!
網(wǎng)站建設哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁設計、網(wǎng)站建設、微信開發(fā)、微信平臺小程序開發(fā)、集團企業(yè)網(wǎng)站建設等服務項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了靈川免費建站歡迎大家使用!
所謂圖片風格遷移,是指利用程序算法學習著名畫作的風格,然后再把這種風格應用到另外一張圖片上的技術。
舉個例子,見上圖。左邊是我們的原始圖片(也稱內(nèi)容圖像):小編在蘇州甪直古鎮(zhèn)的一座小橋上拍下的一張照片。
中間是我們的風格圖片:挪威表現(xiàn)派畫家愛德華·蒙克的代表作《吶喊》(The Scream)。
右邊是將愛德華·蒙克的《吶喊》的風格應用于原始圖片后生成的風格化結果圖。仔細觀察,圖片是如何保留了流水、房屋、房屋在水中的倒影,甚至遠處樹木的內(nèi)容,但卻運用了《吶喊》的風格,就好像愛德華·蒙克在我們的景色中運用了他高超的繪畫技巧一樣!
問題是,我們應該定義一個什么樣的神經(jīng)網(wǎng)絡來執(zhí)行圖片的風格遷移?
這可能嗎?
答案是:可以的。我將在下一節(jié)簡單討論如何基于神經(jīng)網(wǎng)絡來實現(xiàn)圖片風格的遷移。
Gatys等人在2015年發(fā)表了第一篇基于深度學習的風格遷移算法文章,原文鏈接為 https://arxiv.org/abs/1508.06576,隨后文章收錄于2016年的CVPR頂會。
有趣的是,他們提出了一種完全不需要新網(wǎng)絡架構的風格遷移算法,其使用的網(wǎng)絡構架是在前人的VGG19基礎上稍加改造而成的,而且網(wǎng)絡參數(shù)也使用預訓練(通常在ImageNet上)網(wǎng)絡的參數(shù)。我們來看下它的原理:
我們知道,卷積神經(jīng)網(wǎng)絡(CNN)具有很強的圖像特征(feature/representation)提取能力,如上圖所示。
對于內(nèi)容圖片,深層網(wǎng)絡(d和e)提取的是高維特征,同時也丟棄了細節(jié)信息;淺層網(wǎng)絡(a, b和c)提取的是低維特征,圖片的細節(jié)大多都保留下來了。
對于風格圖片,通過包含多層的特征相關性(Gram矩陣),可獲得多尺度圖像風格的重構,捕獲其紋理信息。這樣構建的網(wǎng)絡可以忽略圖像的具體細節(jié),保留風格。
為了將內(nèi)容圖片和風格圖片融合在一起(見下圖),我們應該使風格化結果圖(初始為一張白噪聲圖片)的特征同時與內(nèi)容圖片和風格圖片的特征之間的距離最小化,最終獲取我們所需的風格化結果圖。
因此生成目標圖片的損失函數(shù)可定義為:
其中α和β分別是內(nèi)容圖片和風格圖片的特征所占的權重,通過最小化這個損失函數(shù)就可以獲得我們想要的結果。來看個動態(tài)示意圖:
值得注意的是,這里優(yōu)化的參數(shù)不再是網(wǎng)絡的權重ω和偏差b,而是初始輸入的一張白噪聲圖片。
雖然上述方法可產(chǎn)生非常漂亮的風格遷移效果,但是速度很慢。
2016年,Johnson等人基于Gatys等人的工作,提出了一種速度可提高三個數(shù)量級的風格遷移算法。雖然算法的速度很快,但最大的缺點是不能像Gatys等人那樣隨意選擇你的風格圖片。針對每張風格圖片,你都需要訓練一個網(wǎng)絡來重現(xiàn)這個風格。一旦網(wǎng)絡模型訓練好之后,你就可將它應用于你想要的任何內(nèi)容圖片了。
這篇博客我們將使用Johnson等人的方法,其算法實現(xiàn)和預訓練模型可參考 https://github.com/jcjohnson/fast-neural-style。
下面利用OpenCV來快速實現(xiàn)圖片的風格遷移,我將其封裝成一個叫
style_transfer()
的函數(shù),其使用說明可參考函數(shù)內(nèi)部的注釋。目前只有11個預訓練模型可用。
1. `## 載入所需庫` 2. `import cv2` 3. `import time` 4. `def style_transfer(pathIn='',` 5. `pathOut='',` 6. `model='',` 7. `width=None,` 8. `jpg_quality=80):` 9. `'''` 10. `pathIn: 原始圖片的路徑` 11. `pathOut: 風格化圖片的保存路徑` 12. `model: 預訓練模型的路徑` 13. `width: 設置風格化圖片的寬度,默認為None, 即原始圖片尺寸` 14. `jpg_quality: 0-100,設置輸出圖片的質(zhì)量,默認80,越大圖片質(zhì)量越好` 15. `'''` 16. `## 讀入原始圖片,調(diào)整圖片至所需尺寸,然后獲取圖片的寬度和高度` 17. `img = cv2.imread(pathIn)` 18. `(h, w) = img.shape[:2]` 19. `if width is not None:` 20. `img = cv2.resize(img, (width, round(width*h/w)), interpolation=cv2.INTER_CUBIC)` 21. `(h, w) = img.shape[:2]` 23. `## 從本地加載預訓練模型` 24. `print('加載預訓練模型......')` 25. `net = cv2.dnn.readNetFromTorch(model)` 26. `## 將圖片構建成一個blob:設置圖片尺寸,將各通道像素值減去平均值(比如ImageNet所有訓練樣本各通道統(tǒng)計平均值)` 27. `## 然后執(zhí)行一次前饋網(wǎng)絡計算,并輸出計算所需的時間` 28. `blob = cv2.dnn.blobFromImage(img, 1.0, (w, h), (103.939, 116.779, 123.680), swapRB=False, crop=False)` 29. `net.setInput(blob)` 30. `start = time.time()` 31. `output = net.forward()` 32. `end = time.time()` 33. `print("風格遷移花費:{:.2f}秒".format(end - start))` 35. `## reshape輸出結果, 將減去的平均值加回來,并交換各顏色通道` 36. `output = output.reshape((3, output.shape[2], output.shape[3]))` 37. `output[0] += 103.939` 38. `output[1] += 116.779` 39. `output[2] += 123.680` 40. `output = output.transpose(1, 2, 0)` 42. `## 輸出風格化后的圖片` 43. `cv2.imwrite(pathOut, output, [int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality])`
來測試一下:
1. `>>> models = glob.glob('./*/*/*.t7')` 2. `>>> models ## 列出所有可用的預訓練模型` 3. `['.\\models\\eccv16\\composition_vii.t7',` 4. `'.\\models\\eccv16\\la_muse.t7',` 5. `'.\\models\\eccv16\\starry_night.t7',` 6. `'.\\models\\eccv16\\the_wave.t7',` 7. `'.\\models\\instance_norm\\candy.t7',` 8. `'.\\models\\instance_norm\\feathers.t7',` 9. `'.\\models\\instance_norm\\la_muse.t7',` 10. `'.\\models\\instance_norm\\mosaic.t7',` 11. `'.\\models\\instance_norm\\starry_night.t7',` 12. `'.\\models\\instance_norm\\the_scream.t7',` 13. `'.\\models\\instance_norm\\udnie.t7']` 15. `>>> pathIn = './img/img01.jpg'` 16. `>>> pathOut = './result/result_img01.jpg'` 17. `>>> model = './models/instance_norm/the_scream.t7'` 18. `>>> style_transfer(pathIn, pathOut, model, width=500)` 19. `加載預訓練模型......` 20. `風格遷移花費:1.18秒` 22. `>>> pathIn = './img/img02.jpg'` 23. `>>> pathOut = './result/result_img02.jpg'` 24. `>>> model = './models/instance_norm/starry_night.t7'` 25. `>>> style_transfer(pathIn, pathOut, model, width=500)` 26. `加載預訓練模型......` 27. `風格遷移花費:3.17秒` 29. `>>> pathIn = './img/img03.jpg'` 30. `>>> pathOut = './result/result_img03.jpg'` 31. `>>> model = './models/instance_norm/the_scream.t7'` 32. `>>> style_transfer(pathIn, pathOut, model, width=500)` 33. `加載預訓練模型......` 34. `風格遷移花費:0.90秒` 36. `>>> pathIn = './img/img04.jpg'` 37. `>>> pathOut = './result/result_img04.jpg'` 38. `>>> model = './models/eccv16/the_wave.t7'` 39. `>>> style_transfer(pathIn, pathOut, model, width=500)` 40. `加載預訓練模型......` 41. `風格遷移花費:2.68秒` 43. `>>> pathIn = './img/img05.jpg'` 44. `>>> model = './models/instance_norm/mosaic.t7'` 45. `>>> style_transfer(pathIn, pathOut, model, width=500)` 46. `加載預訓練模型......` 47. `風格遷移花費:1.23秒`
從運行結果可知,在CPU上,一張圖片的風格遷移所花的時間大概也就幾秒。如果使用GPU,完全可以實時對視頻/攝像頭進行風格遷移處理。
自Gatys等人第一次(2015年)實現(xiàn)基于深度學習的風格遷移以來,風格遷移技術仍一直在發(fā)展,如今在速度和質(zhì)量上都有了很大提高。目前的一些進展可以通過下面的鏈接來了解:
https://github.com/jcjohnson/fast-neural-style
https://github.com/DmitryUlyanov/texture_nets
https://github.com/luanfujun/deep-painterly-harmonization
https://junyanz.github.io/CycleGAN/
他們的一些作品:
1. 風格遷移
2. 外來圖片的融合
3. 圖片季節(jié)的變換
4. 圖片背景的虛化
5. 角色互換
到此,相信大家對“利用Python實現(xiàn)圖片風格遷移”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關內(nèi)容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!