如何使用Python3和PyTorch执行神经风格迁移
介绍
机器学习(ML)是人工智能的一个子领域,专注于从数据中学习模型的算法。
让我们看一下机器学习在计算机视觉领域的实际应用,称为 神经风格迁移 。 2015 年,研究人员使用深度学习技术创建了一种算法,将一张图像的内容与另一张图像的艺术风格混合在一起。 这种新算法生成了独特的图像,但也为我们的视觉系统如何推断新的艺术概念提供了独特的视角。
顾名思义,神经风格迁移依赖于神经网络来执行这项任务。 这个实现的具体细节超出了本教程的范围,但你可以在这篇关于艺术风格迁移的博文或原始研究手稿中了解更多。
在本教程中,您将使用 Jupyter Notebook 和 Linux 命令行应用神经风格迁移来拍摄如下图像:
并通过应用文森特梵高的“星夜”的艺术风格来改造它,创造出这样的形象:
先决条件
要完成本教程,您需要:
- 按照Ubuntu 20.04初始服务器设置指南设置一台Ubuntu 20.04服务器,包括sudo非root用户和防火墙。
- Python 3 和按照 我们的 Python 设置教程 设置的编程环境。
- 按照 How to Set Up Jupyter Notebook for Python 3 安装 Jupyter Notebook。
使用机器学习模型可能会占用大量内存,因此您的机器应该至少有 8GB 的内存来执行本教程中的一些计算。
第 1 步 — 安装依赖项并克隆 PyTorch-Style-Transfer GitHub 存储库
在本教程中,我们将使用 Hang Zhang 提供的神经风格迁移的开源实现,称为 PyTorch-Style-Transfer。 此特定实现使用 PyTorch
库。
激活您的编程环境,并使用以下命令安装 torchvision
和 torchfile
包:
pip install torchvision torchfile
Pip 将自动检索它们的依赖项:
OutputSuccessfully installed numpy-1.22.0 pillow-9.0.0 torch-1.10.1 torchfile-0.1.0 torchvision-0.11.2 typing-extensions-4.0.1
为避免将主目录与文件弄乱,请创建一个名为 style_transfer
的新目录并将其用作您的工作目录:
mkdir style_transfer cd style_transfer
接下来,使用 git clone
命令将 PyTorch-Style-Transfer
存储库克隆到您的工作目录。 您可以在 这个 Git 教程系列 中了解更多关于 Git 的知识。
git clone https://github.com/zhanghang1989/PyTorch-Style-Transfer.git
此存储库的作者已将我们将使用的代码放在 PyTorch-Style-Transfer
存储库的 experiments
文件夹中,因此在克隆所有文件后切换到此目录:
cd PyTorch-Style-Transfer/experiments
看一下experiments
目录的内容:
ls
您将看到以下目录:
Outputcamera_demo.py dataset images main.py models net.py option.py utils.py
在本教程中,您将使用包含股票图像的 images/
目录和用于将神经风格迁移应用到图像的 main.py
脚本。
在转到下一部分之前,您还需要下载运行神经风格迁移所需的预训练深度学习模型。 这些模型可能很大,因此不适合存储在 GitHub 上,因此作者提供了一个小脚本来下载文件。 您可以在 models/download_model.sh
找到该脚本。
首先,使脚本可执行:
chmod +x ./models/download_model.sh
然后执行脚本下载模型:
./models/download_model.sh
现在一切都已下载,让我们使用这些工具来转换一些图像。
第 2 步 — 运行您的第一个风格迁移实验
为了说明神经风格迁移的工作原理,让我们从 PyTorch-Style-Transfer
存储库的作者提供的示例开始。 由于我们需要显示和查看图像,使用 Jupyter notebook 会更方便。
从终端启动 Jupyter:
jupyter notebook
然后按照提供的说明访问 Jupyter。
显示 Jupyter 后,通过从右上角的下拉菜单中选择 New > Python 3 创建一个新笔记本:
这将打开一个新笔记本,您可以在其中输入代码。
在笔记本顶部,添加以下代码以加载所需的库。
笔记本
import torch import os import subprocess from IPython.display import Image from IPython.display import display
除了 torch
,我们还导入了标准库 os
和 subprocess
,我们将使用它们直接从 Jupyter notebook 运行 Python 脚本。 我们还包括 IPython.display
库,它让我们可以在 Jupyter 笔记本中显示图像。
注意:键入 ALT+ENTER
(或 macOS 上的 SHIFT+ENTER
)以运行代码并移动到笔记本中的新代码块。 在本教程中的每个代码块之后执行此操作以查看结果。
PyTorch-Style-Transfer
存储库的 README
文件中提供的示例使用位于 images/
目录和 main.py
脚本中的库存图像。 您需要提供至少五个参数才能运行 main.py
脚本:
- 内容图像的路径(位于
/images/content
中)。 - 样式图像的路径(位于
/images/21styles
中)。 - 用于执行样式迁移的预训练 GAN(生成对抗网络)模型的路径(位于
/models
)。 - 输出图像的路径和名称。
- 深度学习模型在 GPU 上运行得更快。 如果您有可用的,则指定
--cuda=1
参数,否则使用--cuda=0
。
要运行神经风格迁移代码,我们将指定所需的参数并使用 subprocess
库在 shell 中运行命令。
首先,让我们定义工作目录的路径。 我们将存储在一个名为 workingdir
的变量中:
笔记本
# define the path to the working directory experiment_dir = 'style_transfer/PyTorch-Style-Transfer/experiments' workingdir = '{}/{}'.format(os.environ['HOME'], experiment_dir)
当我们指向图像和其他文件时,我们将在整个代码中使用这个变量。
现在让我们定义 main.py
脚本的路径,以及我们将用作此测试运行的输入的参数列表。 我们将指定内容图像为 venice-boat.jpg
,样式图像为 starry_night.jpg
,并将神经样式转换的输出保存到名为 test.jpg
的文件中:
笔记本
# specify the path to the main.py script path2script = '{}/main.py'.format(workingdir) # specify the list of arguments to be used as input to main.py args = ['eval', '--content-image', '{}/images/content/venice-boat.jpg'.format(workingdir), '--style-image', '{}/images/21styles/starry_night.jpg'.format(workingdir), '--model', '{}/models/21styles.model'.format(workingdir), '--output-image', '{}/test.jpg'.format(workingdir), '--cuda=0']
在运行测试示例之前,您可以通过在笔记本中执行以下代码来快速查看您为此示例选择的内容和样式图像:
笔记本
content_image = Image('{}/images/content/venice-boat.jpg'.format(workingdir)) style_image = Image('{}/images/21styles/starry_night.jpg'.format(workingdir)) display(content_image) display(style_image)
您将在输出中看到这些图像:
最后,连接对 main.py
的调用及其参数列表,并使用 subprocess.check_output
函数在 shell 中运行它:
笔记本
# build subprocess command cmd = ['python3', path2script] + args # run the command x = subprocess.check_output(cmd, universal_newlines=True)
根据计算机上可用的内存量,这可能需要一两分钟才能运行。 完成后,您应该会在工作目录中看到一个 test.jpg
文件。 在 Jupyter 笔记本中,您可以使用 Ipython 魔术命令 在 Jupyter 笔记本中显示工作目录的内容:
笔记本
!ls $workingdir
或者,您可以在终端中使用 ls
命令。 无论哪种方式,您都会看到以下输出:
Output__pycache__ dataset main.py myutils option.py camera_demo.py images models net test.jpg
您将看到一个名为 test.jpg
的新文件,其中包含使用您的输入内容和样式图像进行的神经样式转换的结果。
使用Image
函数显示test.jpg
的内容:
笔记本
Image('{}/test.jpg'.format(workingdir))
Vincent van Vogh 的星夜画布的艺术风格已映射到我们威尼斯船图像的内容。 您已经通过教科书示例成功应用了神经风格迁移,因此让我们尝试使用不同的图像重复此练习。
第 3 步 — 转换您自己的图像
到目前为止,您已经使用了我们正在使用的库的作者提供的图像。 让我们改用我们自己的图像。 为此,您可以找到您感兴趣的图像并在以下命令中使用该图像的 URL,或者使用提供的 URL 来使用 Sammy the Shark。
我们将再次使用一些 IPython 魔法将图像下载到我们的工作目录并将其放入一个名为 sammy.png
的文件中。
笔记本
!wget -O - 'https://assets.digitalocean.com/blog/static/sammy-the-shark-gets-a-birthday-makeover-from-simon-oxley/sammy-jetpack.png' > $workingdir/sammy.png
在笔记本中运行此命令时,您将看到以下输出:
Output--2017-08-15 20:03:27-- https://assets.digitalocean.com/blog/static/sammy-the-shark-gets-a-birthday-makeover-from-simon-oxley/sammy-jetpack.png Resolving assets.digitalocean.com (assets.digitalocean.com)... 151.101.20.233 Connecting to assets.digitalocean.com (assets.digitalocean.com)|151.101.20.233|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 10483 (10K) [image/png] Saving to: 'STDOUT' - 100%[===================>] 10.24K --.-KB/s in 0.001s 2017-08-15 20:03:27 (12.9 MB/s) - written to stdout [10483/10483]
使用 Image
命令在笔记本中显示新图像:
笔记本
Image('{}/sammy.png'.format(workingdir))
按照与测试运行相同的工作流程,让我们使用 Rocket Sammy 作为内容图像和相同的星夜图片作为我们的风格图像来运行我们的艺术风格迁移模型。
我们将使用与之前相同的代码,但这次我们将指定内容图像为 sammy.png
,样式图像为 starry_night.jpg
,并将输出写入文件称为 starry_sammy.jpg
。 然后我们执行命令:
笔记本
# specify the path to the main.py script path2script = '{}/main.py'.format(workingdir) # specify the list of arguments to be used as input to main.py args = ['eval', '--content-image', '{}/sammy.png'.format(workingdir), '--style-image', '{}/images/21styles/starry_night.jpg'.format(workingdir), '--model', '{}/models/21styles.model'.format(workingdir), '--output-image', '{}/starry_sammy.jpg'.format(workingdir), '--cuda=0'] # build subprocess command cmd = ['python3', path2script] + args # run the bash command x = subprocess.check_output(cmd, universal_newlines=True)
然后使用Image
功能查看将Vincent van Vogh的星夜艺术风格转移到您的Rocket Sammy图像内容的结果。
笔记本
Image('{}/starry_sammy.jpg'.format(workingdir))
您将看到新的风格化 Rocket Sammy:
让我们通过将不同风格的图像映射到我们的 Rocket Sammy 图片来再次尝试。 这次我们将使用毕加索的缪斯。 同样,我们使用 sammy.png
作为我们的内容图像,但我们将样式图像更改为 la_muse.jpg
。 我们将输出保存到 musing_sammy.jpg
:
笔记本
# specify the path to the main.py script path2script = '{}/main.py'.format(workingdir) # specify the list of arguments to be used as input to main.py args = ['eval', '--content-image', '{}/sammy.png'.format(workingdir), '--style-image', '{}/images/21styles/la_muse.jpg'.format(workingdir), '--model', '{}/models/21styles.model'.format(workingdir), '--output-image', '{}/musing_sammy.jpg'.format(workingdir), '--cuda=0'] # build subprocess command cmd = ['python3', path2script] + args # run the bash command x = subprocess.check_output(cmd, universal_newlines=True)
代码完成运行后,使用您指定的输出文件名和 Image
函数显示您的工作输出:
笔记本
Image('{}/musing_sammy.jpg'.format(workingdir))
到目前为止,您应该对如何使用这些转换有了一个很好的了解。 如果您还没有,请尝试使用一些您自己的图像。
结论
在本教程中,您使用 Python 和神经风格迁移模型的开源 PyTorch 实现将风格迁移应用到图像。 机器学习和人工智能领域广阔,这只是其应用之一。 以下是您可以探索的一些其他内容:
- 将上面的代码打包成一个函数,你可以随时调用。
- 使用此处发布的 教程 学习使用时间序列数据进行可视化和预测。
- 尝试 TensorFlow 文档 中共享的一些示例,甚至是 TensorFlow 实现艺术风格迁移。