前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >手把手教你搭建能够实现 Prisma 风格迁移效果的 iOS 酷炫应用(附代码)

手把手教你搭建能够实现 Prisma 风格迁移效果的 iOS 酷炫应用(附代码)

作者头像
AI研习社
发布2018-07-26 16:29:50
1.1K0
发布2018-07-26 16:29:50
举报
文章被收录于专栏:AI研习社

本文为雷锋字幕组编译的技术博客,原标题 Transforming Pictures with Neural Style Transfer in iOS,作者为 Navdeep Singh。 翻译 | 廖明月 吴桐 蔡雨萌 整理 | 凡江

随着 2012 年深度神经网络在 ImageNetchallenge 比赛上以 AlexNet 模型获胜,深度神经网络开创了空前的高潮。AI 工程师已经将深度学习技术应用到越来越多的问题域,包括预训练的深度美国有线电视新闻网模型。还有什么比创造艺术更富有创造力呢?

一种已经提出并实施的想法,称为「神经风格转换」,允许你能够利用预训练的深度神经网络模型,并将某一图像的风格,例如或梵高或莫尼特的任何杰作,迁移到另一个图像,例如你的个人资料图片或你最喜欢的小狗的图片,从而创造了一个混合你的图片内容和名作风格的图像。

实际上有一个 iOS 应用程序称为 Prisma,它赢得了 2016 年度最佳应用程序,就是这样,它在短短几秒钟内,可以将你的图片转换成你所选择的任何风格。

在本文中,您将了解如何训练一个快速的神经风格迁移模型,并在自己的 iOS 上使用,实现 Prisma 可以做到的事情。

快速神经迁移模型的训练

在这一节中,按照以下步骤学习如何利用 TensorFlow 使用快速神经风格转移算法来训练模型:

1. 在你的 Mac 终端或者最好是有着 GPU 驱动的 Ubuntu 上,运行 git clone 命令,复制链接 this Github repo,这是约翰逊快速风格迁移的一个很好的 TensorFlow 实现的分支,修改后经过训练的模型允许在 iOS 或 Android 应用程序中使用。

2. 运行 cd 命令 进入快速风格迁移目录,然后运行 setup.sh 脚本来下载预训练的 VGG-19 模型文件以及 MS COCO 训练数据集。

3. 运行以下命令,使用风格图像 starry_night.jpg 和内容图像 WW1.jPG,通过训练创建检查点文件:

代码语言:javascript
复制
mkdir checkpoints
mkdir test_dir
python style.py --style images/starry_night.jpg --test images/ww1.jpg --test-dir test_dir --content-weight 1.5e1 --checkpoint-dir checkpoints --checkpoint-iterations 1000 --batch-size 10

在图像目录中还有一些其他风格的图像,你可以以此用来创建不同的检查点文件。这里使用的 starry_night.jpg 风格图像是梵高的一幅名画:

使用梵高的画作作为风格图片

在 NVIDIA GTX 1070 GPU 驱动的 Ubuntu 下整个训练需要大约五小时,当然在如果在 CPU 上会花更长的时间。

4. 用文本编辑器打开 evaluate.py 文件,并将以下两行代码取消批注(第 158 和 159 行):

代码语言:javascript
复制
# saver = tf.train.Saver()
# saver.save(sess, "checkpoints_ios/fns.ckpt")

5. 运行以下命令建立一个新的检查点,输入图像命名为 img_placeholder,转移后的图像命名为 preds:

代码语言:javascript
复制
python evaluate.py --checkpoint checkpoints \
--in-path examples/content/dog.jpg \
--out-path examples/content/dog-output.jpg

6. 运行以下命令创建一个 TensorFlow 图文件并载入检查点中的权重参数,这将创建一个约 6.7MB 的大小 .pb 文件:

代码语言:javascript
复制
python freeze.py --model_folder=checkpoints_ios --output_graph fst_frozen.pb

7. 假设你已拥有一个 /ft.file 目录,将生成的 st_frozen.pb 文件复制到 /ft.file 目录下,直接 cd 进入你的 TensorFlow 源代码根目录,如 ~/tensorflow-1.4.0,然后运行以下命令创建为 .pb 文件生成一个量化模型。

