text: import os
  import cv2
  import copy
  import argparse
  import numpy as np
  import matplotlib.pyplot as plt
  from PIL import Image
  
  import paddle
  from paddle.vision.models import vgg16
  from paddle.vision.transforms import transforms
  
  
  def load_image(image_path, max_size=400, shape=None):
      image = Image.open(image_path).convert('RGB')
  
      size = shape if shape is not None else max_size if max(
          image.size) > max_size else max(image.size)
  
      transform = transforms.Compose([
          transforms.Resize(size), transforms.Transpose(), transforms.Normalize(
              [123.675, 116.28, 103.53], [58.395, 57.120, 57.375])
      ])
      image = transform(image)[np.newaxis, :3, :, :]
      image = paddle.to_tensor(image)
      return image
  
  
  def image_restore(image):
      image = np.squeeze(image.numpy(), 0)
      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
  
  
  class StyleTransferModel(paddle.nn.Layer):
      def __init__(self):
          super(StyleTransferModel, self).__init__()
          # pretrained设置为true，会自动下载imagenet上的预训练权重并加载
          vgg = vgg16(pretrained=True)
          self.base_model = vgg.features
  
          for p in self.base_model.parameters():
              p.stop_gradient = True
          self.layers = {
              '0': 'conv1_1',
              '5': 'conv2_1',
              '10': 'conv3_1',
              '17': 'conv4_1',
              '19': 'conv4_2',  ## content representation
              '24': 'conv5_1'
          }
  
      def forward(self, image):
          outputs = []
          for name, layer in self.base_model.named_sublayers():
              image = layer(image)
              if name in self.layers:
                  outputs.append(image)
          return outputs
  
  
  class StyleTransferLoss(paddle.nn.Layer):
      def __init__(self,
                   content_loss_weight=1,
                   style_loss_weight=1e5,
                   style_weights=[1.0, 0.8, 0.5, 0.3, 0.1]):
          super(StyleTransferLoss, self).__init__()
          self.content_loss_weight = content_loss_weight
          self.style_loss_weight = style_loss_weight
          self.style_weights = style_weights
  
      def forward(self, *features):
          outputs = features[:6]
          labels = features[6:]
          content_features = labels[-1]
          style_features = labels[:-1]
  
          # 计算图像内容相似度的loss
          content_loss = paddle.mean((outputs[-2] - content_features)**2)
  
          # 计算风格相似度的loss
          style_loss = 0
          style_grams = [self.gram_matrix(feat) for feat in style_features]
          style_weights = self.style_weights
          for i, weight in enumerate(style_weights):
              target_gram = self.gram_matrix(outputs[i])
              layer_loss = weight * paddle.mean((target_gram - style_grams[i])**
                                                2)
              b, d, h, w = outputs[i].shape
              style_loss += layer_loss / (d * h * w)
  
          total_loss = self.content_loss_weight * content_loss + self.style_loss_weight * style_loss
          return total_loss
  
      def gram_matrix(self, A):
          if len(A.shape) == 4:
              _, c, h, w = A.shape
              A = paddle.reshape(A, (c, h * w))
          GA = paddle.matmul(A, paddle.transpose(A, [1, 0]))
  
          return GA
  
  
  def main():
      content = load_image(FLAGS.content_image)
      style = load_image(FLAGS.style_image, shape=tuple(content.shape[-2:]))
  
      net = StyleTransferModel()
      model = paddle.Model(net)
  
      style_loss = StyleTransferLoss()
  
      # 使用内容图像初始化要生成的图像
      target = net.create_parameter(shape=content.shape)
      target.set_value(content.numpy())
  
      optimizer = paddle.optimizer.Adam(
          parameters=[target], learning_rate=FLAGS.lr)
      model.prepare(optimizer, style_loss)
  
      content_fetures = model.predict_batch(content)
      style_features = model.predict_batch(style)
  
      # 将两个特征组合，作为损失函数的label传给模型
      feats = style_features + [content_fetures[-2]]
  
      # 训练5000个step，每500个step画一下生成的图像查看效果
      steps = FLAGS.steps
      for i in range(steps):
          outs = model.train_batch(target, feats)
          if i % 500 == 0:
              print('iters:', i, 'loss:', outs[0][0])
  
      if not os.path.exists(FLAGS.save_dir):
          os.makedirs(FLAGS.save_dir)
  
      # 保存生成好的图像
      name = FLAGS.content_image.split(os.sep)[-1]
      output_path = os.path.join(FLAGS.save_dir, 'generated_' + name)
      cv2.imwrite(output_path,
                  cv2.cvtColor((image_restore(target) * 255).astype('uint8'),
                               cv2.COLOR_RGB2BGR))
  
  
  if __name__ == '__main__':
      parser = argparse.ArgumentParser("Resnet Training on ImageNet")
      parser.add_argument(
          "--content-image",
          type=str,
          default='./images/chicago_cropped.jpg',
          help="content image")
      parser.add_argument(
          "--style-image",
          type=str,
          default='./images/Starry-Night-by-Vincent-Van-Gogh-painting.jpg',
          help="style image")
      parser.add_argument(
          "--save-dir", type=str, default='./output', help="output dir")
      parser.add_argument(
          "--steps", default=5000, type=int, help="number of steps to run")
      parser.add_argument(
          '--lr',
          '--learning-rate',
          default=1e-3,
          type=float,
          metavar='LR',
          help='initial learning rate')
      FLAGS = parser.parse_args()
      main()
  