写点什么

Serverless 实战:用 20 行 Python 代码轻松搞定图像分类和预测

  • 2020-04-19
  • 本文字数:8211 字

    阅读完需:约 27 分钟

Serverless 实战:用20行Python代码轻松搞定图像分类和预测

图像分类是人工智能领域的一个热门话题,通俗来讲,就是根据各自在图像信息中反映的不同特征,把不同类别的目标区分开。图像分类利用计算机对图像进行定量分析,把图像或图像中的每个像元或区域划归为若干个类别中的某一种,代替人的视觉判读。


在实际生活中,我们也会遇到图像分类的应用场景,例如我们常用的通过拍照花朵来识别花朵信息,通过人脸匹对人物信息等。通常,图像识别或分类工具都是在客户端进行数据采集,在服务端进行运算获得结果。因此,一般都会有专门的 API 来实现图像识别,云厂商也会有偿提供类似的能力:


  • 华为云图像标签



  • 腾讯云图像分析



本文将尝试通过一个有趣的 Python 库,快速将图像分类的功能搭建在云函数上,并且和 API 网关结合,对外提供 API 功能,实现一个 Serverless 架构的"图像分类 API"。

入门 ImageAI

首先,我们需要一个依赖库:ImageAI


什么是 ImageAI 呢?其官方文档是这样描述的:


ImageAI 是一个 python 库,旨在使开发人员能够使用简单的几行代码构建具有包含深度学习和计算机视觉功能的应用程序和系统。

ImageAI 本着简洁的原则,支持最先进的机器学习算法,用于图像预测、自定义图像预测、物体检测、视频检测、视频对象跟踪和图像预测训练。ImageAI 目前支持使用在 ImageNet-1000 数据集上训练的 4 种不同机器学习算法进行图像预测和训练。ImageAI 还支持使用在 COCO 数据集上训练的 RetinaNet 进行对象检测、视频检测和对象跟踪。 最终,ImageAI 将为计算机视觉提供更广泛和更专业化的支持,包括但不限于特殊环境和特殊领域的图像识别。


简单理解,就是 ImageAI 依赖库可以帮助用户完成基本的图像识别和视频的目标提取。不过,ImageAI 虽然提供一些数据集和模型,但我们也可以根据自身需要对其进行额外的训练,进行定制化拓展。


其官方代码给出了这样一个简单的 Demo:


from imageai.Prediction import ImagePredictionimport osexecution_path = os.getcwd()
prediction = ImagePrediction()prediction.setModelTypeAsResNet()prediction.setModelPath(os.path.join(execution_path, "resnet50_weights_tf_dim_ordering_tf_kernels.h5"))prediction.loadModel()
predictions, probabilities = prediction.predictImage(os.path.join(execution_path, "1.jpg"), result_count=5 )for eachPrediction, eachProbability in zip(predictions, probabilities): print(eachPrediction + " : " + eachProbability)
复制代码


我们可以在本地进行初步运行,指定图片1.jpg为下图时:



可以得到结果:


convertible  :  52.459537982940674sports_car  :  37.61286735534668pickup  :  3.175118938088417car_wheel  :  1.8175017088651657minivan  :  1.7487028613686562
复制代码

让 ImageAI 上云(部署到 Serverless 架构上)

通过上面的 Demo,我们可以考虑将这个模块部署到云函数:


  • 首先,在本地创建一个 Python 的项目:mkdir imageDemo

  • 新建文件:vim index.py

  • 根据云函数的一些特殊形式,我们对 Demo 进行部分改造

  • 将初始化的代码放在外层;

  • 将预测部分当做触发所需要执行的部分,放在入口方法中(此处是 main_handler);

  • 云函数与 API 网关结合对二进制文件支持并不是十分的友善,所以此处通过 base64 进行图片传输;

  • 入参定为{"picture": 图片的base64},出参定为:{"prediction": 图片分类的结果}


实现的代码如下:


