opencv 追踪算法

追踪的目的是在当前帧找到前一帧确定的对象。因为我们要在当前帧确定其对象位置,因此我们需要知道它是如何运动的,换句话说,需要知道运动模型参数。
如果对象非常简单且没有什么外貌上的变化,我们可以使用模板匹配。但是现实并未如此,当前模型可能随时随地变换(如人脸,你可能下一秒变成侧脸)。
Opencv中集成了诸多算法,随着其不断更新,算法的种类也越来越多,3.3版本的算法种类是6种-BOOSTING, MIL, KCF, TLD, MEDIANFLOW ,GOTURN
1、 BOOSTING
基于在线的AdaBoost, 这个分类器需要对对象的正、负例进行训练。用户提供的初始化框(或通过其它算法检测到对象,必须MOG2,KNN检测到小车)来作为对象的正例,并将边界框外的图像块作为背景(负类)
优点:没有。这个算法已经有10年的历史了,找不到一个很好的理由去使用它,特别是当其他基于类似原理的高级跟踪器(MIL, KCF)也可用的时候。
缺点:跟踪性能平庸。不知道什么时候跟踪失败。
2、 MIL–Multiple Instance Learning
这个跟踪器与上面描述的boost跟踪器类似。最大的区别是,它不是只考虑对象的当前位置作为正类,还考虑当前位置邻域范围的潜在位置作为正类。
优点: 性能很好。它不boosting跟踪器那样,在部分遮挡下依然表现挺佳。如果使用的是OpenCV 3.0,这可能是最好的跟踪器。但如果使用的是更高版本,请考虑KCF。
缺点:跟踪失败没有可靠的报告。完全遮挡的话性能差
3、 KCF–Kernelized Correlation Filters
这个跟踪器基于前面两个跟踪器中提出的想法。该跟踪器在MIL跟踪器中使用的多个正样本具有较大的重叠区域。
优点:精度和速度都比MIL好,如果使用OpenCV 3.1和以上,建议在大多数应用程序中使用该算法。
缺点:还是完全遮挡
4、TLD
TLD stands for Tracking, learning and detection. 如果有一个视频序列,对象隐藏在另一个对象后面,这个跟踪器可能是一个不错的选择。
优点:在多帧的情况下,在遮挡的情况下工作最好。此外,该算法能很好的应对尺度变化。
缺点:大量的假阳性使得其几乎无法使用
笔者在测试这个算法时候,程序over
5、MEDIANFLOW
经过测试中,发现这个跟踪器在小运动情况下表现最好。不像其他跟踪器,即使跟踪失败了还继续跟踪,这个跟踪器知道什么时候失败。
优点:跟踪失败报告,小运动下表现好
缺点:大运动,该算法失灵
笔者cap=cv2.Videocapture(0),时候使用这个算法并不好。
6、GOTURN
在跟踪器类的所有跟踪算法中,这是唯一基于卷积神经网络(CNN)的算法。也是唯一一个使用离线训练的模型,因此它比其他跟踪器更快。从opencv文档可以看出该算法对视角变化、光照、变形都具有很好的鲁棒性,但是对于遮挡性能较差。
笔者opencv3.3 ,这个算法报错。
这里写图片描述
这里写图片描述

# -*- coding: utf-8 -*-
import cv2
import sys
tracker_type=str(sys.argv[1])
if tracker_type=='BOOSTING':
    tracker=cv2.TrackerBoosting_create()
if tracker_type == 'MIL':
    tracker = cv2.TrackerMIL_create()
if tracker_type == 'KCF':
    tracker = cv2.TrackerKCF_create()
if tracker_type == 'TLD':
    tracker = cv2.TrackerTLD_create()
if tracker_type == 'MEDIANFLOW':
    tracker = cv2.TrackerMedianFlow_create()
if tracker_type == 'GOTURN':
    tracker = cv2.TrackerGOTURN_create()
cap=cv2.VideoCapture(0)
if cap.isOpened() is False:
    raise("IO error") #抛出异常
ret,frame1=cap.read()
box=cv2.selectROI(frame1)#返回一个元组(x,y,w,h)
##笔者试过不能追踪点
##如point=(12,21),ok=tracker.init(frame1,point),报错参数少于4
def centerxy(frame1,box):#计算选择区域的质心
    box_img=frame1[int(box[1]):int(box[1] + box[3]),int(box[0]):int(box[0] + box[2])]
    box_gray=cv2.cvtColor(box_img,cv2.COLOR_BGR2GRAY)
    _,thresh=cv2.threshold(box_gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    _,cnts,h=cv2.findContours(thresh,0,1)
    cnt_max=sorted(cnts,key=lambda x:cv2.contourArea(x),reverse=True)[0]
    M=cv2.moments(cnt_max)
    cx=M["m10"]/M["m00"]
    cy=M["m01"]/M["m00"]
    point=(int(cx),int(cy))
    return box_img,point
_,point1=centerxy(frame1,box)
ok=tracker.init(frame1,box)
while 1:
    ret,frame=cap.read()
    if ret==False:
        sys.exit()
    time1=cv2.getTickCount()
    ok, box_new = tracker.update(frame)#更新追踪
    time2=cv2.getTickCount()
    if ok:
         p1 = (int(box_new[0]), int(box_new[1]))
         p2 = (int(box_new[0] + box_new[2]), int(box_new[1] + box_new[3]))
#         p2=(int(point_new[0]), int(point_new[1]))
         cv2.rectangle(frame, p1, p2, (255,0,0), 2, 1)
         box_im,point2=centerxy(frame,box_new)
         cv2.line(box_im,point1,point2,(255,0,0),2)
         cv2.circle(box_im,point2,10,(0,0,255),2)
         print(point2)
         point1=point2 #前一帧位置和当前帧位置,线越长,运动距离越大
    else:
        cv2.putText(frame,"failure",(20,20),cv2.FONT_HERSHEY_SIMPLEX,1,(255,0,0),2)
    fps=cv2.getTickFrequency()/(time2-time1)
    cv2.putText(frame,str(fps),(20,20),cv2.FONT_HERSHEY_SIMPLEX,1,(255,0,0),2)
    cv2.imshow("frame",frame)
    k=cv2.waitKey(10)
    if k==27:
        break
cap.release()
cv2.destroyAllWindows()

猜你喜欢

转载自blog.csdn.net/qq_15642411/article/details/80069415