Dlib實現目標跟蹤

參考:
一、http://blog.csdn.net/tintinetmilou/article/details/74910558
二、http://blog.csdn.net/tintinetmilou/article/details/75194703
三、https://github.com/davisking/dlib/
四、http://dlib.netpython


本文主要用到的時Python API中的dlib.correlation_tracker類,裏面有關於各個函數的詳細介紹。git

單目標跟蹤

# -*- coding: UTF-8 -*-

import os
import glob
import cv2
import dlib

# Path to the video frames
video_folder = os.path.join("..", "examples", "video_frames")

# Create the correlation tracker - the object needs to be initialized before it can be used
tracker = 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():
    cv2.namedWindow('image',1)
    cv2.setMouseCallback('image',onmouse)
    # We will track the frames as we load them off of disk
    for k, f in enumerate(sorted(glob.glob(os.path.join(video_folder, "*.jpg")))):
        print("Processing Frame {}".format(k))
        img_raw = cv2.imread(f)
        image = img_raw.copy()

        # We need to initialize the tracker on the first frame
        if k == 0:
            # Start a track on the object you want. box the object using the mouse and press 'Enter' to start tracking 
            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)
                cv2.imshow('image',img_first)
                if cv2.waitKey(10) == 10:
                    break
            tracker.start_track(image, dlib.rectangle(track_window[0], track_window[1], track_window[2], track_window[3]))
        else:
            # Else we just attempt to track from the previous frame
            tracker.update(image)

        # Get previous box and draw on showing image
        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,0,255),1)
        cv2.imshow('image',image)
        cv2.waitKey(10)

    cv2.destroyAllWindows()

if __name__ == '__main__':
    main()

該py文件放在此下載,視頻文件(實際上是每幀的圖片)在此下載github

  • 程序運行後,會顯示出第一幀,用鼠標框一個要跟蹤的物體
  • 框好後按回車進行跟蹤

代碼分析

  • 用opencv的鼠標GUI操做來在第一幀框住要跟蹤的目標,這隻須要在顯示框上設置一個回調函數,來返回鼠標框到的框的座標。
  • 根據框好的框肯定要跟蹤的目標物體,並傳入tracker.start_track中
  • 按回車進行跟蹤 ,以後用tracker.update(image)來追蹤當前幀。tracker.get_position()返回追蹤到的框,但要注意的是返回的這個框的數據類型時Dlib中的drectangle,不能直接傳給咱們顯示所用的Opencv函數,因此咱們經過drectangle操做函數來將框的座標信息讀出來(關於dlib.drectangle,詳細信息去Python API中查)。
  • 最後根據跟蹤獲得的框在圖片顯示時框出來就行了。

總結一下,使用 dlib.correlation_tracker分四步:
1. 用dlib.correlation_tracker()建立一個跟蹤類
2. start_track中設置圖片中的要跟蹤物體的框
3. update()中輸入要跟蹤的下一幀圖片
4. get_position()獲得跟蹤到的目標在新一幀中框的位置web


視頻跟蹤

# -*- coding: UTF-8 -*-

import os
import glob
import cv2
import dlib
import time

# Path to the video
video_folder = os.path.join("vtest.avi")
cap = cv2.VideoCapture(video_folder)
if not cap.isOpened():
    print("Could not open video", video_folder);exit(-1)

# Create the correlation tracker - the object needs to be initialized before it can be used
tracker = 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():
    cv2.namedWindow('image',1)
    cv2.setMouseCallback('image',onmouse)
    # We will track the frames as we load them off of disk
    # for k, f in enumerate(sorted(glob.glob(os.path.join(video_folder, "*.jpg")))):
    k=0
    while(1):
        ret, frame = cap.read()
        if not ret:
            print("Game over!")
            break
        print("Processing Frame {}".format(k))
        img_raw =frame #cv2.imread(f)
        image = img_raw.copy()

        # We need to initialize the tracker on the first frame
        if k == 0:
            # Start a track on the object you want. box the object using the mouse and press 'Enter' to start tracking
            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)
                cv2.imshow('image',img_first)
                if cv2.waitKey(10) == 27: # ESC
                    break
            tracker.start_track(image, dlib.rectangle(track_window[0], track_window[1], track_window[2], track_window[3]))
        else:
            # Else we just attempt to track from the previous frame
            tracker.update(image)
            # time.sleep(3)

        # Get previous box and draw on showing image
        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,0,255),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()

多目標跟蹤

# -*- coding: UTF-8 -*-

import os
import glob
import cv2
import dlib
import time

# Path to the video
video_folder = os.path.join("vtest.avi")
cap = cv2.VideoCapture(video_folder)
if not cap.isOpened():
    print("Could not open video", video_folder);exit(-1)

# Create the correlation tracker - the object needs to be initialized before it can be used
# 建立3個目標跟蹤
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)
    # We will track the frames as we load them off of disk
    # for k, f in enumerate(sorted(glob.glob(os.path.join(video_folder, "*.jpg")))):
    k=0
    while(1):
        ret, frame = cap.read()
        if not ret:
            print("Game over!")
            break
        print("Processing Frame {}".format(k))
        img_raw =frame #cv2.imread(f)
        image = img_raw.copy()

        # We need to initialize the tracker on the first frame
        if k == 0:
            # Start a track on the object you want. box the object using the mouse and press 'Enter' to start tracking
            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:
                    cv2.rectangle(img_first, (track_window1[0], track_window1[1]), (track_window1[2], track_window1[3]),
                                  (0, 255, 255), 1)
                if track_window2:
                    cv2.rectangle(img_first, (track_window2[0], track_window2[1]), (track_window2[2], track_window2[3]),
                                  (0, 255, 100), 1)
                if track_window3:
                    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: # ESC
                    if not track_window1:
                        track_window1 = track_window
                    elif not track_window2:
                        track_window2 = track_window
                    elif not track_window3:
                        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()
  • 用鼠標框要跟蹤的物體,框完按回車鍵(回車出問題 這裏按ESC)確認,一樣的手法連框三個
  • 再次按回車鍵開始跟蹤