在多目标跟踪(MOT)或目标检测任务中,**候选框(Bounding Box)**是用于表示目标位置的关键数据结构。候选框的表示形式有多种,不同算法、库或阶段(如训练、推理)可能会采用不同形式。理解这些表示及其相互转换非常重要。
一、常见候选框表示形式
1. 角点表示法(x1, y1, x2, y2
)
-
x1, y1
: 左上角坐标 -
x2, y2
: 右下角坐标
优点:直观、适用于 IoU 计算
应用场景:OpenCV、YOLO 输出、IoU计算
2. 中心点 + 宽高表示(cx, cy, w, h
)
-
cx, cy
: 框中心点 -
w, h
: 框的宽度和高度
优点:便于变换、回归预测更稳定
应用场景:神经网络内部训练回归、Kalman 滤波等跟踪预测
3. Top-Left + 宽高表示(x, y, w, h
)
-
x, y
: 左上角坐标 -
w, h
: 宽度和高度
优点:图像裁剪、OpenCV 原生支持
应用场景:OpenCV 显示、图像裁剪
二、转换公式
1. cx, cy, w, h
→ x1, y1, x2, y2
x1 = cx - w / 2
y1 = cy - h / 2
x2 = cx + w / 2
y2 = cy + h / 2
2. x1, y1, x2, y2
→ cx, cy, w, h
w = x2 - x1
h = y2 - y1
cx = x1 + w / 2
cy = y1 + h / 2
3. x, y, w, h
(top-left) → x1, y1, x2, y2
x1 = x
y1 = y
x2 = x + w
y2 = y + h
4. x1, y1, x2, y2
→ x, y, w, h
x = x1
y = y1
w = x2 - x1
h = y2 - y1
三、Python 示例代码
def xywh2xyxy(box):
x, y, w, h = box
return [x, y, x + w, y + h]
def xyxy2xywh(box):
x1, y1, x2, y2 = box
return [x1, y1, x2 - x1, y2 - y1]
def cxcywh2xyxy(box):
cx, cy, w, h = box
return [cx - w / 2, cy - h / 2, cx + w / 2, cy + h / 2]
def xyxy2cxcywh(box):
x1, y1, x2, y2 = box
w = x2 - x1
h = y2 - y1
return [x1 + w / 2, y1 + h / 2, w, h]
四、实际应用场景对照
框类型 | 使用场景 |
---|---|
x1,y1,x2,y2 | IoU 计算、NMS、检测输出 |
cx,cy,w,h | 跟踪预测(如 Kalman 滤波) |
x,y,w,h | OpenCV 显示、图像剪裁、GUI 可视化 |
五、示例
展示在多目标跟踪任务中使用候选框的表示形式及其转换,尤其针对常见的 YOLOv5 + DeepSORT 跟踪流程。
场景目标:
正在使用 YOLOv5 检测视频帧中的人,然后用 DeepSORT 跟踪这些人,要求:
-
从 YOLOv5 的输出中提取
x1, y1, x2, y2
形式的框 -
转换为
cx, cy, w, h
输入 DeepSORT -
显示框时再转换为 OpenCV 用的
x, y, w, h
Step 1: 模拟 YOLOv5 检测输出(x1, y1, x2, y2, conf, class_id
)
# 模拟一个人类检测框(左上角x1,y1,右下角x2,y2)
yolo_det = [100, 50, 200, 250, 0.92, 0] # 人类类别为0
x1, y1, x2, y2, conf, cls_id = yolo_det[:6]
Step 2: 转为 DeepSORT 所需的 [cx, cy, w, h]
def xyxy2cxcywh(box):
x1, y1, x2, y2 = box
w = x2 - x1
h = y2 - y1
cx = x1 + w / 2
cy = y1 + h / 2
return [cx, cy, w, h]
bbox_deepsort = xyxy2cxcywh([x1, y1, x2, y2])
print("转换为 DeepSORT 格式:", bbox_deepsort)
# 输出: [150.0, 150.0, 100, 200]
Step 3: DeepSORT 跟踪输出(也为 x1,y1,x2,y2
)
# 假设 DeepSORT 返回跟踪框和 ID
track_box = [98, 52, 198, 248] # 跟踪后的框(略有偏移)
track_id = 5
Step 4: 转为 OpenCV 显示框(x, y, w, h
)
def xyxy2xywh(box):
x1, y1, x2, y2 = box
return [int(x1), int(y1), int(x2 - x1), int(y2 - y1)]
display_box = xyxy2xywh(track_box)
print("OpenCV 显示框:", display_box)
# 输出: [98, 52, 100, 196]
Step 5: 用 OpenCV 显示跟踪结果
import cv2
frame = cv2.imread("demo.jpg") # 假设是一帧图像
x, y, w, h = display_box
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(frame, f"ID: {track_id}", (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2)
cv2.imshow("Track", frame)
cv2.waitKey(0)
cv2.destroyAllWindows()
小结:转换流程图
YOLOv5 输出:x1,y1,x2,y2
↓
DeepSORT 需要:cx,cy,w,h
↓
DeepSORT 输出:x1,y1,x2,y2
↓
OpenCV 显示:x,y,w,h
五、图示(便于理解)【描述版】
x1,y1 -------------------
| |
| (cx,cy) |
| |
------------------ x2,y2