from imageai.Prediction import ImagePredictionimport os, base64, random
execution_path = os.getcwd()
prediction = ImagePrediction()prediction.setModelTypeAsSqueezeNet()prediction.setModelPath(os.path.join(execution_path, "squeezenet_weights_tf_dim_ordering_tf_kernels.h5"))prediction.loadModel()

def main_handler(event, context): imgData = base64.b64decode(event["body"]) fileName = '/tmp/' + "".join(random.sample('zyxwvutsrqponmlkjihgfedcba', 5)) with open(fileName, 'wb') as f: f.write(imgData) resultData = {} predictions, probabilities = prediction.predictImage(fileName, result_count=5) for eachPrediction, eachProbability in zip(predictions, probabilities): resultData[eachPrediction] = eachProbability return resultData

复制代码


创建完成之后,下载所依赖的模型:


  • SqueezeNet(文件大小:4.82 MB,预测时间最短,精准度适中)

  • ResNet50 by Microsoft Research (文件大小:98 MB,预测时间较快,精准度高)

  • InceptionV3 by Google Brain team (文件大小:91.6 MB,预测时间慢,精度更高)

  • DenseNet121 by Facebook AI Research (文件大小:31.6 MB,预测时间较慢,精度最高)


因为我们仅用于测试,所以选择一个比较小的模型就可以:SqueezeNet


在官方文档复制模型文件地址:



使用wget直接安装:


wget https://github.com/OlafenwaMoses/ImageAI/releases/download/1.0/squeezenet_weights_tf_dim_ordering_tf_kernels.h5
复制代码



接下来,进行依赖安装:



由于腾讯云 Serveless 产品,在 Python Runtime 中还不支持在线安装依赖,所以需要手动打包依赖,并且上传。在 Python 的各种依赖库中,有很多依赖可能有编译生成二进制文件的过程,这就会导致不同环境下打包的依赖无法通用。


所以,最好的方法就是通过对应的操作系统+语言版本进行打包。我们就是在 CentOS+Python3.6 的环境下进行依赖打包。


对于很多 MacOS 用户和 Windows 用户来说,这确实不是一个很友好的过程,所以为了方便大家使用,我在 Serverless 架构上做了一个在线打包依赖的工具,所以可以直接用该工具进行打包:




生成压缩包之后,直接下载解压,并且放到自己的项目中即可:



最后一步,创建serverless.yaml


imageDemo:  component: "@serverless/tencent-scf"  inputs:    name: imageDemo    codeUri: ./    handler: index.main_handler    runtime: Python3.6    region: ap-guangzhou    description: 图像识别/分类Demo    memorySize: 256    timeout: 10    events:      - apigw:          name: imageDemo_apigw_service          parameters:            protocols:              - http            serviceName: serverless            description: 图像识别/分类DemoAPI            environment: release            endpoints:              - path: /image                method: ANY
复制代码


完成之后,执行sls --debug部署,部署过程中会有扫码登陆,登陆之后等待即可,完成之后,就可以看到部署地址。


基本测试

通过 Python 语言进行测试,接口地址就是刚才复制的+/image,例如:


import jsonimport urllib.requestimport base64
with open("1.jpg", 'rb') as f: base64_data = base64.b64encode(f.read()) s = base64_data.decode()
url = 'http://service-9p7hbgvg-1256773370.gz.apigw.tencentcs.com/release/image'
print(urllib.request.urlopen(urllib.request.Request( url = url, data= json.dumps({'picture': s}).encode("utf-8"))).read().decode("utf-8"))
复制代码


通过网络搜索一张图片:



得到运行结果:


{  "prediction": {    "cheetah": 83.12643766403198,    "Irish_terrier": 2.315458096563816,    "lion": 1.8476998433470726,    "teddy": 1.6655176877975464,    "baboon": 1.5562783926725388  }}
复制代码


