深度學習圖像風格遷移 - opencv python 計算機競賽

文章目錄

  • 0 前言
  • 1 VGG網絡
  • 2 風格遷移
  • 3 內容損失
  • 4 風格損失
  • 5 主代碼實現
  • 6 遷移模型實現
  • 7 效果展示
  • 8 最后

0 前言

🔥 優質競賽項目系列,今天要分享的是

🚩 深度學習圖像風格遷移 - opencv python

該項目較為新穎,適合作為競賽課題方向,學長非常推薦!

🥇學長這里給一個題目綜合評分(每項滿分5分)

  • 難度系數:3分
  • 工作量:3分
  • 創新點:4分

🧿 更多資料, 項目分享:

https://gitee.com/dancheng-senior/postgraduate

圖片風格遷移指的是將一個圖片的風格轉換到另一個圖片中,如圖所示:

在這里插入圖片描述
原圖片經過一系列的特征變換,具有了新的紋理特征,這就叫做風格遷移。

1 VGG網絡

在實現風格遷移之前,需要先簡單了解一下VGG網絡(由于VGG網絡不斷使用卷積提取特征的網絡結構和準確的圖像識別效率,在這里我們使用VGG網絡來進行圖像的風格遷移)。

在這里插入圖片描述
如上圖所示,從A-
E的每一列都表示了VGG網絡的結構原理,其分別為:VGG-11,VGG-13,VGG-16,VGG-19,如下圖,一副圖片經過VGG-19網絡結構可以最后得到一個分類結構。

在這里插入圖片描述

2 風格遷移

對一副圖像進行風格遷移,需要清楚的有兩點。

  • 生成的圖像需要具有原圖片的內容特征
  • 生成的圖像需要具有風格圖片的紋理特征

根據這兩點,可以確定,要想實現風格遷移,需要有兩個loss值:
一個是生成圖片的內容特征與原圖的內容特征的loss,另一個是生成圖片的紋理特征與風格圖片的紋理特征的loss。

而對一張圖片進行不同的特征(內容特征和紋理特征)提取,只需要使用不同的卷積結構進行訓練即可以得到。這時我們需要用到兩個神經網絡。

再回到VGG網絡上,VGG網絡不斷使用卷積層來提取特征,利用特征將物品進行分類,所以該網絡中提取內容和紋理特征的參數都可以進行遷移使用。故需要將生成的圖片經過VGG網絡的特征提取,再分別針對內容和紋理進行特征的loss計算。

在這里插入圖片描述
如圖,假設初始化圖像x(Input image)是一張隨機圖片,我們經過fw(image Transform Net)網絡進行生成,生成圖片y。
此時y需要和風格圖片ys進行特征的計算得到一個loss_style,與內容圖片yc進行特征的計算得到一個loss_content,假設loss=loss_style+loss_content,便可以對fw的網絡參數進行訓練。

現在就可以看網上很常見的一張圖片了:

在這里插入圖片描述
相較于我畫的第一張圖,這即對VGG內的loss求值過程進行了細化。

細化的結果可以分為兩個方面:

  • (1)內容損失
  • (2)風格損失

3 內容損失

由于上圖中使用的模型是VGG-16,那么即相當于在VGG-16的relu3-3處,對兩張圖片求得的特征進行計算求損失,計算的函數如下:

在這里插入圖片描述

簡言之,假設yc求得的特征矩陣是φ(y),生成圖片求得的特征矩陣為φ(y^),且c=φ.channel,w=φ.weight,h=φ.height,則有:

在這里插入圖片描述

代碼實現:

?

def content_loss(content_img, rand_img):content_layers = [('relu3_3', 1.0)]content_loss = 0.0# 逐個取出衡量內容損失的vgg層名稱及對應權重for layer_name, weight in content_layers:# 計算特征矩陣p = get_vgg(content_img, layer_name)x = get_vgg(rand_img, layer_name)# 長x寬xchannelM = p.shape[1] * p.shape[2] * p.shape[3]# 根據公式計算損失,并進行累加content_loss += (1.0 / M) * tf.reduce_sum(tf.pow(p - x, 2)) * weight# 將損失對層數取平均content_loss /= len(content_layers)return content_loss

4 風格損失

風格損失由多個特征一同計算,首先需要計算Gram Matrix

