摘要:这个 notebook 基于论文「Stylized Neural Painting, arXiv:2011.08114.」提供了最基本的「图片生成绘画」变换的可复现例子。

本文分享自华为云社区《基于ModelArts进行图像风格化绘画》,作者: HWCloudAI 。

项目首页 | GitHub | 论文

ModelArts 项目地址:https://developer.huaweicloud.com/develop/aigallery/notebook/detail?id=b4e4c533-e0e7-4167-94d0-4d38b9bcfd63

下载代码和模型

import os
import moxing as mox
mox.file.copy('obs://obs-aigallery-zc/clf/code/stylized-neural-painting.zip','stylized-neural-painting.zip')
os.system('unzip stylized-neural-painting.zip')
cd stylized-neural-painting
import argparse import torch
torch.cuda.current_device()
import torch.optim as optim from painter import *
# 检测运行设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# 配置
parser = argparse.ArgumentParser(description='STYLIZED NEURAL PAINTING')
args = parser.parse_args(args=[])
args.img_path = './test_images/sunflowers.jpg' # 输入图片路径
args.renderer = 'oilpaintbrush' # 渲染器(水彩、马克笔、油画笔刷、矩形) [watercolor, markerpen, oilpaintbrush, rectangle]
args.canvas_color = 'black' # 画布底色 [black, white]
args.canvas_size = 512 # 画布渲染尺寸,单位像素
args.max_m_strokes = 500 # 最大笔划数量
args.m_grid = 5 # 将图片分割为 m_grid x m_grid 的尺寸
args.beta_L1 = 1.0 # L1 loss 权重
args.with_ot_loss = False # 设为 True 以通过 optimal transportation loss 提高收敛。但会降低生成速度
args.beta_ot = 0.1 # optimal transportation loss 权重
args.net_G = 'zou-fusion-net' # 渲染器架构
args.renderer_checkpoint_dir = './checkpoints_G_oilpaintbrush' # 预训练模型路径
args.lr = 0.005 # 笔划搜寻的学习率
args.output_dir = './output' # 输出路径

Download pretrained neural renderer.

Define a helper funtion to check the drawing status.

def _drawing_step_states(pt):
acc = pt._compute_acc().item()
print('iteration step %d, G_loss: %.5f, step_psnr: %.5f, strokes: %d / %d'
% (pt.step_id, pt.G_loss.item(), acc,
(pt.anchor_id+1)*pt.m_grid*pt.m_grid,
pt.max_m_strokes))
vis2 = utils.patches2img(pt.G_final_pred_canvas, pt.m_grid).clip(min=0, max=1)

定义优化循环

def optimize_x(pt):

    pt._load_checkpoint()
pt.net_G.eval() pt.initialize_params()
pt.x_ctt.requires_grad = True
pt.x_color.requires_grad = True
pt.x_alpha.requires_grad = True
utils.set_requires_grad(pt.net_G, False) pt.optimizer_x = optim.RMSprop([pt.x_ctt, pt.x_color, pt.x_alpha], lr=pt.lr) print('begin to draw...')
pt.step_id = 0
for pt.anchor_id in range(0, pt.m_strokes_per_block):
pt.stroke_sampler(pt.anchor_id)
iters_per_stroke = 20
if pt.anchor_id == pt.m_strokes_per_block - 1:
iters_per_stroke = 40
for i in range(iters_per_stroke): pt.optimizer_x.zero_grad() pt.x_ctt.data = torch.clamp(pt.x_ctt.data, 0.1, 1 - 0.1)
pt.x_color.data = torch.clamp(pt.x_color.data, 0, 1)
pt.x_alpha.data = torch.clamp(pt.x_alpha.data, 0, 1) if args.canvas_color == 'white':
pt.G_pred_canvas = torch.ones([args.m_grid ** 2, 3, 128, 128]).to(device)
else:
pt.G_pred_canvas = torch.zeros(args.m_grid ** 2, 3, 128, 128).to(device) pt._forward_pass()
_drawing_step_states(pt)
pt._backward_x()
pt.optimizer_x.step() pt.x_ctt.data = torch.clamp(pt.x_ctt.data, 0.1, 1 - 0.1)
pt.x_color.data = torch.clamp(pt.x_color.data, 0, 1)
pt.x_alpha.data = torch.clamp(pt.x_alpha.data, 0, 1) pt.step_id += 1 v = pt.x.detach().cpu().numpy()
pt._save_stroke_params(v)
v_n = pt._normalize_strokes(pt.x)
pt.final_rendered_images = pt._render_on_grids(v_n)
pt._save_rendered_images()

