【深度学习】图片风格转换应用程序:使用CoreML创建Prisma

WWDC 2017让我们了解了苹果公司对机器学习的看法以及它在移动设备上的应用。CoreML框架使得将ML模型引入iOS应用程序变得非常容易。

大约一年前,我们在iOS和Android上实现了自己的神经网络推理机,现在我们很兴奋,因为苹果已经推出了类似的本机版本。在这篇文章中,我将向你展示如何使用只有开源模型和CoreML的方式实现一个小型的风格转换应用程序。

最近,我们在GitHub上共享了一个工具,这个工具将Torch7模型转换为CoreML。

GitHub地址:https://github.com/prisma-ai/torch2coreml

我将用它来转换Justin Johnson预先训练的模型,该模型来自于他的作品“实时样式传输和超分辨率的知觉损失”。

作品地址:http://cs.stanford.edu/people/jcjohns/eccv16/ repo地址:https://github.com/jcjohnson/fast-neural-style

首先,把我们正在做的事情正则化。我们需要获取图像到图像(image-to-image)神经网络的CoreML(.mlmodel文件)模型,将一些“风格”应用于3个通道的图像输入并且得到输出图像。我们将利用其中一些模型作为示例来创建一个小型应用程序。

要求

你需要安装macOS、Xcode 9、Torch7、PyTorch和torch2coreml。在描述每个组件安装过程的文本中还有一些链接。

步骤1:下载预先训练的模型

复制快速神经风格(fast-neural-style)的repo:

git clone https://github.com/jcjohnson/fast-neural-style

