什么是物体跟踪?
物体跟踪(Object Tracking)是指在视频序列中,对预先选定的目标物体进行连续的位置定位,输出目标在每一帧中的坐标、尺寸信息。与目标检测不同:
-
目标检测:逐帧独立识别画面中的所有目标,无前后帧关联;
-
物体跟踪:仅初始化时选定目标,后续通过帧间关联算法持续追踪,速度更快、资源消耗更低。
简单来说:检测是 "找目标",跟踪是 "跟目标"。
OpenCV 内置跟踪器对比
OpenCV 3.x 及以上版本内置了多种经典跟踪器,适配不同场景,核心跟踪器特性如下:
| 跟踪器类型 | 核心优势 | 局限性 | 适用场景 |
|---|---|---|---|
| BOOSTING | 算法简单,兼容性强 | 速度慢,遮挡后易丢失 | 低分辨率、简单场景 |
| MIL | 精度较高,抗轻微遮挡 | 速度一般,无法处理快速运动 | 静态目标、慢速运动目标 |
| KCF | 速度极快,精度高 | 无法处理完全遮挡、尺度变化 | 实时性要求高的场景 |
| CSRT | 精度极高,抗遮挡、抗尺度变化 | 速度较慢 | 高精度要求、复杂场景 |
| MEDIANFLOW | 运动轨迹平滑 | 遮挡后完全失效 | 运动规律的目标 |
| TLD | 抗长期遮挡 | 速度慢,易误跟踪 | 长期跟踪场景 |
本文选择 CSRT 跟踪器的原因:它在精度和鲁棒性上表现最优,能应对目标尺度变化、轻微遮挡,非常适合入门学习和实际简单场景使用,是物体跟踪入门的首选跟踪器。
ROI:物体跟踪的核心前提
ROI(Region of Interest)即感兴趣区域 ,是物体跟踪的 "起点"。我们需要手动框选视频帧中的目标区域,告诉跟踪器:你需要追踪的目标就是这个区域。跟踪器会基于 ROI 的特征,在后续帧中匹配并更新位置。
完整代码解析
导入库与初始化跟踪器
python
import cv2
# 创建一个CSRT跟踪器实例
tracker = cv2.TrackerCSRT_create()
cv2.TrackerCSRT_create():创建 CSRT 跟踪器对象,这是 OpenCV 提供的标准化 API,无需手动实现算法。
定义状态变量与打开摄像头
python
# 跟踪标志,默认为False
tracking = False
# 打开默认摄像头(通常编号为0)
cap = cv2.VideoCapture(0)
-
tracking:布尔型标志位,控制跟踪的开启与关闭,False表示未开始跟踪; -
cv2.VideoCapture(0):打开摄像头设备。参数0代表默认摄像头,若有多个摄像头,可改为 1、2 切换;若要处理视频文件,可传入视频路径(如cv2.VideoCapture("test.mp4"))。
主循环:读取视频帧
python
while True:
# 从摄像头读取一帧图像
ret, frame = cap.read()
# 如果没有正确读取到图像,则退出循环
if not ret:
break
-
hile True:无限循环,持续读取摄像头帧,实现实时视频流; -
cap.read():读取一帧数据,返回两个值:-
ret:布尔值,True表示读取帧成功,False表示读取失败(摄像头断开、视频结束); -
frame:读取到的视频帧(三维数组,存储图像像素信息);
-
-
if not ret: break:异常处理,读取失败时退出循环,避免程序崩溃。
按键触发:框选目标并初始化跟踪
python
if cv2.waitKey(1) == ord('s'):
tracking = True
# 让用户在当前帧中选择一个矩形区域作为要跟踪的对象
roi = cv2.selectROI('Tracking', frame, False)
# 初始化跟踪器,传入当前帧和选定的ROI
tracker.init(frame, roi)
-
cv2.waitKey(1):监听键盘按键,每 1 毫秒刷新一次; -
ord('s'):获取按键 'S' 的 ASCII 码,按下 S 键时触发跟踪; -
tracking = True:将跟踪标志置为真,启动跟踪; -
cv2.selectROI():弹出窗口,允许用户用鼠标框选目标:-
第一个参数:窗口名称;
-
第二个参数:要框选的帧;
-
第三个参数:
False表示不显示十字线,兼容所有 OpenCV 版本; -
返回值
roi:框选区域的坐标(x, y, w, h)(x = 左上角横坐标,y = 左上角纵坐标,w = 宽度,h = 高度);
-
-
tracker.init(frame, roi):跟踪器初始化,告诉跟踪器 "要跟踪的目标是这个区域"。
实时更新跟踪结果
python
if tracking:
success, box = tracker.update(frame)
if success:
x, y, w, h = [int(v) for v in box]
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
-
仅当
tracking=True时,执行跟踪更新; -
tracker.update(frame):跟踪器根据当前帧,更新目标位置,返回两个值:-
success:布尔值,True表示跟踪成功,False表示目标丢失; -
box:跟踪到的目标坐标(x, y, w, h);
-
-
坐标转换:
box返回的是浮点数,需转为整数才能绘制矩形; -
cv2.rectangle():在视频帧上绘制绿色矩形,标记跟踪目标(颜色:(0,255,0),线条宽度:2)。
显示画面与退出程序
python
cv2.imshow('Tracking', frame)
if cv2.waitKey(1) == 27:
break
cv2.waitKey(1) == 27:监听 ESC 键(ASCII 码 27),按下后退出循环
资源释放
python
cap.release()
cv2.destroyAllWindows()