处理图片,可能需要一些时间,建议使用 32 GB+ 显存

pt = Painter(args=args)
optimize_x(pt)

Check out your results at args.output_dir. Before you download that folder, let’s first have a look at what the generated painting looks like.

plt.subplot(1,2,1)
plt.imshow(pt.img_), plt.title('input')
plt.subplot(1,2,2)
plt.imshow(pt.final_rendered_images[-1]), plt.title('generated')
plt.show()

请下载 args.output_dir 目录到本地查看高分辨率的生成结果/

# 将渲染进度用动交互画形式展现

import matplotlib.animation as animation
from IPython.display import HTML fig = plt.figure(figsize=(4,4))
plt.axis('off')
ims = [[plt.imshow(img, animated=True)] for img in pt.final_rendered_images[::10]] ani = animation.ArtistAnimation(fig, ims, interval=50) # HTML(ani.to_jshtml())
HTML(ani.to_html5_video())

Next, let’s play style-transfer. Since we frame our stroke prediction under a parameter searching paradigm, our method naturally fits the neural style transfer framework.

接下来,让我们尝试风格迁移,由于我们是在参数搜索范式下构建的笔画预测,因此我们的方法自然的适用于神经风格迁移框架

# 配置
args.content_img_path = './test_images/sunflowers.jpg' # 输入图片的路径(原始的输入图片)
args.style_img_path = './style_images/fire.jpg' # 风格图片路径
args.vector_file = './output/sunflowers_strokes.npz' # 预生成笔划向量文件的路径
args.transfer_mode = 1 # 风格迁移模式,0:颜色迁移,1:迁移颜色和纹理
args.beta_L1 = 1.0 # L1 loss 权重
args.beta_sty = 0.5 # vgg style loss 权重
args.net_G = 'zou-fusion-net' # 渲染器架构
args.renderer_checkpoint_dir = './checkpoints_G_oilpaintbrush' # 预训练模型路径
args.lr = 0.005 # 笔划搜寻的学习率
args.output_dir = './output' # 输出路径

Again, Let’s define a helper funtion to check the style transfer status.

def _style_transfer_step_states(pt):
acc = pt._compute_acc().item()
print('running style transfer... iteration step %d, G_loss: %.5f, step_psnr: %.5f'
% (pt.step_id, pt.G_loss.item(), acc))
vis2 = utils.patches2img(pt.G_final_pred_canvas, pt.m_grid).clip(min=0, max=1)

定义优化循环

def optimize_x(pt):

    pt._load_checkpoint()
