基于vgg19神经网络模型实现风格转化的图像处理项目

from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import torch
import torch.optim as optim
from torchvision import transforms, models
#自动下载vgg19的参数文件并导入
vgg = models.vgg19(pretrained=True).features
#查看模型结构
#print(vgg)
for t in vgg.parameters():  #禁止模型的参数被反向传播更新,只改变图片
    t.requires_grad_(False)
#查看模型各层的参数
# for name, layer in vgg._modules.items():
#     print(name, layer)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
vgg.to(device)
#加载图片
def load_image(img_path, max_size=400, shape=None):
    #读入图像,并将图片转换为RGB三通道
    image = Image.open(img_path).convert('RGB')
    #压缩图片
    if max(image.size) > max_size:
        size = max_size
    else:
        size = max(image.size)
    if shape is not None:
        size = shape
    in_transform = transforms.Compose([
        transforms.Resize(size),
        transforms.ToTensor(),
        transforms.Normalize((0.485, 0.456, 0.406),
                             (0.229, 0.224, 0.225))])
    #给图片增加一个维度,使神经网络不报错
    image = in_transform(image)[:3, :, :].unsqueeze(0)
    return image
#读入原图
content = load_image('./data/1.jpg').to(device)
#读入风格图,并将其shape更改为与原图相同
style = load_image('./data/sty.jpg', shape=content.shape[-2:]).to(device)
print(style.cpu().numpy().squeeze().shape)
print(style.cpu().numpy().squeeze().transpose(1, 2, 0).shape)
print(style.cpu().numpy().squeeze().transpose(1, 2, 0).clip(0, 1).shape)
def im_convert(tensor):
    #将tensor类型的数据转换成Image,用于显示图像
    image = tensor.detach()
    image = image.cpu().numpy().squeeze()
    image = image.transpose(1, 2, 0)
    image = image * np.array((0.229, 0.224, 0.225)) + np.array((0.485, 0.456, 0.406))
    image = image.clip(0, 1)
    return image

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(20, 10))
ax1.imshow(im_convert(content))
ax1.set_title("Content Image", fontsize=20)
ax2.imshow(im_convert(style))
ax2.set_title("Style Image", fontsize=20)
plt.show()
print(vgg)
for i in vgg._modules.items():
    print(i)

#获取特定卷积层的输出的图像
def get_features(image, model, layers=None):
    if layers is None:
        layers = {'0': 'conv1_1',
                  '5': 'conv2_1',
                  '10': 'conv3_1',
                  '19': 'conv4_1',
                  '21': 'conv4_2',  ## content representation
                  '28': 'conv5_1'}

    features = {}
    x = image
    #便利model.modules
    for name, layer in model._modules.items():
        #module是一个字典,其k和value分别是第i层和第i层的内容,分别对应name和layer
        x = layer(x)
        #让图像经过该层,得到该层的输出图像对应的feature
        if name in layers: #相当于查询layers索引值的数组,既0,5,10,19,21,28
            features[layers[name]] = x
    return features


#生成gram矩阵
def gram(tensor):
    #tensor的四位:batch,长,宽,高
    _, d, h, w = tensor.size()
    #风格迁移的损失函数一般方式:拉平图片像素,损失内容信息,保留风格信息
    tensor = tensor.view(d, h * w)
    gram = torch.mm(tensor, tensor.t())
    return gram


content_features = get_features(content, vgg)
style_features = get_features(style, vgg)
for layer in style_features:
    print(layer)
content_features = get_features(content, vgg)
style_features = get_features(style, vgg)
style_grams = {layer: gram(style_features[layer]) for layer in style_features}
#requires_grad(True)可以是backward追踪梯度?对具体意义不甚了解,但默认false会报错
#to(device)指定cpu或gpu
target = content.clone().requires_grad_(True).to(device)



#风格损失函数,比重可自定义,更改不同层的比重会得到不同的结果
style_weights = {'conv1_1': 1.,
                 'conv2_1': 0.75,
                 'conv3_1': 0.2,
                 'conv4_1': 0.2,
                 'conv5_1': 0.2}
#风格和内容的权重
content_weight = 1
style_weight = 10e9
#每200次输出一张图
cnt = 200
#优化器
optimizer = optim.Adam([target], lr=0.003)
 #迭代次数4000
for ii in range(1, 4001):
    #获取合成画的特征
    target_features = get_features(target, vgg)
    #内容损失函数
    content_loss = torch.mean((target_features['conv4_2'] - content_features['conv4_2']) ** 2)
    #风格损失函数(初始值为0)
    style_loss = 0

    #比较每层gram矩阵的损失,并增添到styleloss中
    for layer in style_weights:
        #获取某层的合成画特征
        target_feature = target_features[layer]
        #该层gram矩阵
        target_gram = gram(target_feature)
        _, d, h, w = target_feature.shape
        style_gram = style_grams[layer]
        #风格损失函数
        layer_style_loss = style_weights[layer] * torch.mean((target_gram - style_gram) ** 2)
        style_loss += layer_style_loss / (d * h * w)
    #总损失函数
    total_loss = content_weight * content_loss + style_weight * style_loss

    #更新模型
    optimizer.zero_grad()
    total_loss.backward()
    optimizer.step()
    #每200次输出一张并保存
    if ii % cnt == 0:
        print('Total loss: ', total_loss.item())
        plt.imshow(im_convert(target))
        plt.savefig('result'+str(ii)+'.jpg')
        plt.show()

data:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
结果:
在这里插入图片描述在这里插入图片描述

  • 17
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
深度学习是一种机器学习的分支,其目标是通过模仿人脑神经网络的工作方式来模拟和理解人类的智能行为。TensorFlow是一个强大的深度学习框架,它提供了丰富的工具和函数来构建和训练神经网络模型。 在图像领域中,一项有趣的实验是图像风格迁移。这是一种技术,将一张图像的风格应用于另一张图像,创造出一幅以第一幅图像风格为基础的新图像。其中VGG-19是一种深度卷积神经网络模型,被广泛用于图像识别和图像风格迁移任务。 图像风格迁移实验基于VGG-19模型的步骤如下:首先,我们需要将待迁移的风格图像和内容图像加载到模型中。然后,通过计算内容图像和目标图像之间的差异来定义一个损失函数。该损失函数包括内容损失和风格损失两部分,内容损失用于保留内容图像的特征,风格损失用于学习风格图像的特征。 接下来,我们使用梯度下降的优化算法来最小化损失函数,从而生成目标图像。在每次迭代中,我们根据当前生成的图像的梯度来更新输入图像。 在实验过程中,我们可以观察到生成图像逐渐采用了风格图像的特征,并保留了内容图像的主要结构。通过调整不同的参数和迭代次数,我们可以获得不同风格和质量的图像。 综上所述,VGG-19模型的图像风格迁移实验利用了深度学习和TensorFlow的强大功能。它为我们提供了一种有趣的方式来创造具有不同风格的图像,并有助于我们更深入地理解和应用深度学习的原理和技术。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白话机器学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值