AI风格迁移项目 Luxynth's Website| AI风格迁移项目

AI风格迁移项目

目录


准备开发环境

你需要准备好的有

  • python3.8+
  • pip
  • git

你可以创建一个专用于这个项目的虚拟环境

python3 -m venv env-name
#however我使用自己原来使用的用于深度学习的环境DLenvironment

然后你要激活虚拟环境才能安装对应的库

#我的macOS用的是
source env-name/bin/activate
#如果你下载了conda其实会更方便
conda create ...
conda activate ...

#如果你是Windows系统
env-name\Scripts\activate

然后在你的虚拟环境中安装PyTorch

pip install torch torchvision

克隆pytorch风格迁移项目

奈斯!PyTorch 官方已经写好了一个经典的“快速风格迁移”项目(Fast Neural Style)😋

git clone https://github.com/pytorch/examples.git
cd examples/fast_neural_style

里面的结构差不多是: fast_neural_style/

  • evaluate.py
  • train.py
  • transformer_net.py
  • utils.py
  • saved_models/ 也就是放预训练模型的地方
  • images/

配图

接下来我们就要下载预训练风格模型啦😄

下载预训练的风格模型

官方提供了以下几种预训练的画风:

  • 马赛克(mosaic)
  • 糖果风(candy)
  • 雨公主(rain_princess)
  • 梵高印象派(udnie)

接下来我们会用梵高的风格为示例进行实践。

由于我不打算在在这个仓库里面做这个项目,我新建了一个文件夹AI-Style-transfer,然后我将fast_neural_style目录下的所有内容都转移到了AI-Style-transfer中。

  • 接下来我们要下载预训练模型到saved_models目录当中
    mkdir -p saved_models
    

    然后运行download_saved_models.py

示例图生成

现在我们要在项目的根目录下执行这个neural_style.py文件,并且要选定好参数

python neural_style/neural_style.py eval \
    --content-image images/content-images/test.png \
    --model saved_models/udnie.pth \
    --output-image images/output-images/output-udnie.png \
    --cuda 0
#eval表示使用推理模式而不是训练模式
#content-image是需要风格化的图片的路径
#model是你需要使用的预训练的风格迁移模型
#output-image是结果保存路径
#cuda 0表示使用GPU,如果没有GPU则删掉这一行

配图

自定义风格

然后接下来的内容相比刚才会加大难度,我打算训练一个彩铅风格的模型进行风格迁移。

实践步骤大致如下

  • 准备彩铅风格的数据集
  • 准备内容图片集
  • 修改训练脚本(这个neural_style.py有推理模式那么反过来也有–train训练模式)
  • 风格应用

准备彩铅风格数据集

  • 网上尝试下载了一个结果并不符合要求(大哭) 最终尝试调用生图模型生成彩铅画(风格也比较统一) 配图

准备内容图片集

因为不打算找太大规模的数据集,我找了COCO-val2017,里面有5K张图片,对于自己这个小项目绰绰有余矣。(我甚至删减到999张)

我将风格数据集和内容数据集的文件都命名为001开始的编号

对于风格图像的训练,每次仅支持单图,这里参考了GPT先生对neural_style.py的修改方法: 原有的:

    style = utils.load_image(args.style_image, size=args.style_size)
    style = style_transform(style)
    style = style.repeat(args.batch_size, 1, 1, 1).to(device)

    features_style = vgg(utils.normalize_batch(style))
    gram_style = [utils.gram_matrix(y) for y in features_style]

修改为:

    # =============================
    # 支持多张风格图像
    # =============================
    style_paths = []
    if os.path.isdir(args.style_image):
        for fname in os.listdir(args.style_image):
            if fname.lower().endswith(('.jpg', '.jpeg', '.png')):
                style_paths.append(os.path.join(args.style_image, fname))
        if len(style_paths) == 0:
            raise ValueError(f"No style images found in folder: {args.style_image}")
        print(f"Found {len(style_paths)} style images in folder.")
    else:
        # 兼容单张风格图的老用法
        style_paths = [args.style_image]

原来的:

for e in range(args.epochs):
        transformer.train()
        agg_content_loss = 0.
        agg_style_loss = 0.
        count = 0
        for batch_id, (x, _) in enumerate(train_loader):
            n_batch = len(x)
            count += n_batch
            optimizer.zero_grad()

            x = x.to(device)
            y = transformer(x)

            y = utils.normalize_batch(y)
            x = utils.normalize_batch(x)

            features_y = vgg(y)
            features_x = vgg(x)

            content_loss = args.content_weight * mse_loss(features_y.relu2_2, features_x.relu2_2)

            style_loss = 0.
            for ft_y, gm_s in zip(features_y, gram_style):
                gm_y = utils.gram_matrix(ft_y)
                style_loss += mse_loss(gm_y, gm_s[:n_batch, :, :])
            style_loss *= args.style_weight

            total_loss = content_loss + style_loss
            total_loss.backward()
            optimizer.step()

修改为:

for e in range(args.epochs):
    transformer.train()
    agg_content_loss = 0.
    agg_style_loss = 0.
    count = 0
    for batch_id, (x, _) in enumerate(train_loader):
        n_batch = len(x)
        count += n_batch
        optimizer.zero_grad()

        # ========= 随机抽一张风格图 =========
        style_path = np.random.choice(style_paths)
        style_img = utils.load_image(style_path, size=args.style_size)
        style_img = style_transform(style_img)
        style_img = style_img.repeat(n_batch, 1, 1, 1).to(device)

        features_style = vgg(utils.normalize_batch(style_img))
        gram_style = [utils.gram_matrix(y) for y in features_style]

        # ========= 内容和风格特征 =========
        x = x.to(device)
        y = transformer(x)
        y = utils.normalize_batch(y)
        x = utils.normalize_batch(x)

        features_y = vgg(y)
        features_x = vgg(x)

        # 内容损失
        content_loss = args.content_weight * mse_loss(features_y.relu2_2, features_x.relu2_2)

        # 风格损失
        style_loss = 0.
        for ft_y, gm_s in zip(features_y, gram_style):
            gm_y = utils.gram_matrix(ft_y)
            style_loss += mse_loss(gm_y, gm_s[:n_batch, :, :])
        style_loss *= args.style_weight

        total_loss = content_loss + style_loss
        total_loss.backward()
        optimizer.step()

然后使用方法就是

python neural_style/neural_style.py train \
    --dataset dataset/content-images \
    --style-image dataset/colored-pencil \
    --save-model-dir saved_models \
    --epochs 8 #--cuda

ps! 值得注意的是,content-images中必须分类,最简单的方法就是创建train文件夹,把图像都放进去,否则就会报错。

风格应用

由于数据集比较小,经过九九八十一难还是没有完全成功。 最初我将自制的彩铅风格数据集110pcs都用于训练,但由于风格上不够统一,导致很多杂色,生成效果非常阴间 配图 然后我仅挑取一张彩铅质感明显的图片作为风格图像, 配图 效果好了点但是色调单一 配图

小结

尽管由于训练量不够,达成的效果不是很好,但是我相信如果制作素描风格这种黑白、色调单一的应该更能成功,至少训练过程中对笔触的模仿已经有较大进展了

说点什么…

公告图标
×

公告栏🪧

📌亲爱的读者,这里是Luxynth的小破站🌻~



📌很高兴,我们在这片广袤的网络世界相遇。请随意漫步,这里的一切都献给你🎀

📌文章持续更新中,欢迎你经常来访~