在這里插入圖片描述
Gram Matrix實際上可看做是feature之間的偏心協方差矩陣(即沒有減去均值的協方差矩陣),在feature
map中,每一個數字都來自于一個特定濾波器在特定位置的卷積,因此每個數字就代表一個特征的強度,而Gram計算的實際上是兩兩特征之間的相關性,哪兩個特征是同時出現的,哪兩個是此消彼長的等等,同時,Gram的對角線元素,還體現了每個特征在圖像中出現的量,因此,Gram有助于把握整個圖像的大體風格。有了表示風格的Gram
Matrix,要度量兩個圖像風格的差異,只需比較他們Gram Matrix的差異即可。 故在計算損失的時候函數如下:

在這里插入圖片描述
在實際使用時,該loss的層級一般選擇由低到高的多個層,比如VGG16中的第2、4、7、10個卷積層,然后將每一層的style loss相加。

在這里插入圖片描述
第三個部分不是必須的,被稱為Total Variation
Loss。實際上是一個平滑項(一個正則化項),目的是使生成的圖像在局部上盡可能平滑,而它的定義和馬爾科夫隨機場(MRF)中使用的平滑項非常相似。
其中yn+1是yn的相鄰像素。

代碼實現以上函數:

?

# 求gamm矩陣
def gram(x, size, deep):x = tf.reshape(x, (size, deep))g = tf.matmul(tf.transpose(x), x)return gdef style_loss(style_img, rand_img):style_layers = [('relu1_2', 0.25), ('relu2_2', 0.25), ('relu3_3', 0.25), ('reluv4_3', 0.25)]style_loss = 0.0# 逐個取出衡量風格損失的vgg層名稱及對應權重for layer_name, weight in style_layers:# 計算特征矩陣a = get_vgg(style_img, layer_name)x = get_vgg(rand_img, layer_name)# 長x寬M = a.shape[1] * a.shape[2]N = a.shape[3]# 計算gram矩陣A = gram(a, M, N)G = gram(x, M, N)# 根據公式計算損失,并進行累加style_loss += (1.0 / (4 * M * M * N * N)) * tf.reduce_sum(tf.pow(G - A, 2)) * weight# 將損失對層數取平均style_loss /= len(style_layers)return style_loss

5 主代碼實現

代碼實現主要分為4步:

  • 1、隨機生成圖片

  • 2、讀取內容和風格圖片

  • 3、計算總的loss

  • 4、訓練修改生成圖片的參數,使得loss最小

      * def main():# 生成圖片rand_img = tf.Variable(random_img(WIGHT, HEIGHT), dtype=tf.float32)with tf.Session() as sess:content_img = cv2.imread('content.jpg')style_img = cv2.imread('style.jpg')# 計算loss值cost = ALPHA * content_loss(content_img, rand_img) + BETA * style_loss(style_img, rand_img)optimizer = tf.train.AdamOptimizer(LEARNING_RATE).minimize(cost)sess.run(tf.global_variables_initializer())for step in range(TRAIN_STEPS):# 訓練sess.run([optimizer,  rand_img])if step % 50 == 0:img = sess.run(rand_img)img = np.clip(img, 0, 255).astype(np.uint8)name = OUTPUT_IMAGE + "//" + str(step) + ".jpg"cv2.imwrite(name, img)

    6 遷移模型實現

由于在進行loss值求解時,需要在多個網絡層求得特征值,并根據特征值進行帶權求和,所以需要根據已有的VGG網絡,取其參數,重新建立VGG網絡。
注意:在這里使用到的是VGG-19網絡:

在重建的之前,首先應該下載Google已經訓練好的VGG-19網絡,以便提取出已經訓練好的參數,在重建的VGG-19網絡中重新利用。

在這里插入圖片描述
下載得到.mat文件以后,便可以進行網絡重建了。已知VGG-19網絡的網絡結構如上述圖1中的E網絡,則可以根據E網絡的結構對網絡重建,VGG-19網絡:

在這里插入圖片描述
進行重建即根據VGG-19模型的結構重新創建一個結構相同的神經網絡,提取出已經訓練好的參數作為新的網絡的參數,設置為不可改變的常量即可。

?

def vgg19():layers=('conv1_1','relu1_1','conv1_2','relu1_2','pool1','conv2_1','relu2_1','conv2_2','relu2_2','pool2','conv3_1','relu3_1','conv3_2','relu3_2','conv3_3','relu3_3','conv3_4','relu3_4','pool3','conv4_1','relu4_1','conv4_2','relu4_2','conv4_3','relu4_3','conv4_4','relu4_4','pool4','conv5_1','relu5_1','conv5_2','relu5_2','conv5_3','relu5_3','conv5_4','relu5_4','pool5')vgg = scipy.io.loadmat('D://python//imagenet-vgg-verydeep-19.mat')weights = vgg['layers'][0]network={}net = tf.Variable(np.zeros([1, 300, 450, 3]), dtype=tf.float32)network['input'] = netfor i,name in enumerate(layers):layer_type=name[:4]if layer_type=='conv':kernels = weights[i][0][0][0][0][0]bias = weights[i][0][0][0][0][1]conv=tf.nn.conv2d(net,tf.constant(kernels),strides=(1,1,1,1),padding='SAME',name=name)net=tf.nn.relu(conv + bias)elif layer_type=='pool':net=tf.nn.max_pool(net,ksize=(1,2,2,1),strides=(1,2,2,1),padding='SAME')network[name]=netreturn network

