python API:http://dlib.net/python/index.html#dlib.correlation_tracker
dlib 可实现单目标跟踪 和 多目标跟踪,实现流程如下
对应方法如下
correlation_tracker() 创建一个跟踪类;
start_track() 设置图片中的要跟踪物体的框;
update() 实时跟踪下一帧;
get_position() 得到跟踪到的目标的位置
demo
import cv2 import dlib import time tracker = dlib.correlation_tracker() win = dlib.image_window() cap = cv2.VideoCapture(0) i = 1 while i: ret, img = cap.read() # 第一帧,指定一个区域 if i == 1: # tracker.start_track(img, dlib.rectangle(74, 67, 112, 153)) tracker.start_track(img, dlib.centered_rect(dlib.point(int(img.shape[0]/2), int(img.shape[1]/2)), 50, 50)) # 后续帧,自动追踪 else: tracker.update(img) win.clear_overlay() win.set_image(img) win.add_overlay(tracker.get_position()) i += 1 # dlib.hit_enter_to_continue()
单目标跟踪
import cv2 import dlib tracker = dlib.correlation_tracker() # 导入correlation_tracker()类 cap = cv2.VideoCapture(0) # opencv打开摄像头,参数为设备索引号,笔记本电脑,0表示使用其内置摄像头 selection = None # 实时跟踪鼠标的跟踪区域 track_window = None # 要检测的物体所在区域 drag_start = None # 标记,是否开始拖动鼠标 # 鼠标点击事件回调函数 def onmouse(event, x, y, flags, param): global selection, track_window, drag_start # 定义全局变量 if event == cv2.EVENT_LBUTTONDOWN: # 鼠标左键按下 drag_start = (x, y) # 鼠标起始位置 track_window = None if drag_start: # 是否开始拖动鼠标,记录鼠标位置 xmin = min(x, drag_start[0]) ymin = min(y, drag_start[1]) xmax = max(x, drag_start[0]) ymax = max(y, drag_start[1]) selection = (xmin, ymin, xmax, ymax) if event == cv2.EVENT_LBUTTONUP: # 鼠标左键松开 drag_start = None track_window = selection selection = None def main(): # 创建图像与窗口,并将窗口与回调函数绑定 cv2.namedWindow('image', 1) cv2.setMouseCallback('image', onmouse) k = 0 while (1): ret, frame = cap.read() # 从摄像头读入1帧,ret表明成功与否 img_raw = frame # 初始帧 image = img_raw.copy() # 不改变初始帧,拷贝新的帧 # 初始化第一帧 if k == 0: # 用鼠标拖拽一个框来指定区域 while True: img_first = image.copy() # 不改变原来的帧,拷贝一个新的 if track_window: # 跟踪目标的窗口画出后,实时标出跟踪目标 print('track_window') cv2.rectangle(img_first, (track_window[0], track_window[1]), (track_window[2], track_window[3]), (0, 0, 255), 1) elif selection: # 跟踪目标的窗口随鼠标拖动实时显示 print('selection') cv2.rectangle(img_first, (selection[0], selection[1]), (selection[2], selection[3]), (0, 0, 255), 1) cv2.imshow('image', img_first) if cv2.waitKey(5) == 27: # 等待时间为5ms,用户按下按下ESC(ASCII码为27),退出循环 break tracker.start_track(image, dlib.rectangle(track_window[0], track_window[1], track_window[2], track_window[3])) else: # 不是第一帧了 tracker.update(image) # 更新,实时跟踪 # time.sleep(3) box_predict = tracker.get_position() # 得到目标的位置 cv2.rectangle(image, (int(box_predict.left()), int(box_predict.top())), (int(box_predict.right()), int(box_predict.bottom())), (0, 255, 255), 1) cv2.imshow('image', image) c = cv2.waitKey(5) if c == 27: break # 如果按下ESC,则退出 k += 1 cv2.destroyAllWindows() if __name__ == '__main__': main()
多目标跟踪
import cv2 import dlib cap = cv2.VideoCapture(0) tracker1 = dlib.correlation_tracker() tracker2 = dlib.correlation_tracker() tracker3 = dlib.correlation_tracker() selection = None track_window = None drag_start = None # 鼠标选框(做目标跟踪框) def onmouse(event, x, y, flags, param): global selection, track_window, drag_start if event == cv2.EVENT_LBUTTONDOWN: drag_start = (x, y) track_window = None if drag_start: xmin = min(x, drag_start[0]) ymin = min(y, drag_start[1]) xmax = max(x, drag_start[0]) ymax = max(y, drag_start[1]) selection = (xmin, ymin, xmax, ymax) if event == cv2.EVENT_LBUTTONUP: drag_start = None track_window = selection selection = None def main(): track_window1 = () track_window2 = () track_window3 = () cv2.namedWindow('image', 1) cv2.setMouseCallback('image', onmouse) k = 0 while (1): ret, img = cap.read() image = img.copy() if k == 0: while True: img_first = image.copy() if track_window: cv2.rectangle(img_first, (track_window[0], track_window[1]), (track_window[2], track_window[3]), (0, 0, 255), 1) elif selection: cv2.rectangle(img_first, (selection[0], selection[1]), (selection[2], selection[3]), (0, 0, 255), 1) # 选择多个跟踪目标 if track_window1: print(1) cv2.rectangle(img_first, (track_window1[0], track_window1[1]), (track_window1[2], track_window1[3]), (0, 255, 255), 1) if track_window2: print(2) cv2.rectangle(img_first, (track_window2[0], track_window2[1]), (track_window2[2], track_window2[3]), (0, 255, 100), 1) if track_window3: print(3) cv2.rectangle(img_first, (track_window3[0], track_window3[1]), (track_window3[2], track_window3[3]), (200, 0, 200), 1) cv2.imshow('image', img_first) if cv2.waitKey(10) == 27: # 按4次 ESC print('esc') if not track_window1: print(11) track_window1 = track_window elif not track_window2: print(22) track_window2 = track_window elif not track_window3: print(33) track_window3 = track_window else: break tracker1.start_track(image, dlib.rectangle(track_window1[0], track_window1[1], track_window1[2], track_window1[3])) tracker2.start_track(image, dlib.rectangle(track_window2[0], track_window2[1], track_window2[2], track_window2[3])) tracker3.start_track(image, dlib.rectangle(track_window3[0], track_window3[1], track_window3[2], track_window3[3])) else: # Else we just attempt to track from the previous frame tracker1.update(image) tracker2.update(image) tracker3.update(image) # Get previous box and draw on showing image box1_predict = tracker1.get_position() box2_predict = tracker2.get_position() box3_predict = tracker3.get_position() cv2.rectangle(image, (int(box1_predict.left()), int(box1_predict.top())), (int(box1_predict.right()), int(box1_predict.bottom())), (0, 255, 255), 1) cv2.rectangle(image, (int(box2_predict.left()), int(box2_predict.top())), (int(box2_predict.right()), int(box2_predict.bottom())), (0, 255, 100), 1) cv2.rectangle(image, (int(box3_predict.left()), int(box3_predict.top())), (int(box3_predict.right()), int(box3_predict.bottom())), (200, 0, 200), 1) cv2.imshow('image', image) # cv2.waitKey(10) c = cv2.waitKey(10) & 0xff if c == 27: break # ESC k += 1 cv2.destroyAllWindows() if __name__ == '__main__': main()
以上代码是 手动 创建 跟踪 区域,也可 通过 目标检测 模型,检测到物体得到 bbox 后,进行跟踪,详见 资料3
参考资料:
https://blog.csdn.net/wc781708249/article/details/78563543 Dlib实现目标跟踪 汇总
https://blog.csdn.net/weixin_40277254/article/details/82188461 dlib 目标跟踪
https://blog.csdn.net/qq_36758914/article/details/104062419 Opencv之多目标追踪(基于Dlib库) 【加上了 目标检测 模型】