本文目录导读:

我来介绍几个使用OpenCV进行目标跟踪的Python案例。
基本目标跟踪(使用预训练跟踪器)
import cv2
import numpy as np
def basic_object_tracking():
"""
基本目标跟踪示例
"""
# 初始化视频捕获
cap = cv2.VideoCapture(0) # 0表示默认摄像头
# 读取第一帧
ret, frame = cap.read()
if not ret:
print("无法读取视频")
return
# 选择跟踪区域
bbox = cv2.selectROI("选择跟踪目标", frame, False)
cv2.destroyWindow("选择跟踪目标")
# 创建跟踪器(多种可选)
# tracker = cv2.TrackerKCF_create() # KCF跟踪器
# tracker = cv2.TrackerCSRT_create() # CSRT跟踪器
# tracker = cv2.TrackerMIL_create() # MIL跟踪器
tracker = cv2.TrackerKCF_create()
# 初始化跟踪器
tracker.init(frame, bbox)
while True:
ret, frame = cap.read()
if not ret:
break
# 更新跟踪器
success, bbox = tracker.update(frame)
# 绘制跟踪结果
if success:
x, y, w, h = [int(v) for v in bbox]
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(frame, "Tracking", (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
else:
cv2.putText(frame, "Lost", (50, 50),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.imshow("目标跟踪", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
基于颜色的目标跟踪
import cv2
import numpy as np
def color_based_tracking():
"""
基于颜色的目标跟踪
"""
cap = cv2.VideoCapture(0)
# 读取第一帧并选择目标
ret, frame = cap.read()
if not ret:
return
# 选择ROI
bbox = cv2.selectROI("选择目标", frame, False)
roi = frame[int(bbox[1]):int(bbox[1]+bbox[3]),
int(bbox[0]):int(bbox[0]+bbox[2])]
# 计算目标颜色直方图
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
roi_hist = cv2.calcHist([hsv_roi], [0], None, [180], [0, 180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)
# 设置追踪窗口初始位置
track_window = (int(bbox[0]), int(bbox[1]),
int(bbox[2]), int(bbox[3]))
# 设置终止条件
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)
while True:
ret, frame = cap.read()
if not ret:
break
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)
# 使用MeanShift进行跟踪
ret, track_window = cv2.meanShift(dst, track_window, term_crit)
# 绘制跟踪结果
x, y, w, h = track_window
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
cv2.imshow("颜色跟踪", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
光流法目标跟踪
import cv2
import numpy as np
def optical_flow_tracking():
"""
基于光流法的目标跟踪
"""
cap = cv2.VideoCapture(0)
# 读取第一帧
ret, old_frame = cap.read()
if not ret:
return
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
# 选择跟踪点
points = cv2.goodFeaturesToTrack(old_gray, maxCorners=100,
qualityLevel=0.3, minDistance=7)
# 光流参数
lk_params = dict(winSize=(15, 15),
maxLevel=2,
criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))
# 创建掩码用于绘制轨迹
mask = np.zeros_like(old_frame)
while True:
ret, frame = cap.read()
if not ret:
break
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 计算光流
new_points, status, error = cv2.calcOpticalFlowPyrLK(
old_gray, frame_gray, points, None, **lk_params)
# 选择好的点
good_new = new_points[status == 1]
good_old = points[status == 1]
# 绘制轨迹
for i, (new, old) in enumerate(zip(good_new, good_old)):
a, b = new.ravel()
c, d = old.ravel()
mask = cv2.line(mask, (int(a), int(b)), (int(c), int(d)),
(0, 255, 0), 2)
frame = cv2.circle(frame, (int(a), int(b)), 5, (0, 0, 255), -1)
# 合并帧和轨迹
img = cv2.add(frame, mask)
# 更新旧帧和点
old_gray = frame_gray.copy()
points = good_new.reshape(-1, 1, 2)
cv2.imshow("光流跟踪", img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 如果点太少,重新检测
if len(points) < 10:
points = cv2.goodFeaturesToTrack(old_gray, maxCorners=100,
qualityLevel=0.3, minDistance=7)
cap.release()
cv2.destroyAllWindows()
多目标跟踪
import cv2
import numpy as np
def multi_object_tracking():
"""
多目标跟踪示例
"""
cap = cv2.VideoCapture(0)
# 读取第一帧
ret, frame = cap.read()
if not ret:
return
# 创建多目标跟踪器
tracker = cv2.MultiTracker_create()
# 选择多个跟踪目标(选择后按空格确认,按ESC取消)
bboxes = []
colors = [(0, 255, 0), (255, 0, 0), (0, 0, 255)] # 不同目标的颜色
while True:
# 选择ROI
bbox = cv2.selectROI("选择目标 (按空格确认, ESC结束)", frame, False)
if bbox == (0, 0, 0, 0): # 按ESC退出
break
bboxes.append(bbox)
cv2.rectangle(frame, (int(bbox[0]), int(bbox[1])),
(int(bbox[0]+bbox[2]), int(bbox[1]+bbox[3])),
colors[len(bboxes)-1], 2)
# 使用KCF跟踪器
tracker.add(cv2.TrackerKCF_create(), frame, bbox)
print(f"已选择 {len(bboxes)} 个目标")
cv2.destroyWindow("选择目标 (按空格确认, ESC结束)")
while True:
ret, frame = cap.read()
if not ret:
break
# 更新所有跟踪器
success, boxes = tracker.update(frame)
# 绘制所有跟踪结果
for i, box in enumerate(boxes):
x, y, w, h = [int(v) for v in box]
cv2.rectangle(frame, (x, y), (x+w, y+h),
colors[i % len(colors)], 2)
cv2.putText(frame, f"Object {i+1}", (x, y-10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, colors[i % len(colors)], 2)
cv2.imshow("多目标跟踪", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
移动物体检测与跟踪
import cv2
import numpy as np
def motion_detection_tracking():
"""
移动物体检测与跟踪
"""
cap = cv2.VideoCapture(0)
# 背景减法器
backSub = cv2.createBackgroundSubtractorMOG2()
# 创建KCF跟踪器用于持续跟踪
tracker = None
tracking = False
while True:
ret, frame = cap.read()
if not ret:
break
# 应用背景减法
fgMask = backSub.apply(frame)
# 查找轮廓
contours, _ = cv2.findContours(fgMask, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
# 处理检测到的移动物体
for contour in contours:
area = cv2.contourArea(contour)
if area > 1000: # 过滤小面积噪声
x, y, w, h = cv2.boundingRect(contour)
if not tracking:
# 开始跟踪新的物体
tracker = cv2.TrackerCSRT_create()
tracker.init(frame, (x, y, w, h))
tracking = True
print("开始跟踪")
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
# 如果已经在跟踪,更新跟踪器
if tracking and tracker is not None:
success, bbox = tracker.update(frame)
if success:
x, y, w, h = [int(v) for v in bbox]
cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 3)
cv2.putText(frame, "Tracking", (x, y-10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
else:
tracking = False
print("跟踪丢失")
# 显示结果
cv2.imshow("原始帧", frame)
cv2.imshow("前景掩码", fgMask)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
使用预训练YOLO进行目标检测和跟踪
import cv2
import numpy as np
def yolo_with_tracking():
"""
YOLO检测 + 跟踪
"""
# 加载YOLO
net = cv2.dnn.readNet("yolov3.weights", "yolov3.cfg")
# 加载类别名称
with open("coco.names", "r") as f:
classes = [line.strip() for line in f.readlines()]
# 获取输出层
layer_names = net.getLayerNames()
output_layers = [layer_names[i - 1] for i in net.getUnconnectedOutLayers()]
cap = cv2.VideoCapture(0)
# 存储跟踪器
trackers = []
tracked_objects = []
while True:
ret, frame = cap.read()
if not ret:
break
height, width, channels = frame.shape
# YOLO检测(每30帧检测一次)
if cv2.waitKey(1) % 30 == 0:
# 准备输入
blob = cv2.dnn.blobFromImage(frame, 0.00392, (416, 416),
(0, 0, 0), True, crop=False)
net.setInput(blob)
outs = net.forward(output_layers)
# 处理检测结果
boxes = []
confidences = []
class_ids = []
for out in outs:
for detection in out:
scores = detection[5:]
class_id = np.argmax(scores)
confidence = scores[class_id]
if confidence > 0.5:
center_x = int(detection[0] * width)
center_y = int(detection[1] * height)
w = int(detection[2] * width)
h = int(detection[3] * height)
x = int(center_x - w / 2)
y = int(center_y - h / 2)
boxes.append([x, y, w, h])
confidences.append(float(confidence))
class_ids.append(class_id)
# 应用非极大值抑制
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
# 为检测到的目标创建跟踪器
trackers = []
tracked_objects = []
if len(indexes) > 0:
for i in indexes.flatten():
x, y, w, h = boxes[i]
label = str(classes[class_ids[i]])
# 创建跟踪器
tracker = cv2.TrackerCSRT_create()
tracker.init(frame, (x, y, w, h))
trackers.append(tracker)
tracked_objects.append(label)
# 更新所有跟踪器
for i, tracker in enumerate(trackers):
success, bbox = tracker.update(frame)
if success:
x, y, w, h = [int(v) for v in bbox]
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
cv2.putText(frame, tracked_objects[i], (x, y-10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
cv2.imshow("YOLO + 跟踪", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
常用跟踪器对比
def compare_trackers():
"""
比较不同跟踪器的性能
"""
trackers = {
'BOOSTING': cv2.TrackerBoosting_create(),
'MIL': cv2.TrackerMIL_create(),
'KCF': cv2.TrackerKCF_create(),
'TLD': cv2.TrackerTLD_create(),
'MEDIANFLOW': cv2.TrackerMedianFlow_create(),
'CSRT': cv2.TrackerCSRT_create()
}
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
# 选择跟踪目标
bbox = cv2.selectROI("选择目标", frame, False)
cv2.destroyWindow("选择目标")
# 初始化所有跟踪器
active_trackers = {}
for name, tracker in trackers.items():
tracker.init(frame, bbox)
active_trackers[name] = tracker
# 显示跟踪结果对比
while True:
ret, frame = cap.read()
if not ret:
break
results_frame = frame.copy()
for name, tracker in active_trackers.items():
success, bbox = tracker.update(frame)
if success:
x, y, w, h = [int(v) for v in bbox]
cv2.rectangle(results_frame, (x, y), (x+w, y+h),
(0, 255, 0), 2)
cv2.putText(results_frame, f"{name}: OK", (x, y-10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
else:
cv2.putText(results_frame, f"{name}: Lost",
(50, 50 + list(active_trackers.keys()).index(name)*30),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.imshow("跟踪器对比", results_frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
使用建议
-
选择合适的跟踪器:
- CSRT: 准确度高,适合复杂场景
- KCF: 速度快,适合实时应用
- MIL: 鲁棒性好,但速度较慢
-
性能优化:
- 降低分辨率
- 使用灰度图像
- 限制跟踪区域
-
鲁棒性提升:
- 结合多种跟踪方法
- 定期重新检测
- 使用光流法辅助
这些案例涵盖了OpenCV中常见的跟踪方法,可以根据具体需求选择和调整。