基于 Notebook 的物体检测模板使用指南

全功能AI开发平台 BML

  • 版本发布记录
  • 快速开始
    • 用BML实现表格预测
    • 用BML实现序列标注
    • 用BML实现文本实体抽取
    • 用BML实现图片分类
    • 用BML实现实例分割
    • 用BML评价短文本相似度
    • 用BML实现开源大模型的预训练(Post-pretrain)
    • 用BML实现文本分类
    • 用BML实现物体检测
  • 模型仓库
    • 从训练任务导入模型
    • 查看模型
    • 创建模型
    • 模型仓库简介
    • 从本地导入模型
    • 校验模型
    • 服务代码文件示例
      • Sklearn服务代码文件示例
      • XGBoost服务代码文件示例
  • 平台管理
    • 权限管理
    • 在BML平台使用并行文件系统PFS和对象存储BOS
    • 在BML平台使用容器镜像服务CCR
    • 在BML使用外部镜像
    • 项目空间管理
    • 镜像管理
      • 镜像使用
      • 镜像管理简介
      • 常见问题
      • 自定义镜像
    • 资源管理
      • 资源池管理简介
      • 资源池使用简介
  • 预测部署
    • 批量预测(用户资源池)API
    • 文字识别模型部署
      • 文字识别任务API参考文档
      • 文字识别任务公有云部署
    • 通用模型部署
      • 标准接口规范参考
      • Paddle框架API调用文档
      • sklearn框架API调用文档
      • 公有云部署
      • XGBoost框架API调用文档
      • tensorflow框架API调用文档
      • Pytorch框架API调用文档
      • 通用类模型API参考
      • 错误码
    • 语音技术模型部署
      • 声音分类API调用文档
    • 视觉模型部署
      • 智能边缘控制台-多节点版
      • 端云协同服务部署
      • 智能边缘控制台-单节点版
      • 视觉任务模型部署整体说明
      • 软硬一体方案部署
        • 视觉任务Jetson专用SDK集成文档
        • 如何获取视觉任务软硬一体产品
        • 视觉任务EdgeBoard(VMX)专用SDK集成文档
        • 视觉任务EdgeBoard(FZ)专用SDK集成文档
        • 视觉任务专用辨影SDK集成开发文档
      • 私有服务器部署
        • 视觉模型如何部署在私有服务器
        • 私有API
          • 如何发布私有API
          • 图像分类-单图单标签私有API集成文档
          • 图像分类-单图多标签私有API集成文档
          • 物体检测私有API集成文档
        • 服务器端SDK
          • 视觉任务服务器端LinuxSDK集成文档-Python
          • 视觉任务服务器端LinuxSDK集成文档-C++
          • 如何发布服务器端SDK
          • 视觉任务服务器端WindowsSDK集成文档
          • 视觉任务服务器端SDK简介
      • 设备端SDK部署
        • 视觉任务WindowsSDK集成文档
        • 视觉任务iOSSDK集成文档
        • 视觉任务LinuxSDK集成文档-Python
        • 视觉任务LinuxSDK集成文档-C++
        • 视觉任务设备端SDK使用说明
        • 如何发布视觉任务设备端SDK
        • 视觉任务AndroidSDK集成文档
      • 公有云部署
        • 文字识别API参考文档
        • 视觉任务公有云部署
        • 物体检测API参考文档
        • 图像分类-单图单标签API参考文档
        • 实例分割API参考文档
        • 图像分类-单图多标签API参考文档
    • 表格预测模型部署
      • 整体说明
      • 公有云部署
    • 公有云部署管理
      • 配置AB测试版本
      • 批量预测服务
      • 公有云部署
      • 公有云部署简介
      • 配置休眠策略
    • NLP模型部署
      • 自然语言处理任务模型部署整体说明
      • 私有服务器部署
        • 如何部署在私有服务器
        • 私有服务API说明
          • 私有部署说明-短文本相似度
          • 私有化部署接口说明-文本分类
          • 私有部署文档-序列标注
          • 文本实体抽取API调用文档
      • 公有云部署
        • 短文本匹配API调用文档
        • 文本实体抽取私有API调用说明
        • 如何发布自然语言处理任务API
        • 文本分类-多标签API调用文档
        • 文本分类API调用文档
        • 序列标注API调用文档
  • 数据服务
    • 数据服务简介
    • 智能数据API
    • 公有云服务调用数据反馈
    • 智能标注
      • 文本智能标注介绍及原理说明
      • 图像智能标注介绍说明
    • 管理视觉数据
      • 实例分割数据导入与标注
        • 数据标注说明
        • 导入未标注数据
        • 导入已标注数据
      • 物体检测数据导入与标注
        • 物体检测数据标注说明
        • 物体检测导入未标注数据
        • 物体检测导入已标注数据
      • 图像分类数据导入与标注
        • 图像分类导入未标注数据
        • 图像分类导入已标注数据
        • 图像分类数据标注说明
    • 管理文本数据
      • 文本分类数据导入与标注
        • 文本分类数据标注说明
        • 文本分类数据导入与标注
        • 数据去重策略
      • 序列标注数据导入与标注
        • 序列标注标注说明
        • 序列标注数据导入
        • 数据去重策略
      • 文本实体抽取数据标注
        • 文本实体抽取数据标注
        • 文本实体抽取数据导入
        • 数据去重策略
      • 短文本匹配数据导入与标注
        • 短文本匹配数据导入与标注
        • 数据去重策略说明
        • 短文本匹配数据标注
  • 产品简介
    • BML平台升级公告
    • 平台重点升级介绍
    • 产品优势
    • 产品功能
    • 什么是BML
    • 文心大模型
  • 产品定价
    • 服务器部署价格说明
    • 专项适配硬件部署价格说明
    • 公有云部署计费说明
    • 批量预测计费说明
    • 模型训练计费说明
    • 通用小型设备部署价格说明
  • 模型训练
    • Notebook建模
      • 创建并启动Notebook
      • Notebook导入数据集
      • 保存Notebook中的模型
      • Notebook使用参考
      • 常见问题
      • 数据模型可视化功能说明
      • Notebook简介
      • 发布模型
      • 配置模型
      • 使用Notebook开发模型
      • 如何使用Notebook SSH 功能
      • Notebook从训练到部署快速入门
        • Codelab Notebook自定义环境部署最佳实践
        • 基于Notebook的图像分类模板使用指南
        • 基于 Notebook 的 NLP 通用模板使用指南
        • Notebook 模板使用指南概述
        • 基于 Notebook 的通用模板使用指南
        • 基于 Notebook 的物体检测模板使用指南
    • 自定义作业建模
      • 自定义作业简介
      • 训练作业API
      • 训练作业
        • 使用训练作业训练模型
        • 创建训练作业
        • 发布模型
        • 训练作业代码示例
          • TensorFlow 1.13.2
          • AIAK- Training Pytorch版
          • TensorFlow 2.3.0
          • Blackhole 1.0.0
          • Pytorch 1.7.1
          • Sklearn 0.23.2
          • XGBoost 1.3.1
          • PaddlePaddle 2.0.0rc
      • 自动搜索作业
        • 创建自动搜索作业
        • yaml文件编写规范
        • 自动搜索作业简介
        • 自动搜索作业代码编写规范
        • 自动搜索作业代码示例
          • XGBoost 1.3.1代码规范
          • TensorFlow 1.13.2代码规范
          • Sklearn 0.23.2代码规范
          • Pytorch 1.7.1代码规范
          • Tensorflow2.3.0代码规范
          • PaddlePaddle 2.1.1代码规范
    • 可视化建模
      • 快速入门
      • 概述
      • 组件菜单
        • 001-基本操作
        • 003-查看模型特征溯源
        • 007-组件状态
        • 008-组件资源配置
        • 006-组件列选择
        • 002-查看模型可解释性
        • 004-查看特征重要性
      • 组件说明
        • 015-图算法
        • 004-特征工程组件
        • 003-数据处理组件
        • 012-预测组件
        • 008-聚类算法
        • 009-Python算法组件
        • 002-数据集组件
        • 014-自然语言处理组件
        • 010-NLP算法
        • 016-统计分析组件
        • 006-回归算法
        • 007-异常检测算法
        • 013-模型评估组件
        • 005-分类算法
        • 018-时间序列组件
      • 画布操作说明
        • 005-AutoML(自动调参)
        • 002-开始训练
        • 001-概述
    • 预置模型调参建模
      • 预置模型调参简介
      • 神经网络训练搜索
      • 开发视觉模型
        • 视觉任务简介
        • 查看训练结果
        • 创建视觉任务
        • 配置视觉任务
        • 开发参考
          • 视觉预训练模型
          • 超参数配置参考
          • 评估报告参考
          • 自动超参搜索配置参考
          • 数据增强算子参考
          • 训练时长设置参考
          • 网络选型参考
      • 开发表格预测模型
        • 创建表格预测任务
        • 配置专家模式表格数据预测任务
        • 查看训练结果
        • 配置AUTOML模式表格数据预测任务
        • 表格预测任务简介
      • 开发文字识别模型
        • 文字识别任务简介
        • 文字识别任务操作流程
      • 开发自然语言处理模型
        • 查看训练结果
        • 自然语言处理任务简介
        • 配置NLP任务
        • 创建NLP任务
        • 代码模板升级及迁移说明
