ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

CANN ops-cv NMSWithMask 算子全解析:NPU 上带掩码的非极大值抑制实现与 aclnnNMSWithMask 调用指南

CANN ops-cv NMSWithMask 算子全解析:NPU 上带掩码的非极大值抑制实现与 aclnnNMSWithMask 调用指南 CANN ops-cv NMSWithMask 算子全解析NPU 上带掩码的非极大值抑制实现与 aclnnNMSWithMask 调用指南【免费下载链接】ops-cv本项目是CANN提供的图像处理、目标检测相关的算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-cv导读本文围绕 CANN ops-cv 开源算子库中的NMSWithMask算子展开完整讲解其在 Atlas A2 训练/推理系列产品上对候选框执行非极大值抑制NMS的功能语义、IOU 计算流程、输入输出参数约束并结合仓库源码算子注册、infershape、tiling、AscendC kernel剖析其在 NPU 上的实际实现方式。读完本文你将掌握 NMSWithMask 的算法细节、参数用法并能够基于 aclnn 调用样例 独立编写两段式 aclnnNMSWithMask 调用程序。一、算子概述与产品支持情况NMSWithMask 是 ops-cv 仓库 experimental/image/nms_with_mask 目录下实现的实验性图像目标检测算子。与常规直接输出过滤后候选框坐标的 NMS 算子不同它的输出是一个候选框保留掩码mask即对于输入的 N 个候选框逐框标记保留1/抑制0由上层网络根据掩码自行决定后续如何使用候选框。产品是否支持Atlas A2 训练系列产品 / Atlas A2 推理系列产品√从源码看该产品限定与算子注册信息一致在 nms_with_mask_def.cpp 中通过this-AICore().AddConfig(ascend910b)声明其 AICore 目标平台配置对应配置文件也位于 op_host/config/ascend910b 目录下。二、功能说明与算法原理2.1 算子功能对候选框执行非极大值抑制NMS输出候选框保留掩码支持IOU 阈值iou_threshold与置信度阈值scores_threshold双重过滤输入坐标格式为x1, y1, x2, y2左下角坐标与右上角坐标在代码中以一维数组形式存储即[N, 4]维度展开为长度N*4的一维数据。2.2 计算流程Step1 ~ Step5算法以按置信度从高到低贪心挑选、抑制与已选框高度重叠的框为核心思路官方文档给出的计算节点流程如下Step1按置信度降序生成排序索引idx_sorted。注意该算子默认输入已按置信度降序排序需用户自行保证算子内部不执行排序Step2初始化临时掩码标记所有候选框为保留状态值为 1输出掩码初始化为 0Step3遍历候选框跳过已标记为过滤的框若当前框置信度低于scores_threshold将其临时掩码置 0过滤Step4对保留的候选框将其输出掩码标记为 1并计算它与后续所有候选框的 IOU$$IOU \frac{交集面积}{当前框面积 对比框面积 - 交集面积}$$Step5将 IOU 高于iou_threshold的后续框标记为过滤临时掩码置 0重复 Step3 ~ Step5直至所有候选框处理完成。2.3 输入输出节点输入节点x候选框坐标shape 为[N, 4]FLOAT32y候选框置信度shape 为[N]FLOAT32iou_thresholdIOU 过滤阈值shape 为[1]FLOAT32scores_threshold置信度过滤阈值shape 为[1]FLOAT32。输出节点z候选框保留掩码shape 为[N]UINT81 表示保留0 表示被抑制。说明从 nms_with_mask_def.cpp 的算子注册结构看x、y在算子定义层面分别对应必选输入x1、x2输出对应yUINT8iou_threshold与scores_threshold在算子定义层面被注册为可选属性Attr默认值均为1e-1。而 aclnn 接口层见第六节调用示例则把两个阈值作为 API 的入参直接传入。三、参数说明参数名输入/输出/属性描述数据类型数据格式x输入候选框坐标左下和右上[N, 4]。FLOAT32NDy输入置信度。FLOAT32NDiou_threshold输入IOU 阈值。FLOAT32NDscores_threshold输入置信度阈值。FLOAT32NDz输出选中候选框对应掩码。UINT8ND补充说明来自源码属性默认值在算子定义nms_with_mask_def.cpp中iou_threshold与scores_threshold均为AttrType(OPTIONAL).Float(1e-1)即未显式传入时默认取0.1Tiling 层取属性在 nms_with_mask_tiling.cpp 中通过context-GetAttrs()-GetAttrPointerfloat读取两个阈值写入 tiling 数据结构传递给 kernel输入规模上限tiling 中定义LIMIT_INPUT_NUM 2048 * 4即最多 2048 个候选框当totalIdx N * 4超过该上限时会报invalid Input错误nms_with_mask_tiling.cpp输出 shape 推导infershape 实现将输出 shape 取输入 x 去掉最后一维的结果nms_with_mask_infershape.cpp即输入[N, 4]时输出[N]与掩码语义一致。四、约束说明目前只支持 float32 输入。虽然 tiling 中supportedDtype集合同时声明了DT_FLOAT与DT_INT32nms_with_mask_tiling.cpp但 tiling key 分发逻辑只在dataType DT_FLOAT时进入正常分支其他数据类型直接返回失败nms_with_mask_tiling.cppkernel 侧也仅实例化了NMSWithMaskfloat模板nms_with_mask.cpp。因此实际使用请统一使用 FLOAT32 输入与 UINT8 输出。输入坐标与置信度需预先按置信度降序排列算子内部不负责排序候选框数量建议不超过 2048见第三节输入规模上限。五、源码级实现剖析5.1 算子注册与平台配置nms_with_mask_def.cpp 通过OpDef框架完成算子信息注册输入x1坐标与x2置信度REQUIRED必选、DT_FLOAT、FORMAT_ND并调用AutoContiguous()要求内存自动连续化输出yREQUIRED、DT_UINT8、FORMAT_ND两个阈值属性OPTIONAL可选属性默认1e-1OP_ADD(NMSWithMask)将算子写入算子信息库AddConfig(ascend910b)声明目标芯片配置。对应的 nms_with_mask_binary.json 以 opc 二进制算子配置的形式声明了算子名、输入输出 dtype/formatfloat32/ND 与 uint8/ND、shape 通配-2以及两个 float32 属性nms_with_mask_simplified_key.ini 则为[NMSWithMask]配置了default0的 simplified key 模式用于 opc 工具编译二进制 kernel 时确定--simplified_key_mode取值。5.2 Tiling 与 Workspacenms_with_mask_tiling.cpp 完成 host 侧 tiling 分发平台信息通过GetPlatformInfo获取 UB 大小与 AIV core 数GetCoreNumAivshape 校验输入 x 必须为 2 维、输入 y 与输出 z 必须为 1 维否则报错Workspace 申请GetWorkspaceSize固定申请16MBWS_SYS_SIZE 16U * 1024U * 1024U系统 workspaceTiling 数据下发将totalLength N * 4、iou_threshold、scores_threshold写入 NMSWithMaskTilingData 结构体int64_t totalLength 两个float阈值Block 设置SetBlockDim(CoreNum)CoreNum 1即该算子当前以单核方式执行tiling key 取ELEMENTWISE_TPL_SCH_MODE_0对应浮点分支。5.3 Kernel 实现IOU 计算与掩码更新kernel 入口 nms_with_mask.cpp 以schMode模板参数分发float 场景实例化NsNMSWithMask::NMSWithMaskfloat依次执行Init与Process。核心算法位于 nms_with_mask.h 的IOU函数实现要点如下初始化先将 zLocal 全部置 1默认保留面积预计算通过GatherIdxAscendCGatherMask向量指令按列抽取每个框的x1/y1/x2/y2四个坐标Sub计算宽高Mul得到每个框的面积并存入 areaBuffer主循环i从 0 到scoresLength - 1若该框已被抑制掩码为 0直接continue若yLocal[i] scores_threshold说明从当前框开始含后续框置信度全部更低降序前提将i到末尾的掩码全部置 0 并break对保留框执行GatherIdx重新取回坐标用Duplicate将当前框坐标广播到向量寄存器通过Max/Min计算与每个后续框的重叠区间交宽、交高再做Max(..., 0)负值裁剪与Mul得到交集面积按公式IOU area_inter / (area_box1 area_box2 - area_inter)用Add/Sub/Div计算 IOU顺序遍历t i的后续框凡IOU iou_threshold者置掩码为 0。kernel 中注释特别指出由于向量And指令不支持 int8/uint8 类型掩码比较更新采用普通比较赋值方式逐框完成nms_with_mask.h。边界情况Process中若rawLength BOX_NEED_IDX即只有一个候选框BOX_NEED_IDX 4直接输出掩码 1不再进入流水线计算nms_with_mask.h数据搬运CopyIn将 GM 侧 x、y 数据拷入 Local TensorCopyOut通过DataCopyPad按scoresLength * sizeof(uint8_t)字节把掩码写回 GMnms_with_mask.h。从整体结构看该算子采用单队列单 bufferBUFFER_NUM 1、单核串行处理的实现策略逻辑清晰适合作为理解 NPU 上 NMS 类算子向量化实现的入门样例。六、调用说明基于 aclnnNMSWithMask 的两段式接口官方调用方式为aclnn 调用通过aclnnNMSWithMask接口执行 NMSWithMask 算子完整可运行样例见 test_aclnn_nms_with_mask.cpp。样例整体遵循 CANN aclnn 算子调用的标准流程初始化环境aclInit→aclrtSetDevice(deviceId)→aclrtCreateStream构造 TensoraclrtMalloc申请 device 内存aclrtMemcpy将 host 数据拷入aclCreateTensor创建aclTensorND 格式、连续 strides。样例构造了21 个候选框shape[21, 4]坐标与置信度均为降序排列的 float 数据输出 shape 为[21]、UINT8第一段接口Workspace 计算uint64_t workspaceSize 0; aclOpExecutor* executor; double iou_threshold 0.1; double socres_threshold 0.1; ret aclnnNMSWithMaskGetWorkspaceSize(selfX, selfY, iou_threshold, socres_threshold, out, workspaceSize, executor);申请 Workspace 内存若workspaceSize 0通过aclrtMalloc按该大小申请对应 tiling 中固定的 16MB 系统 workspace第二段接口执行ret aclnnNMSWithMask(workspaceAddr, workspaceSize, executor, stream);同步与取回结果aclrtSynchronizeStream等待执行完成aclrtMemcpyDEVICE_TO_HOST将掩码拷回 host逐元素打印result[i]资源释放aclDestroyTensor销毁 TensoraclrtFree释放 device 内存与 workspaceaclrtDestroyStream、aclrtResetDevice、aclFinalize收尾。该样例在PrintOutResult中以 UINT8 逐个打印掩码值读者可直接观察到哪些候选框被保留1、哪些被抑制0。注意样例中阈值变量名socres_threshold为scores_threshold的笔误实际传参位置对应 API 的置信度阈值入参。七、工程组织与文件结构NMSWithMask 算子遵循 ops-cv 仓库标准算子目录结构目录总览路径作用op_host/nms_with_mask_def.cpp算子定义与注册输入输出、属性、平台配置op_host/nms_with_mask_infershape.cpp输出 shape 推导op_host/nms_with_mask_tiling.cppTiling 计算、workspace 申请、shape/dtype 校验op_host/config/ascend910bopc 二进制算子配置json与 simplified key 配置iniop_kernel/nms_with_mask.cppKernel 入口模板分发op_kernel/nms_with_mask.hKernel 核心实现IOU 算法与流水线op_kernel/nms_with_mask_tiling_data.hTiling 数据结构定义op_kernel/nms_with_mask_tiling_key.hTiling key 模板参数声明examples/test_aclnn_nms_with_mask.cppaclnn 调用样例CMakeLists.txt算子目录构建入口ENABLE_TEST控制 tests 子目录是否参与构建八、使用建议与注意事项排序前提NMSWithMask 要求候选框已按置信度降序排列若输入顺序不满足请在上层先完成排序否则低置信度框可能抢先被保留导致结果错误数据类型严格使用 FLOAT32 输入 UINT8 输出避免踩中 tiling 层对非 float 输入的直接报错分支候选框规模单次调用候选框数 N 请控制在 2048 以内超出会触发 tiling 校验错误阈值语义iou_threshold控制重叠抑制的严格程度值越小抑制越激进scores_threshold控制低置信度框的整体过滤两者默认均为 0.1可按检测任务的 precision/recall 需求调整接口调用遵循aclnnNMSWithMaskGetWorkspaceSize→ 申请 workspace →aclnnNMSWithMask的两段式流程并记得在结束后释放 Tensor、workspace 与 device 资源完整写法可参考样例 test_aclnn_nms_with_mask.cpp掩码使用输出z是逐框的保留标记1/0上层需自行根据掩码从原始候选框数组中选择保留框这赋予了调用方更高的灵活性。综上NMSWithMask 以输出掩码这一独特形式为 NPU 上的目标检测后处理提供了轻量、可控的 NMS 能力配合 ops-cv 仓库提供的完整算子源码与 aclnn 样例开发者可以快速理解其原理并将其接入自己的检测推理流水线。【免费下载链接】ops-cv本项目是CANN提供的图像处理、目标检测相关的算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-cv创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表