plainify

2022的取舍与得失

每年双十二结束都意味着新年降至,回想这一年发生了太多太多的事情,总觉得需要写些什么,但又不知从何下笔。提笔前翻了一下待办,里面收集了很多自己想写的文章,比如之前一直想写一篇文章来聊一聊内卷的,又或者聊一聊自己工作这一年的总结感悟,但总是由于这样或那样的原因耽搁了,如今正好趁着🐑了在家隔离的这段时间把这些想写的东西收一下。这篇不算年终总结的文章,也没什么脉络,就是想到什么就说什么了。 如今疫情终于放开,报复性消费没有看见,反而是越来越多的小🐑人涌现出来。很不幸的,笔者近期也中招了,本想着分享一些自己的新冠自愈过程,但也不知是杭州的毒株较为温和还是我的抵抗力较强,除了第一天晚上有轻微的发热外,其他时候的感觉甚至不如普通感冒让我难受。而网上所传的喉咙刀片的感觉、食欲不振等情况也都没有经历过,这点看来还是较为幸运的,而且事后为了奖励我的免疫系统,我的食欲也随之提升,这么看来明年的减肥又变得艰巨起来了。 先说说内卷,提到阿里,除了996、福报这些词之外,更多的就是“卷”这个词了,卷王、奋斗逼这一系列名词应运而生。而且由于国内这种“形同虚设”的劳动法以及中国人骨子里“艰苦奋斗”的精神又让这一切变得那么正常与合理。仿佛你从小一路成绩优异、名校毕业后就该在这岗位上累死累活。说了这么多,接下来举几个例子来说说什么是内卷。 抢火车票,一个人先用抢票软件,逼得其他人也用抢票软件,因为票没有变多,最后大家都回到了起跑线,但是开发抢票软件的赚了。 孩子上学,一个孩子上辅导班,逼得大家都去上辅导班,最后排名还是没变,但开辅导班的赚了。 本来大家都是工作8小时,有人开始加班,最后逼得所有人都加班,所有人挣得还是那点钱,但是老板的3系换5系了。 内卷是啥,内卷就是大家都损失了,只有一小撮人赚了。 内卷是无法带来质变的量变。 至于怎么摆脱内卷,无非两条路,要么多一点,要么均一点。 “华盛顿不是一个生活的地方。这里房租高,这里吃的差,这里的灰尘令人作呕,这里的道德令人厌恶。去西部吧,年轻人。去西部,并和国家一起成长。”——纽约论坛报,1865年。 “好在苦惯了,而且什么人都是一样苦,从军长到伙夫,除粮食外一律吃五分钱的伙食。发零用钱,两角即一律两角,四角即一律四角。因此士兵也不怨恨什么人。”——毛选《井冈山的斗争》 掐指一算,从去年7月毕业入职到现在工作也有一年半了,期间经历过业务方向调整、团队成员变更、好友离职等等,当时实习时一起留下来的小伙伴们如今也是走的走,散的散,没留下多少人了。近来也时常会思考,要不要看看外面的机会,留在这里的意义又是什么?思来想去仍然没有一个明确的答案,一来因为业务确实还行,内容化本来就是每个大厂在做的事情,相对来说还是有些前景的。二来团队氛围确实很棒,自从前段时间换了leader之后,团队氛围有了质的提升,轻松的氛围确实有助于工作效率的提升。 试想一下,如果长时间处在一个被挤压、高强度push的环境下,员工的心理是否健康都需要划一个问号,更别说静心工作了。个人看来,不仅仅是阿里,现在的大厂里有很多leader是极其不称职的,这个不称职不仅仅体现在专业能力上,更多的是个人素养,说的难听点就是**“早生几年吃到时代红利而趾高气昂的油腻中年人”**。这些人个人能力并不突出,却要通过不断的否定下属以此获取所谓优越感。这里也不好多说什么,总之还是很庆幸脱离苦海了。 这一年,因为疫情的原因,各家效益都很差,裁员的裁员,倒闭的倒闭的。之前看过一个观点,当一个行业走下坡路时,大家如果都还在希望自己拿到裁员补贴的话,这个行业还有救。当大家都开始希望自己不被裁的时候,这个行业才是真的危机了。所以这么看来的话,现在应该还远没到最差的时候。只是随着获客成本的不断增加,以及其他同行的步步紧逼,留给淘宝的时间又有多少呢?只是这个问题就不该是我操心的了。 说说失与得吧。 因为一开始选择的是业务部门,导致自己与技术偏离的越来越远,这一年多全在做业务需求,哪怕是技术沉淀也没什么好说的,无非是各种架构的设计、各种方案的选型,各种漏洞的治理。真正沉下心做技术的时间太短太短了。做业务or做技术一直是一个两难的话题,有一个段子是说所有的后台需求最终都会归结到excel上,侧面也反映了业务需求的难度其实大抵如此。除了对所用的中间件越来越熟之外,底层原理却也不像读书时一样能钻研进去了,这是下一年需要好好改进的地方。 这一年有没有其他什么明显的成长呢?我想还是有的。看待问题的角度确实相较以前更加多元化了,也越来越明白了个人的力量在一个庞大的组织面前是那么的无力。有的时候哪怕你发现了团队中的一些问题,初出茅庐的你指出了这个问题,可后来发现其实大家早就知道这个问题,但就是无能为力。我不清楚是只有阿里是这样自上而下的,还是说其他公司也大多如此,如果真是这样,那恐怕希望自己媳妇熬成婆的那天仍然能一直年轻吧。 总的来说这一年因为疫情过的相对平淡很多,出行不方便以至于除了团建没别的外出游玩的机会了。另一方面也由于工作的原因,公众号的更新也基本维持在一个月一篇,而且也从技术科普类的转向架构设计,算是对平时工作的一个梳理与总结。而且马上新的一年就要来了,对于flag啥的没什么想法,就是希望能顺利晋升,快乐一些。 最后,2022年要恭喜梅老板手捧大力神杯。