通过这个结果,我们可以看到图片的基础分类/预测已经成功了,为了证明这个接口的时延情况,可以对程序进行基本改造:


import urllib.requestimport base64, time
for i in range(0,10): start_time = time.time() with open("1.jpg", 'rb') as f: base64_data = base64.b64encode(f.read()) s = base64_data.decode()
url = 'http://service-9p7hbgvg-1256773370.gz.apigw.tencentcs.com/release/image' print(urllib.request.urlopen(urllib.request.Request( url = url, data= json.dumps({'picture': s}).encode("utf-8") )).read().decode("utf-8"))
print("cost: ", time.time() - start_time)
复制代码


输出结果:


{"prediction":{"cheetah":83.12643766403198,"Irish_terrier":2.315458096563816,"lion":1.8476998433470726,"teddy":1.6655176877975464,"baboon":1.5562783926725388}}cost:  2.1161561012268066{"prediction":{"cheetah":83.12643766403198,"Irish_terrier":2.315458096563816,"lion":1.8476998433470726,"teddy":1.6655176877975464,"baboon":1.5562783926725388}}cost:  1.1259253025054932{"prediction":{"cheetah":83.12643766403198,"Irish_terrier":2.315458096563816,"lion":1.8476998433470726,"teddy":1.6655176877975464,"baboon":1.5562783926725388}}cost:  1.3322770595550537{"prediction":{"cheetah":83.12643766403198,"Irish_terrier":2.315458096563816,"lion":1.8476998433470726,"teddy":1.6655176877975464,"baboon":1.5562783926725388}}cost:  1.3562259674072266{"prediction":{"cheetah":83.12643766403198,"Irish_terrier":2.315458096563816,"lion":1.8476998433470726,"teddy":1.6655176877975464,"baboon":1.5562783926725388}}cost:  1.0180821418762207{"prediction":{"cheetah":83.12643766403198,"Irish_terrier":2.315458096563816,"lion":1.8476998433470726,"teddy":1.6655176877975464,"baboon":1.5562783926725388}}cost:  1.4290671348571777{"prediction":{"cheetah":83.12643766403198,"Irish_terrier":2.315458096563816,"lion":1.8476998433470726,"teddy":1.6655176877975464,"baboon":1.5562783926725388}}cost:  1.5917718410491943{"prediction":{"cheetah":83.12643766403198,"Irish_terrier":2.315458096563816,"lion":1.8476998433470726,"teddy":1.6655176877975464,"baboon":1.5562783926725388}}cost:  1.1727900505065918{"prediction":{"cheetah":83.12643766403198,"Irish_terrier":2.315458096563816,"lion":1.8476998433470726,"teddy":1.6655176877975464,"baboon":1.5562783926725388}}cost:  2.962592840194702{"prediction":{"cheetah":83.12643766403198,"Irish_terrier":2.315458096563816,"lion":1.8476998433470726,"teddy":1.6655176877975464,"baboon":1.5562783926725388}}cost:  1.2248001098632812
复制代码


通过上面一组数据,我们可以看到整体的耗时基本控制在 1-1.5 秒之间。


当然,如果想要对接口性能进行更多的测试,例如通过并发测试来看并发情况下接口性能表现等。


至此,我们通过 Serveerless 架构搭建的 Python 版本的图像识别/分类小工具做好了。

总结

Serverless 架构下进行人工智能相关的应用可以是说是非常多的,本文是通过一个已有的依赖库,实现一个图像分类/预测的接口。imageAI这个依赖库相对来说自由度比较高,可以根据自身需要用来定制化自己的模型。本文算是抛砖引玉,期待更多人通过 Serverless 架构部署自己的"人工智能"API。


2020-04-19 22:1611454

评论 3 条评论

发布
用户头像
没有明白你的数据和图片是什么关系
2020-04-27 09:16
回复
识别图片给出分类啊。。。。文章里面都说了要拿来做图像识别分类了,数据分别是识别结果和概率。。。。
2020-04-28 10:14
回复
用户头像
学习学习!
2020-04-23 12:23
回复
没有更多了
发现更多内容

