| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
feat: support BoundingboxEncode ascend950 Co-authored-by: ugzhangyiyi<zhangyiyi4@huawei.com> # message auto-generated for no-merge-commit merge: !1049 merge master into master feat: support BoundingboxEncode ascend950 Created-by: ugzhangyiyi Commit-by: ugzhangyiyi Merged-by: cann-robot Description: ## 描述 本 MR 支持 bounding_box_encode 算子,适配 Ascend 950(arch35)平台。 ### 算子功能 计算锚框(anchor box)与真实边界框(ground truth box)之间的编码偏移量,生成目标检测回归目标。计算公式(含 +1 偏移,与 canndev 内置定义一致): pw = px2 - px1 + 1, ph = py2 - py1 + 1 pcx = (px1 + px2) * 0.5, pcy = (py1 + py2) * 0.5 dx = (gcx - pcx) / pw, dy = (gcy - pcy) / ph dw = ln(gw / pw), dh = ln(gh / ph) delta_i = (raw_i - means_i) / stds_i, i ∈ {x, y, w, h} ### 代码结构(commit dabe4550) | 层级 | 文件 | 说明 | |------|------|------| | **op_graph** | bounding_box_encode_proto.h | IR 原型定义:2 INPUT(anchor_box, ground_truth_box) + 2 ATTR(means/stds ListFloat) + 1 OUTPUT(delats),支持 FP16/FP32/BF16,与 canndev nn_detect_ops.h 内置定义保持一致 | | **op_host** | bounding_box_encode_def.cpp | OpDef 注册:Input/Output/Attr 声明,AICore 配置 ascend950,DynamicCompileStatic + DynamicRank + DynamicShape | | | bounding_box_encode_infershape.cpp | InferShape:输出 shape = 输入 shape(anchor_box shape 透传) | | | arch35/bounding_box_encode_tiling_arch35.cpp | Tiling 函数:从 attrs->GetListFloat(0/1) 读取 means/stds 属性,计算 invStds 写入 TilingData;UB 容量感知的 ubFactor 计算 + MAX_DATACOPY_BLOCKLEN(65535) 双重约束防 blockLen 截断 | | **op_kernel** | arch35/bounding_box_encode.h | Kernel 实现:FP16/BF16 输入 Cast→FP32 中间计算→Cast 回原 dtype;Scalar-Vector 交叉流水(S_V/V_S 同步 + FetchEventID);CopyIn/Compute/CopyOut 三级流水 + UB 分块循环 | | | arch35/bounding_box_encode_tiling_data.h | TilingData 结构:dim0/blockFactor/ubFactor + means0-3/invStds0-3(8 个 float) | | | bounding_box_encode_apt.cpp | Kernel 入口:2 input(anchorBox, groundTruthBox) + 1 output(delats),REGISTER_TILING_DEFAULT + GET_TILING_DATA_WITH_STRUCT | | **examples** | test_geir_bounding_box_encode.cpp | GEIR 通路示例:SetAttr("means"/"stds") 设置属性 | | **CMakeLists** | CMakeLists.txt | 算子构建配置:SUPPORT_COMPUTE_UNIT=ascend950, TILING_DIR=arch35 | | **docs** | README.md | 算子说明:功能/支持产品/数据类型/参数/约束 | | | docs/zh/op_list.md | 仓级算子清单条目 | ### 接口定义(与 canndev 一致) cpp // IR 原型(与 canndev nn_detect_ops.h 一致) REG_OP(BoundingBoxEncode) .INPUT(anchor_box, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(ground_truth_box, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(delats, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(means, ListFloat, {0.0, 0.0, 0.0, 0.0}) .ATTR(stds, ListFloat, {1.0, 1.0, 1.0, 1.0}) .OP_END_FACTORY_REG(BoundingBoxEncode) ### 关键设计决策 1. **means/stds 使用 ATTR 而非 INPUT**:与 canndev 内置定义保持一致,确保 GEIR 图模式通路兼容(避免 IR 兼容性检查冲突) 2. **DataCopyExtParams**:Kernel 使用 uint32_t blockLen 的 DataCopyExtParams,配合 tiling 侧 MAX_DATACOPY_BLOCKLEN 约束,防止大 UB 场景下 blockLen 截断 3. **+1 偏移**:pw = px2 - px1 + 1,与 canndev tbe 实现一致,保证宽高至少为 1 ## 关联的Issue https://gitcode.com/cann/ops-cv/issues/583 ## 测试 - 冒烟: 23091 - **UT 编译验证**:bash build.sh -u --ops=bounding_box_encode --soc=ascend950 --noexec,全部 target 编译通过(cv_op_host_ut / cv_op_api_ut / cv_op_kernel_ut) - tiling UT:5 例(fp32/fp16/empty/n1) - infershape UT:4 例(fp32/fp16/empty) - aclnn UT:4 例(nullptr/dtype/shape/mismatch 参数校验) - kernel UT:3 例(golden 计算:默认参数/非零参数/退化框) - **TTK 精度验证**:44/44 用例全部通过(fp16/fp32 × 多种 shape),通过率 100% - **GEIR 图模式验证**:test_geir_bounding_box_encode.cpp 执行 Session run ir compute graph success + Precision is ok ## 文档更新 - 新增 objdetect/bounding_box_encode/README.md:算子说明文档 - 更新 docs/zh/op_list.md:添加 bounding_box_encode 条目 ## 类型标签 - [ ] 🐛 Bug修复 - [x] ✨ 新特性 - [ ] ⚡ 性能优化 - [ ] ♻️ 重构 - [ ] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [x] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [ ] 🔒 安全修复 - [ ] 🧹 代码清理 - [ ] ❓ 其他,请描述: ## 重点说明 为了对齐原cann版本tbe接口,**其拼写错误**delats不进行修复,保持与原版一致。 See merge request: cann/ops-cv!1049 | 1 个月前 | |
fix(bounding_box_encode): add validations in geir path and inferdatatype Co-authored-by: ugzhangyiyi<zhangyiyi4@huawei.com> # message auto-generated for no-merge-commit merge: !1182 merge fix into master fix(bounding_box_encode): add validations in geir path and inferdatatype Created-by: ugzhangyiyi Commit-by: ugzhangyiyi Merged-by: cann-robot Description: 本 PR 针对 bounding_box_encode 算子的 geir(图模式)通路补齐了 5 条缺失的参数校验代码,并通过真实 NPU 负向测试矩阵验证了拦截有效性。 ### 问题背景 经静态分析和 NPU 实测发现,geir 通路的 InferShape/InferDataType 为空壳透传实现,README 中声明的 8 条约束仅有 2 条(dtype 集合、stds≠0)能被拦截,其余 5 条约束(dtype 一致性、shape[1]==4、shape 完全一致、rank==2、means/stds 长度==4)在代码中无任何校验逻辑,导致非法输入静默通过或越界读。 ### 修复方案 在 tiling 层(真实执行路径)补齐全部缺失校验: 1. **ParseMeansStds**:在读取 means[0..3] 和 stds[0..3] 前先调用 GetSize() 验证长度为 4,消除越界读风险 2. **CheckInputsConsistency**(新增函数):在 tiling 入口校验 anchor 与 groundtruth 的 dtype 一致性、rank==2、shape[1]==4、shape 完全相等 3. **InferShape4BoundingBoxEncode**:同步补齐 README 约束校验(注:geir 路径被内置 V1 proto 屏蔽,实际由 tiling 生效,但保留以对齐规范) ### 验证方法 构造 14 例负向/对照测试矩阵(覆盖全部 README 约束 + 边界情况),在真实 NPU 上以完整 AddGraph+RunGraph 流程执行 Before/After 对比: - **Before(基线)**:8 处 silent leak(shape[1]≠4、shape 不匹配、rank≠2、means/stds 长度异常静默通过或越界) - **After(修复后)**:未拦截项从 8 降至 1,仅 dtype 不一致因 FE 自动插入 Cast 节点统一类型的结构性限制无法在算子层拦截(已在报告中实证归因) ## 关联的Issue https://gitcode.com/cann/ops-cv/issues/650 ## 测试 ### 1. 负向拦截测试(NPU 真机) - **测试工程**:tests/geir_intercept/test_geir_intercept.cpp + run_intercept.sh - **测试矩阵**:14 例(控制 1 例 + 负向 13 例) - C0: 对照(全合法输入)→ 预期通过 ✅ - C1: anchor=fp16, gt=fp32(dtype 不一致)→ 结构性不可拦 ⚠️ - C2: dtype=int32(非法 dtype)→ 拦截 ✅ - C3/C4: shape=(N,3)/(N,8)(K≠4)→ 拦截 ✅ - C5: anchor=(10,4), gt=(8,4)(shape 不匹配)→ 拦截 ✅ - C6/C7: rank=1/rank=3(非 rank-2)→ 拦截 ✅ - C8/C9: means 长度=3/5(长度异常)→ 拦截 ✅ - C10/C11: stds 长度=3/5(长度异常)→ 拦截 ✅ - C12: stds=[0,1,1,1](含 0)→ 拦截 ✅ - C13/C14: 动态 shape/rank 正常情况 → 通过 ✅ - **结果**:13/14 达预期(C1 因 FE 框架层自动类型转换无法拦截,已归因) ### 2. 回归测试 - **白盒测试**:原有白盒用例全部通过(包括之前 shape[1]≠4 被误判为"正常"的用例,现在被正确拦截) - **ST 测试**:L0+L1+L2 用例覆盖度保持,正常用例精度不受影响 ### 3. 环境清理验证 - 确认修改后需清除 /root/atc_data/kernel_cache/* 以避免旧 tiling 行为残留 - 重编译+重装 vendors 包后负向用例拦截 100% 生效(除 C1) ## 文档更新 - **新增**:tests/geir_intercept/INTERCEPT_REPORT.md(Before/After 对照 + 根因分析 + 修改清单) - **新增**:tests/geir_intercept/test_geir_intercept.cpp(负向测试工程源码) - **新增**:tests/geir_intercept/run_intercept.sh(NPU 编译执行脚本) ## 类型标签 - [x] 🐛 Bug修复 - [ ] ✨ 新特性 - [ ] ⚡ 性能优化 - [ ] ♻️ 重构 - [x] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [ ] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [x] 🔒 安全修复 - [ ] 🧹 代码清理 - [ ] ❓ 其他,请描述: See merge request: cann/ops-cv!1182 | 23 天前 | |
修复日志质量扫描发现不合理日志 Co-authored-by: liu-wei<lovline.liuwei@huawei.com> # message auto-generated for no-merge-commit merge: !1297 merge master_log_fix into master 修复日志质量扫描发现不合理日志 Created-by: liu-wei Commit-by: liu-wei Merged-by: cann-robot Description: Closes #750 ## 描述 修复日志质量扫描发现的不合理日志,统一日志风格和代码格式。共 44 个文件,均为非功能性修改。 ### 修复类型 | 类型 | 示例 | 文件数 | |------|------|--------| | 日志文案规范化 | "set tiling data error" → "Failed to set tiling data" | 20+ | | 日志换行修复 | 字符串中嵌入 \n 的多行日志 → 单行 | 3 | | 代码格式对齐 | clang-format 缩进/换行统一 | 15+ | | License 头标准化 | HIT OpenBOAT 头 → 标准 CANN License 头 | 2 | | 多余空行清理 | 连续 2 个空行 → 1 个 | 2 | ### 涉及文件(按模块) | 模块 | 文件数 | |------|--------| | experimental/image | 4 | | experimental/objdetect | 1 | | image/ 各算子 tiling | 20+ | | image/ aicpu kernel | 4 | | objdetect/ | 8 | | common/ | 2 | | examples/ | 1 | ### 功能影响 纯日志文案和代码格式修改,无任何逻辑变更。 ## 关联的Issue ## 测试 ## 文档更新 ## 类型标签 - [ ] 🐛 Bug修复 - [ ] ✨ 新特性 - [ ] ⚡ 性能优化 - [ ] ♻️ 重构 - [ ] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [ ] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [ ] 🔒 安全修复 - [x] 🧹 代码清理 - [ ] ❓ 其他,请描述: See merge request: cann/ops-cv!1297 | 5 天前 | |
fix(bounding_box_encode): fix precision tolerance mapping(extreme mismatched ranges) & add validations in geir path and inferdatatype Co-authored-by: ugzhangyiyi<zhangyiyi4@huawei.com> # message auto-generated for no-merge-commit merge: !1260 merge bbe into master fix(bounding_box_encode): fix precision tolerance mapping(extreme mismatched ranges) & add validations in geir path and inferdatatype Created-by: ugzhangyiyi Commit-by: ugzhangyiyi Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> 本次提交修复了 BoundingBoxEncode kernel 在处理极端或失配坐标范围的边界框(例如 anchor 坐标接近 FP32 最大值 ~3.4e38、ground-truth 坐标 ~0.01)时的精度问题。该场景下 rw = gw / pw 会下溢趋近于零,触发 NPU 硬件 Ln 指令返回 -inf 而非有限负数值。 **根因:** NPU AscendC::Ln 硬件指令对极小正数输入(接近 FP32 下溢阈值 ~1e-38)返回 -inf,而 CPU numpy.log 与 GPU cuda::log 能正确返回有限值(如 log(1e-30) ≈ -69.07)。原始 kernel 在 FP16 和 FP32 两条计算路径中均直接消费 Ln 原始输出,当 rw/rh 下溢时,编码后的 dw/dh 变为 -inf,经 (dw - means) / stds 归一化后输出包含 -inf 或 NaN,导致与 CPU golden 的精度比对失败。 **修复方法 — 在 BoxDeltaCalc 中新增 FixLnResult + SoftLnPositive 兜底逻辑:** 1. FixLnResult(origInput, npuLnResult) —— 后处理守卫函数,同时检查原始输入和 NPU Ln 结果: - origInput 为 NaN → 返回 NaN(符合 IEEE 754) - origInput == 0.0 → 返回 -inf(符合 log(0)) - origInput < 0.0 → 返回 NaN(符合 log(负数)) - npuLnResult 为 NaN → 返回 NaN(传播硬件错误) - npuLnResult == -inf && origInput > 0.0 → 转入 SoftLnPositive 软件兜底(核心修复点) - 其余情况 → 原样返回 npuLnResult(正常路径,零开销) 2. SoftLnPositive(x) —— 针对 -inf 兜底场景的软件 ln 实现,采用 atanh 泰勒级数: - 将 x 归一化为尾数 m ∈ [1, 2) 和指数 e(通过反复乘/除 2 实现) - 计算 z = (m - 1) / (m + 1),再算 atanh(z) ≈ z * (1 + z²/3 + z⁴/5 + z⁶/7 + z⁸/9 + z¹⁰/11) - 返回 2 * atanh(z) + e * ln(2),其中 ln(2) = 0.69314718 3. ComputeFp16Path 和 ComputeFp32Path 同步更新:dw/dh 计算改为先从 buffer 读取原始 rw/rh,经 FixLnResult 处理后再做 (lnRw - means) / stds 归一化,替换原先直接消费 buf2.GetValue(base+2) 的方式。 **影响范围:** 正常值域(rw ∈ [0.5, 2.0])不受影响 —— FixLnResult 原样透传硬件 Ln 结果,行为零变化。该修复仅在硬件会产出 -inf 的退化输入场景下激活,使 NPU 输出与 CPU/GPU 行为对齐。 ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。例如:关联Issue #000--> https://gitcode.com/cann/ops-cv/issues/734 ## 测试 <!--描述进行了哪些测试来验证你的改动。--> - **GEIR 静态测试**(test_geir_bounding_box_encode):FP32 (2,4) 单节点图编译 + NPU 执行 —— **PASS** - **GEIR 动态 Shape 测试**(test_geir_bounding_box_encode_dynamic):[-1,-1] 5 种 shape + [-2](unknown rank)5 种 shape —— **10/10 PASS** - **GEIR 负向拦截测试**(test_geir_intercept):14 例矩阵(合法/非法 dtype、shape、rank、means/stds 长度、stds=0)—— **13/14 PASS**(1 例结构性不可拦截:dtype 不一致被内置 proto V1 InferShape 屏蔽 + FE 自动插 Cast) - **NPU Ln 行为验证**:确认 FixLnResult 正确将 rw=1e-30 路由至 SoftLnPositive,产出 ≈ -69.07 与 CPU numpy.log(1e-30) 一致;正常 rw=1.07 原样透传硬件 Ln,误差 ≤ 3.3e-7 ## 类型标签 <!-- [x] 表示选中 --> - [x] Bug修复 - [ ] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-cv!1260 | 6 天前 | |
feat: support BoundingboxEncode ascend950 Co-authored-by: ugzhangyiyi<zhangyiyi4@huawei.com> # message auto-generated for no-merge-commit merge: !1049 merge master into master feat: support BoundingboxEncode ascend950 Created-by: ugzhangyiyi Commit-by: ugzhangyiyi Merged-by: cann-robot Description: ## 描述 本 MR 支持 bounding_box_encode 算子,适配 Ascend 950(arch35)平台。 ### 算子功能 计算锚框(anchor box)与真实边界框(ground truth box)之间的编码偏移量,生成目标检测回归目标。计算公式(含 +1 偏移,与 canndev 内置定义一致): pw = px2 - px1 + 1, ph = py2 - py1 + 1 pcx = (px1 + px2) * 0.5, pcy = (py1 + py2) * 0.5 dx = (gcx - pcx) / pw, dy = (gcy - pcy) / ph dw = ln(gw / pw), dh = ln(gh / ph) delta_i = (raw_i - means_i) / stds_i, i ∈ {x, y, w, h} ### 代码结构(commit dabe4550) | 层级 | 文件 | 说明 | |------|------|------| | **op_graph** | bounding_box_encode_proto.h | IR 原型定义:2 INPUT(anchor_box, ground_truth_box) + 2 ATTR(means/stds ListFloat) + 1 OUTPUT(delats),支持 FP16/FP32/BF16,与 canndev nn_detect_ops.h 内置定义保持一致 | | **op_host** | bounding_box_encode_def.cpp | OpDef 注册:Input/Output/Attr 声明,AICore 配置 ascend950,DynamicCompileStatic + DynamicRank + DynamicShape | | | bounding_box_encode_infershape.cpp | InferShape:输出 shape = 输入 shape(anchor_box shape 透传) | | | arch35/bounding_box_encode_tiling_arch35.cpp | Tiling 函数:从 attrs->GetListFloat(0/1) 读取 means/stds 属性,计算 invStds 写入 TilingData;UB 容量感知的 ubFactor 计算 + MAX_DATACOPY_BLOCKLEN(65535) 双重约束防 blockLen 截断 | | **op_kernel** | arch35/bounding_box_encode.h | Kernel 实现:FP16/BF16 输入 Cast→FP32 中间计算→Cast 回原 dtype;Scalar-Vector 交叉流水(S_V/V_S 同步 + FetchEventID);CopyIn/Compute/CopyOut 三级流水 + UB 分块循环 | | | arch35/bounding_box_encode_tiling_data.h | TilingData 结构:dim0/blockFactor/ubFactor + means0-3/invStds0-3(8 个 float) | | | bounding_box_encode_apt.cpp | Kernel 入口:2 input(anchorBox, groundTruthBox) + 1 output(delats),REGISTER_TILING_DEFAULT + GET_TILING_DATA_WITH_STRUCT | | **examples** | test_geir_bounding_box_encode.cpp | GEIR 通路示例:SetAttr("means"/"stds") 设置属性 | | **CMakeLists** | CMakeLists.txt | 算子构建配置:SUPPORT_COMPUTE_UNIT=ascend950, TILING_DIR=arch35 | | **docs** | README.md | 算子说明:功能/支持产品/数据类型/参数/约束 | | | docs/zh/op_list.md | 仓级算子清单条目 | ### 接口定义(与 canndev 一致) cpp // IR 原型(与 canndev nn_detect_ops.h 一致) REG_OP(BoundingBoxEncode) .INPUT(anchor_box, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(ground_truth_box, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(delats, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(means, ListFloat, {0.0, 0.0, 0.0, 0.0}) .ATTR(stds, ListFloat, {1.0, 1.0, 1.0, 1.0}) .OP_END_FACTORY_REG(BoundingBoxEncode) ### 关键设计决策 1. **means/stds 使用 ATTR 而非 INPUT**:与 canndev 内置定义保持一致,确保 GEIR 图模式通路兼容(避免 IR 兼容性检查冲突) 2. **DataCopyExtParams**:Kernel 使用 uint32_t blockLen 的 DataCopyExtParams,配合 tiling 侧 MAX_DATACOPY_BLOCKLEN 约束,防止大 UB 场景下 blockLen 截断 3. **+1 偏移**:pw = px2 - px1 + 1,与 canndev tbe 实现一致,保证宽高至少为 1 ## 关联的Issue https://gitcode.com/cann/ops-cv/issues/583 ## 测试 - 冒烟: 23091 - **UT 编译验证**:bash build.sh -u --ops=bounding_box_encode --soc=ascend950 --noexec,全部 target 编译通过(cv_op_host_ut / cv_op_api_ut / cv_op_kernel_ut) - tiling UT:5 例(fp32/fp16/empty/n1) - infershape UT:4 例(fp32/fp16/empty) - aclnn UT:4 例(nullptr/dtype/shape/mismatch 参数校验) - kernel UT:3 例(golden 计算:默认参数/非零参数/退化框) - **TTK 精度验证**:44/44 用例全部通过(fp16/fp32 × 多种 shape),通过率 100% - **GEIR 图模式验证**:test_geir_bounding_box_encode.cpp 执行 Session run ir compute graph success + Precision is ok ## 文档更新 - 新增 objdetect/bounding_box_encode/README.md:算子说明文档 - 更新 docs/zh/op_list.md:添加 bounding_box_encode 条目 ## 类型标签 - [ ] 🐛 Bug修复 - [x] ✨ 新特性 - [ ] ⚡ 性能优化 - [ ] ♻️ 重构 - [ ] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [x] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [ ] 🔒 安全修复 - [ ] 🧹 代码清理 - [ ] ❓ 其他,请描述: ## 重点说明 为了对齐原cann版本tbe接口,**其拼写错误**delats不进行修复,保持与原版一致。 See merge request: cann/ops-cv!1049 | 1 个月前 | |
feat: support BoundingboxEncode ascend950 Co-authored-by: ugzhangyiyi<zhangyiyi4@huawei.com> # message auto-generated for no-merge-commit merge: !1049 merge master into master feat: support BoundingboxEncode ascend950 Created-by: ugzhangyiyi Commit-by: ugzhangyiyi Merged-by: cann-robot Description: ## 描述 本 MR 支持 bounding_box_encode 算子,适配 Ascend 950(arch35)平台。 ### 算子功能 计算锚框(anchor box)与真实边界框(ground truth box)之间的编码偏移量,生成目标检测回归目标。计算公式(含 +1 偏移,与 canndev 内置定义一致): pw = px2 - px1 + 1, ph = py2 - py1 + 1 pcx = (px1 + px2) * 0.5, pcy = (py1 + py2) * 0.5 dx = (gcx - pcx) / pw, dy = (gcy - pcy) / ph dw = ln(gw / pw), dh = ln(gh / ph) delta_i = (raw_i - means_i) / stds_i, i ∈ {x, y, w, h} ### 代码结构(commit dabe4550) | 层级 | 文件 | 说明 | |------|------|------| | **op_graph** | bounding_box_encode_proto.h | IR 原型定义:2 INPUT(anchor_box, ground_truth_box) + 2 ATTR(means/stds ListFloat) + 1 OUTPUT(delats),支持 FP16/FP32/BF16,与 canndev nn_detect_ops.h 内置定义保持一致 | | **op_host** | bounding_box_encode_def.cpp | OpDef 注册:Input/Output/Attr 声明,AICore 配置 ascend950,DynamicCompileStatic + DynamicRank + DynamicShape | | | bounding_box_encode_infershape.cpp | InferShape:输出 shape = 输入 shape(anchor_box shape 透传) | | | arch35/bounding_box_encode_tiling_arch35.cpp | Tiling 函数:从 attrs->GetListFloat(0/1) 读取 means/stds 属性,计算 invStds 写入 TilingData;UB 容量感知的 ubFactor 计算 + MAX_DATACOPY_BLOCKLEN(65535) 双重约束防 blockLen 截断 | | **op_kernel** | arch35/bounding_box_encode.h | Kernel 实现:FP16/BF16 输入 Cast→FP32 中间计算→Cast 回原 dtype;Scalar-Vector 交叉流水(S_V/V_S 同步 + FetchEventID);CopyIn/Compute/CopyOut 三级流水 + UB 分块循环 | | | arch35/bounding_box_encode_tiling_data.h | TilingData 结构:dim0/blockFactor/ubFactor + means0-3/invStds0-3(8 个 float) | | | bounding_box_encode_apt.cpp | Kernel 入口:2 input(anchorBox, groundTruthBox) + 1 output(delats),REGISTER_TILING_DEFAULT + GET_TILING_DATA_WITH_STRUCT | | **examples** | test_geir_bounding_box_encode.cpp | GEIR 通路示例:SetAttr("means"/"stds") 设置属性 | | **CMakeLists** | CMakeLists.txt | 算子构建配置:SUPPORT_COMPUTE_UNIT=ascend950, TILING_DIR=arch35 | | **docs** | README.md | 算子说明:功能/支持产品/数据类型/参数/约束 | | | docs/zh/op_list.md | 仓级算子清单条目 | ### 接口定义(与 canndev 一致) cpp // IR 原型(与 canndev nn_detect_ops.h 一致) REG_OP(BoundingBoxEncode) .INPUT(anchor_box, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(ground_truth_box, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(delats, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(means, ListFloat, {0.0, 0.0, 0.0, 0.0}) .ATTR(stds, ListFloat, {1.0, 1.0, 1.0, 1.0}) .OP_END_FACTORY_REG(BoundingBoxEncode) ### 关键设计决策 1. **means/stds 使用 ATTR 而非 INPUT**:与 canndev 内置定义保持一致,确保 GEIR 图模式通路兼容(避免 IR 兼容性检查冲突) 2. **DataCopyExtParams**:Kernel 使用 uint32_t blockLen 的 DataCopyExtParams,配合 tiling 侧 MAX_DATACOPY_BLOCKLEN 约束,防止大 UB 场景下 blockLen 截断 3. **+1 偏移**:pw = px2 - px1 + 1,与 canndev tbe 实现一致,保证宽高至少为 1 ## 关联的Issue https://gitcode.com/cann/ops-cv/issues/583 ## 测试 - 冒烟: 23091 - **UT 编译验证**:bash build.sh -u --ops=bounding_box_encode --soc=ascend950 --noexec,全部 target 编译通过(cv_op_host_ut / cv_op_api_ut / cv_op_kernel_ut) - tiling UT:5 例(fp32/fp16/empty/n1) - infershape UT:4 例(fp32/fp16/empty) - aclnn UT:4 例(nullptr/dtype/shape/mismatch 参数校验) - kernel UT:3 例(golden 计算:默认参数/非零参数/退化框) - **TTK 精度验证**:44/44 用例全部通过(fp16/fp32 × 多种 shape),通过率 100% - **GEIR 图模式验证**:test_geir_bounding_box_encode.cpp 执行 Session run ir compute graph success + Precision is ok ## 文档更新 - 新增 objdetect/bounding_box_encode/README.md:算子说明文档 - 更新 docs/zh/op_list.md:添加 bounding_box_encode 条目 ## 类型标签 - [ ] 🐛 Bug修复 - [x] ✨ 新特性 - [ ] ⚡ 性能优化 - [ ] ♻️ 重构 - [ ] 🧪 测试 - [ ] 📦 构建/CI - [ ] 🔧 配置变更 - [x] 📝 文档更新 - [ ] ⬆️ 依赖升级 - [ ] 🔒 安全修复 - [ ] 🧹 代码清理 - [ ] ❓ 其他,请描述: ## 重点说明 为了对齐原cann版本tbe接口,**其拼写错误**delats不进行修复,保持与原版一致。 See merge request: cann/ops-cv!1049 | 1 个月前 |
BoundingBoxEncode
产品支持情况
| 产品 | 是否支持 |
|---|---|
| Ascend 950PR/Ascend 950DT | √ |
| Atlas A3 训练系列产品/Atlas A3 推理系列产品 | √ |
| Atlas A2 训练系列产品/Atlas A2 推理系列产品 | √ |
| Atlas 200I/500 A2 推理产品 | × |
| Atlas 推理系列产品 | × |
| Atlas 训练系列产品 | × |
功能说明
-
算子功能:计算锚框(anchor box)与真实边界框(ground truth box)之间的编码偏移量,生成目标检测回归目标。
-
计算公式:
先将输入坐标 (x1,y1,x2,y2)(x_1, y_1, x_2, y_2)(x1,y1,x2,y2) 转换为中心点+宽高格式:
cx=(x1+x2)/2,cy=(y1+y2)/2,w=x2−x1+1,h=y2−y1+1cx = (x_1 + x_2) / 2, \quad cy = (y_1 + y_2) / 2, \quad w = x_2 - x_1 + 1, \quad h = y_2 - y_1 + 1 cx=(x1+x2)/2,cy=(y1+y2)/2,w=x2−x1+1,h=y2−y1+1
再计算编码偏移量:
dx=gcx−pcxpw,dy=gcy−pcyph,dw=ln(gwpw),dh=ln(ghph)dx = \frac{g_{cx} - p_{cx}}{p_w}, \quad dy = \frac{g_{cy} - p_{cy}}{p_h}, \quad dw = \ln\left(\frac{g_w}{p_w}\right), \quad dh = \ln\left(\frac{g_h}{p_h}\right) dx=pwgcx−pcx,dy=phgcy−pcy,dw=ln(pwgw),dh=ln(phgh)
最后做均值标准化:
δi=rawi−meansistdsi,i∈{0,1,2,3}\delta_i = \frac{raw_i - means_i}{stds_i}, \quad i \in \{0,1,2,3\} δi=stdsirawi−meansi,i∈{0,1,2,3}
其中ppp为anchor_box对应值,ggg为ground_truth_box对应值。
参数说明
| 参数名 | 输入/输出/属性 | 描述 | 数据类型 | 数据格式 |
|---|---|---|---|---|
| anchor_box | 输入 | 锚框坐标张量,坐标格式为(x1, y1, x2, y2)。数据类型需与ground_truth_box一致。 | FLOAT16、FLOAT | ND |
| ground_truth_box | 输入 | 真实边界框坐标张量,坐标格式为(x1, y1, x2, y2)。数据类型和shape需与anchor_box一致。 | FLOAT16、FLOAT | ND |
| means | 属性 | 编码均值偏移量,长度为4。默认值为[0.0, 0.0, 0.0, 0.0]。 | ListFloat | - |
| stds | 属性 | 编码标准差缩放量,长度为4,各元素不可为0。默认值为[1.0, 1.0, 1.0, 1.0]。 | ListFloat | - |
| delats | 输出 | 编码偏移量输出张量。数据类型与anchor_box一致,shape与anchor_box相同。 | FLOAT16、FLOAT | ND |
约束说明
- anchor_box和ground_truth_box的数据类型必须相同,支持float16和float32。
- anchor_box和ground_truth_box的shape必须完全一致,均为(N, 4)。
- means和stds的长度必须为4,stds各元素不可为0。
- 坐标格式为标准(x1, y1, x2, y2)格式,即左上角和右下角坐标。
- 公式中宽高计算包含+1偏移(w = x2 - x1 + 1, h = y2 - y1 + 1),保证宽高至少为1,防止除零。
- 支持空Tensor(N=0时返回空输出)。
调用说明
| 调用方式 | 样例代码 | 说明 |
|---|---|---|
| 图模式 | test_geir_bounding_box_encode | 通过算子IR构图方式调用BoundingBoxEncode算子。 |