转自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 应用还是存在不少问题,比如加载慢,性能弱等等

  • 相比本地原生应用化部署,前端部署可以轻松实现跨平台,也更容易构建一个好看的界面

  • 总之有利有弊,在合适的场景选择合适的技术就是最好的

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