代码语言:javascript
复制
bazel-bin/tensorflow/tools/quantization/quantize_graph \
--input=/tf_files/fst_frozen.pb  \
--output_node_names=preds \
--output=/tf_files/fst_frozen_quantized.pb \
--mode=weights

这将把固化图文件的大小从 6.7 MB 缩减到 1.7 MB,它意味着如果你在 App 中为 50 个不同的风格载入了 50 个模型,增加的大小将会是 85 MB。

以上就是利用一张风格图像和输入图像训练和量化一个快速神经风格迁移模型的全部步骤。你可以在 test_dir 目录下检查步骤三中生成的图像,看一看风格迁移的效果。如果需要的话,你还可以试着玩一玩含超参数的模型,看一看那些不同的,很可能更好的风格迁移效果。代码文件提供在 https://github.com/jeffxtang/fast-style-transfer/blob/master/docs.md#style 上。

一个重要提示:当你在你的 iOS 或者 Android app 上使用这些模型之前,需要记录下输入图像的精确宽度和高度值作为步骤五中 --in-path 的参数,iOS 或 Android 的代码将会调用图像的宽度和高度值(你很快就会看到是如何调用的),否则当你在 App 上运行这些模型的时候将会得到 Conv2DCustomBackpropInput: Size of out_backprop doesn't match computed 的错误提示。

在 iOS 系统上添加和测试神经风格迁移模型

第一件事是手动建立 TensorFlow 库,如果你此前尚未安装过这个库。然后执行以下步骤就可以在你的 iOS App 上获取 TensorFlow 支持和并添加神经风格迁移模型,并试运行你的 App。

  1. 如果你已经拥有了一个添加了 TensorFlow 手册库的 iOS app,可以跳过下面这一步。否则,创建一个新的基于 Objective-C 语言的 iOS app,比如可以命名它为 NeuralStyleTransfer,或者在已经存在的 app 中,在 PROJECT 下的 Build Settings 配置中创建一个新的自定义设置,名称是 TENSORFLOW_ROOT,值为 $HOME/tensorflow-1.4.0,假定上面是你 TensorFlow 1.4.0 的安装地址。然后在 TARGET 下的 Build Settings 配置中将 Other Linker Flags 设置如下:
代码语言:javascript
复制
-force_load $(TENSORFLOW_ROOT)/tensorflow/contrib/makefile/gen/lib/libtensorflow-core.a $(TENSORFLOW_ROOT)/tensorflow/contrib/makefile/gen/protobuf_ios/lib/libprotobuf.a $(TENSORFLOW_ROOT)/tensorflow/contrib/makefile/gen/protobuf_ios/lib/libprotobuf-lite.a $(TENSORFLOW_ROOT)/tensorflow/contrib/makefile/downloads/nsync/builds/lipo.ios.c++11/nsync.a

然后将 Header Search Paths 设置如下:

代码语言:javascript
复制
$(TENSORFLOW_ROOT) $(TENSORFLOW_ROOT)/tensorflow/contrib/makefile/downloads/protobuf/src $(TENSORFLOW_ROOT)/tensorflow/contrib/makefile/downloads $(TENSORFLOW_ROOT)/tensorflow/contrib/makefile/downloads/eigen $(TENSORFLOW_ROOT)/tensorflow/contrib/makefile/gen/proto

2. 将 fst_frozen_quantized.pb 文件和几个测试所用图片拖放到你的工程文件夹中,在 https://github.com/PacktPublishing/Intelligent-Mobile-Projects-with-TensorFlow/tree/master/ch4/ios/NeuralStyleTransfer 中的 NeuralStyleTransfer app 文件夹中找到相同的 ios_image_load.mm 和 .h 文件,把它们复制到工程文件夹下。

3. 将 ViewController.m 文件重命名为 ViewController.mm,把它和原 ViewController.h 文件替换为从上面的 GitHub 网址链接获取中的 ViewController.h 和 .mm 文件。

4. 在 iOS 模拟器中或者你的 iOS 设备中运行 App,你会看到一个狗图片:

5. 点击选择 Fast Style Transfer 选项,过几秒钟,你会看到一个带有 starry night 风格的新图片。