由于計算風格特征和內容特征時數據都不會改變,所以為了節省訓練時間,在訓練之前先計算出特征結果(該函數封裝在以下代碼get_neck()函數中)。

總的代碼如下:

?

import tensorflow as tfimport numpy as npimport scipy.ioimport cv2import scipy.miscHEIGHT = 300WIGHT = 450LEARNING_RATE = 1.0NOISE = 0.5ALPHA = 1BETA = 500TRAIN_STEPS = 200OUTPUT_IMAGE = "D://python//img"STYLE_LAUERS = [('conv1_1', 0.2), ('conv2_1', 0.2), ('conv3_1', 0.2), ('conv4_1', 0.2), ('conv5_1', 0.2)]CONTENT_LAYERS = [('conv4_2', 0.5), ('conv5_2',0.5)]def vgg19():layers=('conv1_1','relu1_1','conv1_2','relu1_2','pool1','conv2_1','relu2_1','conv2_2','relu2_2','pool2','conv3_1','relu3_1','conv3_2','relu3_2','conv3_3','relu3_3','conv3_4','relu3_4','pool3','conv4_1','relu4_1','conv4_2','relu4_2','conv4_3','relu4_3','conv4_4','relu4_4','pool4','conv5_1','relu5_1','conv5_2','relu5_2','conv5_3','relu5_3','conv5_4','relu5_4','pool5')vgg = scipy.io.loadmat('D://python//imagenet-vgg-verydeep-19.mat')weights = vgg['layers'][0]network={}net = tf.Variable(np.zeros([1, 300, 450, 3]), dtype=tf.float32)network['input'] = netfor i,name in enumerate(layers):layer_type=name[:4]if layer_type=='conv':kernels = weights[i][0][0][0][0][0]bias = weights[i][0][0][0][0][1]conv=tf.nn.conv2d(net,tf.constant(kernels),strides=(1,1,1,1),padding='SAME',name=name)net=tf.nn.relu(conv + bias)elif layer_type=='pool':net=tf.nn.max_pool(net,ksize=(1,2,2,1),strides=(1,2,2,1),padding='SAME')network[name]=netreturn network# 求gamm矩陣def gram(x, size, deep):x = tf.reshape(x, (size, deep))g = tf.matmul(tf.transpose(x), x)return gdef style_loss(sess, style_neck, model):style_loss = 0.0for layer_name, weight in STYLE_LAUERS:# 計算特征矩陣a = style_neck[layer_name]x = model[layer_name]# 長x寬M = a.shape[1] * a.shape[2]N = a.shape[3]# 計算gram矩陣A = gram(a, M, N)G = gram(x, M, N)# 根據公式計算損失,并進行累加style_loss += (1.0 / (4 * M * M * N * N)) * tf.reduce_sum(tf.pow(G - A, 2)) * weight# 將損失對層數取平均style_loss /= len(STYLE_LAUERS)return style_lossdef content_loss(sess, content_neck, model):content_loss = 0.0# 逐個取出衡量內容損失的vgg層名稱及對應權重for layer_name, weight in CONTENT_LAYERS:# 計算特征矩陣p = content_neck[layer_name]x = model[layer_name]# 長x寬xchannelM = p.shape[1] * p.shape[2]N = p.shape[3]lss = 1.0 / (M * N)content_loss += lss * tf.reduce_sum(tf.pow(p - x, 2)) * weight# 根據公式計算損失,并進行累加# 將損失對層數取平均content_loss /= len(CONTENT_LAYERS)return content_lossdef random_img(height, weight, content_img):noise_image = np.random.uniform(-20, 20, [1, height, weight, 3])random_img = noise_image * NOISE + content_img * (1 - NOISE)return random_imgdef get_neck(sess, model, content_img, style_img):sess.run(tf.assign(model['input'], content_img))content_neck = {}for layer_name, weight in CONTENT_LAYERS:# 計算特征矩陣p = sess.run(model[layer_name])content_neck[layer_name] = psess.run(tf.assign(model['input'], style_img))style_content = {}for layer_name, weight in STYLE_LAUERS:# 計算特征矩陣a = sess.run(model[layer_name])style_content[layer_name] = areturn content_neck, style_contentdef main():model = vgg19()content_img = cv2.imread('D://a//content1.jpg')content_img = cv2.resize(content_img, (450, 300))content_img = np.reshape(content_img, (1, 300, 450, 3)) - [128.0, 128.2, 128.0]style_img = cv2.imread('D://a//style1.jpg')style_img = cv2.resize(style_img, (450, 300))style_img = np.reshape(style_img, (1, 300, 450, 3)) - [128.0, 128.2, 128.0]# 生成圖片rand_img = random_img(HEIGHT, WIGHT, content_img)with tf.Session() as sess:# 計算loss值content_neck, style_neck = get_neck(sess, model, content_img, style_img)cost = ALPHA * content_loss(sess, content_neck, model) + BETA * style_loss(sess, style_neck, model)optimizer = tf.train.AdamOptimizer(LEARNING_RATE).minimize(cost)sess.run(tf.global_variables_initializer())sess.run(tf.assign(model['input'], rand_img))for step in range(TRAIN_STEPS):print(step)# 訓練sess.run(optimizer)if step % 10 == 0:img = sess.run(model['input'])img += [128, 128, 128]img = np.clip(img, 0, 255).astype(np.uint8)name = OUTPUT_IMAGE + "//" + str(step) + ".jpg"img = img[0]cv2.imwrite(name, img)img = sess.run(model['input'])img += [128, 128, 128]img = np.clip(img, 0, 255).astype(np.uint8)cv2.imwrite("D://end.jpg", img[0])main()