plainify

AI换脸——汝怎饰品如面

事先说明,该篇文章中的代码是我无意中发现的,这里仅做一个分享,文末会给出参考文章,不喜勿喷。 完整源码和预训练模型可在公众号:「01 二进制」后台回复:「AI 换脸」获取 前言 作为一个经常逛 b 站的肥宅,前段时间无意中看到了一个名为"换脸哥"做的换脸视频,让杨幂“穿越”到了 1994 年版的《射雕英雄传》里,“代替”了朱茵,“出演”了黄蓉这个角色。视频如下(b 站视频已经被删了,只能转载知乎的视频了,原地址是杨幂“换脸”,AI 换脸究竟有多可怕 - 科技富能量的文章 - 知乎): 看完我便虎躯一震,这也太厉害了吧,这种技术一旦流行起来,ab 不用去片场就能拍戏了啊,真的是躺着赚钱啊。这要是运用到 H 片上,岂不是 😅😅😅 言归正传,作为一个 coder,在看到这个视频之后我就很想知道这究竟是怎么做出来的,在查阅了一些资料后,我才发现最悲伤的事情莫过于,好不容易把源码找到了,数据集下载好了,结果显卡带不起来… Tips:这里给出我之前找到的两个有关视频换脸的仓库,有兴趣的自己去了解下: deepfakes_faceswap FaceIt 既然条件不允许,那我们只能降低成本,既然视频里的脸不好换,那就退而求其次,换一下图片里面的脸,果然在我的苦苦寻觅后,我找到了一个低配版的 Python 换脸大法: 《Switching Eds: Face swapping with Python, dlib, and OpenCV》 以下内容均参考上述所标注的文章,在这感谢原作者。 接下来我将会介绍如何通过一段简短的 Python 脚本(200 行左右)将一张图片中面部特征自动替换为另外一张图片中的面部特征。 具体过程分为四个步骤: 检测面部标志; 旋转、缩放和平移图 2 以适应图 1; 调整图 2 的白平衡以匹配图 1; 将图 2 的特征融合到图 1 中; 实验环境 MacOS 10....

plainify

AI画家第三弹——毕业设计大杀器之Flask

上一篇介绍了图像风格迁移的一个最基本实现,虽然在控制台实现了功能,但是想要实际使用,应用到一个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 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。...

plainify

AI画家第五弹——从0到1部署你的RESTful API

上一篇文章中我们已经利用 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 部署,还是再详细说一下吧。...

AI画家第六弹——终章

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》

plainify

AI画家第四弹——利用Flask发布风格迁移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....

plainify

AI绘画第二弹——图像风格迁移

这篇文章是我的《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....

plainify

API与SDK:有什么区别?

