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

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

作者头像
AI研习社
发布于 2018-07-26 08:29:50
发布于 2018-07-26 08:29:50
1.2K00
代码可运行
举报
文章被收录于专栏:AI研习社AI研习社
运行总次数:0
代码可运行

本文为雷锋字幕组编译的技术博客,原标题 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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
# saver = tf.train.Saver()
# saver.save(sess, "checkpoints_ios/fns.ckpt")

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
python evaluate.py --checkpoint checkpoints \
--in-path examples/content/dog.jpg \
--out-path examples/content/dog-output.jpg

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
-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
代码运行次数:0
运行
AI代码解释
复制
$(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
代码运行次数:0
运行
AI代码解释
复制
const int wanted_width = 300;
const int wanted_height = 400;

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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
代码运行次数:0
运行
AI代码解释
复制
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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
原来 8 张图,就能学废 Reactor 和 Proactor
别小看这两个东西,特别是 Reactor 模式,市面上常见的开源软件很多都采用了这个方案,比如 Redis、Nginx、Netty 等等,所以学好这个模式设计的思想,不仅有助于我们理解很多开源软件,而且也能在面试时吹逼。
小林coding
2021/05/27
9930
原来 8 张图,就能学废 Reactor 和 Proactor
​网络 IO 演变发展过程和模型介绍
作者:jaydenwen,腾讯 pcg 后台开发工程师 在互联网中提起网络,我们都会避免不了讨论高并发、百万连接。而此处的百万连接的实现,脱离不了网络 IO 的选择,因此本文作为一篇个人学习的笔记,特此进行记录一下整个网络 IO 的发展演变过程。以及目前广泛使用的网络模型。 1.网络 IO 的发展 在本节内容中,我们将一步一步介绍网络 IO 的演变发展过程。介绍完发展过程后,再对网络 IO 中几组容易混淆的概念进行对比、分析。 1.1 网络 IO 的各个发展阶段 通常,我们在此讨论的网络 IO 一
腾讯技术工程官方号
2021/02/25
1.6K0
高性能实践IO之Reactor模式
讲到高性能IO绕不开Reactor模式,它是大多数IO相关组件如Netty、Redis在使用的IO模式,为什么需要这种模式,它是如何设计来解决高性能并发的呢?
张哥编程
2024/12/19
1510
高性能实践IO之Reactor模式
高性能IO模型浅析
服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型。 (2)同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为NONBLOCK。注意这里所说的NIO并非Java的NIO(New IO)库。 (3)IO多路复用(IO Multiplexing):即经典的Reactor设计模式,有时也称为异步阻塞IO,Java中的Selector和Linux中的epoll都是这种模型
李海彬
2018/03/23
1.1K0
高性能IO模型浅析
Linux高性能IO网络模型对比分析:Reactor vs Proactor
随着互联网的发展,面对海量用户高并发业务,传统的阻塞式的服务端架构模式已经无能为力。本文旨在为大家提供有用的高性能网络编程的I/O模型概览以及网络服务进程模型的比较,以揭开设计和实现高性能网络架构的神秘面纱。 2、关于作者 陈彩华(caison):主要从事服务端开发、需求分析、系统设计、优化重构工作,主要开发语言是 Java。 3、线程模型 上篇《高性能网络编程(五):一文读懂高性能网络编程中的I/O模型》介绍完服务器如何基于 I/O 模型管理连接,获取输入数据,下面将介绍基于进程/线程模型,服务器如何处理请求。 值得说明的是,具体选择线程还是进程,更多是与平台及编程语言相关。 例如 C 语言使用线程和进程都可以(例如 Nginx 使用进程,Memcached 使用线程),Java 语言一般使用线程(例如 Netty),为了描述方便,下面都使用线程来进行描述。 4、线程模型1:传统阻塞 I/O 服务模型
sunsky
2021/01/06
3.9K0
彻底搞懂Reactor模型和Proactor模型
在高性能的I/O设计中,有两个著名的模型:Reactor模型和Proactor模型,其中Reactor模型用于同步I/O,而Proactor模型运用于异步I/O操作。
全菜工程师小辉
2019/08/16
42.2K4
一文搞懂什么是阻塞IO、信号驱动IO、Reactor模型、零拷贝
公众号《鲁大猿》 ,寻精品资料,帮你构建Java全栈知识体系 http://www.jiagoujishu.cn
鲁大猿
2024/01/05
4370
一文搞懂什么是阻塞IO、信号驱动IO、Reactor模型、零拷贝
IO你了解了,NIO你会吗?
作者:海 子 地址:cnblogs.com/dolphin0520   也许很多朋友在学习NIO的时候都会感觉有点吃力,对里面的很多概念都感觉不是那么明朗。在进入Java NIO编程之前,我们今天先来讨论一些比较基础的知识:I/O模型。下面本文先从同步和异步的概念 说起,然后接着阐述了阻塞和非阻塞的区别,接着介绍了阻塞IO和非阻塞IO的区别,然后介绍了同步IO和异步IO的区别,接下来介绍了5种IO模型,最后介绍了两种和高性能IO设计相关的设计模式(Reactor和Proactor)。   以下是本文的目录
Tanyboye
2018/07/02
4620
高性能IO编程设计
? 首先,在讲述高性能IO编程设计的时候,我们先思考一下何为“高性能”呢,如果自己来设计一个web体系服务,选择BIO还是NIO的编程方式呢?其次,我们可以了解下构建一个web体系服务中,为了能够支撑
小坤探游架构笔记
2020/04/07
1.2K0
彻底搞懂Java的网络IO
应用程序向操作系统发出IO请求:应用程序发出IO请求给操作系统内核,操作系统内核需要等待数据就绪,这里的数据可能来自别的应用程序或者网络。一般来说,一个IO分为两个阶段:
全菜工程师小辉
2019/08/16
2.2K0
搞懂I/O多路复用及其技术
高性能是每个程序员的追求,无论写一行代码还是做一个系统,都希望能够达到高性能的效果。高性能架构设计主要集中在两方面:
BUG弄潮儿
2021/01/05
6770
网络基础篇-网络编程
在内核中,为每个socket维护两个队列,一个是已建立连接的队列,也就是完成了三次握手,处于established状态,一个是还没有完全建立连接的队列,处于sync_rcvd状态。
Check King
2021/08/09
7320
架构设计-高性能篇
大家好,我是易安!今天我们谈一谈架构设计中的高性能架构涉及到的底层思想。本文分为缓存架构,单服务器高性能模型,集群下的高性能模型三个部分,内容很干,希望你仔细阅读。
架构狂人
2023/08/16
4330
架构设计-高性能篇
聊聊Netty那些事儿之从内核角度看IO模型
从今天开始我们来聊聊Netty的那些事儿,我们都知道Netty是一个高性能异步事件驱动的网络框架。
bin的技术小屋
2022/01/12
8002
聊聊Netty那些事儿之从内核角度看IO模型
如何设计真正高性能高并发分布式系统(万字长文)
“世间可称之为天经地义的事情没几样,复杂的互联网架构也是如此,万丈高楼平地起,架构都是演变而来,那么演变的本质是什么?”
玄姐谈AGI
2019/11/25
2.4K0
整天背诵五种I/O模型/epoll区别,换个马甲确不认识了!
Java 中的 BIO、NIO和 AIO 理解为是 Java 语言对操作系统的各种 IO 模型的封装。
早起的鸟儿有虫吃
2021/06/25
1.2K0
整天背诵五种I/O模型/epoll区别,换个马甲确不认识了!
Netty网络编程第六卷
1)获取请求数据,客户端与服务器建立连接发出请求,服务器接受请求(1-3); 2)构建响应,当服务器接收完请求,并在用户空间处理客户端的请求,直到构建响应完成(4); 3)返回数据,服务器将已构建好的响应再通过内核空间的网络 I/O 发还给客户端(5-7)。
大忽悠爱学习
2022/05/06
3820
Netty网络编程第六卷
Java NIO之理解I/O模型(二)
上一篇文章讲解了I/O模型的一些基本概念,包括同步与异步,阻塞与非阻塞,同步IO与异步IO,阻塞IO与非阻塞IO。这次一起来了解一下现有的几种IO模型,以及高效IO的两种设计模式,也都是属于IO模型的基础知识。
纪莫
2019/09/23
4800
Java NIO之理解I/O模型(二)
高性能服务器程序框架
http://blog.csdn.net/zs634134578/article/details/19806429
bear_fish
2018/09/20
2.1K0
高性能服务器程序框架
Java NIO:浅析I/O模型
也许很多朋友在学习NIO的时候都会感觉有点吃力,对里面的很多概念都感觉不是那么明朗。在进入Java NIO编程之前,我们今天先来讨论一些比较基础的知识:I/O模型。下面本文先从同步和异步的概念 说起,然后接着阐述了阻塞和非阻塞的区别,接着介绍了阻塞IO和非阻塞IO的区别,然后介绍了同步IO和异步IO的区别,接下来介绍了5种IO模型,最后介绍了两种和高性能IO设计相关的设计模式(Reactor和Proactor)。   以下是本文的目录大纲:   一.什么是同步?什么是异步?   二.什么是阻塞?什么是非阻塞
范蠡
2018/04/04
6970
Java NIO:浅析I/O模型
相关推荐
原来 8 张图,就能学废 Reactor 和 Proactor
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档