7 效果展示

在這里插入圖片描述

8 最后

🧿 更多資料, 項目分享:

https://gitee.com/dancheng-senior/postgraduate

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/166693.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/166693.shtml
英文地址,請注明出處:http://en.pswp.cn/news/166693.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

uniapp高德、百度、騰訊地圖配置 SHA1

uniapp高德、百度、騰訊地圖配置 SHA1 當winr彈出cmd彈框后輸入 keytool -list -v -keystore debug.keystore 顯示keytool 不是內部或外部命令,也不是可運行的程序或批處理文件。可以先看看是否有下載jdk且配置了環境變量,具體操作如下:keyto…

please upgrade numpy version to >=1.20

升級 upgrade numpy_升級numpy-CSDN博客 pip install numpy --upgrade 沒有pip conda install numpy --upgrade 會報錯 conda list numpy來查看numpy版本 似乎這個numpy要看numpy-base這個 似乎沒有pip

【開源】基于JAVA的計算機機房作業管理系統

項目編號: S 017 ,文末獲取源碼。 \color{red}{項目編號:S017,文末獲取源碼。} 項目編號:S017,文末獲取源碼。 目錄 一、摘要1.1 項目介紹1.2 項目錄屏 二、功能模塊2.1 登錄注冊模塊2.2 課程管理模塊2.3 課…

K8S如何部署ActiveMQ(單機、集群)

前言 大家好,在今天的討論中,我們將深入研究如何將ActiveMQ遷移到云端,以便更好地利用Kubernetes的容器調度和資源管理能力,確保ActiveMQ的高可用性和可擴展性。 ActiveMQ是Apache開源組織推出的一款開源的、完全支持JMS1.1和J2…

申請二級域名

1、登錄騰訊云 騰訊云 產業智變云啟未來 - 騰訊 (tencent.com) 2、進入我的域名,點擊主域名 3、點擊前往DNSPod管理 4、點擊我的域名,然后點擊主域名 5、點擊添加記錄,進行添加二級域名信息 6、添加相應二級域名信息 7、添加后需要進行驗證…

系列一、Spring Framework

一、Spring Framework 1.1、概述 Spring是一個輕量級的開源的JavaEE框架;Spring可以解決企業應用開發的復雜性;Spring有兩個核心部分:IOC和AOP ① IOC:控制反轉,把創建對象的過程交給Spring進行管理; ② …

PSP - 從頭搭建 抗原類別 (GPCR) 的 蛋白質結構預測 項目流程

歡迎關注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/134595717 GPCRs(G Protein-Coupled Receptors,G蛋白偶聯受體),又稱為7次跨膜受體,是細…

界面組件Telerik UI for WinForms中文教程 - 創建明暗模式的桌面應用