前言 什么是 API? 什么是 SDK? 两者之间有何关系? 欢迎来到本次的每周一问系列。 既然点进来了,相信你或多或少都听说过这两个名词了,因此,在为你解答之前,让我们先从一个例子出发。 假如你想开发一个 OCR 应用(通俗的说就是文字识别应用),他的功能是识别用户上传的一张图片,然后将图片中的文字识别出来返回给用户。如下图所示: 通常,OCR 应用的后端服务都会部署在云上,那么我们应该如何在移动应用程序与基于云的服务之间进行通信呢? 这就是 API 和 SDK 的用武之地了。 API API 的特点 通信 首先我们要明白的是 API 是和通信有关的,是用于应用(服务)与其他应用(服务)对话所定义的协议。在上述例子中,你可以简单理解为 API 是 OCR 应用和云端服务之间沟通的桥梁。 那么 API 到底是什么? API 全称 Application Programming Interface,即 「应用程序接口」 。 一般是指一些预先定义的函数,目的是供应用程序与开发人员基于某软件或硬件得以访问一组程序的能力,而又无需访问源码,或理解内部工作机制的细节。 以 Java 为例,当你想要实现一个数组排序的功能时,你是会先手写一个排序算法,还是直接使用Arrays.sort()函数?我想你心里是有答案的。 抽象 其次,我们要理解,API 的另一个重要特点——抽象。 抽象指的又是什么? 还是以这个 OCR 应用为例,当我们在使用云端提供的文字识别能力时(比如百度文字识别),他的背后可能会有成千上万的代码,比如提供识别能力的机器学习的代码、提供 Web 能力的后端代码等等。 但是你作为一个 APP 的开发者,你需要去看这些代码是怎么写的吗?难道不知道背后的源码就不能调用百度提供的文字识别能力了吗?当然不是。 通常服务商已经给你提供了文档,告诉你如何去调用相应服务,只要你按照他的要求来即可。 因此,在你的 APP 和 OCR 服务之间,API 抽象出所有复杂的逻辑,简化了调用过程,这使得你只需要考虑获取所需的数据即可。 标准化 API 是标准化的,这意味着存在有关如何定义 API 的行业标准,比如 SOAP、REST、GraphQL 等。...

plainify

Docker 安装 RocketMQ 并结合 SpringBoot 使用实例

在之前的《浅入浅出消息队列》一文中,我们了解了消息队列的作用、优缺点和使用场景,相信你对消息队列已经有了一个大致的概念,文末给自己埋的坑说日后会写一篇实战教程,正好现在实习结束了,也许久没有写实战教程了,于是这就来填坑了。 前置知识 阅读本文前,建议有一些前置知识,包括且不限于: 常见的 Linux 命令 消息队列的相关知识 Docker 的基本使用 docker-compose 的基础知识 SpringBoot 的基本使用 那废话不多说,我们就开始吧。 本文的所涉及到的代码可在微信公众号「01 二进制」后台回复「rocketmq」获得。 为什么要以 RocketMQ 为例? 本文主要是为了通过实例的方式直观的了解消息队列。那么问题来了,消息队列那么多(ActiveMQ、RabbitMQ、Kafka),我为什么要选择 RocketMQ 呢?这里我们不谈原理,只说说体验,仅是个人选择,不喜勿喷。 背靠阿里,不看测评,纯粹看他经历过多次双十一的检验就已经知道其性能是处于第一批次的。 作为一个 Java 程序员,如果选择一个纯 Java 编写的软件,后期阅读其源码难度也会小很多。(RabbitMQ 底层是 Erlang,kafka 底层是 Scala) 在阿里实习的时候一直都是使用 RocketMQ 的内部版本,于我而言,RocketMQ 更熟悉。 初识 RocketMQ 在使用消息队列前,我们要知道消息队列是什么,这一块内容参考之前的文章《浅入浅出消息队列》,这里不再赘述。 本段节来讲解 RocketMQ 所涉及到的相关概念,我们先来简单看下官方给出的 RocketMQ 架构图 从上图我们可以很直观的看出,一个完整的 RocketMQ 架构包含四个部分:NameServer、Broker、Producer 和 Consumer。 NameServer:主要用作注册中心,用于管理 Topic 信息和路由信息的管理 Broker:负责存储、消息 tag 过滤和转发。需将自身信息上报给注册中心 NameServer Producer:生产者 Consumer:消费者 从寄信的角度理解 上面的解释可能难以理解,我们从寄信这一实例来看以下四个部分所承担的责任。 Producer 和 Consumer 不必多说,消息的生产者和消费者,生产者负责投递消息,消费者负责接收消息,是我们要编写的应用程序。可以理解为寄信人和收信人。 Broker 负责消息存储,以 Topic(主题)为维度,以队列的形式存储消息。可以理解为信箱,专门存储信件,收信人(Consumer)可以从这里获取信件。 NameServer 负责对源数据进行管理,包括了对 Topic 和 Broker 的管理。可以理解为邮局,负责管理邮件的分发,维护信箱(Broker)的状态。 由上各部分角色的功能可知,我们需要先安装启动 NameServer,再启动 Broker 即可搭建完 RocketMQ...

Flutter 表单组件

前言 最近在利用flutter制作校园软件,需要制作一个登录界面,所以要用到Flutter中的一些表单控件,今天就来总结下flutter中的一些表单控件。 本文参考: 《Flutter 基础组件-表单》 FormState class Form Class TextField class TextFormField ...