你可以很简单的通过选择你最喜欢的图片作为风格图片然后跟随之前的步骤编译带有不同风格的其他模型。然后可以按照这段的步骤在你的 iOS App 中使用模型。这里有使用 iOS 的详细代码。

使用快速神经迁移模型回顾 iOS 代码

在 ViewController.mm 中包含许多重要的代码片断它在输入图片的预处理和转移图片的后处理中是独特的。

1. 两个常量,wanted_width,wanted_height,作为图片的高度和宽度定义为相同的值,这里的图片就是步骤 5 中的 dog.jpg:

代码语言:javascript
复制
const int wanted_width = 300;
const int wanted_height = 400;

2. iOS 的 dispatch 队列是用来在 non-UI 线程加载和运行你的快速神经迁移模型并且在风格迁移后图片生成了,以下为将图片发送到 UI 线程的代码:

代码语言:javascript
复制
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    UIImage *img = imageStyleTransfer(@"fst_frozen_quantized");
    dispatch_async(dispatch_get_main_queue(), ^{
        _lbl.text = @"Tap Anywhere";
        _iv.image = img;
    });
});

3. 定义浮点型 3 维张量用于转换输入图片:

代码语言:javascript
复制
tensorflow::Tensor image_tensor(tensorflow::DT_FLOAT, tensorflow::TensorShape({wanted_height, wanted_width, wanted_channels}));
auto image_tensor_mapped = image_tensor.tensor<float, 3>();

4. 发送到 tensorflow Sess->Run 方法中的输入节点名和输出节点名与训练模型的时候是相同的 :

代码语言:javascript
复制
std::string input_layer = "img_placeholder";
std::string output_layer = "preds";
std::vector<tensorflow::Tensor> outputs;
tensorflow::Status run_status = session->Run({{input_layer, image_tensor}} {output_layer}, {}, &outputs);

5. 当模型运行完成并且返回输出张量 (包含 0 到 255 的 RGB 值) 时,你需要调用 tensorToUIImage 通用函数把张量数据转换为 RGB buffer:

代码语言:javascript
复制
UIImage *imgScaled = tensorToUIImage(model, output->flat<float>(), image_width, image_height);
static UIImage* tensorToUIImage(NSString *model, const Eigen::TensorMap<Eigen::Tensor<float, 1, Eigen::RowMajor>, Eigen::Aligned>& outputTensor, int image_width, int image_height) {
    const int count = outputTensor.size();
    unsigned char* buffer = (unsigned char*)malloc(count);
    for (int i = 0; i < count; ++i) {
        const float value = outputTensor(i);
        int n;
        if (value < 0) n = 0;
        else if (value > 255) n = 255;
        else n = (int)value;
        buffer[i] = n;
}

6. 现在,你可以把 buffer 转化成 UIImage 实例在调整它的大小之前,以下为代码:

代码语言:javascript
复制
UIImage *img = [ViewController convertRGBBufferToUIImage:buffer withWidth:wanted_width withHeight:wanted_height];
UIImage *imgScaled = [img scaleToSize:CGSizeMake(image_width, image_height)];
return imgScaled;

如果你对这个主题感兴趣,你可以使用 Jeff Tange 的书来研究更多的深度学习和强化学习 app。这本书包括超过 10 种 iOS,android 和 raspberry pi app 使用 tensorflow 来运行,使用 scratch 进行编译,离线运行所有绚丽的 tensorflow 模型:从计算机视觉,语音合成到生成对抗网络和类似于 Alphazero 的深度强化学习模型。

原文链接:https://medium.com/@navdeepsingh_2336/transforming-pictures-with-neural-style-transfer-in-ios-6988b79b34ee

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-07-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI研习社 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 快速神经迁移模型的训练
  • 在 iOS 系统上添加和测试神经风格迁移模型
  • 使用快速神经迁移模型回顾 iOS 代码
相关产品与服务
语音合成
语音合成(Text To Speech,TTS)满足将文本转化成拟人化语音的需求,打通人机交互闭环。提供多场景、多语言的音色选择,支持 SSML 标记语言,支持自定义音量、语速等参数,让发音更专业、更符合场景需求。语音合成广泛适用于智能客服、有声阅读、新闻播报、人机交互等业务场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档