supervision 中边界框坐标工具详解boxes 模块六大核心函数的原理、参数与实战【免费下载链接】supervisionWe write your reusable computer vision tools. 项目地址: https://gitcode.com/GitHub_Trending/su/supervisionsupervision 的detection/utils/boxes模块提供了一组基于 NumPy 的边界框坐标变换工具覆盖平移、缩放、裁剪、填充、反归一化和旋转框转换六类基本操作。本文围绕官方文档页 Boxes Utils 所列的六个公开函数逐一展开结合 src/supervision/detection/utils/boxes.py 的源码实现与 tests/detection/utils/test_boxes.py 的测试用例讲清每个函数的参数约定、边界行为和库内部的实际调用位置帮助你在后处理检测结果时做出准确的坐标变换。boxes 模块的定位与公开 APIboxes模块位于 src/supervision/detection/utils/boxes.py是 supervision 中所有对框坐标做几何变换逻辑的汇聚点。从包入口 src/supervision/init.py 可以看到共有六个函数被提升到顶层命名空间可通过import supervision as sv直接调用公开函数输入形状输出形状核心用途sv.move_boxes(N, 4)(N, 4)按像素偏移平移所有框sv.scale_boxes(N, 4)(N, 4)以框中心为基准按比例缩放sv.clip_boxes(N, 4)(N, 4)将坐标裁剪到帧分辨率[0, width] × [0, height]sv.pad_boxes(N, 4)(N, 4)向外扩展固定像素的填充sv.denormalize_boxes(N, 4)(N, 4)归一化坐标还原为绝对像素坐标sv.xyxyxyxy_to_xyxy(N, 4, 2)(N, 4)旋转框四角点转轴对齐外接框除这六个公开函数外模块内还定义了若干内部函数如move_oriented_boxes、spread_out_boxes、obb_polygon_area、_oriented_box_anchors它们不通过顶层 API 导出但被库的其他子系统直接引用本文最后会统一说明。move_boxes按像素偏移平移边界框move_boxes将一组(x1, y1, x2, y2)格式的框整体平移[dx, dy]源码见 boxes.py 的 move_boxes。import numpy as np import supervision as sv xyxy np.array([ [10, 10, 20, 20], [30, 30, 40, 40] ]) offset np.array([5, 5]) print(sv.move_boxes(xyxyxyxy, offsetoffset)) # array([[15, 15, 25, 25], # [35, 35, 45, 45]])参数说明xyxy形状(N, 4)的数组每行是一个[x_min, y_min, x_max, y_max]框offset形状(2,)的整数数组[dx, dy]负值合法表示向左/上移动。从源码结构看实现只有一行xyxy np.hstack([offset, offset])boxes.py#L200。offset被复制拼成[dx, dy, dx, dy]后做广播加法因此左上角和右下角坐标平移相同的量框的宽高保持不变。tests/detection/utils/test_boxes.py 的 test_move_boxes 覆盖了空数组、零偏移、多框和负偏移四类场景。库内调用位置分块推理工具InferenceSlicer在把检测框从分块局部坐标搬回原图全局坐标时正是调用本函数。见 src/supervision/detection/tools/inference_slicer.pymove_boxes负责平移轴对齐框配套的内部函数move_oriented_boxes则平移xyxyxyxy形状(N, 4, 2)的旋转框四个角点实现为xyxyxyxy offset的广播加法见 boxes.py#L203-L249保证同一次分块平移中两类坐标同步移动。scale_boxes以框中心为基准的等比缩放scale_boxes将每个框的宽和高按factor倍缩放且缩放以框中心为不动点源码见 boxes.py 的 scale_boxes。xyxy np.array([ [10, 10, 20, 20], [30, 30, 40, 40] ]) print(sv.scale_boxes(xyxyxyxy, factor1.5)) # array([[ 7.5, 7.5, 22.5, 22.5], # [27.5, 27.5, 42.5, 42.5]])参数说明xyxy形状(N, 4)格式[x1, y1, x2, y2]factor缩放倍数。factor 1放大factor 1缩小factor 1.0原样返回。从源码实现看boxes.py#L457-L459算法分三步先求中心centers (xyxy[:, :2] xyxy[:, 2:]) / 2再算新尺寸new_sizes (xyxy[:, 2:] - xyxy[:, :2]) * factor最后以中心向两侧各展开new_sizes / 2得到新坐标。也就是说缩放不会改变框的中心位置这与从左上角扩张的直觉不同。tests/detection/utils/test_boxes.py 的 test_scale_boxes 验证了factor2.0时[0,0,10,10]变成[-5,-5,15,15]——中心(5,5)不变宽高翻倍。典型用法是给检测框加外扩余量以缓解小目标框贴边问题若只需要整数像素的固定外扩则应选用下一节的pad_boxes。clip_boxes把坐标裁剪到帧分辨率内clip_boxes将所有坐标钳制到[0, width] × [0, height]范围内源码见 boxes.py 的 clip_boxes。xyxy np.array([ [10, 20, 300, 200], [15, 25, 350, 450], [-10, -20, 30, 40] ]) print(sv.clip_boxes(xyxyxyxy, resolution_wh(320, 240))) # array([[ 10, 20, 300, 200], # [ 15, 25, 320, 240], # [ 0, 0, 30, 40]])参数说明xyxy形状(N, 4)每行一个(x_min, y_min, x_max, y_max)框resolution_wh(width, height)元组即目标帧的分辨率。注意顺序是宽在前、高在后与 NumPy 图像shape的(height, width)顺序相反传参时容易出错。从源码实现看boxes.py#L49-L53函数先np.copy再对列[0, 2]x 坐标clip(0, width)、对列[1, 3]y 坐标clip(0, height)。两个实现细节值得注意函数不会修改输入数组总是返回新数组裁剪是逐坐标钳制不保证x_max x_min。如果原框整体在画面左侧外如[-10, -20, -5, 40]裁剪后x1 x2 0产生退化框。tests/detection/utils/test_boxes.py 的 test_clip_boxes 参数化了空数组、恰好贴边、负坐标、超宽/超高坐标等六种边界输入。库内调用位置annotators模块中多个标注器在绘制前都会先裁剪坐标例如BlurAnnotator在 src/supervision/annotators/core.py 中对detections.xyxy执行clip_boxes(...).astype(int)随后跳过x2 x1 or y2 y1的退化框再取 ROI——这正是上面第 2 条注意事项的实际处理方式。pad_boxes固定像素的外扩填充pad_boxes向每个框的四边外扩固定像素数源码见 boxes.py 的 pad_boxes。xyxy np.array([ [10, 20, 30, 40], [15, 25, 35, 45] ]) print(sv.pad_boxes(xyxyxyxy, px5, py10)) # array([[ 5, 10, 35, 50], # [10, 15, 40, 55]])参数说明xyxy形状(N, 4)格式(x_min, y_min, x_max, y_max)px左右两侧各扩展的像素数py上下两侧各扩展的像素数可选缺省时回退为py pxboxes.py#L93-L94实现各向同性填充。px允许传负值此时函数等效于向内收缩这一约定在内部代码中有实际使用关键点标注器在 src/supervision/key_points/annotators.py 中先用pad_boxes(xyxyxyxy, pxself.text_padding)扩大框以容纳文字渲染完成后又用pad_boxes(..., px-self.text_padding)精确还原。tests/detection/utils/test_boxes.py 的 test_pad_boxes 覆盖了单框各向同性、单框不对称、多框与空数组场景。pad_boxes与scale_boxes的选型关系需要边距加 N 像素用pad_boxes需要尺寸乘以 k 倍用scale_boxes。denormalize_boxes归一化坐标还原为绝对像素坐标denormalize_boxes将归一化框坐标映射到指定分辨率的绝对像素坐标源码见 boxes.py 的 denormalize_boxes。xyxy np.array([ [0.1, 0.2, 0.5, 0.6], [0.3, 0.4, 0.7, 0.8], [0.2, 0.1, 0.6, 0.5] ]) print(sv.denormalize_boxes(xyxy, (1280, 720))) # array([[128., 144., 640., 432.], # [384., 288., 896., 576.], # [256., 72., 768., 360.]])参数说明xyxy形状(N, 4)的归一化框坐标取值范围为[0, normalization_factor]每行(x_min, y_min, x_max, y_max)resolution_wh目标图像分辨率(width, height)normalization_factor输入坐标的最大值默认1.0。当模型输出不是[0,1]而是如[0,1024]的量化坐标时需显式传入例如sv.denormalize_boxes(xyxy, (1280, 720), normalization_factor1024.0)见 boxes.py 的第二个文档示例。实现上boxes.py#L159-L169函数构造缩放向量[width, height, width, height] / normalization_factor后与输入逐元素相乘即x方向乘width/factor、y方向乘height/factor。两个值得注意的行为dtype 保留策略浮点输入保留原 dtype如 float32 输入返回 float32整数输入则提升为 float64以免把小数像素坐标静默截断。这一契约由 test_denormalize_boxes_returns_expected_dtype 专门守护其中整数输入不得截断小数坐标也是 test_denormalize_boxes 的一条回归用例弃用提醒函数通过deprecated装饰器声明参数重映射——旧参数名normalized_xyxy自 0.27.0 起更名为xyxy计划在 0.31.0 移除boxes.py#L103-L108。调用时请直接使用xyxy关键字参数。库内调用位置视觉语言模型VLM推理模块 src/supervision/detection/vlm.py 在把模型返回的归一化框还原为像素坐标时多处调用本函数如 vlm.py#L716、vlm.py#L810是 VLM 检测管线中坐标还原的标准入口。xyxyxyxy_to_xyxy旋转框角点转轴对齐外接框xyxyxyxy_to_xyxy将旋转框OBB的四个角点转换为其轴对齐外接框AABB源码见 boxes.py 的 xyxyxyxy_to_xyxy。corners np.array([ [[0, 0], [10, 0], [10, 5], [0, 5]], [[5, 5], [15, 5], [15, 10], [5, 10]], ], dtypenp.float32) print(sv.xyxyxyxy_to_xyxy(corners)) # array([[ 0., 0., 10., 5.], # [ 5., 5., 15., 10.]], dtypefloat32)参数说明xyxyxyxy形状(N, 4, 2)的 OBB 角点坐标每个框表示为[[x1,y1], [x2,y2], [x3,y3], [x4,y4]]返回值形状(N, 4)的(x_min, y_min, x_max, y_max)数组保留输入 dtypefloat32 输入返回 float32。从源码实现看boxes.py#L331-L335算法即对四个角点分别取min/max后np.stackx_min xyxyxyxy[..., 0].min(axis-1)以此类推。对未旋转的矩形结果与角点本身一致对旋转矩形结果是一个面积更大的外接框。形状校验不通过时会抛出ValueError。test_xyxyxyxy_to_xyxy 用旋转 45° 的菱形用例验证了外接框的正确性菱形[[5,0],[10,5],[5,10],[0,5]]的外接框为[0, 0, 10, 10]。库内调用位置平滑滤波器DetectionsSmoother在对旋转框角点做时序平滑后用本函数重新导出detections.xyxy见 src/supervision/detection/tools/smoother.pyDetections核心类合并 OBB 检测结果时同样调用它src/supervision/detection/core.py。内部函数速览模块中的其余工具除文档页列出的六个公开函数外boxes模块还有三个被库内部子系统依赖的工具函数了解它们有助于理解模块全貌spread_out_boxes(xyxy, max_iterations100)boxes.py#L462-L531将相互重叠的框按迭代式排斥力推开——每轮用box_iou_batch计算 N×N 的 IoU 矩阵为每个框合成方向向量远离所有与之重叠的框与力度向量IoU 之和放大 10 倍并限制在 ±2 像素内直至全部 IoU 为零或达到最大迭代次数。LabelAnnotator等标注器用它避免标签互相压叠src/supervision/annotators/core.py、src/supervision/key_points/annotators.pyobb_polygon_area(corners)boxes.py#L252-L295用鞋带公式shoelace formula批量计算 OBB 面积。实现上先把每个框平移到以其首角点为原点的局部坐标系再做叉积运算避免大地坐标如地理空间或拼接大图下大数坐标的浮点舍入误差tests/detection/utils/test_boxes.py 中的回归测试 验证了原点位于10**10处时面积仍精确为 5000。该函数被几何分发器 src/supervision/detection/_geometry_dispatch.py 引用_oriented_box_anchors(xyxyxyxy, anchor)boxes.py#L353-L424在旋转框本体上定位九宫格锚点角点映射到角点、边锚点映射到边中点用于让标签、关键点在旋转框上贴住目标本体。源码注释明确了一个边界条件当旋转角度超过arctan(w/h)时宽度边的判定会翻转BOTTOM_CENTER等锚点位置会出现约|w - h|像素的跳变属已知的外观性现象。test_oriented_box_anchors_are_rotation_covariant 验证了锚点随框旋转的协变性质。组合使用模式与小结六个公开函数在典型检测管线中往往成对出现以下是从库内部代码归纳的组合模式归一化 → 像素 → 裁剪VLM 或归一化模型输出 →denormalize_boxes还原像素坐标 →clip_boxes钳制到帧内 → 交给标注器渲染。库内标注器渲染前几乎都会先做一次clip_boxes见 src/supervision/annotators/core.py分块推理 → 平移回全局InferenceSlicer分块预测后用move_boxes/move_oriented_boxes把每块结果平移回原图坐标src/supervision/detection/tools/inference_slicer.py外扩与还原pad_boxes加正余量做文字区/检测余量负值精确还原src/supervision/key_points/annotators.py旋转框 ↔ 轴对齐框xyxyxyxy_to_xyxy在 OBB 平滑、合并等流程中导出 AABB 表示src/supervision/detection/tools/smoother.py。需要牢记的参数约定resolution_wh一律是(width, height)而非(height, width)scale_boxes以框中心为不动点clip_boxes不修改输入且不保证裁剪后框非退化渲染前建议按库内标注器的做法过滤x2 x1 or y2 y1的框。所有函数均为纯 NumPy 向量化实现可直接作用于整批(N, 4)数组适合作为检测结果后处理的基础构件。【免费下载链接】supervisionWe write your reusable computer vision tools. 项目地址: https://gitcode.com/GitHub_Trending/su/supervision创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考