【深度学习】图片风格转换应用程序:使用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 条评论
登录 后参与评论

相关文章

来自专栏计算机视觉战队

实战——目标检测与识别

最近总是有很多入门的朋友问我,我进入计算机视觉这个领域难不难?是不是要学习很多知识?到底哪个方向比较好?。。。。。这些问题其实我也不好回答他们,只能衷心告诉他...

2945
来自专栏数据科学与人工智能

【Python语言】Scikit-learn 快速入门

环境 ubuntu 12.04, 64 bits python 2.7 sklearn 0.14 准备 sklearn 快速入门的官方文档7。这个文档主要描述机...

2986
来自专栏Unity Shader

Shader初学笔记:一种三维等值线的算法

把反距离加权算法转换到三维空间,是不是很方便的算出三维空间下的等值线了呢,再结合Shatter Toolkit插件进行剖切,修改修改代码。应该可以解决地层模型任...

50518
来自专栏ATYUN订阅号

人脸图像识别实例:使用Keras-MXNet在MXNet模型服务器上部署“笑脸检测器”

AWS最近宣布发布了针对Keras 2的Apache MXNet后端,与使用多GPU的默认后端相比,它可以为你提供高达3倍的速度提升。它可以改进训练和推理性能。...

1732
来自专栏新智元

横扫各项NLP任务的BERT模型有了PyTorch实现!提供转换脚本

上周,谷歌最强NLP模型BERT开源了官方TensorFlow代码和预训练模型,引起大量关注。

2032
来自专栏深度学习之tensorflow实战篇

R包—iGraph

这几天收到师兄的任务,熟悉iGRaph包的使用,通过查资料,外加自己的实践,在此做个简单的学习笔记。 以下例子均是在R 3.0.1版本下测试的。 1.用igr...

3265
来自专栏机器之心

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

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

2907
来自专栏量子位

Keras 2正式发布,推出深度整合进TensorFlow的新API

允中 编译整理 量子位·QbitAI 出品 今天,深度学习框架Keras在博客上发表文章,介绍了深度整合进TensorFlow的内部版本tf.keras,以及...

3428
来自专栏ATYUN订阅号

【实践操作】 在iOS11中使用Core ML 和TensorFlow对手势进行智能识别

在计算机科学中,手势识别是通过数学算法来识别人类手势的一个议题。用户可以使用简单的手势来控制或与设备交互,让计算机理解人类的行为。 这篇文章将带领你实现在你自己...

4856
来自专栏AI科技大本营的专栏

重磅消息 | 深度学习框架竞争激烈 TensorFlow也支持动态计算图

今晨 Google 官方发布消息,称 TensorFlow 支持动态计算图。 原文如下: 在大部分的机器学习中,用来训练和分析的数据需要经过一个预处理过程,输入...

2715

扫码关注云+社区