单目标跟踪 (五)cv2.Tracker

from imutils.video import VideoStream
from imutils.video import FPS
import argparse
import imutils
import time
import cv2

ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video", type=str,
                help="path to input video file")
ap.add_argument("-t", "--tracker", type=str, default="mil",
                help="OpenCV object tracker type")
args = vars(ap.parse_args())

(major, minor) = cv2.__version__.split(".")[:2]

if int(major) == 3 and int(minor) < 3:
    tracker = cv2.Tracker_create(args["tracker"].upper())
else:
    OPENCV_OBJECT_TRACKERS = {
        "boosting": cv2.TrackerBoosting_create,#慢 无尺度 效果差 抖动
        "mil": cv2.TrackerMIL_create,#慢 无尺度
        "tld": cv2.TrackerTLD_create,  # 慢 应对大尺度变换,运行以及遮挡  容易无跟踪位置跳变
        "medianflow": cv2.TrackerMedianFlow_create,  # 较快 对追踪失败反馈敏锐  快速移动效果较差
        "kcf": cv2.TrackerKCF_create,  # 较快 无尺度  完全遮挡难以恢复
        "mosse": cv2.TrackerMOSSE_create,  # 较快 无尺度  鲁棒性较好,可以应对光线变换,尺度变换,姿势变动以及非网格化的变形  可以在目标消失时暂停并在目标出现时重启
        "csrt": cv2.TrackerCSRT_create,  # 慢 无尺度
    }


    tracker = OPENCV_OBJECT_TRACKERS[args["tracker"]]()   ###

#写
#tracker.save(args["tracker"]+'_params.json')
#读
#fs = cv2.FileStorage(args["tracker"]+'_params.json', cv2.FileStorage_READ)
#tracker.read(fs.getFirstTopLevelNode())


initBB = None

if not args.get("video", False):
    print("[INFO] starting video stream...")
    vs = VideoStream(src=0).start()
    time.sleep(1.0)
else:
    vs = cv2.VideoCapture(args["video"])

fps = None

while True:
    frame = vs.read()
    frame = frame[1] if args.get("video", False) else frame
    if frame is None:
        break
    frame = imutils.resize(frame, width=720)
    (H, W) = frame.shape[:2]

    if initBB is not None:
        (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)
        fps.update()
        fps.stop()

        info = [
            ("Tracker", args["tracker"]),
            ("Success", "Yes" if success else "No"),
            ("FPS", "{:.2f}".format(fps.fps())),
        ]

        for (i, (k, v)) in enumerate(info):
            text = "{}: {}".format(k, v)
            cv2.putText(frame, text, (10, H - ((i * 20) + 20)),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(1) & 0xFF

    if key == ord("s"):
        initBB = cv2.selectROI("Frame", frame, fromCenter=False,showCrosshair=False)
        tracker.init(frame, initBB)  ###
        fps = FPS().start()

    elif key == ord("q"):
        break
if not args.get("video", False):
    vs.stop()

else:
    vs.release()

cv2.destroyAllWindows()
###光流
now_gray=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
now_landmarks=np.array(results[0,15:]).reshape(-1,2).astype('float32')
lk_params=dict(winSize  = (5,5),maxLevel = 2,
               criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

# 前一帧的角点和当前帧的图像作为输入来得到角点在当前帧的位置
now_landmarks_1, match, err = cv2.calcOpticalFlowPyrLK(last_gray, now_gray, last_landmarks, None, **lk_params)
# 当前帧跟踪到的角点及图像和前一帧的图像作为输入来找到前一帧的角点位置
now_landmarks_2, match, err = cv2.calcOpticalFlowPyrLK(now_gray, last_gray,now_landmarks_1, None,**lk_params)  

# 得到角点回溯与前一帧实际角点的位置变化关系
d = abs(last_landmarks - now_landmarks_2).reshape(-1, 2).max(-1)  
#判断d内的值是否小于1,大于1跟踪被认为是错误的跟踪点
good = d < 0.1

Median-Flow追踪算法

 作者假设一个“好”的追踪算法应该具有正反向连续性(forward-backward consistency),即无论是按照时间上的正序追踪还是反序追踪,产生的轨迹应该是一样的。

作者根据这个性质规定了任意一个追踪器的FB误差(forward-backward error):从时间t的初始位置x(t)开始追踪产生时间t+p的位置x(t+p),再从位置x(t+p)反向追踪产生时间t的预测位置x`(t),初始位置和预测位置之间的欧氏距离就作为追踪器在t时间的FB误差。

Median-Flow追踪算法采用的是Lucas-Kanade追踪器,也就是光流法追踪器。

首先在上一帧t的物体包围框里均匀地产生一些点,然后用Lucas-Kanade追踪器正向追踪这些点到t+1帧,再反向追踪到t帧,计算FB误差,筛选出FB误差最小的一半点作为最佳追踪点。最后根据这些点的坐标变化和距离的变化计算t+1帧包围框的位置和大小(平移的尺度取中值,缩放的尺度取中值)。

《Forward-Backward Error: Automatic Detection of Tracking Failures》

还可以用NCC(Normalized Cross Correlation,归一化互相关)和SSD(Sum-of-Squared Differences,差值平方和)作为筛选追踪点的衡量标准。

NCC:ncc

SSD:ssd

Lucas-Kanade追踪器(LKT)cv.calcOpticalFlowPyrLK()

假设条件:

(1)亮度恒定:同一点随着时间的变化,其亮度不会发生改变;

(2)小运动:短时间的变化不会引起位置的剧烈变化,这样灰度才能对位置求偏导(用前后帧之间单位位置变化引起的灰度变化去近似灰度对位置的偏导数);

(3)空间一致:一个场景上邻近的点投影到图像上也是邻近点,且邻近点速度一致。这是Lucas-Kanade光流法特有的假定。

设在短时间内前一帧图像块A与后一帧图像块B的值(图像的内容)不变,那么就是图像块在图像坐标系下的的速度。

 

おすすめ

転載: blog.csdn.net/weixin_41386168/article/details/109721754