所有文档
menu
没有找到结果,请重新输入

全功能AI开发平台 BML

  • 版本发布记录
  • 快速开始
    • 用BML实现表格预测
    • 用BML实现序列标注
    • 用BML实现文本实体抽取
    • 用BML实现图片分类
    • 用BML实现实例分割
    • 用BML评价短文本相似度
    • 用BML实现开源大模型的预训练(Post-pretrain)
    • 用BML实现文本分类
    • 用BML实现物体检测
  • 模型仓库
    • 从训练任务导入模型
    • 查看模型
    • 创建模型
    • 模型仓库简介
    • 从本地导入模型
    • 校验模型
    • 服务代码文件示例
      • Sklearn服务代码文件示例
      • XGBoost服务代码文件示例
  • 平台管理
    • 权限管理
    • 在BML平台使用并行文件系统PFS和对象存储BOS
    • 在BML平台使用容器镜像服务CCR
    • 在BML使用外部镜像
    • 项目空间管理
    • 镜像管理
      • 镜像使用
      • 镜像管理简介
      • 常见问题
      • 自定义镜像
    • 资源管理
      • 资源池管理简介
      • 资源池使用简介
  • 预测部署
    • 批量预测(用户资源池)API
    • 文字识别模型部署
      • 文字识别任务API参考文档
      • 文字识别任务公有云部署
    • 通用模型部署
      • 标准接口规范参考
      • Paddle框架API调用文档
      • sklearn框架API调用文档
      • 公有云部署
      • XGBoost框架API调用文档
      • tensorflow框架API调用文档
      • Pytorch框架API调用文档
      • 通用类模型API参考
      • 错误码
    • 语音技术模型部署
      • 声音分类API调用文档
    • 视觉模型部署
      • 智能边缘控制台-多节点版
      • 端云协同服务部署
      • 智能边缘控制台-单节点版
      • 视觉任务模型部署整体说明
      • 软硬一体方案部署
        • 视觉任务Jetson专用SDK集成文档
        • 如何获取视觉任务软硬一体产品
        • 视觉任务EdgeBoard(VMX)专用SDK集成文档
        • 视觉任务EdgeBoard(FZ)专用SDK集成文档
        • 视觉任务专用辨影SDK集成开发文档
      • 私有服务器部署
        • 视觉模型如何部署在私有服务器
        • 私有API
          • 如何发布私有API
          • 图像分类-单图单标签私有API集成文档
          • 图像分类-单图多标签私有API集成文档
          • 物体检测私有API集成文档
        • 服务器端SDK
          • 视觉任务服务器端LinuxSDK集成文档-Python
          • 视觉任务服务器端LinuxSDK集成文档-C++
          • 如何发布服务器端SDK
          • 视觉任务服务器端WindowsSDK集成文档
          • 视觉任务服务器端SDK简介
      • 设备端SDK部署
        • 视觉任务WindowsSDK集成文档
        • 视觉任务iOSSDK集成文档
        • 视觉任务LinuxSDK集成文档-Python
        • 视觉任务LinuxSDK集成文档-C++
        • 视觉任务设备端SDK使用说明
        • 如何发布视觉任务设备端SDK
        • 视觉任务AndroidSDK集成文档
      • 公有云部署
        • 文字识别API参考文档
        • 视觉任务公有云部署
        • 物体检测API参考文档
        • 图像分类-单图单标签API参考文档
        • 实例分割API参考文档
        • 图像分类-单图多标签API参考文档
    • 表格预测模型部署
      • 整体说明
      • 公有云部署
    • 公有云部署管理
      • 配置AB测试版本
      • 批量预测服务
      • 公有云部署
      • 公有云部署简介
      • 配置休眠策略
    • NLP模型部署
      • 自然语言处理任务模型部署整体说明
      • 私有服务器部署
        • 如何部署在私有服务器
        • 私有服务API说明
          • 私有部署说明-短文本相似度
          • 私有化部署接口说明-文本分类
          • 私有部署文档-序列标注
          • 文本实体抽取API调用文档
      • 公有云部署
        • 短文本匹配API调用文档
        • 文本实体抽取私有API调用说明
        • 如何发布自然语言处理任务API
        • 文本分类-多标签API调用文档
        • 文本分类API调用文档
        • 序列标注API调用文档
  • 数据服务
    • 数据服务简介
    • 智能数据API
    • 公有云服务调用数据反馈
    • 智能标注
      • 文本智能标注介绍及原理说明
      • 图像智能标注介绍说明
    • 管理视觉数据
      • 实例分割数据导入与标注
        • 数据标注说明
        • 导入未标注数据
        • 导入已标注数据
      • 物体检测数据导入与标注
        • 物体检测数据标注说明
        • 物体检测导入未标注数据
        • 物体检测导入已标注数据
      • 图像分类数据导入与标注
        • 图像分类导入未标注数据
        • 图像分类导入已标注数据
        • 图像分类数据标注说明
    • 管理文本数据
      • 文本分类数据导入与标注
        • 文本分类数据标注说明
        • 文本分类数据导入与标注
        • 数据去重策略
      • 序列标注数据导入与标注
        • 序列标注标注说明
        • 序列标注数据导入
        • 数据去重策略
      • 文本实体抽取数据标注
        • 文本实体抽取数据标注
        • 文本实体抽取数据导入
        • 数据去重策略
      • 短文本匹配数据导入与标注
        • 短文本匹配数据导入与标注
        • 数据去重策略说明
        • 短文本匹配数据标注
  • 产品简介
    • BML平台升级公告
    • 平台重点升级介绍
    • 产品优势
    • 产品功能
    • 什么是BML
    • 文心大模型
  • 产品定价
    • 服务器部署价格说明
    • 专项适配硬件部署价格说明
    • 公有云部署计费说明
    • 批量预测计费说明
    • 模型训练计费说明
    • 通用小型设备部署价格说明
  • 模型训练
    • Notebook建模
      • 创建并启动Notebook
      • Notebook导入数据集
      • 保存Notebook中的模型
      • Notebook使用参考
      • 常见问题
      • 数据模型可视化功能说明
      • Notebook简介
      • 发布模型
      • 配置模型
      • 使用Notebook开发模型
      • 如何使用Notebook SSH 功能
      • Notebook从训练到部署快速入门
        • Codelab Notebook自定义环境部署最佳实践
        • 基于Notebook的图像分类模板使用指南
        • 基于 Notebook 的 NLP 通用模板使用指南
        • Notebook 模板使用指南概述
        • 基于 Notebook 的通用模板使用指南
        • 基于 Notebook 的物体检测模板使用指南
    • 自定义作业建模
      • 自定义作业简介
      • 训练作业API
      • 训练作业
        • 使用训练作业训练模型
        • 创建训练作业
        • 发布模型
        • 训练作业代码示例
          • TensorFlow 1.13.2
          • AIAK- Training Pytorch版
          • TensorFlow 2.3.0
          • Blackhole 1.0.0
          • Pytorch 1.7.1
          • Sklearn 0.23.2
          • XGBoost 1.3.1
          • PaddlePaddle 2.0.0rc
      • 自动搜索作业
        • 创建自动搜索作业
        • yaml文件编写规范
        • 自动搜索作业简介
        • 自动搜索作业代码编写规范
        • 自动搜索作业代码示例
          • XGBoost 1.3.1代码规范
          • TensorFlow 1.13.2代码规范
          • Sklearn 0.23.2代码规范
          • Pytorch 1.7.1代码规范
          • Tensorflow2.3.0代码规范
          • PaddlePaddle 2.1.1代码规范
    • 可视化建模
      • 快速入门
      • 概述
      • 组件菜单
        • 001-基本操作
        • 003-查看模型特征溯源
        • 007-组件状态
        • 008-组件资源配置
        • 006-组件列选择
        • 002-查看模型可解释性
        • 004-查看特征重要性
      • 组件说明
        • 015-图算法
        • 004-特征工程组件
        • 003-数据处理组件
        • 012-预测组件
        • 008-聚类算法
        • 009-Python算法组件
        • 002-数据集组件
        • 014-自然语言处理组件
        • 010-NLP算法
        • 016-统计分析组件
        • 006-回归算法
        • 007-异常检测算法
        • 013-模型评估组件
        • 005-分类算法
        • 018-时间序列组件
      • 画布操作说明
        • 005-AutoML(自动调参)
        • 002-开始训练
        • 001-概述
    • 预置模型调参建模
      • 预置模型调参简介
      • 神经网络训练搜索
      • 开发视觉模型
        • 视觉任务简介
        • 查看训练结果
        • 创建视觉任务
        • 配置视觉任务
        • 开发参考
          • 视觉预训练模型
          • 超参数配置参考
          • 评估报告参考
          • 自动超参搜索配置参考
          • 数据增强算子参考
          • 训练时长设置参考
          • 网络选型参考
      • 开发表格预测模型
        • 创建表格预测任务
        • 配置专家模式表格数据预测任务
        • 查看训练结果
        • 配置AUTOML模式表格数据预测任务
        • 表格预测任务简介
      • 开发文字识别模型
        • 文字识别任务简介
        • 文字识别任务操作流程
      • 开发自然语言处理模型
        • 查看训练结果
        • 自然语言处理任务简介
        • 配置NLP任务
        • 创建NLP任务
        • 代码模板升级及迁移说明
  • 文档中心
  • arrow
  • 全功能AI开发平台BML
  • arrow
  • 模型训练
  • arrow
  • Notebook建模
  • arrow
  • Notebook从训练到部署快速入门
  • arrow
  • 基于 Notebook 的物体检测模板使用指南
