网页端抗原检测试剂盒图片结果识别模型的训练和部署(2)
转自AI Studio,原文链接:网页端抗原检测试剂盒图片结果识别模型的训练和部署(2) - 飞桨AI Studio1. 引入上一次介绍了如何训练一个抗原试剂盒结果检测模型本次继续上回内容,来接着介绍如何将这个模型部署至网页前端2. 参考资料AgentMaker/WebAI.jsAgentMaker/COVID-19_Antigen_Test_Kit_Detection模型量化(3):ONNX 模
转自AI Studio,原文链接:网页端抗原检测试剂盒图片结果识别模型的训练和部署(2) - 飞桨AI Studio
1. 引入
-
上一次介绍了如何训练一个抗原试剂盒结果检测模型
-
本次继续上回内容,来接着介绍如何将这个模型部署至网页前端
2. 参考资料
3. 部署流程
-
这里使用 WebAI.js 来部署检测模型至前端网页,需要如下几个步骤:
-
转换格式:WebAI.js 使用的模型格式为 ONNX,所以需要将 Paddle 推理模型转换为 ONNX 模型
-
模型量化:为了提高前端网页加载模型的速度,可以通过模型量化来缩小模型的体积,提高传输和加载的速度
-
模型配置:手动编写或者生成一份适用于 WebAI.js 的模型配置文件
-
前端页面:需要使用前端工具构建一个前端网页,实现功能交互
-
网页部署:将构建好的网页部署至 Githu
-
4. 安装依赖
- 转换模型和量化模型需要依赖如下的模块,使用如下命令进行安装
In [ ]
!pip install paddle2onnx onnxruntime onnx --upgrade
5. 模型部署
5.1 格式转换
-
将上一个项目中训练的模型文件下载下来
-
使用 Paddle2ONNX 将 Paddle 模型转换为 ONNX 模型
-
具体的转换代码如下:
In [ ]
!paddle2onnx \
--model_dir inference_model \
--model_filename model.pdmodel \
--params_filename model.pdiparams \
--save_file inference_model/model.onnx \
--opset_version 12 \
--input_shape_dict "{'image':[1, 3, 640, 640], 'scale_factor': [1, 2]}"
5.2 模型量化
-
为了缩小模型文件的体积,提交加载速度,可以使用模型量化技术来压缩模型
-
这里使用最简单方便的动态量化来对模型进行压缩
-
具体的量化代码如下:
In [ ]
from onnxruntime.quantization import QuantType, quantize_dynamic
# 模型路径
model_fp32 = 'inference_model/model.onnx'
model_quant_dynamic = 'inference_model/model_quant_dynamic.onnx'
# 动态量化
quantize_dynamic(
model_input=model_fp32, # 输入模型
model_output=model_quant_dynamic, # 输出模型
weight_type=QuantType.QUInt8, # 参数类型 Int8 / UInt8
optimize_model=True # 是否优化模型
)
5.3 模型配置
-
使用 WebAI.js 的示例网站中的配置文件转换器可以直接转换 PaddleDetection 导出的模型配置文件
-
当然也可以手动编写一个,如下:
{
"Preprocess": [
{
"type": "Decode",
"mode": "RGB"
},
{
"type": "Resize",
"interp": 2,
"keep_ratio": false,
"limit_max": false,
"target_size": [
640,
640
]
},
{
"type": "Normalize",
"is_scale": true,
"mean": [
0.485,
0.456,
0.406
],
"std": [
0.229,
0.224,
0.225
]
},
{
"type": "Permute"
}
],
"label_list": [
"positive",
"negative",
"invalid"
]
}
5.4 前端页面
-
提示:以下内容需要一些前端编程的知识
-
本项目的前端页面基于 react / vite / antd / ts / webai-js 等技术构建
-
主页面为 react 编写的简单的单页应用,效果图如下:
-
核心的页面代码如下,更多细节请参考 AgentMaker/COVID-19_Antigen_Test_Kit_Detection:
import 'antd/dist/antd.less';
import { WebAI, cv } from 'webai-js'
import { ResultStatusType } from 'antd/lib/result'
import { useState, useRef, ReactNode } from 'react';
import { FileImageOutlined } from '@ant-design/icons';
import { Image, message, Button, Result, Spin } from 'antd';
// 初始化检测器
const detector = new WebAI.Det(
'./model.dynamic.quant.onnx.json',
'./configs.json'
)
export default function App() {
// 初始化页面元素引用
const refImg = useRef<HTMLImageElement>(null)
const refCanvas = useRef<HTMLCanvasElement>(null)
const refInput = useRef<HTMLInputElement>(null)
// 初始化状态
const [src, setSrc] = useState<string>('./example.png')
const [dst, setDst] = useState<string>('./example.png')
const [icon, setIcon] = useState<ReactNode>(<FileImageOutlined />)
const [status, setStatus] = useState<ResultStatusType>('info')
const [visible, setVisible] = useState<boolean>(false)
const [spinning, setSpinning] = useState<boolean>(true)
// 如果在加载的时候
if (spinning) {
// 等待模型加载完成
detector.promises.then(() => {
// 停止加载
setSpinning(false)
// 当图片完成加载时
refImg.current!.onload = () => {
// 读取图片
const imgRGBA = cv.imread(refImg.current!)
// 检测器预测
detector.infer(imgRGBA).then((bboxes) => {
// 如果检出
if (bboxes.length > 0) {
// 显示图像
const imgShow = WebAI.drawBBoxes(imgRGBA, bboxes)
cv.imshow(refCanvas.current!, imgShow)
setDst(refCanvas.current?.toDataURL("image/png")!)
// 删除图像指针
imgRGBA.delete()
imgShow.delete()
// 将结果设置到页面上
bboxes.forEach(({
label
}) => {
if (label == 'negative') {
message.info('阴性')
setIcon(undefined)
setStatus('success')
}
else if (label == 'positive') {
message.error('阳性')
setIcon(undefined)
setStatus('error')
}
else {
message.error('无效')
setIcon(undefined)
setStatus('warning')
}
})
}
// 未检出
else {
setDst(refImg.current!.src)
message.info('未检出')
setIcon(undefined)
setStatus('warning')
}
})
}
})
}
return <Spin
spinning={spinning}
tip='正在加载模型,请稍后...'
>
<input
ref={refInput}
style={{ display: 'none' }}
type='file'
accept='image/*'
onChange={({ target }) => setSrc(URL.createObjectURL(target.files![0]))}
/>
<canvas
ref={refCanvas}
style={{ display: 'none' }}
/>
<img
src={src}
ref={refImg}
style={{ display: 'none' }}
/>
<Image
style={{ display: 'none' }}
src={dst}
preview={{
visible,
src: dst,
onVisibleChange: value => setVisible(value)
}}
/>
<Result
icon={icon}
title="COVID-19 抗原检测试剂盒结果检测"
status={status}
extra={[
<Button
key='upload'
type="primary"
onClick={() => refInput.current?.click()}
>
上传图片
</Button>,
<Button
key='preview'
type="primary"
onClick={() => setVisible(true)}
>
预览结果
</Button>
]}
/>
</Spin>
}
- 编写完网页之后使用 vite 构建工具对前端项目进行构建,导出可供部署的网页文件和脚本文件
5.5 网页部署
-
将模型文件和配置文件及编写的前端网页构建好,上传至服务器中,然后运行网页服务即可
-
或者使用 Github Page 选择构建好的文件目录,就可以轻松部署
-
具体的部署细节就不赘述了
6. 体验优化
-
网页应用化,目前这个 体验网页 已经可以直接通过浏览器安装至设备上,离线加载使用
-
只需要打开网页,等待其加载完成,浏览器(IOS / MacOS 需要手动添加应用)会提示应用安装,点击安装即可
-
安装后就会变成这样的一个应用(其实和直接用网页没啥区别,只是可以离线直接运行而已):
-
当然目前网页依赖的文件体积还是过大,加载的速度还是比较慢的(几分钟),这个有待后续继续优化
7. 尾巴
-
前端部署这样的应用成本很低,无需自己购买服务器资源,而且天生支持跨平台
-
因为计算在用户端,无需上传数据至服务器,可以更好的保护用户的隐私安全
-
但是相比服务端部署,单纯依靠前端实现的 AI 应用还是存在不少问题,比如加载慢,性能弱等等
-
相比本地原生应用化部署,前端部署可以轻松实现跨平台,也更容易构建一个好看的界面
-
总之有利有弊,在合适的场景选择合适的技术就是最好的
更多推荐
所有评论(0)