黑暗模式現在在很多應用程序中都挺常見的,但如何在桌面應用程序中實現它呢?這很簡單,本文將為大家介紹如何使用一個類和命令行調用來實現! Telerik UI for WinForms擁有適用Windows Forms的110多個令人驚嘆的UI控件。所有的UI fo…

Appium 全新 2.0 全新跨平臺生態,版本特性搶鮮體驗!

關于Appium V2 Appium V2 beta版本在2021年發布,從2022年1月1號開始,Appium核心團隊不會再維護Appium 1.x版本了,所有近期官方發布的平臺驅動(如Android平臺的UIAutomator,IOS平臺的XCUITest)不再兼容Appi…

shrio----(1)基礎

文章目錄 前言 一、Shrio1、什么是shiro2、為什么使用shrio 二、主要類2.1、Subject2.2、SecurityManager2.3、Realms 三、認證授權3.1、認證(Authentication)3.2、授權(authorization)四、入門示例參考文章 前言 簡單入門介紹 一、Shrio http://shir…

【譯】Spring 6 入參數據校驗: 綜合指南

一、前言 在 Spring 6.1 中,有一個非常值得注意的重要改進——編程式驗證器實現。Spring 長期以來一直通過注解支持聲明式驗證,而 Spring 6.1 則通過提供專用的編程式驗證方法引入了這一強大的增強功能。 編程式驗證允許開發人員對驗證過程進行細粒度控…

網站定制開發有哪些分類?|企業軟件app小程序定制

網站定制開發有哪些分類?|企業軟件app小程序定制 網站定制開發是指根據客戶需求,為其量身定制設計和開發的網站服務。目前,網站定制開發主要分為以下幾個分類: 1. 靜態網站定制開發:靜態網站是由HTML、CSS和JavaScrip…

手寫promise(3)-- 實例方法 靜態方法

目錄 實例方法 catch finally 靜態方法 reslove reject race all allSettled any 實例方法 提供給promise實例的方法 包括catch 與finally catch Promise 實例的 catch() 方法用于注冊一個在 promise 被拒絕時調用的函數。它會立即返回一個等效的 Promise 對象&…

一文詳解 requests 庫中 json 參數和 data 參數的用法

在requests庫當中,requests請求方法,當發送post/put/delete等帶有請求體的請求時,有json和data2個參數可選。 眾所周知,http請求的請求體格式主要有以下4種: application/json applicaiton/x-www-from-urlencoded …

java堆文件排查

技術主題 在之前的開發的一個項目中,因為程序的一個bug,導致一些引用的對象一直沒有回收,從而導致堆內存一直在增大,老年代一直在增大,老年代進行堆積,后來的排查思路是通過dump堆的文件,然后對…

Dockerfile-CentOS7.9+Python3.11.2

本文為CentOS7.9下安裝Python3.11.2環境的Dockerfile # CentOS with Python3.11.2 # Author xxmail.com# build a new image with basic centos FROM centos:centos7.9.2009 # who is the author MAINTAINER xxmail.comRUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/…

vue的生命周期及不同階段狀態可以進行的行為

什么是vue的生命周期? Vue 的實例從創建到銷毀的過程 ,就是生命周期 ,也就是從開始創建 ,初始化數據 ,編譯模板 ,掛載Dom到渲染DOM ,更新數據再到渲染 ,卸載等一系列的過程 &#x…

OpenAI研發神秘“Q*”模型:科學家認輸,AI贏了人類關鍵一戰

圖片來源:視覺中國 作者丨葉蓁 編輯丨康曉 出品丨深網騰訊新聞小滿工作室 在山姆奧特曼(Sam Altman)被OpenAI前董事會突然罷免之前,數位研究人員向董事會發送了一封信,警告稱他們發現了一種能夠威脅到人類的強大人工…

IIS 基線安全加固操作

目錄 賬號管理、認證授權 ELK-IIS-01-01-01 ELK-IIS-01-01-02 ELK-IIS-01-01-03 ELK-IIS-01-01-04 日志配置 ELK-IIS-02-01-01 ELK-IIS-02-01-02 ??????? ELK-IIS-02-01-03 通信協議 ELK-IIS-03-01-01 設備其他安全要求 ELK-IIS-04-01-01 ??????? ELK-I…

【DDS】OpenDDS配置與使用

😏★,:.☆( ̄▽ ̄)/$:.★ 😏 這篇文章主要介紹OpenDDS配置與使用。 無專精則不能成,無涉獵則不能通。——梁啟超 歡迎來到我的博客,一起學習,共同進步。 喜歡的朋友可以關注一下,下次更…