日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無(wú)先后,達(dá)者為師

網(wǎng)站首頁(yè) 編程語(yǔ)言 正文

利用OpenCV進(jìn)行對(duì)象跟蹤的示例代碼_python

作者:AI浩 ? 更新時(shí)間: 2022-04-12 編程語(yǔ)言

OpenCV 對(duì)象跟蹤

這篇文章使用 OpenCV 中內(nèi)置的八種不同的對(duì)象跟蹤算法,實(shí)現(xiàn)對(duì)物體的跟蹤。

首先,介紹一下8種跟蹤算法。

然后,演示如何使用OpenCV實(shí)現(xiàn)這些跟蹤算法。

最后,對(duì)本文做總結(jié)。

OpenCV 對(duì)象跟蹤器

OpenCV 八種對(duì)象跟蹤器:

BOOSTING Tracker:基于用于驅(qū)動(dòng) Haar 級(jí)聯(lián) (AdaBoost) 背后的機(jī)器學(xué)習(xí)的相同算法,但與 Haar 級(jí)聯(lián)一樣,已有十多年的歷史。這個(gè)跟蹤器很慢,而且效果不太好。僅出于遺留原因和比較其他算法而感興趣。 (最低 OpenCV 3.0.0)

MIL Tracker:比 BOOSTING 跟蹤器更準(zhǔn)確,但在報(bào)告失敗方面做得很差。 (最低 OpenCV 3.0.0)

KCF 跟蹤器:內(nèi)核化相關(guān)過(guò)濾器。比 BOOSTING 和 MIL 更快。與 MIL 和 KCF 類(lèi)似,不能很好地處理完全遮擋。 (最低 OpenCV 3.1.0)

CSRT Tracker:判別相關(guān)濾波器(具有通道和空間可靠性)。往往比 KCF 更準(zhǔn)確,但速度稍慢。 (最低 OpenCV 3.4.2)

MedianFlow Tracker:很好地報(bào)告失敗;但是,如果運(yùn)動(dòng)中的跳躍太大,例如快速移動(dòng)的物體,或者外觀快速變化的物體,模型就會(huì)失敗。 (最低 OpenCV 3.0.0)

TLD 跟蹤器:我不確定 TLD 跟蹤器的 OpenCV 實(shí)現(xiàn)或?qū)嶋H算法本身是否存在問(wèn)題,但 TLD 跟蹤器極易出現(xiàn)誤報(bào)。我不推薦使用這個(gè) OpenCV 對(duì)象跟蹤器。 (最低 OpenCV 3.0.0)

MOSSE Tracker:非常非常快。不如 CSRT 或 KCF 準(zhǔn)確,但如果您需要純粹的速度,這是一個(gè)不錯(cuò)的選擇。 (最低 OpenCV 3.4.1)

GOTURN Tracker:OpenCV 中唯一基于深度學(xué)習(xí)的目標(biāo)檢測(cè)器。它需要額外的模型文件才能運(yùn)行(本文不會(huì)涉及)。我最初的實(shí)驗(yàn)表明,盡管據(jù)說(shuō)它可以很好地處理查看變化,但使用起來(lái)還是有點(diǎn)痛苦(盡管我最初的實(shí)驗(yàn)并沒(méi)有證實(shí)這一點(diǎn))。我將嘗試在以后的帖子中介紹它,但與此同時(shí),請(qǐng)看一下 Satya 的文章。 (最低 OpenCV 3.2.0)

個(gè)人建議:

  • 當(dāng)需要更高的對(duì)象跟蹤精度并且可以容忍較慢的 FPS 吞吐量時(shí),請(qǐng)使用 CSRT
  • 當(dāng)需要更快的 FPS 吞吐量但可以處理稍低的對(duì)象跟蹤精度時(shí)使用 KCF
  • 當(dāng)需要純粹的速度時(shí)使用 MOSSE

物體跟蹤

在開(kāi)始算法之前,先寫(xiě)輔助方法和類(lèi)。

fps類(lèi):

import datetime

class FPS:
?? ?def __init__(self):
?? ??? ?# 定義開(kāi)始時(shí)間、結(jié)束時(shí)間和總幀數(shù)
?? ??? ?self._start = None
?? ??? ?self._end = None
?? ??? ?self._numFrames = 0