这个repo包含用于训练新模型的代码,并使用Torch7来运行推断(在图片上应用风格转换。需要正确地安装和配置Torch7。

Torch7安装地址:http://torch.ch/docs/getting-started.html(本教程适用于没有CUDA的CPU版本)

然后下载预先训练的风格转换模型:

cd fast-neural-style && bash models/download_style_transfer_models.sh

下载的模型将出现在“model / eccv16”和“model / instance_norm”的子目录中。我们将使用“instance_norm”(带有实例规范化(InstanceNormalization)层的神经网络)模型,本教程中的所有内容都与“eccv16”模型兼容。你也可以训练自己的模型,该模型在快速神经样式(fast-neural-style)的repo中被描述,并用于进一步的实验。

步骤2:准备转换模型

如果我们深入研究快速神经风格(fast-neural-style)模型,我们会发现该模型存储在具有相应的预处理参数的Lua表格中,我们需要提取它。本教程的这一步包含了一些简单的Lua代码。

local model= torch.load(model_path).model

下一个问题是在模型中定制Torch7层(由Lua实现)。以下不是标准torch.nn程序包分布的一部分:

  • ShaveImage;
  • TotalVariation;
  • 实例规范化(InstanceNormalization)。

看一下这些层的内部,并修改模型以准备转换。我们只对正向传递感兴趣,因此只对“updateOutput”方法进行了研究。

ShaveImage是一个简单的裁剪输入的层,它可以从左、右、顶部和图像底部裁剪一些像素。我们可以简单地把它改成标准torch的SpatialZeroPadding层。

如果我们看一下TotalVariation层,我们会看到它只是在前进阶段的一个无op层。因此,我们可以安全地从模型中删除这个层。

ShaveImage层:https://github.com/jcjohnson/fast-neural-style/blob/master/ fast_neural_style/ShaveImage.lua SpatialZeroPadding层:https://github.com/torch/nn/blob/master/SpatialZero Padding.lua TotalVariation层:https://github.com/jcjohnson/fast-neural-style/blob/master/fast_ neural_style/TotalVariation.lua

我们不能修改实例规范化(InstanceNormalization)层,因为它没有类似torch.nn的程序包,我们可以将它转换为相应的CoreML层,因为最新的coremltools python程序包支持该层。因此,我们将这个层保留在模型中。

完整的脚本准备模型:https://github.com/prisma-ai/torch2coreml/blob/master/example /fast-neural-style/prepare_model.lua

步骤3:实现CoreML的转换器

在这一步骤中,我们将使用torch2coreml python程序包。我们编写一些python代码。我们从前面的步骤中得到了一些模型,这些模型是由Lua脚本编写的。我们将为快速神经样式(fast-neural-style )的torch模型实现一个python转换器。

必须安装PyTorch。你可以遵循以下安装步骤:http://pytorch.org/。

还需要安装最新版本的torch2coreml python程序包,用于python 2.7(coremltools库只支持python版本作为撰写时间):

[sudo] pip install-U torch2coreml

torch2coreml库可以转换模型,该模型来自文件或已经加载的PyTorch模型(它在内部使用PyTorch来推断某些层的输入/输出形状并解析.t7文件)。我们需要使用PyTorch来加载Torch7模型,因为我们需要在python中使用存储在Lua模型中的参数来实现定制的实例规范化(InstanceNormalization)层。

from torch.utils.serializationimport load_lua
model= load_lua(path, unknown_classes=True)

当模型中有实例规范化(InstanceNormalization)层时,我们需要打开“unknown_classes”引数。否则它会引发异常。

来自torch2coreml的“Convert”函数在PyTorch模型上运行推理,这就是为什么我们需要用它的工作模拟来替换实例规范化(InstanceNormalization)。在PyTorch中,我们找到InstanceNorm3d类,它和Justin Johnson在Lua的实现完全一样。因此,让我们使用这个类来实现PyTorch传统模块(我们只在PyTorch中使用Torch7等价代码)。

InstanceNorm3d类:https://github.com/pytorch/pytorch/blob/master/torch/ nn/modules/instancenorm.py#L127

from torch.legacy.nnimport Module
from torch.autogradimport Variable
from torch.nnimport InstanceNorm3d

class InstanceNormalization(Module):
    def __init__(self, num_features, eps=1e-5, momentum=0.1, affine=False):
        super(Module,self).__init__()
        if momentumis None:
            momentum= 0.1
        self._instance_norm= InstanceNorm3d(
            num_features,
            eps=eps,
            momentum=momentum,
            affine=True
        )

    @property
    def eps(self):
        return self._instance_norm.eps

    @property
    def weight(self):
        return self._instance_norm.weight.data

    @weight.setter
    def weight(self, value):
        self._instance_norm.weight.data= value

    @property
    def bias(self):
        return self._instance_norm.bias.data

    @bias.setter
    def bias(self, value):
        self._instance_norm.bias.data= value

    def updateOutput(self,input):
        return self._instance_norm.forward(Variable(input, volatile=True)).data

接下来,我们用新实现的类的实例替换模型中的每个未知的实例规范化(instancenalization)对象。从这一点来看,我们有完全工作的PyTorch模型,它已经准备好被转换了。

我们没有实现在torch2coreml库中转换自定义的实例规范化(InstanceNormalization)层,但是幸运的是,它有一种机制,可以为未知的层添加自己的转换函数。

def convert_instance_norm(builder, name, layer, input_names, output_names):
    if not isinstance(layer, InstanceNormalization):
        raise TypeError('Unsupported type {}'.format(layer,))

    epsilon= layer.eps
    weight= layer.weight.numpy()
    bias= None
    if layer.biasis not None:
        bias= layer.bias.numpy()

    builder.add_batchnorm(
        name=name,
        channels=weight.shape[0],
        gamma=weight,
        beta=bias,
        compute_mean_var=True,
        instance_normalization=True,
        input_name=input_names[0],
        output_name=output_names[0],
        epsilon=epsilon
    )

    return output_names

现在,将准备好的torch7模型转换成CoreML。使用这个完整的python转换器脚本。

脚本地址:https://github.com/prisma-ai/torch2coreml/blob/master/example/fast-neural-style/convert-fast-neural-style.py

它有一些额外的修改,例如,修复空间全卷积层(SpatialFullConvolution)的加载。

.mlmodel文件可以嵌入到iOS应用程序内部,运行生成的python CoreML模型来测试是否在图像上应用了风格转换。为此,我创建了一个简单的脚本:

import argparse

from PILimport Image
from coremltools.modelsimport MLModel


def main():
    parser= argparse.ArgumentParser(
        description='Stylize image using CoreML'
    )

    parser.add_argument('-input', required=True,help='Path to input image')
    parser.add_argument('-output', required=True,help='Output path')
    parser.add_argument('-model', required=True,help='CoreML model path')

    args= parser.parse_args()

    image= Image.open(args.input)

    net= MLModel(args.model)
    stylized_image= net.predict({'inputImage': image})['outputImage']
    stylized_image= stylized_image.convert('RGB')

    stylized_image.save(args.output)


if __name__== "__main__":
    main()

请注意使用输入大小与模型兼容的图像,或者你可以在调用MLModel的“predict”方法之前简单地添加图像扩展。

马赛克模型的输出示例:

步骤4:iOS应用程序

利用上一步使用的4个风格转换模型实现了一个简单的应用程序。由于它超出了当前文章的范围,你可以在Apple教程和文档中找到使用CoreML的详细解释。它非常简单直观。你可以找到完整的iOS应用程序源代码(本教程的第一个截图是这个应用程序)。

源代码:https://github.com/prisma-ai/torch2coreml/tree/master/example/fast-neural-style/ios。

结论

我们使用torch2coreml软件包将原始Justin Johnson的快速神经风格(fast-neural-style)模型转换为CoreML。 获得的模型可以在iOS和macOS应用程序中使用。 你可以将torch2coreml包用于风格转换和其他模型。

本教程的完整的源代码:https://github.com/prisma- ai/torch2coreml/tree/master/ example/fast-neural-style

原文发布于微信公众号 - ATYUN订阅号(atyun_com)

原文发表时间:2017-10-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏漫漫深度学习路

tensorflow学习笔记(二十九):merge_all引发的血案

merge_all引发的血案 在训练深度神经网络的时候,我们经常会使用Dropout,然而在test的时候,需要把dropout撤掉.为了应对这种问题,我们通常...

23110
来自专栏和蔼的张星的图像处理专栏

LCT代码跑起来先文章思路总结

论文才刚开始看,但是代码先跑了一下看结果,有一点小坑,记录下: 首先去论文的github上去下载代码:点这里 readme里其实写了怎么搞:

593
来自专栏机器之心

开源 | 深度安卓恶意软件检测系统:用卷积神经网络保护你的手机

选自GitHub 机器之心编译 参与:Panda 恶意软件可以说是我们现代生活的一大威胁,为了保护我们电子设备中的财产和资料安全,我们往往需要寻求安全软件的帮助...

2617
来自专栏磐创AI技术团队的专栏

Tensorboard详解(下篇)

1354
来自专栏ATYUN订阅号

【干货】圣诞老人是否真实存在?训练Tensorflow的对象检测API能够告诉你答案

背景:最近我们看到了一篇文章,关于如何用于你自己的数据集,训练Tensorflow的对象检测API。这篇文章让我们对对象检测产生了关注,正巧圣诞节来临,我们打算...

2838
来自专栏ATYUN订阅号

【实践操作】在iPhone上创建你的第一个机器学习模型

最近的苹果iPhone X发布会,你会看到iPhone X有一些很酷的功能,比如FaceID,Animoji和AR。我们需要弄明白建立这样一个系统需要什么。 当...

3326
来自专栏玉树芝兰

如何用Python和深度神经网络寻找近似图片?

给你10万张图片,让你从中找出与某张图片最为近似的10张,你会怎么做?不要轻言放弃,也不用一张张浏览。使用Python,你也可以轻松搞定这个任务。

551
来自专栏机器之心

深度 | 详解苹果Core ML:如何为iOS创建机器学习应用?

选自developer.apple 机器之心编译 参与:吴攀 在昨天开幕的 WWDC 2017 开发者大会上,苹果宣布了一系列新的面向开发者的机器学习 API...

3317
来自专栏专知

【干货】手把手教你用苹果Core ML和Swift开发人脸目标识别APP

【导读】CoreML是2017年苹果WWDC发布的最令人兴奋的功能之一。它可用于将机器学习整合到应用程序中,并且全部脱机。CoreML提供的机器学习 API,包...

2676
来自专栏深度学习思考者

图像分割 | FCN数据集制作的全流程(图像标注)

一 全卷积神经网络 文章所有代码已上传至github,觉得好用就给个star吧,谢谢 https://github.com/315386775/FCN_trai...

7209

扫描关注云+社区