本页目录
  • 创建并启动Notebook
  • 训练物体检测模型
  • 下载 PaddleDetection 套件
  • 安装环境
  • 准备训练数据
  • 训练模型
  • 配置并发布模型
  • 校验模型
  • 部署在线服务
  • 总结

基于 Notebook 的物体检测模板使用指南

更新时间:2025-08-21

目录

1.创建并启动Notebook
2.训练物体检测模型
3.配置并发布模型
4.校验模型
5.部署在线服务

基于 Notebook 的物体检测模板使用指南

本文介绍了物体检测模板下,从创建 Notebook 任务到引入数据、训练模型,再到保存模型、部署模型的全流程。

创建并启动Notebook

1、在 BML 左侧导航栏中点击『Notebook』

2、在 Notebook 页面点击『新建』,在弹出框中填写公司/个人信息以及项目信息,示例如下:

填写基础信息

image.png

填写项目信息

image.png

3、对 Notebook 任务操作入口中点击『配置』进行资源配置,示例如下:

选择开发语言、AI 框架,由于本次采用 PaddleDetection 进行演示,所以需要选择 python3.7、PaddlePaddle2.0.0。选择资源规格,由于深度学习所需的训练资源一般较多,需要选择GPU V100的资源规格。

image.png

完成配置后点击『确认并启动』,即可启动 Notebook,启动过程中需要完成资源的申请以及实例创建,请耐心等待。

4、等待 Notebook 启动后,点击『打开』,页面跳转到 Notebook,即完成 Notebook 的创建与启动,示例如下:

image.png

训练物体检测模型

下载 PaddleDetection 套件

打开进入 Notebook,点击进入终端,输入如下命令切换到 /home/work/ 目录。

Bash
1cd /home/work/

本文以 PaddleDetection 代码库 release/2.3 分支为例,输入如下命令克隆PaddleDetection代码库并切换至release/2.3分支。整个过程需要数十秒,请耐心等待。

Bash
1# gitee 国内下载比较快
2git clone https://gitee.com/paddlepaddle/PaddleDetection.git -b release/2.3  
3# github
4# git clone https://github.com/PaddlePaddle/PaddleDetection.git -b release/2.3