pt.net_G.eval() if args.transfer_mode == 0: # transfer color only
pt.x_ctt.requires_grad = False
pt.x_color.requires_grad = True
pt.x_alpha.requires_grad = False
else: # transfer both color and texture
pt.x_ctt.requires_grad = True
pt.x_color.requires_grad = True
pt.x_alpha.requires_grad = True pt.optimizer_x_sty = optim.RMSprop([pt.x_ctt, pt.x_color, pt.x_alpha], lr=pt.lr) iters_per_stroke = 100
for i in range(iters_per_stroke):
pt.optimizer_x_sty.zero_grad() pt.x_ctt.data = torch.clamp(pt.x_ctt.data, 0.1, 1 - 0.1)
pt.x_color.data = torch.clamp(pt.x_color.data, 0, 1)
pt.x_alpha.data = torch.clamp(pt.x_alpha.data, 0, 1) if args.canvas_color == 'white':
pt.G_pred_canvas = torch.ones([pt.m_grid*pt.m_grid, 3, 128, 128]).to(device)
else:
pt.G_pred_canvas = torch.zeros(pt.m_grid*pt.m_grid, 3, 128, 128).to(device) pt._forward_pass()
_style_transfer_step_states(pt)
pt._backward_x_sty()
pt.optimizer_x_sty.step() pt.x_ctt.data = torch.clamp(pt.x_ctt.data, 0.1, 1 - 0.1)
pt.x_color.data = torch.clamp(pt.x_color.data, 0, 1)
pt.x_alpha.data = torch.clamp(pt.x_alpha.data, 0, 1) pt.step_id += 1 print('saving style transfer result...')
v_n = pt._normalize_strokes(pt.x)
pt.final_rendered_images = pt._render_on_grids(v_n) file_dir = os.path.join(
args.output_dir, args.content_img_path.split('/')[-1][:-4])
plt.imsave(file_dir + '_style_img_' +
args.style_img_path.split('/')[-1][:-4] + '.png', pt.style_img_)
plt.imsave(file_dir + '_style_transfer_' +
args.style_img_path.split('/')[-1][:-4] + '.png', pt.final_rendered_images[-1])

运行风格迁移

pt = NeuralStyleTransfer(args=args)
optimize_x(pt)

高分辨率生成文件保存在 args.output_dir

让我们预览一下输出结果:

plt.subplot(1,3,1)
plt.imshow(pt.img_), plt.title('input')
plt.subplot(1,3,2)
plt.imshow(pt.style_img_), plt.title('style')
plt.subplot(1,3,3)
plt.imshow(pt.final_rendered_images[-1]), plt.title('generated')
plt.show()

点击关注,第一时间了解华为云新鲜技术~

