计算机视觉人工智能【免费下载链接】sahiFramework agnostic sliced/tiled inference interactive ui error analysis plots项目地址https://gitcode.com/gh_mirrors/sa/sahi点击查看免费下载本篇技术指南以 docs/zh/postprocess/combine.md 为骨架系统讲解 SAHI 在切片推理Sliced Inference之后如何通过sahi.postprocess.combine模块合并或抑制重复检测结果。你将掌握nms、greedy_nmm、nmm三组函数级 API 与NMSPostprocess、NMMPostprocess、GreedyNMMPostprocess类级 API 的完整用法理解 IOU/IOS 两种匹配指标的差异学会通过get_sliced_prediction的后处理参数与 numpy/numba/torchvision 后端调度进行实战调优并能读懂底层源码与测试用例。一、为什么切片推理需要合并后处理SAHI 的核心工作流是切图 → 逐切片推理 → 结果映射回原图 → 合并去重。由于相邻切片之间存在重叠区域如overlap_height_ratio0.2、overlap_width_ratio0.2同一个目标物体通常会在多个切片中被重复检测到产生大量近乎重合的边界框。此外perform_standard_predTrue时还会额外对整幅图像做一次标准推理进一步叠加重复检测。因此get_sliced_prediction在收集完所有切片的预测后必须执行一次后处理来消除重复。这一步骤正是由 sahi/postprocess/combine.py 中的后处理策略完成的。从源码看get_sliced_prediction会在推理结束后调用postprocess(object_prediction_list)见 sahi/predict.py把全部检测结果压缩为最终输出。二、核心 API 一览函数级与类级sahi.postprocess.combine同时提供两类接口直接操作(N, 6)numpy 数组的函数级 API以及操作ObjectPrediction对象列表的类级 API。2.1 统一的数组约定所有函数级 API 共享同一输入约定形状为(N, 6)的 numpy 数组列顺序为[x1, y1, x2, y2, score, category_id]其中坐标采用xyxy左上角 右下角格式。这一约定由 sahi/postprocess/utils.py 中的object_prediction_list_to_numpy定义——它会把ObjectPrediction的bbox.to_xyxy()、score.value和category.id依次填入数组。2.2 函数级 APInms / greedy_nmm / nmm 及其 batched 变体combine 模块共导出 6 个函数按语义分为抑制型返回保留索引列表与合并型返回保留索引到被合并索引的映射函数语义返回值类型nms(predictions, match_metricIOU, match_threshold0.5)非极大值抑制保留重叠框中分数最高的丢弃其余list[int]按分数降序的保留索引batched_nms(...)按类别分别执行 NMSlist[int]greedy_nmm(...)贪心非极大值合并每个保留框只合并与其直接重叠的框dict[int, list[int]]batched_greedy_nmm(...)按类别分别执行贪心 NMMdict[int, list[int]]nmm(...)非极大值合并传递式A 合并 B、B 合并 C 时A 会获得全部三个框dict[int, list[int]]batched_nmm(...)按类别分别执行传递式 NMMdict[int, list[int]]直接使用示例源自 docs/zh/postprocess/backends.mdimport numpy as np from sahi.postprocess.combine import nms, batched_nms, greedy_nmm, nmm, batched_greedy_nmm predictions np.array([ [100, 100, 200, 200, 0.95, 0], [105, 105, 205, 205, 0.80, 0], [300, 300, 400, 400, 0.90, 1], ]) # 全局 NMS所有类别一起参与比较 keep nms(predictions, match_metricIOU, match_threshold0.5) print(predictions[keep]) # 按类别执行 NMS类别 0 与类别 1 分别独立处理 keep batched_nms(predictions, match_metricIOU, match_threshold0.5) print(predictions[keep]) # 贪心 NMM{kept_index: [merged_index, ...], ...} keep_to_merge greedy_nmm(predictions, match_metricIOU, match_threshold0.5) # 完整 NMM传递式合并 keep_to_merge nmm(predictions, match_metricIOU, match_threshold0.5) # 按类别执行贪心 NMM keep_to_merge batched_greedy_nmm(predictions, match_threshold0.5)实现细节sahi/postprocess/combine.pynms/greedy_nmm/nmm三个全局函数直接通过后端分发执行batched_*变体则经由_batched_applycombine.py按category_id分组对每个类别独立调用对应函数再把局部索引映射回全局索引。注意batched_greedy_nmm与batched_nmm对空输入返回{}batched_nms对空输入返回[]有专门的边界测试覆盖见下文。2.3 类级 APIPostprocessPredictions 及其子类类级 API 直接与 SAHI 的ObjectPrediction列表集成是get_sliced_prediction内部使用的形态。所有类继承自抽象基类PostprocessPredictionscombine.py构造函数统一接收三个参数参数类型默认值含义match_thresholdfloat0.5判定两个预测匹配的最小重叠度IoU 或 IoSmatch_metricstrIOU重叠指标IOU或IOSclass_agnosticboolTrue为True时跨类别统一后处理为False时按类别独立处理四个具体实现NMSPostprocess保留最高分框、丢弃重叠框不合并边界框或掩码combine.pyNMMPostprocess传递式非极大值合并会合并边界框、掩码与分数combine.pyGreedyNMMPostprocess贪心版本每个保留框只合并与其直接重叠的框无传递合并速度更快、合并出的框更紧凑combine.pyLSNMSPostprocess基于lsnms包的空间索引 NMS适合大量预测仅支持 IOU 指标且标注为实验性、不建议生产使用combine.py。类级用法示例from sahi.postprocess.combine import NMSPostprocess, NMMPostprocess, GreedyNMMPostprocess # NMS保留最佳边界框丢弃其余 postprocessor NMSPostprocess( match_threshold0.5, match_metricIOU, class_agnosticTrue, # False 表示按类别处理 ) filtered postprocessor(object_prediction_list) # 贪心 NMM合并重叠边界框速度快 postprocessor GreedyNMMPostprocess(match_threshold0.5) merged postprocessor(object_prediction_list) # 完整 NMM传递式合并 postprocessor NMMPostprocess(match_threshold0.5) merged postprocessor(object_prediction_list)传入class_agnosticFalse后每个后处理器都会按类别独立运行因此car的预测不会抑制person的预测。需要安装LSNMSPostprocess时执行pip install lsnms0.3.1若match_metric设为IOS该类会抛出NotImplementedError。三、三种合并策略的语义差异理解三种策略的区别是调参的前提NMS抑制按分数从高到低遍历保留当前最高分框把与之重叠度 ≥ 阈值的所有框标记为被抑制并丢弃。最终输出是一组互不重叠的独立检测框。GreedyNMM贪心合并同样按分数遍历但重叠框不是被丢弃而是被合并进保留框。合并后的边界框变为两框的最小外接包围盒union分数取两者最大值类别取分数更高的一方。由于只考虑直接相邻的框它不会把间接重叠的检测连成一条。NMM传递合并在贪心的基础上支持传递性——如果 A 与 B 重叠、B 与 C 重叠即使 A 与 C 不直接重叠三者也会被合并为一组。这在目标被切成多个碎片、且碎片之间形成链式重叠时非常有用。从源码看合并的具体规则由 sahi/postprocess/utils.py 中的merge_object_prediction_pair定义边界框取 unioncalculate_box_union、分数取最大值get_merged_score、类别取分数较高的预测get_merged_category、掩码则做几何并集get_merged_mask通过 shapely 的buffer(0)修复无效多边形后取union。需要特别注意的是匹配阈值是包含边界的源码中使用metric match_threshold判定匹配。测试 tests/test_combine.py 专门验证了重叠度恰好等于阈值 0.5 的框会被合并而不是被丢弃这一行为。四、指标选择IOU 与 IOSNMS 与 NMM 都支持两种重叠指标IOUIntersection over Union交集面积 / 并集面积。标准指标合并行为相对保守。两个完全一样的框 IoU1.0不重叠则为 0。IOSIntersection over Smaller交集面积 /较小框面积。当目标尺寸差异悬殊时非常实用——例如一个小框完全落在一个大框内部IoU 可能只有约 1%交集/大框面积远低于 0.5 阈值两者都会保留而 IoS 是 100%交集/小框面积小框会被正确抑制或合并。测试用例 TestIOSMetric 用[0,0,100,100]的大框与[10,10,20,20]的小框精确复现了这一差异IOU下两个框都保留len(keep_iou) 2IOS下小框被抑制len(keep_ios) 1。调用方式# IOS 指标一个框远小于另一个框时更激进 keep nms(predictions, match_metricIOS, match_threshold0.5)正因如此get_sliced_prediction的默认postprocess_match_metric是IOS见 sahi/predict.py因为切片推理产生的重复框往往是同一目标被部分切片切到尺寸差异较大IOS 能更彻底地消除重复。五、与 get_sliced_prediction 的集成在完整推理流程中你不需要手动构造后处理器——通过get_sliced_prediction的后处理参数即可控制合并行为sahi/predict.py参数默认值说明postprocess_typeGREEDYNMM可选NMS、NMM、GREEDYNMM、LSNMSpostprocess_match_metricIOSIOU或IOSpostprocess_match_threshold0.5匹配阈值值越小合并越积极postprocess_class_agnosticFalse为True时后处理忽略类别 IDforce_postprocess_typeFalse为True时禁用下述自动切换逻辑完整示例from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction detection_model AutoDetectionModel.from_pretrained( model_typeultralytics, model_pathyolo26n.pt, confidence_threshold0.25, devicecuda:0, ) result get_sliced_prediction( image.jpg, detection_model, slice_height512, slice_width512, overlap_height_ratio0.2, overlap_width_ratio0.2, postprocess_typeGREEDYNMM, # 默认 postprocess_match_metricIOS, # 默认 postprocess_match_threshold0.5, postprocess_class_agnosticFalse, )get_sliced_prediction内部通过POSTPROCESS_NAME_TO_CLASS注册表predict.py把字符串映射为后处理类并实例化后应用到预测列表。源码中还有两条自动切换逻辑值得注意predict.py低置信度保护当模型confidence_threshold 0.1常量LOW_MODEL_CONFIDENCE见 predict.py且未强制指定后处理类型时会把postprocess_type强制切换为NMS、指标切换为IOU并打印警告。原因是低置信度下会产生大量小分数框合并类后处理容易把噪声也合并进来。OBB 限制当检测模型是UltralyticsDetectionModel且输出为旋转框is_obb时强制使用NMS——旋转框目前只支持 NMS 抑制。若不想被上述逻辑干扰可传入force_postprocess_typeTrue。此外在低内存场景可设置merge_buffer_length当收集到的预测超过该长度时会先执行一次后处理predict.py实现流式合并代价是可能轻微影响 AP。命令行CLI同样暴露了这些参数参见 docs/zh/cli.md--postprocess_type GREEDYNMM默认、--postprocess_match_metric IOS默认、--postprocess_match_threshold 0.5、--postprocess_class_agnostic。六、后端调度numpy / numba / torchvisionNMS/NMM 的计算可以在三种可互换的后端上运行选择取决于硬件与已安装的包详见 后处理后端后端适用场景额外依赖numpy仅 CPU预测结果数量较少或中等无始终可用numbaCPU 且预测结果数量较多首次调用约 1 秒 JIT 预热之后较快pip install numbatorchvisionCUDA 或 Apple MPS GPU 可用处理大型批次时最快pip install torch torchvision默认采用自动检测sahi/postprocess/backends.py优先级为torchvision已安装且存在 CUDA 或 Apple MPS GPU→ numba已安装→ numpy兜底。解析结果会被缓存可通过以下方式查看或强制指定from sahi.postprocess.backends import get_postprocess_backend, set_postprocess_backend # 检查解析出的后端触发自动检测 print(get_postprocess_backend()) # 首次执行后处理操作前为 auto # 强制使用纯 numpy无额外依赖可在所有环境中运行 set_postprocess_backend(numpy) # 强制使用 numba JIT set_postprocess_backend(numba) # 强制使用 torchvision GPU set_postprocess_backend(torchvision) # 恢复自动检测 set_postprocess_backend(auto)该调用会影响当前进程中后续所有NMS/NMM 操作包括get_sliced_prediction内部触发的操作。从源码看set_postprocess_backend还会清空 combine 模块的_dispatch_cachebackends.py确保下一次调用重新解析函数。combine.py的分发机制是一个两级查表combine.py_BACKEND_MODULE_MAP把后端名映射到模块路径sahi.postprocess._numpy_backend、sahi.postprocess._numba_backend、sahi.postprocess._torchvision_backend_FUNC_NAME_MAP再把操作类型nms/greedy_nmm/nmm映射到具体函数名最终通过importlib.import_module动态加载并按(backend, func_type)缓存结果。七、底层实现原理源码级7.1 从 ObjectPrediction 到 (N, 6) 数组类级后处理器先把ObjectPrediction列表包装为ObjectPredictionListutils.py调用tonumpy()转为(N, 6)数组再交给函数级 API得到保留/合并索引后用object_prediction_list[keep]按索引取回预测对象。ObjectPredictionList支持整数、列表以及类张量tolist()可调用的对象作为索引兼容 numpy 数组与 torch 张量返回的索引。7.2 密集矩阵、稀疏路径与流式路径numpy 后端sahi/postprocess/_numpy_backend.py默认用向量化的广播计算N×N两两重叠矩阵compute_metric_matrixL36-L68超过_MAX_FULL_MATRIX 8000时按行分批计算以控制中间变量内存。随后在矩阵上跑贪心循环NMS 用nms_from_matrixL227-L248、Greedy NMM 用greedy_nmm_from_matrixL251-L288、NMM 用nmm_from_matrixL291-L367预先构建支配关系矩阵实现传递合并记账。对于大规模输入sahi/postprocess/_sparse_backend.py 提供了更省内存的路径SPARSE_MIN_BOXES 2000表示低于该数量时密集矩阵更划算STRtree 的构建成本超过省下的矩阵当平均邻居数超过NMM_MAX_DEGREE 40、SURVIVOR_MAX_DEGREE 150时改用流式读取L26-L39。稀疏路径用 shapelySTRtree只求是否重叠的邻接关系把峰值内存从O(N²)降到O(N max_degree)。另一个优化是阈值归零特例当match_threshold 0时任意两框都满足metric threshold邻接图成为完全图直接走nms_match_all/greedy_nmm_match_all/nmm_match_all等快速路径L124-L196无需计算任何重叠矩阵。7.3 确定性的分数排序与 tie-break所有后端在按分数排序时都使用_score_tiebreak_orderL97-L121通过np.lexsort((y2, x2, y1, x1, -scores))先按分数降序、分数相同时再按框坐标确定顺序保证结果可复现。测试 test_nms_equal_scores_deterministic 验证了等分场景下两次调用的结果完全一致。7.4 torchvision 后端的混合策略torchvision 后端sahi/postprocess/_torchvision_backend.py并非把所有逻辑都搬上 GPUIOU指标下的 NMS 直接调用torchvision.ops.nms原生 CUDA 内核L86-L92而 IOS 指标与 NMM 系列则先在 GPU 上用 torch 计算重叠矩阵_compute_metric_matrix_torch再把矩阵拷回 CPU复用 numpy 后端的nms_from_matrix/greedy_nmm_from_matrix/nmm_from_matrix合并逻辑。torchvision 后端在输入过大时同样会回退到 numpy 的稀疏路径。八、测试与质量保证tests/test_combine.py 是理解本模块行为的最佳入口覆盖了以下关键场景边界情况空输入batched_*返回{}或[]、单框输入、完全相同框、完全不重叠框、等分确定性L58-L140IOS 指标小框完全在大框内时 IOS1.0 被抑制而 IOU1.0 被保留以及 batched IOS 的按类别行为L148-L218合并语义NMM 的传递合并映射、阈值恰好等于匹配度时框被合并而非丢弃L250-L368后端一致性TestNumbaBackend断言 numba 与 numpy 在固定样例、IOS 指标、随机数据50 个框上的输出完全一致L536-L618TestTorchParity断言 torch 张量输入与 numpy 输入的结果一致L626-L667后端注册表set_postprocess_backend的取值校验非法值抛ValueError、缓存失效、CUDA/MPS 自动检测到 torchvision 等L376-L451。这意味着无论选择哪个后端你得到的后处理结果在语义上是一致的切换后端只影响性能不影响正确性。九、实战建议与常见问题阈值怎么调postprocess_match_threshold控制合并/抑制的积极程度。值越小合并越多0 时甚至所有框合并为一组值越大保留的独立框越多。默认 0.5 对大多数场景适用若发现同一目标被切成多个碎片框可适当调低如 0.3若发现不同目标被错误合并则调高。GreedyNMM vs NMM默认GREEDYNMM速度更快、合并框更紧凑当目标碎片呈链式排列、需要跨链合并时改用NMM获得传递合并效果。IOU vs IOS切片推理场景默认 IOS 更激进地消除重复在需要保守合并、避免误并的场景改用 IOU。注意LSNMSPostprocess只支持 IOU。后端选择CPU 小批量用 numpy 零依赖CPU 大批量用 numbaCUDA/Apple Silicon 用 torchvision。注意 numba 首次调用有约 1 秒 JIT 预热。低置信度陷阱当confidence_threshold 0.1时 SAHI 会自动把后处理切换到 NMS/IOU这是有意为之如果你确实需要低置信度下的合并类后处理请显式传入force_postprocess_typeTrue。OBB 模型Ultralytics 的旋转框OBB输出只支持 NMSpostprocess_type会被强制覆盖。十、延伸阅读后处理后端backends.md后端选择、自动检测与直接调用后处理函数的完整指南切片推理指南sliced-inference.md切图 → 检测 → 合并的完整工作流与参数调优CLI 参考cli.md命令行下--postprocess_*系列参数后处理工具函数utils.mdObjectPredictionList与合并算子的细节源码 sahi/postprocess/combine.py、sahi/postprocess/backends.py、sahi/postprocess/utils.py、sahi/postprocess/_numpy_backend.py、sahi/postprocess/_sparse_backend.py、sahi/postprocess/_torchvision_backend.py、sahi/predict.py测试 tests/test_combine.py。赞分享计算机视觉人工智能【免费下载链接】sahiFramework agnostic sliced/tiled inference interactive ui error analysis plots项目地址https://gitcode.com/gh_mirrors/sa/sahi点击查看免费下载相关推荐SAHI 切片推理结果合并Combine指南NMS、NMM 与 Greedy NMM 后处理全解析SAHI 切片推理结果合并Combine指南NMS、NMM 与 Greedy NMM 后处理全解析 切片Sliced/Tiled推理是 SAHI 处理计算机视觉人工智能SAHI后处理算法详解GreedyNMM、NMS、LSNMS核心原理SAHI后处理算法详解GreedyNMM、NMS、LSNMS核心原理 在目标检测任务中当使用切片推理Sliced Inference技术处理大尺寸图像时计算机视觉人工智能SAHI 切片推理Sliced Inference完全指南大图中检测小目标的切块-检测-合并原理与实战调优SAHI 切片推理Sliced Inference完全指南大图中检测小目标的切块 检测 合并原理与实战调优 SAHI 切片推理是框架无关framewor计算机视觉人工智能创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考