上一篇介绍了图像风格迁移的一个最基本实现,虽然在控制台实现了功能,但是想要实际使用,应用到一个app或者网页上光靠上一节的内容肯定是不行的。那怎么样才可以将风格迁移这个功能变成一个可以实际使用的小程序呢?不着急,在实现上述功能前,我们先来介绍一个小东西,也就是这篇文章的主角,我把他称为"毕业设计大杀器“的Flask框架。
前后端分离 在介绍Flask之前,我们先介绍下什么是前后端分离。因为如果不介绍前后端分离就不会理解为啥要选择Flask了。前后端分离是目前互联网项目开发的标准使用方式,其核心思想简单理解为是前端页面(或者app等多端)通过ajax(或者其他请求方式)调用后端的restuful api接口并使用json数据进行交互。其目的是为了将项目解耦合,达到**“术业有专攻”**的效果。因为在以往的web项目中,后端人员的工作量非常大,用过jsp的人都知道,那真的是又当爹又当妈,既要会写后台逻辑还要会弄样式。但是采用了前后端分离的架构之后,前后端人员就可以各司其职了。
前端人的追求 前端追求的是:页面表现,速度流畅,兼容性,用户体验等等。
把精力放在html5,css3,jquery,angularjs,bootstrap,reactjs,vuejs,webpack,less/sass,gulp,nodejs,Google V8引擎,javascript多线程,模块化,设计模式,浏览器兼容性,性能优化等等。
后端人的追求 后端追求的是:三高(高并发,高可用,高性能),安全,存储,业务等等。
把精力放在语言基础,设计模式,底层原理,linux,mysql事务隔离与锁机制,mongodb,http/tcp,多线程,分布式架构,弹性计算架构,微服务架构,性能优化,以及相关的项目管理等等。
应用服务器、Web服务器、Restful 应用服务器:一般指像tomcat,jetty这类的服务器可以解析动态资源也可以解析静态资源,但解析静态资源的能力没有web服务器好。
Web服务器:一般指像nginx,apache这类的服务器,他们一般只能解析静态资源。
静态资源就是类似于html、js、图片这些多次访问也不会变化的资源
一般都是只有web服务器才能被外网访问,应用服务器只能内网访问。
RESTful REST的全称是representational state transfer,即表征状态转移。在理解这个名词之前我们先来看几个名词(感觉需要知道的前置知识好多啊)。
资源(resources) 所谓的资源就是网络上的一个实体,它可以使一个图片,一个文本,一个服务,你可以用一个URI指向它,每种资源对应一个特定的URI,要获取这个资源访问它的URI就行了,所谓的上网,其实就是与网络上的资源进行一系列的互动就是了。
表征(representation) 怎么把资源表现出来就是表征的意义,比如一段文本是txt、html还是json,图片是jpg还是png,以http协议为例,就是Accept和content-type中的内容,说明了资源的类型。
状态转移(state tranfer) 访问一个网站,就是客户端和服务端的一个交互过程,客户端想要操作服务端,就必须通过某种手段让服务端的状态发生变化,具体到http协议中就是http的几种方法:GET用来获取资源,POST用来新建资源,PUT用来更新资源,DELETE用来删除资源。
理解RESTful 使用URI来表示每一个资源 为每一个资源确定它的表现形式 使用4个方法来操作这些资源 什么是Flask? 介绍完前后端分离后,我们就开始介绍下Flask是什么吧。
Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2。Flask也被称为 “microframework” ,即**“微框架”**,因为它使用简单的核心,用 extension 增加其他功能。Flask没有默认使用的数据库、窗体验证工具。
理解下"微” “微"框架中的“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。...
上一篇文章中我们已经利用 Flask 制作了一个 RESTful API,然而文中末尾我们我们将代码运行起来的时候确发现是 localhost:xxxx,这也就意味着我们没法通过外网访问我们提供的 API,所以这样做出来的程序即使部署到服务器上也没有任何用处。这一篇我们就来详细的说下怎么部署到服务器上然后实现外网访问吧。
环境准备 工欲善其事,必先利其器。还是老样子,既然要选择部署到服务器上,我们首先肯定得要有一个服务器,这里我选择 XX 云的学生机(别问为什么,问就是便宜)。系统选择 Ubuntu18.04,需要安装的东西有:
Python 3.6 Nginx pyenv pipenv Flask + Gunicorn 这里我们用 pyenv 管理不同的 python 版本,这里可能就有人要问了,Ubuntu 不是自带 python2 和 python3 吗,为什么还要用 pyenv 来管理,之前的文章我们也说过,用 pyenv 管理 python 会非常的方便,方便到只需要一行代码就可以安装切换系统的 Python 版本,废话不多说,接下来就开始我们的操作吧。
连接到远程服务器 如何购买 XX 云的云主机我就不多说了,当你买好之后我们在后台查看到我们购买的云主机的外网 IP,比如我的服务器的外网 IP 地址就是94.191.9.43(希望各位大佬手下留情,别弄他):
接下来就是连接到服务器了,工具有很多,xshell、putty 或者 terminal 都可以,这里我推荐一个工具Termius,推荐他的原因有两个:颜值,作为一个颜控,Termius 是我见过的最好看的 SSH 客户端,没有之一。同时还是跨平台的,win/mac/linux/android/ios 都支持,这点不知道比 xshell 高到哪里去了。
连接也很简单,我们在 termius 中添加需要连接的 host,然后输入用户名和密码即可登录了,出现如下字样说明登录成功。
利用 pyenv 安装制定版本的 python 之前的文章介绍过如何在 mac 下安装 pyenv,虽然 linux 下的安装方法类似,但毕竟本文的题目是是从 0 到 1 部署,还是再详细说一下吧。...
Photo by Tim Gouw from Pexels
正如文章标题所言,本文是我的**《AI画家》**系列的终章,从4月16号开始的第一篇文章《介绍一下我的毕业设计》到今天已经过了将近2个月了(2个月就更新7篇文章我也是服了我自己了😂),其实这个系列就是我的毕业设计,如今我的毕设做完了,论文也定稿了,想着也该给这个系列画个句号了。
在公众号上发系列文章是我的一次尝试,因为知道自己的文笔不好,写不好什么感悟感想,只能水水技术文了,然而即使要写技术文也得找个切入点,可事实上哪会有那么多切入点,无奈只能靠弄个技术文系列,吸引下路人的眼球,勉强度日了。
既然是终章,那就对整个系列做个简单的总结吧,希望这篇不会是烂尾文。
开题 在《介绍一下我的毕业设计》一文中我提到,刚开始我单纯因为觉得好玩才开始研究图像风格迁移,后来认为名字逼格够高,足够唬住老师才把这个课题作为我的毕设,现在回过头来结合最后的答辩觉得自己选这个题目的毕设是真的傻X,不是因为这个选题不好,而是把这个选题作为毕业设计的题目真的傻X,说到这就想起一些在答辩现场不好的事情了,溜了溜了。
过程 作者自认为在这个系列中思路还是比较清晰的。
首先是第一弹,想要做深度学习有关的东西,刚开始肯定是要搭建好一个深度学习的环境的。在这篇文章中,详细的介绍了在我的游戏本上利用GPU搭建深度学习环境的过程,包括安装nvidia drive、CUDA、cuDNN和TensorFlow的GPU版本,以及简单介绍了如何利用Pyenv和Pipenv管理自己电脑上的Python虚拟环境。
然后是第二弹,介绍了什么是图像风格迁移,以及如何用TensorFlow实现了一个基本的图像风格迁移的程序,在这篇文章中我只是简单的介绍了图像风格迁移的原理,一方面是因为公式实在是有点多,公众号对于公式的支持不是很好,另一方面作为一个入门介绍,放太多的数学公式的话估计本来人数不多的公众号又要取关一批人了。
第三弹介绍了一个目前非常流行的Python web框架Flask,介绍他的原因不仅仅是因为我的毕业设计就是用这玩意做的,而且在开题的时候我也提到了最后要将这个深度学习算法落地,能够做出一个可用的RESTful API,而相较于其他Web框架,Flask有着得天独厚的优势:首先TensorFlow的首选语言是Python,Flask也是用Python写的,调用起来非常方便;相对于Django,Flask非常轻便,使用起来也非常的灵活。然而在用Flask之前,必须要有些基础知识,因此在这篇文章开篇,我又介绍了前后端分离,介绍了什么是RESTful API,如果对这些概念没有理解的话就算把代码写出来了也很难知道是干嘛的。
既然在第三弹介绍了一个用来编写RESTful API的工具,那第四弹自然就是如何编写这个RESTful API了。其实在第二弹中就指出了那个算法的不足之处——“慢”,所以在这篇文章中就使用了第二个算法训练出来的模型,之所以不介绍新的风格迁移算法,主要是因为这个算法有点难度,我理解的时候也花了好长时间,等到基本上理解了,第四弹都已经写完了😂。所以在这篇文章中我干脆直接用别人训练好的现成的模型了。其中介绍了如何利用蓝图(BluePrint)进行模块化开发,并给出了我自己认为的比较好的分层方法,然后利用七牛云存储为服务器减压,最后利用Postman请求该API完成测试。
第五弹的主要内容就是介绍如何将第四弹中已经在本地测试成功的项目发布到服务器上实现公网访问,介绍了如何使用了XX云主机,并在上面安装配置了项目所需要使用到的环境的过程,介绍了Termius、FileZilla等工具。在这篇文章中我希望会有些和别的文章不一样的东西,因此我不仅把实现过程展现了出来,还分享了一些我在实际使用过程中产生的疑问,踩到的坑以及我个人在部署过程中总结的一些经验。
最后 总的来说,这个系列不仅仅是我在做毕业设计时的一个缩影,也是我自己对于公众号运营的一个探索。期间也收到了很多读者的支持与鼓励,感谢你们的一路陪伴🙏
推荐阅读
《介绍一下我的毕业设计》 《AI 绘画第一弹——用GPU为你的训练过程加速》 《AI绘画第二弹——图像风格迁移》 《AI画家第三弹——毕业设计大杀器之Flask》 《AI画家第四弹——利用Flask发布风格迁移API》 《AI画家第五弹——从0到1部署你的RESTful API》
上篇文章介绍了python web开发中经常使用到的一个框架flask,如果有遗忘的,可以点此回顾👉AI画家第三弹——毕业设计大杀器之Flask,本文的主要任务就是完成上篇文章末尾的要求,利用Flask发布你自己的风格迁移API。
本文源码可在微信公众号「01二进制」后台回复「风格迁移API」获得
需求分析 我们知道软件工程的第一步就是需求分析,放在这里就是要知道我们需要实现的功能是什么样的。我画了一张简陋的图来描述这次的需求:
真的是很简陋的一张图啊,其实理解起来很容易,就是用户上传一张图片,Flask获取到这张图片,调用风格迁移的模型,然后生成结果图,在传递回前端即可。
环境准备 既然明白了需求,那么接下来要做的事情自然是环境搭建了,老样子,这里我们仍然使用Pipenv来创建虚拟环境,如何搭建pipenv环境我就不说了,在微信公众号「01二进制」后台回复「风格迁移API」获得源码之后直接在终端输入pipenv install即可。
开始 hello world 我们首先在项目根目录创建一个main.py的文件作为整个项目的启动文件,上文我们说过,为了简化大型应用并为扩展提供集中的注册入口,我们并不会将所有的视图函数直接写在main.py,而是采用蓝图的方式分模块开发,因此我们需要在项目根目录新建app/文件夹,在其中的__init__.py中编写如下代码:
from flask import Flask def create_app(): app = Flask(__name__) return app 这样我们就可以通过在main.py中编写如下代码实现一个hello world应用了。
from app import create_app app = create_app() @app.route('/') def hello(): return 'hello,world' if __name__ == '__main__': app.run(port=8080, debug=True) 启动main.py即可发现项目启动了,在浏览器输入localhost:8080即可看到hello,world字样。
蓝图编写 我们肯定是不能满足于小小的hello world的,既然说到了模块化开发,那怎么个模块法?
这里每个人的想法都是不一样的,其实也没有一个统一的标准,这里我就说下我自己的分级方法吧。
stylize是项目根路径 app是项目 app/api是项目的api部分,一个项目肯定不只有api,还可能会有web等页面内容 app/api/v1表明该api的版本是v1,当然日后也有可能会有v2、v3等等 app/api/v1/img表明这里存放的都是和img有关的api app/api/v1/img/stylize.py表明这个文件存放的是风格迁移的视图函数 认识完结构的划分之后,就来编写我们的蓝图吧。
首先我们需要在app/api/v1/img/__init__.py中编写如下代码:
from flask import Blueprint # 定义一个蓝图 img = Blueprint('img', __name__) from app....
这篇文章是我的《AI 绘画系列》的第三篇,点击此处可以查看整个系列的文章
本篇文章的源码可以在微信公众号「01 二进制」后台回复「图像风格迁移」获得
简介 所谓图像风格迁移,是指将一幅内容图 A 的内容,和一幅风格图 B 的风格融合在一起,从而生成一张具有 A 图风格和 B 图内容的图片 C 的技术。目前这个技术已经得到了比较广泛的应用,这里安利一个 app——“大画家”,这个软件可以将用户的照片自动变换为具有艺术家的风格的图片。
准备 其实刚开始写这篇文章的时候我是准备详细介绍下原理的,但是后来发现公式实在是太多了,就算写了估计也没什么人看,而且这篇文章本来定位的用户就是只需要实现功能的新人。此外,有关风格迁移的原理解析的博客实在是太多了,所以这里我就把重点放在如何使用 TensorFlow 实现一个快速风格迁移的应用上,原理的解析就一带而过了。如果只想实现这个效果的可以跳到**“运行”**一节。
第一步我们需要提前安装好 TensorFlow,如果有 GPU 的小伙伴可以参考我的这篇文章搭建一个 GPU 环境:《AI 绘画第一弹——用 GPU 为你的训练过程加速》,如果打算直接用 CPU 运行的话,执行下面一行话就可以了
pip install numpy tensorflow scipy 原理 本篇文章是基于A Neural Algorithm of Artistic Style一文提出的方法实现的,如果嫌看英文论文太麻烦的也可以查看我对这篇文章的翻译【译】一种有关艺术风格迁移的神经网络算法。
为了将风格图的风格和内容图的内容进行融合,所生成的图片,在内容上应当尽可能接近内容图,在风格上应当尽可能接近风格图,因此需要定义内容损失函数和风格损失函数,经过加权后作为总的损失函数。
预训练模型 CNN 具有抽象和理解图像的能力,因此可以考虑将各个卷积层的输出作为图像的内容,这里我们采用了利用 VGG19 训练好的模型来进行迁移学习,一般认为,卷积神经网络的训练是对数据集特征的一步步抽取的过程,从简单的特征,到复杂的特征。训练好的模型学习到的是对图像特征的抽取方法,而该模型就是在 imagenet 数据集上预训练的模型,所以理论上来说,也可以直接用于抽取其他图像的特征,虽然效果可能没有在原有数据集上训练出的模型好,但是能够节省大量的训练时间,在特定情况下非常有用。
加载预训练模型 def vggnet(self): # 读取预训练的vgg模型 vgg = scipy.io.loadmat(settings.VGG_MODEL_PATH) vgg_layers = vgg['layers'][0] net = {} # 使用预训练的模型参数构建vgg网络的卷积层和池化层 # 全连接层不需要 # 注意,除了input之外,这里参数都为constant,即常量 # 和平时不同,我们并不训练vgg的参数,它们保持不变 # 需要进行训练的是input,它即是我们最终生成的图像 net['input'] = tf....