安装环境

在终端环境中,安装该版本的 PaddleDetection 代码包依赖的 paddlepaddle-gpu,执行如下命令:

Bash
1python -m pip install paddlepaddle-gpu==2.1.3.post101 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html

安装完成后,使用 python 或 python3 进入python解释器,输入 import paddle ,再输入 paddle.utils.run_check()

如果出现 PaddlePaddle is installed successfully!,说明成功安装。

准备训练数据

训练数据是模型生产的重要条件,优质的数据集可以很大程度上的提升模型训练效果,准备数据可以参考链接。本文所用的安全帽检测数据集可前往此链接进行下载:下载链接。

1、导入用户数据。

在 Notebook 中并不能直接访问您在 BML 中创建的数据集,需要通过左边选择栏的导入数据集选项,进行数据集导入。导入的数据位于用户目录的 data/ 文件夹(当原始数据集有更新时,不会自动同步,需要手工进行同步)。

image.png

注:若在BML中未创建数据集,请先参考 数据服务 ,创建、上传、标注数据集。

2、数据转换。

PaddleDetection 训练所需要的数据格式与 BML 默认的数据格式有所不同,所以需要利用脚本将导入的数据转为 PaddleDetection 支持的数据格式,并进行3:7切分。

PaddleDetection 默认支持的标注格式为 COCO格式,转换脚本如下:

Python
1import os
2import cv2
3import json
4import glob
5import codecs
6import random
7from pycocotools.coco import COCO
8
9def parse_bml_json(json_file):
10    """
11    解析BML标注文件
12    :return:
13    """
14    annos = json.loads(codecs.open(json_file).read())
15    labels = annos['labels']
16    bboxes = []
17    for label in labels:
18        x1 = label["x1"]
19        y1 = label["y1"]
20        x2 = label["x2"]
21        y2 = label["y2"]
22        id = label["name"]
23        bboxes.append([x1, y1, x2, y2, id])
24    return bboxes
25
26
27def bbox_transform(box):
28    """
29    x1, y1, x2, y2 转为 x1, y1, width, height
30    :return
31    """
32    box = list(map(lambda x: float(x), box))
33    box[2] = box[2] - box[0]
34    box[3] = box[3] - box[1]
35    return box
36
37
38def parse_label_list(src_data_dir, save_dir):
39    """
40    遍历标注文件,获取label_list
41    :return:
42    """
43    label_list = []
44    anno_files = glob.glob(src_data_dir + "*.json")
45    for anno_f in anno_files:
46        annos = json.loads(codecs.open(anno_f).read())
47        for lb in annos["labels"]:
48            label_list.append(lb["name"])
49    label_list = list(set(label_list))
50    with codecs.open(os.path.join(save_dir, "label_list.txt"), 'w', encoding="utf-8") as f:
51        for id, label in enumerate(label_list):
52            f.writelines("%s:%s\n" % (id, label))
53    return len(label_list), label_list
54
55
56def bml2coco(src_dir, coco_json_file):
57    """
58    BML标注格式转为COCO标注格式
59    :return:
60    """
61    coco_images = []
62    coco_annotations = []
63
64    image_id = 0
65    anno_id = 0
66    image_list = glob.glob(src_dir + "*.[jJPpBb][PpNnMm]*")
67    for image_file in image_list:
68        anno_f = image_file.split(".")[0] + ".json"
69        if not os.path.isfile(anno_f):
70            continue
71        bboxes = parse_bml_json(anno_f)
72        im = cv2.imread(image_file)
73        h, w, _ = im.shape
74        image_i = {"file_name": os.path.basename(image_file), "id": image_id, "width": w, "height": h}
75        coco_images.append(image_i)
76        for id, bbox in enumerate(bboxes):
77            # bbox : [x1, y1, x2, y2, label_name]
78            anno_i = {"image_id": image_id, "bbox": bbox_transform(bbox[:4]), 'category_id': label_list.index(bbox[4]),
79                      'id': anno_id, 'area': 1.1, 'iscrowd': 0, "segmentation": None}
80            anno_id += 1
81            coco_annotations.append(anno_i)
82
83        image_id += 1
84
85    coco_categories = [{"id": id, "name": label_name} for id, label_name in enumerate(label_list)]
86    coco_dict = {"info": "info", "licenses": "BMLCloud", "images": coco_images, "annotations": coco_annotations,
87                 "categories": coco_categories}
88    with open(coco_json_file, 'w', encoding="utf-8") as fin:
89        json.dump(coco_dict, fin, ensure_ascii=False)
90
91
92def split_det_origin_dataset(
93        origin_file_path,
94        train_file_path,
95        eval_file_path,
96        ratio=0.7):
97    """
98    按比例切分物体检测原始数据集
99    :return:
100    """
101    coco = COCO(origin_file_path)
102    img_ids = coco.getImgIds()
103    items_num = len(img_ids)
104    train_indexes, eval_indexes = random_split_indexes(items_num, ratio)
105    train_items = [img_ids[i] for i in train_indexes]
106    eval_items = [img_ids[i] for i in eval_indexes]
107
108    dump_det_dataset(coco, train_items, train_file_path)
109    dump_det_dataset(coco, eval_items, eval_file_path)
110
111    return items_num, len(train_items), len(eval_items)
112
113
114def random_split_indexes(items_num, ratio=0.7):
115    """
116    按比例分割整个list的index
117    :return:分割后的两个index子列表
118    """
119    offset = round(items_num * ratio)
120    full_indexes = list(range(items_num))
121    random.shuffle(full_indexes)
122    sub_indexes_1 = full_indexes[:offset]
123    sub_indexes_2 = full_indexes[offset:]
124
125    return sub_indexes_1, sub_indexes_2
126
127
128def dump_det_dataset(coco, img_id_list, save_file_path):
129    """
130    物体检测数据集保存
131    :return:
132    """
133    imgs = coco.loadImgs(img_id_list)
134    img_anno_ids = coco.getAnnIds(imgIds=img_id_list, iscrowd=0)
135    instances = coco.loadAnns(img_anno_ids)
136    cat_ids = coco.getCatIds()
137    categories = coco.loadCats(cat_ids)
138    common_dict = {
139        "info": coco.dataset["info"],
140        "licenses": coco.dataset["licenses"],
141        "categories": categories
142    }
143    img_dict = {
144        "image_nums": len(imgs),
145        "images": imgs,
146        "annotations": instances
147    }
148    img_dict.update(common_dict)
149
150    json_file = open(save_file_path, 'w', encoding='UTF-8')
151    json.dump(img_dict, json_file)
152
153
154class_nums, label_list = parse_label_list("/home/work/data/${dataset_id}/", "/home/work/PretrainedModel/")
155bml2coco("/home/work/data/${dataset_id}/", "/home/work/PretrainedModel/org_data_list.json")
156split_det_origin_dataset("/home/work/PretrainedModel/org_data_list.json", "/home/work/PretrainedModel/train_data_list.json", "/home/work/PretrainedModel/eval_data_list.json")