论文复现丨基于ModelArts进行图像风格化绘画的更多相关文章

  1. 实践案例丨基于ModelArts AI市场算法MobileNet_v2实现花卉分类

    概述 MobileNetsV2是基于一个流线型的架构,它使用深度可分离的卷积来构建轻量级的深层神经网,此模型基于 MobileNetV2: Inverted Residuals and Linear ...

  2. 论文解读丨基于局部特征保留的图卷积神经网络架构(LPD-GCN)

    摘要:本文提出一种基于局部特征保留的图卷积网络架构,与最新的对比算法相比,该方法在多个数据集上的图分类性能得到大幅度提升,泛化性能也得到了改善. 本文分享自华为云社区<论文解读:基于局部特征保留 ...

  3. Python图像处理丨基于OpenCV和像素处理的图像灰度化处理

    摘要:本篇文章讲解图像灰度化处理的知识,结合OpenCV调用cv2.cvtColor()函数实现图像灰度操作,使用像素处理方法对图像进行灰度化处理. 本文分享自华为云社区<[Python图像处理 ...

  4. Visualizing and Understanding Convolutional Networks论文复现笔记

    目录 Visualizing and Understanding Convolutional Networks 论文复现笔记 Abstract Introduction Approach Visual ...

  5. FCOS论文复现:通用物体检测算法

    摘要:本案例代码是FCOS论文复现的体验案例,此模型为FCOS论文中所提出算法在ModelArts + PyTorch框架下的实现.本代码支持FCOS + ResNet-101在MS-COCO数据集上 ...

  6. 笔记:基于DCNN的图像语义分割综述

    写在前面:一篇魏云超博士的综述论文,完整题目为<基于DCNN的图像语义分割综述>,在这里选择性摘抄和理解,以加深自己印象,同时达到对近年来图像语义分割历史学习和了解的目的,博古才能通今!感 ...

  7. Demo分享丨看ModelArts与HiLens是如何让车自己跑起来的

    摘要:基于HiLens Kit已经基本开发完成,可部署到HiLens Kit,模型的选择为基于DarkNet53的YOLOv3模型,权重为基于COCO2014训练的数据集,而车道线的检测是基于Open ...

  8. 昇腾CANN论文上榜CVPR,全景图像生成算法交互性再增强!

    摘要:近日,CVPR 2022放榜,基于CANN的AI论文<Interactive Image Synthesis with Panoptic Layout Generation>强势上榜 ...

  9. Split to Be Slim: 论文复现

    摘要:在本论文中揭示了这样一种现象:一层内的许多特征图共享相似但不相同的模式. 本文分享自华为云社区<Split to Be Slim: 论文复现>,作者: 李长安 . Split to ...

  10. 基于clahe的图像去雾

    基于clahe的图像去雾     通过阅读一些资料,我了解到clahe算法对图像去雾有所价值,正好opencv中有了实现,拿过来看一看.   但是现在实现的效果还是有所差异 #);    clahe] ...

随机推荐

  1. Java并发编程和多线程的区别

    并发编程: 并发编程是一种编程范式,它关注的是编写能够正确和高效处理多个并发任务的程序.并发编程不仅包括多线程,还包括了处理多个独立任务的各种技术和模式,如进程.协程.分布式编程等.并发编程的目标是实 ...

  2. 你也许不再需要使用 CSS Media Queries(媒体查询)了

    你也许不再需要使用 CSS Media Queries(媒体查询)了 最近,CSS 引入了一项新功能:Container Queries.它可以替代 Media Queries 并实现 Media Q ...

  3. FSCTF 2023(公开赛道)CRYPTO WP

    RSA 1 1.题目信息 提交格式:FSCTF{你所解出的内容} p=1458769258361 q=4556983871563 e=17 求d 2.解题方法 exp from gmpy2 impor ...

  4. Python 潮流周刊#25:性能最快的代码格式化工具 Ruff!

    你好,我是猫哥.这里每周分享优质的 Python.AI 及通用技术内容,大部分为英文.标题取自其中一则分享,不代表全部内容都是该主题,特此声明. 本周刊由 Python猫 出品,精心筛选国内外的 25 ...

  5. 【scipy 基础】--积分和微分方程

    对于手工计算来说,积分计算是非常困难的,对于一些简单的函数,我们可以直接通过已知的积分公式来求解,但在更多的情况下,原函数并没有简单的表达式,因此确定积分的反函数变得非常困难. 另外,相对于微分运算来 ...

  6. C语言一个单链表L=(a1 , a2 , … , an-1 , an),其逆单链表定义为L’=( an , an-1 , … , a2 , a1),要求逆单链表仍占用原单链表的空间。

    /* 开发者:慢蜗牛 开发时间:2020.6.11 程序功能:顺序输出和逆序输出 */ #include<stdio.h> #include<malloc.h> #define ...

  7. [WPF]动手写一个简单的消息对话框

    消息对话框是UI界面中不可或缺的组成部分,用于给用户一些提示,警告或者询问的窗口.在WPF中,消息对话框是系统原生(user32.dll)的MessageBox,无法通过Style或者Template ...

  8. JAVAweek4

    本周学习: 1.JAVA环境的搭建,包括JDK的下载,和classpath环境设置 2.*.java和*.class程序的运行 class Demo {public static void main( ...

  9. C++ Qt开发:如何使用信号与槽

    在Qt中,信号与槽(Signal and Slot)是一种用于对象之间通信的机制.是Qt框架引以为傲的一项机制,它带来了许多优势,使得Qt成为一个强大且灵活的开发框架之一.信号与槽的关联通过QObje ...

  10. 高效的 Json 解析框架 kotlinx.serialization

    一.引出问题 你是否有在使用 Gson 序列化对象时,见到如下异常: Abstract classes can't be instantiated! Register an InstanceCreat ...