深度学习实践——二十八图像风格迁移(

# 建议使用cpu版本运行

代码

导入包

import paddle
from paddle import ParamAttr
import paddle.nn as nn
import paddle.nn.functional as F
from paddle.nn import Conv2D,BatchNorm,Linear,Dropout,AdaptiveAvgPool2D,MaxPool2D,AvgPool2D
import numpy as np
import PIL
from sklearn.neighbors import KNeighborsRegressor
import os
from skimage import io
from skimage.color import rgb2lab,lab2rgb
from skimage.transform import resize
import matplotlib.pyplot as plt
import math

初始化风格图片

means = np.array([0.485, 0.456, 0.406])
# 风格图片的路径
image_style = io.imread('/home/aistudio/data/风车.png') 
image_style = image_style[:,:,:3]# 因为我的图片的维度是4(rgba),所以在这里取3维(rgb)
image_style = resize(image_style, (384,512))
image_style = (image_style - means) * 255
# 想要迁移风格的图片的路径
image_content = io.imread('/home/aistudio/data/星月夜.png')
image_content = image_content[:,:,:3] 
sz = image_content.shape[:2]
image_content = resize(image_content, (384,512))
image_content = (image_content - means) * 255

image_transfer = 0.3*image_content + 0.7*np.random.randint(-20, 20, (image_content.shape[0],image_content.shape[1],image_content.shape[2]))
print('初始化的迁移图像:')
plt.imshow(PIL.Image.fromarray(np.uint8(image_transfer/255+means)))
plt.show()
image_transfer = paddle.to_tensor(image_transfer[:,:,:,None].transpose([3,2,0,1]).astype('float32'), stop_gradient=False)

定义卷积快

class ConvBlock(nn.Layer):
    def __init__(self, input_channels, output_channels, groups, name=None):
        super(ConvBlock, self).__init__()

        self.groups = groups
        self._conv_1 = Conv2D(
            in_channels=input_channels,
            out_channels=output_channels,
            kernel_size=3,
            stride=1,
            padding=1,
            weight_attr=ParamAttr(name=name + "1_weights"),
            bias_attr=False)
        if groups == 2 or groups == 3 or groups == 4:
            self._conv_2 = Conv2D(
                in_channels=output_channels,
                out_channels=output_channels,
                kernel_size=3,
                stride=1,
                padding=1,
                weight_attr=ParamAttr(name=name + "2_weights"),
                bias_attr=False)
        if groups == 3 or groups == 4:
            self._conv_3 = Conv2D(
                in_channels=output_channels,
                out_channels=output_channels,
                kernel_size=3,
                stride=1,
                padding=1,
                weight_attr=ParamAttr(name=name + "3_weights"),
                bias_attr=False)
        if groups == 4:
            self._conv_4 = Conv2D(
                in_channels=output_channels,
                out_channels=output_channels,
                kernel_size=3,
                stride=1,
                padding=1,
                weight_attr=ParamAttr(name=name + "4_weights"),
                bias_attr=False)

        # self._pool = MaxPool2D(kernel_size=2, stride=2, padding=0)
        self._pool = AvgPool2D(kernel_size=2, stride=2, padding=0)

    def forward(self, inputs):
        conv1 = self._conv_1(inputs)
        x = F.relu(conv1)
        if self.groups == 2 or self.groups == 3 or self.groups == 4:
            conv2 = self._conv_2(x)
            x = F.relu(conv2)
        if self.groups == 3 or self.groups == 4:
            x = self._conv_3(x)
            x = F.relu(x)
        if self.groups == 4:
            x = self._conv_4(x)
            x = F.relu(x)
        x = self._pool(x)
        return x, conv1, conv2

定义网络(VGG19)


class VGGNet(nn.Layer):
    def __init__(self):
        super(VGGNet, self).__init__()
        self.groups = [2, 2, 4, 4, 4]
        self._conv_block_1 = ConvBlock(3, 64, self.groups[0], name="conv1_")
        self._conv_block_2 = ConvBlock(64, 128, self.groups[1], name="conv2_")
        self._conv_block_3 = ConvBlock(128, 256, self.groups[2], name="conv3_")
        self._conv_block_4 = ConvBlock(256, 512, self.groups[3], name="conv4_")
        self._conv_block_5 = ConvBlock(512, 512, self.groups[4], name="conv5_")

    def forward(self, inputs):
        x, conv1_1, _ = self._conv_block_1(inputs)
        x, conv2_1, _ = self._conv_block_2(x)
        x, conv3_1, _ = self._conv_block_3(x)
        x, conv4_1, conv4_2 = self._conv_block_4(x)
        _, conv5_1, _ = self._conv_block_5(x)
        return conv4_2, conv1_1, conv2_1, conv3_1, conv4_1, conv5_1

创建模型

vgg19 = VGGNet()
vgg19.set_state_dict(P.load('/home/aistudio/work/vgg19_ww.pdparams'))
vgg19.eval()

定义损失函数

# 内容损失
def contentloss(content, transfer):
    return 0.5 * P.sum((content - transfer)**2)
# 计算Gram矩阵
def gram(feature):
    _, c, h, w = feature.shape
    feature = feature.reshape([c,h*w])
    return P.matmul(feature, feature.transpose([1,0]))
# 风格损失
def styleloss(style, transfer, weight):
    loss = 0
    for i in range(len(style)):
        gram_style = gram(style[i])
        gram_transfer = gram(transfer[i])
        _, c, h, w = style[i].shape
        loss += weight[i] * P.sum((gram_style - gram_transfer)**2) / (2*c*h*w)**2
    return loss

# 定义trainer函数通过调用上面的函数实现函数的调用
def trainer(image_transfer, m, v, net, features_content, features_style, t, η):
    features_transfer = net(image_transfer)
    loss_content = contentloss(features_content[0], features_transfer[0])
    weight_style = [0.5,1.0,1.5,3.0,4.0]
    loss_style = styleloss(features_style[1:], features_transfer[1:], weight_style)
    loss = 1e0*loss_content + 1e3*loss_style
    net.clear_gradients()
    gradients = P.grad(loss, image_transfer)[0] 
    m,v=0,0
    image_transfer, m, v = adam(image_transfer, m, v, gradients, t, η)
    return image_transfer, m, v

定义adam优化器

def adam(image_transfer, m, v, g, t, η, β1=0.9, β2=0.999, ε=1e-8):
    m = β1*m + (1-β1)*g
    v = β2*v + (1-β2)*g**2
    m_hat = m / (1 - β1**t)
    v_hat = v / (1 - β2**t)
    image_transfer -= η*m_hat / (P.sqrt(v_hat) + ε)
    return image_transfer, m, v

定义训练函数


def train(image_transfer, net, epoch_num):
    features_content = net(P.to_tensor(image_content[:,:,:,None].transpose([3,2,0,1]).astype('float32')))
    features_style = net(P.to_tensor(image_style[:,:,:,None].transpose([3,2,0,1]).astype('float32')))
    m = P.zeros_like(image_transfer)
    v = P.zeros_like(image_transfer)

    for epoch in range(epoch_num):
        image_transfer, m, v = trainer(image_transfer, m, v, net, features_content, features_style, epoch+1, 2)

        if (epoch) % 50 == 0:
            print('Epoch: ', epoch+1)
            im = np.squeeze(image_transfer.numpy().transpose([2,3,1,0]))
            im = im/255 + means
            im = resize(im, sz)
            im = PIL.Image.fromarray(np.uint8(im*255))
            plt.imshow(im)
            plt.show()


训练模型

train(image_transfer, vgg19, 250)

问题

       skimage包的导入:

                1)直接导入
!pip install scikit-image
                2)使用镜像导入(不需要使用科技,速度很快)
# 不在paddle中使用去点 ! 就行
!pip install scikit-image -i https://pypi.tuna.tsinghua.edu.cn/simple
        预训练参数文件下载
                1)下载后上传(文件大小不能大于500M)
                2)在终端中下载
# 首先进入保存路径中(我的在work文件夹中)

cd work

# 使用wget导入

 wget https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/VGG19_pretrained.pdparams
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值