将上述脚本存放为 coversion.py 代码脚本,并将脚本最后两行的 ${dataset_id} 替换为所指定数据集的 ID(下图红框中的ID),在终端中运行即可。

image.png

运行代码。

Bash
1python coversion.py

注意:如果报错 No module named 'pycocotools',需要通过如下命令安装相关依赖包,再运行 coversion.py 代码。

Bash
1pip install pycocotools

运行 coversion.py 代码成功之后将在 PretrainedModel/ 文件夹下生成对应的数据文件,包括 label_list.txt、train_data_list.json、eval_data_list.json、org_data_list.json。

image.png

训练模型

开发者准备好训练数据和安装环境之后即可开始训练物体检测模型。

1、在终端中打开 PaddleDetection 目录。

Bash
1cd /home/work/PaddleDetection

2、修改yaml配置文件。

在PaddleDetection 2.0后续版本,采用了模块解耦设计,用户可以组合配置模块实现检测器,并可自由修改覆盖各模块配置,本文以 configs/yolov3/yolov3_darknet53_270e_coco.yml 为例:

YAML
1yolov3_darknet53_270e_coco.yml 主配置入口文件
2coco_detection.yml 主要说明了训练数据和验证数据的路径
3runtime.yml 主要说明了公共的运行参数,比如说是否使用GPU、每多少个epoch存储checkpoint等
4optimizer_270e.yml 主要说明了学习率和优化器的配置。
5yolov3_darknet53.yml 主要说明模型、和主干网络的情况。
6yolov3_reader.yml 主要说明数据读取器配置,如batch size,并发加载子进程数等,同时包含读取后预处理操作,如resize、数据增强等等

需要修改/覆盖的参数均可写在主配置入口文件中,主要修改点为训练、验证数据集路径、运行epoch数、学习率等,修改后的主配置文件如下(注释行即为需要修改的点):

YAML
1_BASE_: [
2  '../datasets/coco_detection.yml',
3  '../runtime.yml',
4  '_base_/optimizer_270e.yml',
5  '_base_/yolov3_darknet53.yml',
6  '_base_/yolov3_reader.yml',
7]
8
9snapshot_epoch: 5
10weights: output/yolov3_darknet53_270e_coco/model_final
11
12# 预训练权重地址
13pretrain_weights: https://paddledet.bj.bcebos.com/models/yolov3_darknet53_270e_coco.pdparams
14
15# coco_detection.yml
16num_classes: 2 #实际类别数
17TrainDataset:
18  !COCODataSet
19    image_dir: data/${dataset_id}/   # 图片地址
20    anno_path: PretrainedModel/train_data_list.json # 标注文件
21    dataset_dir: /home/work/ # 数据集根目录
22    data_fields: ['image', 'gt_bbox', 'gt_class', 'is_crowd']
23
24EvalDataset:
25  !COCODataSet
26    image_dir: data/${dataset_id}/   # 图片地址
27    anno_path: PretrainedModel/eval_data_list.json   # 标注文件
28    dataset_dir: /home/work/   # 数据集根目录
29
30# optimizer_270e.yml
31epoch: 50 # 迭代轮数
32LearningRate:
33  base_lr: 0.0001 # 学习率
34  schedulers:
35  - !PiecewiseDecay
36    gamma: 0.1
37    milestones:
38    - 30
39    - 45
40  - !LinearWarmup
41    start_factor: 0.
42    steps: 400

3、训练模型。

在终端中执行以下命令,开始模型训练。

Bash
1cd /home/work/PaddleDetection/
2python tools/train.py -c configs/yolov3/yolov3_darknet53_270e_coco.yml --eval 

注意:如果报错 No module named 'lap' 和 No module named 'motmetrics' ,则需要通过如下命令安装相关依赖包,再运行 coversion.py 代码。(如果缺失其他模块,也可用类似命令下载安装)

Bash
1pip install lap motmetrics

4、模型评估

在终端中执行以下命令,开始模型评估。

Plain Text
1python tools/eval.py -c configs/yolov3/yolov3_darknet53_270e_coco.yml \
2                     -o weights=output/yolov3_darknet53_270e_coco/model_final

运行完成输出如下结果:

image.png

5、模型预测。

在终端中执行以下命令,开始模型预测(注意修改图片路径)。

Bash
1python tools/infer.py -c configs/yolov3/yolov3_darknet53_270e_coco.yml \
2                    --infer_img=/home/work/data/${task_id}/xxx.jpeg \
3                    --output_dir=infer_output/ \
4                    --draw_threshold=0.5 \
5                    -o weights=output/yolov3_darknet53_270e_coco/model_final

6、导出模型。

在终端中执行以下命令,将最佳模型转为可以用于发布的 inference 模型

Bash
1python tools/export_model.py -c configs/yolov3/yolov3_darknet53_270e_coco.yml \
2           --output_dir=/home/work/PretrainedModel/ \
3           -o weights=output/yolov3_darknet53_270e_coco/model_final

在终端中执行以下命令,将导出模型移至 /home/work/PretrainedModel/ 目录。

