Python 超简单实现9种图像风格迁移

Python 图像风格迁移已经属于比较成熟的领域了,现在连实时的风格迁移都不成问题。之前一直想出一篇这样的文章,但无奈于大部分开源项目配置起来非常麻烦,比如 luanfujun/deep-photo-styletransfer 项目,需要安装 CUDA、pytorch、cudnn等等,配置完一天都过去了。

不过现在我们有了非常好的开源应用项目,那就是OpenCV的DNN图像风格迁移。你只需要安装OpenCV就可以使用了,在cmd/terminal中输入(如果你还没有安装Python,请看这篇文章:Python安装):

pip install python-opencv

不过它也是有局限性的,我们只能用别人训练好的模型进行风格迁移,如果我们要自定义风格,那就必须配置cudn等工具,使用 deep-photo-styletransfer 等项目的方法进行训练,今天的教程我们拿**fast-neural-style**训练好的模型对下面的图片做一次风格迁移。

喵喵喵

1.选择模型

**fast-neural-style**放出的模型风格一共有9种,我们将一一尝试,其中部分风格如下比如:

candy.jpg

mosaic.jpg

starry_night.jpg

udnie.jpg

模型文件可以关注我们下方公众号 Python实用宝典,回复 风格迁移 下载,里面有全部10个模型风格的资源。

2.克隆OpenCV源码

我们直接克隆OpenCV开源项目中关于Python DNN图像迁移的例子,地址是:

https://github.com/opencv/opencv/blob/3.4.0/samples/dnn/fast_neural_style.py

代码如下:

import cv2 as cv
import numpy as np
import argparse

parser = argparse.ArgumentParser(
        description='This script is used to run style transfer models from '
                    'https://github.com/jcjohnson/fast-neural-style using OpenCV')
parser.add_argument('--input', help='Path to image or video. Skip to capture frames from camera')
parser.add_argument('--model', help='Path to .t7 model')
parser.add_argument('--width', default=-1, type=int, help='Resize input to specific width.')
parser.add_argument('--height', default=-1, type=int, help='Resize input to specific height.')
parser.add_argument('--median_filter', default=0, type=int, help='Kernel size of postprocessing blurring.')
args = parser.parse_args()

net = cv.dnn.readNetFromTorch(args.model)

if args.input:
    cap = cv.VideoCapture(args.input)
else:
    cap = cv.VideoCapture(0)

cv.namedWindow('Styled image', cv.WINDOW_NORMAL)
while cv.waitKey(1) < 0:
    hasFrame, frame = cap.read()
    if not hasFrame:
        cv.waitKey()
        break

    inWidth = args.width if args.width != -1 else frame.shape[1]
    inHeight = args.height if args.height != -1 else frame.shape[0]
    inp = cv.dnn.blobFromImage(frame, 1.0, (inWidth, inHeight),
                              (103.939, 116.779, 123.68), swapRB=False, crop=False)

    net.setInput(inp)
    out = net.forward()

    out = out.reshape(3, out.shape[2], out.shape[3])
    out[0] += 103.939
    out[1] += 116.779
    out[2] += 123.68
    out /= 255
    out = out.transpose(1, 2, 0)

    t, _ = net.getPerfProfile()
    freq = cv.getTickFrequency() / 1000
    print(t / freq, 'ms')

    if args.median_filter:
        out = cv.medianBlur(out, args.median_filter)

    cv.imshow('Styled image', out) 

注意,源代码是基于Python2的,所以第46行少了括号,如果你是Python3请注意补上括号。这份代码可以直接使用, parser 里定义了5个参数,–input输入要迁移的图像位置,–model指要使用的模型,–width/–height指的是迁移后的图像宽度和高度, median_filter 是中值滤波器, 基本思想是用像素点邻域灰度值的中值来代替该像素点的灰度值,因此理论上数值越大,图像越平滑,输出的结果细节越好(不确定)。 median_filter 亲自试了一下,对结果的影响不大。

3.开始迁移

将上述代码保存到一个文件中,命名为1.py,在CMD/Terminal中带参数运行脚本即可迁移。如:

$ python 1.py --input 1.jpg --model udnie.t7

效果如下:

全部9种风格的迁移效果:

文章到此就结束啦,如果你喜欢今天的Python 教程,请持续关注Python实用宝典,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典
阅读更多的Python实战教程

原文来自Python实用宝典:Python 迁移9种图像风格
Python实用宝典

图像风格迁移是一将一张图像的风格应用到另一张图像上的技术。下面是使用Python函数实现图像风格迁移的步骤: 1. 导入所需的模块和库[^2]: ```python import torch from PIL import Image import matplotlib.pyplot as plt import torchvision.transforms as transforms import torchvision.models as models ``` 2. 加载预训练的VGG-19模型[^1]: ```python device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = models.vgg19(pretrained=True).features model.to(device).eval() ``` 3. 定义图像转换函数: ```python def image_transform(image_path): image = Image.open(image_path) image_transform = transforms.Compose([ transforms.Resize(400), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) image = image_transform(image).unsqueeze(0) return image.to(device) ``` 4. 加载内容图像和风格图像: ```python content_image = image_transform("content.jpg") style_image = image_transform("style.jpg") ``` 5. 定义内容损失函数和风格损失函数: ```python def content_loss(content_features, target_features): return torch.mean((content_features - target_features) ** 2) def style_loss(style_features, target_features): _, c, h, w = style_features.size() style_features = style_features.view(c, h * w) target_features = target_features.view(c, h * w) gram_style = torch.mm(style_features, style_features.t()) gram_target = torch.mm(target_features, target_features.t()) return torch.mean((gram_style - gram_target) ** 2) ``` 6. 定义总损失函数: ```python def total_loss(content_features, style_features, target_features): content_weight = 1 style_weight = 1000 content_loss_value = content_loss(content_features, target_features) style_loss_value = style_loss(style_features, target_features) total_loss = content_weight * content_loss_value + style_weight * style_loss_value return total_loss ``` 7. 进行图像风格迁移: ```python input_image = content_image.clone().requires_grad_(True).to(device) optimizer = torch.optim.Adam([input_image], lr=0.01) num_epochs = 2000 for epoch in range(num_epochs): optimizer.zero_grad() input_features = model(input_image) content_features = model(content_image) style_features = model(style_image) loss = total_loss(content_features, style_features, input_features) loss.backward() optimizer.step() if (epoch+1) % 100 == 0: print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}") output_image = input_image.detach().squeeze(0).cpu() output_image = transforms.ToPILImage()(output_image) output_image.save("output.jpg") ``` 这样,你就可以使用Python函数实现图像风格迁移了。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值