?? ?def start(self):
?? ??? ?# 開(kāi)始計(jì)時(shí)
?? ??? ?self._start = datetime.datetime.now()
?? ??? ?return self

?? ?def stop(self):
?? ??? ?# 停止計(jì)時(shí)
?? ??? ?self._end = datetime.datetime.now()

?? ?def update(self):
?? ??? ?# 增加在開(kāi)始和結(jié)束間隔期間檢查的總幀數(shù)
?? ??? ?self._numFrames += 1

?? ?def elapsed(self):
?? ??? ?# 返回開(kāi)始和結(jié)束間隔之間的總秒數(shù)
?? ??? ?return (self._end - self._start).total_seconds()

?? ?def fps(self):
?? ??? ?# 計(jì)算每秒幀數(shù)
?? ??? ?return self._numFrames / self.elapsed()

請(qǐng)打開(kāi)一個(gè)新文件,將其命名為 object_tracker.py ,定義resize方法,等比例縮放圖片。

import cv2
from fps import FPS
def resize(image, width=None, height=None, inter=cv2.INTER_AREA):
    # 初始化要調(diào)整大小的圖像的尺寸并抓取圖像大小
    dim = None
    (h, w) = image.shape[:2]
    # 如果寬高都為None,則返回原圖
    if width is None and height is None:
        return image
    # 檢查寬度是否為None
    if width is None:
        # 計(jì)算高度的比例并構(gòu)造尺寸
        r = height / float(h)
        dim = (int(w * r), height)
    # 否則,高度為 None
    else:
        # 計(jì)算寬度的比例并構(gòu)造尺寸
        r = width / float(w)
        dim = (width, int(h * r))
    resized = cv2.resize(image, dim, interpolation=inter)
    return resized

定義全局變量:

videos = 0
tracker_type = 'kcf'

我們的命令行參數(shù)包括:

videos:輸入視頻文件或者攝像頭的ID。

tracker_type:跟蹤器的類(lèi)型,接下來(lái)的代碼定義了跟蹤器列表。

接下來(lái)定義不同類(lèi)型的跟蹤器:

# 提取 OpenCV 版本信息
(major, minor) = cv2.__version__.split(".")[:2]
# 如果我們使用 OpenCV 3.2 或之前版本,我們可以使用特殊的工廠函數(shù)來(lái)創(chuàng)建我們的對(duì)象跟蹤器
if int(major) == 3 and int(minor) < 3:
    tracker = cv2.Tracker_create(tracker_type)
# 否則,對(duì)于 OpenCV 3.3 或更新版本,我們需要顯式調(diào)用對(duì)應(yīng)的對(duì)象跟蹤器構(gòu)造函數(shù):
else:
    # 初始化一個(gè)字典,將字符串映射到其對(duì)應(yīng)的 OpenCV 對(duì)象跟蹤器實(shí)現(xiàn)
    OPENCV_OBJECT_TRACKERS = {
        "csrt": cv2.TrackerCSRT_create,
        "kcf": cv2.TrackerKCF_create,
        "boosting": cv2.legacy.TrackerBoosting_create,
        "mil": cv2.TrackerMIL_create,
        "tld": cv2.legacy.TrackerTLD_create,
        "medianflow": cv2.legacy.TrackerMedianFlow_create,
        "mosse": cv2.legacy.TrackerMOSSE_create
    }
    # 使用我們的 OpenCV 對(duì)象跟蹤器對(duì)象字典獲取適當(dāng)?shù)膶?duì)象跟蹤器
    tracker = OPENCV_OBJECT_TRACKERS[tracker_type]()

在OpenCV 3.3之前,必須使用cv2.Tracker_create創(chuàng)建跟蹤器對(duì)象,并傳遞跟蹤器名稱(chēng)的大寫(xiě)字符串。

對(duì)于OpenCV 3.3+,可以使用各自的函數(shù)調(diào)用創(chuàng)建每個(gè)跟蹤器,例如cv2.TrackerCSRT_create。字典OPENCV_OBJECT_TRACKERS包含8個(gè)內(nèi)置OpenCV對(duì)象跟蹤器中的七個(gè)。它將對(duì)象跟蹤器命令行參數(shù)字符串(鍵)與實(shí)際的OpenCV對(duì)象跟蹤器函數(shù)(值)進(jìn)行映射。