Bash
1mv /home/work/PretrainedModel/yolov3_darknet53_270e_coco/* /home/work/PretrainedModel/

7、生成模型版本。

Notebook 中的模型文件只有生成模型版本后,才可以执行发布和部署功能:

  • 请确保要保存的模型文件在/home/work/PretrainedModel目录下。模型支持版本管理功能,在保存时可以生成新版本也可以覆盖已有的且尚未部署的模型版本,每个版本的模型都可以独立部署。每个模型版本中保存的模型文件大小上限为1.5GB。
  • 在保存模式时也可以将训练模型的代码一并保存。代码支持版本管理功能,用户再次启动Notebook时,可以使用指定的代码版本来初始化Notebook工作空间即/home/work目录下data以外的空间。每个代码版本中保存的文件大小上限为150M。

点击左侧导航栏中的生成模型版本组件,打开弹窗填写信息。

image.png

模型属性-选择 AI 框架选择 PaddlePaddle2.0.0,若上一次操作中进行了代码保存,可在“代码版本”选择对应的代码版本。

image.png

选择模型文件-选择 label_list.txt、model.pdiparams、model.pdmodel 、 infer_cfg.yaml 文件。

image.png

点击『生成』即可生成模型版本,生成模型版本一般需要数十秒,请耐心等待。

配置并发布模型

BML NoteBook 的物体检测模板产出的模型支持进行部署,下面以 PaddleDetection 的模型为例,详细介绍如何配置模型:

1、查看前置条件是否满足:需要训练完成,并生成了相应的模型生成版本(详见训练模型的第六步)。

2、回到 BML Notebook 列表页,点击对应 Notebook 项目的『模型发布列表』即可进入配置页面。

image.png

3、点击配置,即可进入配置流程。

image.png

4、填写模型信息。

image.png

5、选择待发布的模型文件,点击确定按钮。

image.png

对于 Paddle2.x 的模型而言:

  • 网络结构文件 model.pdmodel:必需选择,且名字固定。
  • 网络参数文件 model.pdiparams:必需选择,且名字固定。
  • 模型标签文件:label_list.txt,非必须,主要看自定义逻辑代码是如何实现的。本文中在【配置出入参及数据处理逻辑脚本】的脚本代码里面会用到,所以需要选择。
  • 预/后处理配置文件等其他文件:infer_cfg.yaml,非必须,主要看自定义逻辑代码是如何实现的。本文中在【配置出入参及数据处理逻辑脚本】的脚本代码里面会用到,所以需要选择。

6、配置出入参及数据逻辑处理。

这部分配置主要实现自定义的模型预处理和后处理逻辑。该脚本用于将选择的模型文件发布成模型服务。用户可以通过修改 PredictWrapper 的 preprocess 和 postprocess 方法来实现自定义的请求预处理和预测结果后处理。当提交该脚本时,系统会根据用户选择的模型文件和脚本内容,来验证是否可以启动模型服务,只有验证通过,才可以进行模型效果校验以及将模型发布到模型仓库。

实现脚本有一些建议和限制:

  • CustomException 必需存在且是异常类;在自定义的逻辑中,建议当处理进入错误的分支时,抛出 CustomException 并指定 message,指定的 message 在请求回包中会作为 error_msg 返回。
  • PredictWrapper 类必需存在,且必需包含 preprocess 和 postprocess 两个方法。
  • PredictWrapper 的 preprocess 和 postprocess 方法,是用户自定义模型服务请求预处理和预测结果后处理的入口。
  • preprocess 方法接收的第一个参数为用户请求的 json 字典,对于图像类服务,传入图像的参数 key 必须是"image",且传入的是图片的 base64 编码。
  • 系统会根据 postprocess 方法的返回结果 result 类型的不同,做以下处理:

    Plain Text
    1	 - dict: 不作修改
    2	 - list: 转换为 {"results": result}
    • 其他: 转换为 {"result": result}
    • 最终的处理结果可以转换为json字符串,以确保能够正常将结果作为请求回包返回
  • 单击“提交”,完成模型配置。 提交后,系统会自动对当前版本模型进行代码验证,通过后模型会更新为“有效”状态。

配置出入参及数据处理逻辑脚本:实现图片的预处理和模型输出结果后处理的逻辑;这一步是比较关键,但也比较复杂的一步。上面介绍了脚本实现时的限制和建议。这里针对PaddleDetection套件,实现了一套对应的脚本代码(在后面),可以点击立即编辑,将脚本代码拷贝替换掉。

image.png

注:

可以看下平台预置代码文件,以及各个类及函数的注释了解实现细节。这里贴了PaddleDetection套件对应的脚本文件,整个代码比较长,但大部分内容都拷贝于PaddleDetection套件的推理示例。如果自身训练模型比较特殊,当前脚本支持不了,需要自己去PaddleDetection套件中寻找逻辑,并更新到该脚本中。

PaddleDetection脚本样例:

Python
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# *******************************************************************************
4#
5# Copyright (c) 2020 Baidu.com, Inc. All Rights Reserved
6#
7# *******************************************************************************
8
9# 注意事项:
10# 该脚本用于将通过notebook训练产出的模型发布成模型服务
11# 用户可以通过修改PredictWrapper的preprocess和postprocess方法来实现自定义的请求预处理和预测结果后处理
12# 当在EasyDL提交该脚本时,系统会根据用户选择的模型文件和脚本内容,来验证是否可以启动模型服务,如果验证通过,即可进行模型效果校验以及部署模型服务
13# 下面是修改脚本的一些限制和建议:
14# 1. CustomException必须存在且是异常类;在自定义的逻辑中,建议当处理进入错误的分支时,抛出CustomException并指定message,指定的message在请求回包中会作为error_msg返回;
15# 2. PredictWrapper类必须存在,且必需包含preprocess和postprocess两个方法;
16# 3. PredictWrapper的preprocess和postprocess方法,是用户自定义模型服务请求预处理和预测结果后处理的入口;
17# 4. preprocess方法接收的第一个参数为用户请求的json字典,对于图像类服务,传入图像的参数key必须是"image",且传入的是图片的base64编码
18# 5. 系统会根据postprocess方法的返回结果`result`类型的不同,做以下处理:
19#       dict: 不作修改
20#       list: 转换为 {"results": result}
21#       其他: 转换为 {"result": result}
22#    处理结果将转换为json字符串,以确保系统能正常将结果作为请求回包返回。
23
24import base64
25import cv2
26import numpy as np
27import yaml
28
29DEFAULT_THRESHOLD = 0.5
30
31
32class CustomException(RuntimeError):
33    """
34    进行模型验证和部署服务必需的异常类,缺少该类在代码验证时将会失败
35    在处理异常数据或者请求时,推荐在`PredictWrapper`中的自定义预处理preprocess和后处理postprocess函数中抛出`CustomException`类,
36    并为`message`指定准确可读的错误信息,以便在服务响应包中的`error_msg`参数中返回。
37    """
38    def __init__(self, message, orig_error=None):
39        """ 根据`message`初始化 """
40        super(CustomException, self).__init__(message)
41        self.orig_error = orig_error
42
43
44class PredictWrapper(object):
45    """ 模型服务预测封装类,支持用户自定义对服务请求数据的预处理和模型预测结果的后处理函数 """
46
47    def __init__(self, model_path):
48        """
49        根据`model_path`初始化`PredictWrapper`类,如解析label_list.txt,加载模型输出标签id和标签名称的映射关系
50        :param model_path: 该目录下存放了用户选择的模型版本中包含的所有文件
51        """
52        # 加载推理配置文件,获取【预处理配置】及【标签id和名称的映射关系】
53        conf_path = '{model_path}/{conf_file}'.format(model_path=model_path, conf_file='infer_cfg.yml')
54        with open(conf_path) as conf_fin:
55            infer_conf = yaml.load(conf_fin, Loader=yaml.FullLoader)
56            self._preprocess_args = infer_conf["Preprocess"]
57            self._label_list = infer_conf["label_list"]
58
59    def preprocess(self, request_body, **preprocess_args):
60        """
61        自定义对请求体的预处理,针对图像类模型服务,包括对图片对图像的解析、转化等
62        :param request_body: 请求体的json字典
63        :param preprocess_args: 从`{model_path}/preprocess_args.json`中加载的预处理参数字典,json文件不存在时,传入为空字典
64        :return:
65            data: 用于模型预测的输入。注意:data结构为dict,key为模型输入节点的名称,value为对应需要喂入的值,batch只能为1
66            infer_args: 用于模型预测的其他参数
67            request_context: 透传给自定义后处理函数`postprocess`的参数,例如指定返回预测结果的top N,过滤低score的阈值threshold.
68        """
69        # decode image from base64 string in request
70        try:
71            image_b64 = request_body['image']
72            img_bin = base64.b64decode(image_b64)
73        except KeyError:
74            raise CustomException('Missing required parameter')
75        except Exception:
76            raise CustomException('Invalid BASE64')
77
78        data = np.frombuffer(img_bin, dtype='uint8')
79        im = cv2.imdecode(data, 1)  # BGR mode, but need RGB mode
80        im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
81
82        # paddle detection preprocess
83        # code: https://github.com/PaddlePaddle/PaddleDetection/blob/develop/deploy/python/infer.py#L99
84        try:
85            preprocess_ops = []
86            for op_info in self._preprocess_args:
87                new_op_info = op_info.copy()
88                op_type = new_op_info.pop('type')
89                preprocess_ops.append(eval(op_type)(**new_op_info))
90
91            input_im_lst = []
92            input_im_info_lst = []
93            im, im_info = preprocess(im, preprocess_ops)
94            input_im_lst.append(im)
95            input_im_info_lst.append(im_info)
96            input_info = create_inputs(input_im_lst, input_im_info_lst)
97        except Exception:
98            raise CustomException('Failed decoding input')
99
100        return input_info, {}, {"threshold": request_body.get("threshold", DEFAULT_THRESHOLD)}
101
102    def postprocess(self, infer_result, request_context, **postprocess_args):
103        """
104        自定义对图像分类模型输出结果的后处理,例如根据score对label进行排序,获取top N分类结果等
105        :param infer_result: fluid模型的预测结果
106        :param request_context: 自定义预处理函数中返回的`request context`
107        :param postprocess_args: 从`{model_path}/postprocess_args.json`中加载的后处理参数字典,json文件不存在时,传入为空字典
108        :return: request results 请求的处理结果
109        """
110        threshold = request_context["threshold"]
111        boxes = infer_result[0]
112        bboxes_num = int(infer_result[1][0])
113
114        results = []
115        for i in range(bboxes_num):
116            box_info = boxes[i, :]
117            label = int(box_info[0])
118            score = float(box_info[1])
119            x1 = int(box_info[2])
120            y1 = int(box_info[3])
121            x2 = int(box_info[4])
122            y2 = int(box_info[5])
123
124            if score < threshold:
125                continue
126            results.append({
127                'name': self._label_list[label],
128                'score': score,
129                'location': {
130                    'left': x1,
131                    'top': y1,
132                    'width': x2 - x1,
133                    'height': y2 - y1,
134                }
135            })
136        return results
137
138
139# copy from PaddleDetection: https://github.com/PaddlePaddle/PaddleDetection/blob/develop/deploy/python/preprocess.py
140# note: Only copy used preprocess OPs, if model used other op, show copy into this file
141def preprocess(im, preprocess_ops):
142    # process image by preprocess_ops
143    im_info = {
144        'scale_factor': np.array(
145            [1., 1.], dtype=np.float32),
146        'im_shape': None,
147    }
148    im, im_info = decode_image(im, im_info)
149    for operator in preprocess_ops:
150        im, im_info = operator(im, im_info)
151    return im, im_info
152
153
154def decode_image(im_file, im_info):
155    """read rgb image
156    Args:
157        im_file (str|np.ndarray\bytes): input can be image path or np.ndarray
158        im_info (dict): info of image
159    Returns:
160        im (np.ndarray):  processed image (np.ndarray)
161        im_info (dict): info of processed image
162    """
163    if isinstance(im_file, str):
164        with open(im_file, 'rb') as f:
165            im_read = f.read()
166        data = np.frombuffer(im_read, dtype='uint8')
167        im = cv2.imdecode(data, 1)  # BGR mode, but need RGB mode
168        im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
169    else:
170        im = im_file
171    im_info['im_shape'] = np.array(im.shape[:2], dtype=np.float32)
172    im_info['scale_factor'] = np.array([1., 1.], dtype=np.float32)
173    return im, im_info
174
175
176class Resize(object):
177    """resize image by target_size and max_size
178    Args:
179        target_size (int): the target size of image
180        keep_ratio (bool): whether keep_ratio or not, default true
181        interp (int): method of resize
182    """
183
184    def __init__(self, target_size, keep_ratio=True, interp=cv2.INTER_LINEAR):
185        if isinstance(target_size, int):
186            target_size = [target_size, target_size]
187        self.target_size = target_size
188        self.keep_ratio = keep_ratio
189        self.interp = interp
190
191    def __call__(self, im, im_info):
192        """
193        Args:
194            im (np.ndarray): image (np.ndarray)
195            im_info (dict): info of image
196        Returns:
197            im (np.ndarray):  processed image (np.ndarray)
198            im_info (dict): info of processed image
199        """
200        assert len(self.target_size) == 2
201        assert self.target_size[0] > 0 and self.target_size[1] > 0
202        im_channel = im.shape[2]
203        im_scale_y, im_scale_x = self.generate_scale(im)
204        im = cv2.resize(
205            im,
206            None,
207            None,
208            fx=im_scale_x,
209            fy=im_scale_y,
210            interpolation=self.interp)
211        im_info['im_shape'] = np.array(im.shape[:2]).astype('float32')
212        im_info['scale_factor'] = np.array(
213            [im_scale_y, im_scale_x]).astype('float32')
214        return im, im_info
215
216    def generate_scale(self, im):
217        """
218        Args:
219            im (np.ndarray): image (np.ndarray)
220        Returns:
221            im_scale_x: the resize ratio of X
222            im_scale_y: the resize ratio of Y
223        """
224        origin_shape = im.shape[:2]
225        im_c = im.shape[2]
226        if self.keep_ratio:
227            im_size_min = np.min(origin_shape)
228            im_size_max = np.max(origin_shape)
229            target_size_min = np.min(self.target_size)
230            target_size_max = np.max(self.target_size)
231            im_scale = float(target_size_min) / float(im_size_min)
232            if np.round(im_scale * im_size_max) > target_size_max:
233                im_scale = float(target_size_max) / float(im_size_max)
234            im_scale_x = im_scale
235            im_scale_y = im_scale
236        else:
237            resize_h, resize_w = self.target_size
238            im_scale_y = resize_h / float(origin_shape[0])
239            im_scale_x = resize_w / float(origin_shape[1])
240        return im_scale_y, im_scale_x
241
242
243class NormalizeImage(object):
244    """normalize image
245    Args:
246        mean (list): im - mean
247        std (list): im / std
248        is_scale (bool): whether need im / 255
249        is_channel_first (bool): if True: image shape is CHW, else: HWC
250    """
251
252    def __init__(self, mean, std, is_scale=True):
253        self.mean = mean
254        self.std = std
255        self.is_scale = is_scale
256
257    def __call__(self, im, im_info):
258        """
259        Args:
260            im (np.ndarray): image (np.ndarray)
261            im_info (dict): info of image
262        Returns:
263            im (np.ndarray):  processed image (np.ndarray)
264            im_info (dict): info of processed image
265        """
266        im = im.astype(np.float32, copy=False)
267        mean = np.array(self.mean)[np.newaxis, np.newaxis, :]
268        std = np.array(self.std)[np.newaxis, np.newaxis, :]
269
270        if self.is_scale:
271            im = im / 255.0
272        im -= mean
273        im /= std
274        return im, im_info
275
276
277class Permute(object):
278    """permute image
279    Args:
280        to_bgr (bool): whether convert RGB to BGR
281        channel_first (bool): whether convert HWC to CHW
282    """
283
284    def __init__(self, ):
285        super(Permute, self).__init__()
286
287    def __call__(self, im, im_info):
288        """
289        Args:
290            im (np.ndarray): image (np.ndarray)
291            im_info (dict): info of image
292        Returns:
293            im (np.ndarray):  processed image (np.ndarray)
294            im_info (dict): info of processed image
295        """
296        im = im.transpose((2, 0, 1)).copy()
297        return im, im_info
298
299
300class PadStride(object):
301    """ padding image for model with FPN, instead PadBatch(pad_to_stride) in original config
302    Args:
303        stride (bool): model with FPN need image shape % stride == 0
304    """
305
306    def __init__(self, stride=0):
307        self.coarsest_stride = stride
308
309    def __call__(self, im, im_info):
310        """
311        Args:
312            im (np.ndarray): image (np.ndarray)
313            im_info (dict): info of image
314        Returns:
315            im (np.ndarray):  processed image (np.ndarray)
316            im_info (dict): info of processed image
317        """
318        coarsest_stride = self.coarsest_stride
319        if coarsest_stride <= 0:
320            return im, im_info
321        im_c, im_h, im_w = im.shape
322        pad_h = int(np.ceil(float(im_h) / coarsest_stride) * coarsest_stride)
323        pad_w = int(np.ceil(float(im_w) / coarsest_stride) * coarsest_stride)
324        padding_im = np.zeros((im_c, pad_h, pad_w), dtype=np.float32)
325        padding_im[:, :im_h, :im_w] = im
326        return padding_im, im_info
327
328
329class LetterBoxResize(object):
330    def __init__(self, target_size):
331        """
332        Resize image to target size, convert normalized xywh to pixel xyxy
333        format ([x_center, y_center, width, height] -> [x0, y0, x1, y1]).
334        Args:
335            target_size (int|list): image target size.
336        """
337        super(LetterBoxResize, self).__init__()
338        if isinstance(target_size, int):
339            target_size = [target_size, target_size]
340        self.target_size = target_size
341
342    def letterbox(self, img, height, width, color=(127.5, 127.5, 127.5)):
343        # letterbox: resize a rectangular image to a padded rectangular
344        shape = img.shape[:2]  # [height, width]
345        ratio_h = float(height) / shape[0]
346        ratio_w = float(width) / shape[1]
347        ratio = min(ratio_h, ratio_w)
348        new_shape = (round(shape[1] * ratio),
349                     round(shape[0] * ratio))  # [width, height]
350        padw = (width - new_shape[0]) / 2
351        padh = (height - new_shape[1]) / 2
352        top, bottom = round(padh - 0.1), round(padh + 0.1)
353        left, right = round(padw - 0.1), round(padw + 0.1)
354
355        img = cv2.resize(
356            img, new_shape, interpolation=cv2.INTER_AREA)  # resized, no border
357        img = cv2.copyMakeBorder(
358            img, top, bottom, left, right, cv2.BORDER_CONSTANT,
359            value=color)  # padded rectangular
360        return img, ratio, padw, padh
361
362    def __call__(self, im, im_info):
363        """
364        Args:
365            im (np.ndarray): image (np.ndarray)
366            im_info (dict): info of image
367        Returns:
368            im (np.ndarray):  processed image (np.ndarray)
369            im_info (dict): info of processed image
370        """
371        assert len(self.target_size) == 2
372        assert self.target_size[0] > 0 and self.target_size[1] > 0
373        height, width = self.target_size
374        h, w = im.shape[:2]
375        im, ratio, padw, padh = self.letterbox(im, height=height, width=width)
376
377        new_shape = [round(h * ratio), round(w * ratio)]
378        im_info['im_shape'] = np.array(new_shape, dtype=np.float32)
379        im_info['scale_factor'] = np.array([ratio, ratio], dtype=np.float32)
380        return im, im_info
381
382
383def create_inputs(imgs, im_info):
384    """generate input for different model type
385    Args:
386        imgs (list(numpy)): list of images (np.ndarray)
387        im_info (list(dict)): list of image info
388    Returns:
389        inputs (dict): input of model
390    """
391    inputs = {}
392
393    im_shape = []
394    scale_factor = []
395    if len(imgs) == 1:
396        inputs['image'] = np.array((imgs[0], )).astype('float32')
397        inputs['im_shape'] = np.array(
398            (im_info[0]['im_shape'], )).astype('float32')
399        inputs['scale_factor'] = np.array(
400            (im_info[0]['scale_factor'], )).astype('float32')
401        return inputs
402
403    for e in im_info:
404        im_shape.append(np.array((e['im_shape'], )).astype('float32'))
405        scale_factor.append(np.array((e['scale_factor'], )).astype('float32'))
406
407    inputs['im_shape'] = np.concatenate(im_shape, axis=0)
408    inputs['scale_factor'] = np.concatenate(scale_factor, axis=0)
409
410    imgs_shape = [[e.shape[1], e.shape[2]] for e in imgs]
411    max_shape_h = max([e[0] for e in imgs_shape])
412    max_shape_w = max([e[1] for e in imgs_shape])
413    padding_imgs = []
414    for img in imgs:
415        im_c, im_h, im_w = img.shape[:]
416        padding_im = np.zeros(
417            (im_c, max_shape_h, max_shape_w), dtype=np.float32)
418        padding_im[:, :im_h, :im_w] = img
419        padding_imgs.append(padding_im)
420    inputs['image'] = np.stack(padding_imgs, axis=0)
421    return inputs

7、点击提交即可进入模型验证阶段,验证时间一般需要数十秒,请耐心等待。

image.png

验证通过后,显示有效。

image.png

8、点击发布,填写相关信息后,即可发布成功。

9、点击左侧导航栏模型管理,即可查看发布成功的模型。

image.png

校验模型

1、点击『版本列表』。

image.png

2、点击『校验模型』。

image.png

3、点击『启动模型校验』,启动约需5分钟,请耐心等待。

image.png

4、上传图像即可开始校验,示例如下:

image.png

部署在线服务

1、点击『版本列表』。

image.png

2、点击部署-在线服务。

image.png

3、完成信息填写及资源规格选择后,即可开始部署。

image.png

4、部署过程需要数十秒时间,请耐心等待。部署完成后,示例如下:

image.png

5、API调用方法请参考 公有云部署管理。

总结

  • 更多丰富的内容与示例可以参考PaddleDetection的github与教程文档。

    • PaddleDetection github地址:https://github.com/PaddlePaddle/PaddleDetection/
    • PaddleDetection教程文档地址:https://github.com/PaddlePaddle/PaddleDetection/blob/release/2.3/docs/tutorials/GETTING_STARTED_cn.md
  • 如果在使用PaddleDetection的过程中遇到问题,欢迎去PaddleDetection的github上提issue:https://github.com/PaddlePaddle/PaddleDetection/issues/new

上一篇
基于 Notebook 的通用模板使用指南
下一篇
自定义作业建模