混合编程:如何用pybind11调用C++

华为云开发者联盟

c++ Python API 混合编程 pybind11

ModStartCMS模块化建站系统 v3.3.0 组件功能升级,事件触发增强

ModStart开源

Milvus 图形化管理工具 Attu 来袭!

Zilliz

数据库

基于 Kafka 的实时数仓在搜索的实践应用

vivo互联网技术

kafka 服务器 搜索 数据舱

乘冬奥之风:北京2022年冬奥会用户信息获取偏好专题分析

易观分析

冬奥会用户分析

产品经理:「点这里,我要跳到任何我想跳的页面」—— 解耦提效神器「统跳路由」

百瓶技术

ios 前端 客户端 路由

【重磅发布】蚂蚁动态卡片,让 App 首页实现敏捷更新

蚂蚁集团移动开发平台 mPaaS

ios android 前端 mPaaS

百度飞桨大企业开放创新中心联合赋能计划启动!助力浦东产业智能化升级

百度大脑

为什么我的 ORDER BY create_time ASC 变成了 order by ASC

LigaAI

Java 数据库 sql 程序员

了解 DevOps,必读这十本书!

禅道项目管理

DevOps

Android技术分享| 【你画我猜】Android 快速实现

anyRTC开发者

音视频 移动开发 互动白板 Andriod 你画我猜

一个关于 += 的谜题

AlwaysBeta

Python 编程语言

“pip不是内部或外部命令,也不是可运行的程序或批处理文件” 到底有多么神秘

华为云开发者联盟

Python pip 批处理 scripts pip install

极致用云,数智护航

阿里云云效

阿里云 DevOps 运维 云原生 运维安全

前所未有的 Milvus 源码架构解析

Zilliz

掌握这些招数,你也能写出HR眼中的高分简历

Tom弹架构

求职面试

2022年中国智慧医疗行业洞察

易观分析

智慧医疗

边缘计算场景下Service Mesh的延伸和扩展

华为云原生团队

开源 边缘计算 边缘技术 边缘 边缘云

优化| 手把手教你学会杉数求解器(COPT)的安装、配置与测试

杉数科技

线性规划 求解器 优化求解器 混合整数规划 杉数科技

混合云管平台哪家强?采购时候需要注意什么?

行云管家

混合云 云管平台

Deep dive #2:API 与 Python SDKs 详解

Zilliz

Python 数据库

移动开发er,10万奖金等你来战!

Speedoooo

活动 前端开发 移动开发 黑客马拉松 黑客松

Hudi Bucket Index 在字节跳动的设计与实践

字节跳动数据平台

数据库 字节跳动 数据湖 Hudi

Go 语言入门很简单:读写锁

宇宙之一粟

读写锁 Go 语言 2月月更

云效发布策略指南|滚动、分批、灰度怎么选?

阿里云云效

云计算 阿里云 云原生 持续交付 发布策略

oracle数据库审计用什么数据库审计软件好?可以用什么方式部署?

行云管家

数据库 IT运维 数据库审计

大咖说|对话路特斯科技副总裁李博:如何看待智能驾驶的未来?

大咖说

阿里巴巴 智能 汽车 无人驾驶 路特斯

「前端CI/CD系列」第二篇:如何用建木CI更新七牛云CDN证书

Jianmu

CDN 自动化运维 七牛云 建木CI

虎符交易所2022年首届交易大赛 最高瓜分5万USDT奖励

区块链前沿News

虎符交易所

web前端培训:vue3源码中细节知多少

@零度

Vue 前端开发

如何通过 draftjs 设计留言框

全象云低代码

前端 低代码 留言 draftjs 留言框

Serverless 实战:用20行Python代码轻松搞定图像分类和预测_服务革新_刘宇_InfoQ精选文章