# 初始化我們要追蹤的物體的邊界框坐標(biāo)
initBB = None
vs = cv2.VideoCapture(videos)
fps = None

initBB初始化為None,此變量將保存我們使用鼠標(biāo)選擇的對(duì)象的邊界框坐標(biāo)。

接下來(lái),初始化VideoCapture對(duì)象和FPS計(jì)數(shù)器。

讓我們開(kāi)始循環(huán)來(lái)自視頻流的幀:

# 循環(huán)播放視頻流中的幀
while True:
    # 抓取當(dāng)前幀。
    (grabbed, frame) = vs.read()
    if not grabbed:
        break
    # 調(diào)整框架大小并獲取框架尺寸。
    frame = resize(frame, width=500)
    (H, W) = frame.shape[:2]

    # 檢查是否正在跟蹤一個(gè)對(duì)象
    if initBB is not None:
        # 抓取物體的新邊界框坐標(biāo)
        (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 計(jì)數(shù)器
        fps.update()
        fps.stop()
        # 初始化在框架上顯示的信息集
        info = [
            ("Tracker", tracker_type),
            ("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

抓住一個(gè)幀,如果獲取不到幀,則退出。

為了使對(duì)象跟蹤算法能夠更快地處理幀,我們將輸入幀的大小調(diào)整為500像素。

然后輸出框架的高和寬。

如果已選擇對(duì)象,則需要更新對(duì)象的位置。 update方法將定位對(duì)象的新位置并返回成功布爾值和對(duì)象的邊界框。

如果成功,我們?cè)诳蚣苌侠L制新的,更新的邊界框位置。

更新FPS。

初始化顯示的文本信息列表。隨后,繪制到frame上。

顯示輸出幀。

   # 使用's'鍵選擇一個(gè)邊界框來(lái)跟蹤
    if key == ord("s"):
        # 選擇跟蹤的對(duì)象的邊界框(選擇 ROI 后按 ENTER 或 SPACE)
        initBB = cv2.selectROI("Frame", frame, fromCenter=False,
                               showCrosshair=True)
        # 使用提供的邊界框坐標(biāo)啟動(dòng) OpenCV 對(duì)象跟蹤器,然后也啟動(dòng) FPS 吞吐量估計(jì)器
        tracker.init(frame, initBB)
        fps = FPS().start()
    # 如果 `q` 鍵被按下,則退出循環(huán)
    elif key == ord("q"):
        break
vs.release()
cv2.destroyAllWindows()

按下“s”鍵時(shí),使用cv2.selectROI“選擇”對(duì)象ROI。此時(shí),視頻幀凍結(jié),用鼠標(biāo)繪制跟蹤對(duì)象的邊界框。

繪制完邊界框,然后按“ENTER”或“SPACE”確認(rèn)選擇。如果需要重新選擇區(qū)域,只需按“ESCAPE”即可。

然后,啟動(dòng)OpenCV 對(duì)象跟蹤器,再啟動(dòng) FPS 吞吐量估計(jì)器。

最后一個(gè)段代碼只是處理我們已經(jīng)脫離循環(huán)的情況。釋放所有指針并關(guān)閉窗口。

總結(jié)

在今天的博客文章中,您學(xué)習(xí)了如何利用OpenCV進(jìn)行對(duì)象跟蹤。具體來(lái)說(shuō),我們回顧了OpenCV庫(kù)中包含的8個(gè)對(duì)象跟蹤算法(從OpenCV 3.4開(kāi)始):

CSRT、KCF、Boosting、MIL、TLD、MedianFlow、MOSSE、GOTURN。

建議對(duì)大多數(shù)對(duì)象跟蹤應(yīng)用程序使用CSRT,KCF或MOSSE:

當(dāng)需要更高的對(duì)象跟蹤精度并且可以容忍更慢的FPS吞吐量時(shí),請(qǐng)使用CSRT

當(dāng)需要更快的FPS吞吐量時(shí)使用KCF,但可以處理稍低的對(duì)象跟蹤精度

當(dāng)需要純粹的速度時(shí)使用MOSSE

原文鏈接:https://blog.csdn.net/hhhhhhhhhhwwwwwwwwww/article/details/122815739

欄目分類(lèi)
最近更新