網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
目標(biāo)跟蹤的過程:
1、獲取對(duì)象檢測(cè)的初始集
2、為每個(gè)初始檢測(cè)創(chuàng)建唯一的ID
3、然后在視頻幀中跟蹤每個(gè)對(duì)象的移動(dòng),保持唯一ID的分配
本文使用OpenCV實(shí)現(xiàn)質(zhì)心跟蹤,這是一種易于理解但高效的跟蹤算法。
質(zhì)心跟蹤算法步驟
步驟1:接受邊界框坐標(biāo)并計(jì)算質(zhì)心
質(zhì)心跟蹤算法假設(shè)我們?yōu)槊恳粠械拿總€(gè)檢測(cè)到的對(duì)象傳入一組邊界框 (x, y) 坐標(biāo)。
這些邊界框可以由任何類型的對(duì)象檢測(cè)器(顏色閾值 + 輪廓提取、Haar 級(jí)聯(lián)、HOG + 線性 SVM、SSD、Faster R-CNN 等)生成,前提是它們是針對(duì) 該視頻。
通過邊界框坐標(biāo),就可以計(jì)算“質(zhì)心”(邊界框的中心 (x, y) 坐標(biāo))。 如上圖演示了通過一組邊界框坐標(biāo)計(jì)算出質(zhì)心。
給初始的邊界框分配ID。
步驟2:計(jì)算新邊界框和現(xiàn)有對(duì)象之間的歐幾里得距離
對(duì)于視頻流中的每個(gè)后續(xù)幀,首先執(zhí)行步驟1; 然后,我們首先需要確定是否可以將新的對(duì)象質(zhì)心(黃色)與舊的對(duì)象質(zhì)心(紫色)相關(guān)聯(lián),而不是為每個(gè)檢測(cè)到的對(duì)象分配一個(gè)新的唯一 ID(這會(huì)破壞對(duì)象跟蹤的目的)。 為了完成這個(gè)過程,我們計(jì)算每對(duì)現(xiàn)有對(duì)象質(zhì)心和輸入對(duì)象質(zhì)心之間的歐幾里得距離(用綠色箭頭突出顯示)。
上圖可以看出,我們這次在圖像中檢測(cè)到了三個(gè)對(duì)象。 靠近的兩對(duì)是兩個(gè)現(xiàn)有對(duì)象。
然后我們計(jì)算每對(duì)原始質(zhì)心(黃色)和新質(zhì)心(紫色)之間的歐幾里得距離。 但是我們?nèi)绾问褂眠@些點(diǎn)之間的歐幾里得距離來實(shí)際匹配它們并關(guān)聯(lián)它們呢?
答案在步驟3。
步驟 3:更新現(xiàn)有對(duì)象的 (x, y) 坐標(biāo)
質(zhì)心跟蹤算法的主要假設(shè)是給定對(duì)象可能會(huì)在后續(xù)幀之間移動(dòng),但幀 F_t 和 F_{t + 1} 的質(zhì)心之間的距離將小于對(duì)象之間的所有其他距離。
因此,如果我們選擇將質(zhì)心與后續(xù)幀之間的最小距離相關(guān)聯(lián),我們可以構(gòu)建我們的對(duì)象跟蹤器。
在上圖中,可以看到質(zhì)心跟蹤器算法如何選擇關(guān)聯(lián)質(zhì)心以最小化它們各自的歐幾里得距離。
但是左下角的孤獨(dú)點(diǎn)呢?
它沒有與任何東西相關(guān)聯(lián)——我們?nèi)绾翁幚硭?/p>
步驟4:注冊(cè)新對(duì)象
如果輸入檢測(cè)比跟蹤的現(xiàn)有對(duì)象多,我們需要注冊(cè)新對(duì)象。 “注冊(cè)”僅僅意味著我們通過以下方式將新對(duì)象添加到我們的跟蹤對(duì)象列表中:
為其分配一個(gè)新的對(duì)象 ID
存儲(chǔ)該對(duì)象的邊界框坐標(biāo)的質(zhì)心
然后我們可以返回到步驟2,重復(fù)執(zhí)行。
上圖演示了使用最小歐幾里得距離關(guān)聯(lián)現(xiàn)有對(duì)象 ID,然后注冊(cè)新對(duì)象的過程。
步驟5:注銷舊對(duì)象
當(dāng)舊的對(duì)象超出范圍時(shí),注銷舊對(duì)象、
項(xiàng)目結(jié)構(gòu)
使用 OpenCV 實(shí)現(xiàn)質(zhì)心跟蹤
新建 centroidtracker.py,寫入代碼:
# import the necessary packages from scipy.spatial import distance as dist from collections import OrderedDict import numpy as np class CentroidTracker(): ? ? def __init__(self, maxDisappeared=50): ? ? ? ? self.nextObjectID = 0 ? ? ? ? self.objects = OrderedDict() ? ? ? ? self.disappeared = OrderedDict() ? ? ? ? # 存儲(chǔ)給定對(duì)象被允許標(biāo)記為“消失”的最大連續(xù)幀數(shù),直到我們需要從跟蹤中注銷該對(duì)象 ? ? ? ? self.maxDisappeared = maxDisappeared
導(dǎo)入了所需的包和模塊:distance 、 OrderedDict 和 numpy 。
定義類 CentroidTracker 。構(gòu)造函數(shù)接受一個(gè)參數(shù)maxDisappeared,即給定對(duì)象必須丟失/消失的最大連續(xù)幀數(shù),如果超過這個(gè)數(shù)值就將這個(gè)對(duì)象刪除。
四個(gè)類變量:
nextObjectID :用于為每個(gè)對(duì)象分配唯一 ID 的計(jì)數(shù)器。如果一個(gè)對(duì)象離開幀并且沒有返回 maxDisappeared 幀,則將分配一個(gè)新的(下一個(gè))對(duì)象 ID。
objects :使用對(duì)象 ID 作為鍵和質(zhì)心 (x, y) 坐標(biāo)作為值的字典。
disappeared:保持特定對(duì)象 ID(鍵)已被標(biāo)記為“丟失”的連續(xù)幀數(shù)(值)。
maxDisappeared :在我們?nèi)∠?cè)對(duì)象之前,允許將對(duì)象標(biāo)記為“丟失/消失”的連續(xù)幀數(shù)。
讓我們定義負(fù)責(zé)向我們的跟蹤器添加新對(duì)象的 register 方法:
def register(self, centroid): ? ? ? ? # 注冊(cè)對(duì)象時(shí),我們使用下一個(gè)可用的對(duì)象ID來存儲(chǔ)質(zhì)心 ? ? ? ? self.objects[self.nextObjectID] = centroid ? ? ? ? self.disappeared[self.nextObjectID] = 0 ? ? ? ? self.nextObjectID += 1 ? ? def deregister(self, objectID): ? ? ? ? # 要注銷注冊(cè)對(duì)象ID,我們從兩個(gè)字典中都刪除了該對(duì)象ID ? ? ? ? del self.objects[objectID] ? ? ? ? del self.disappeared[objectID]
register 方法接受一個(gè)質(zhì)心,然后使用下一個(gè)可用的對(duì)象 ID 將其添加到對(duì)象字典中。
對(duì)象消失的次數(shù)在消失字典中初始化為 0。
最后,我們?cè)黾?nextObjectID,這樣如果一個(gè)新對(duì)象進(jìn)入視野,它將與一個(gè)唯一的 ID 相關(guān)聯(lián)。
與我們的注冊(cè)方法類似,我們也需要一個(gè)注銷方法。
deregister 方法分別刪除對(duì)象和消失字典中的 objectID。
質(zhì)心跟蹤器實(shí)現(xiàn)的核心位于update方法中
?def update(self, rects): ? ? ? ? # 檢查輸入邊界框矩形的列表是否為空 ? ? ? ? if len(rects) == 0: ? ? ? ? ? ? # 遍歷任何現(xiàn)有的跟蹤對(duì)象并將其標(biāo)記為消失 ? ? ? ? ? ? for objectID in list(self.disappeared.keys()): ? ? ? ? ? ? ? ? self.disappeared[objectID] += 1 ? ? ? ? ? ? ? ? # 如果達(dá)到給定對(duì)象被標(biāo)記為丟失的最大連續(xù)幀數(shù),請(qǐng)取消注冊(cè) ? ? ? ? ? ? ? ? if self.disappeared[objectID] > self.maxDisappeared: ? ? ? ? ? ? ? ? ? ? self.deregister(objectID) ? ? ? ? ? ? # 由于沒有質(zhì)心或跟蹤信息要更新,請(qǐng)盡早返回 ? ? ? ? ? ? return self.objects ? ? ? ? # 初始化當(dāng)前幀的輸入質(zhì)心數(shù)組 ? ? ? ? inputCentroids = np.zeros((len(rects), 2), dtype="int") ? ? ? ? # 在邊界框矩形上循環(huán) ? ? ? ? for (i, (startX, startY, endX, endY)) in enumerate(rects): ? ? ? ? ? ? # use the bounding box coordinates to derive the centroid ? ? ? ? ? ? cX = int((startX + endX) / 2.0) ? ? ? ? ? ? cY = int((startY + endY) / 2.0) ? ? ? ? ? ? inputCentroids[i] = (cX, cY) ? ? ? ? # 如果我們當(dāng)前未跟蹤任何對(duì)象,請(qǐng)輸入輸入質(zhì)心并注冊(cè)每個(gè)質(zhì)心 ? ? ? ? if len(self.objects) == 0: ? ? ? ? ? ? for i in range(0, len(inputCentroids)): ? ? ? ? ? ? ? ? self.register(inputCentroids[i]) ? ? ? ? # 否則,當(dāng)前正在跟蹤對(duì)象,因此我們需要嘗試將輸入質(zhì)心與現(xiàn)有對(duì)象質(zhì)心進(jìn)行匹配 ? ? ? ? else: ? ? ? ? ? ? # 抓取一組對(duì)象ID和相應(yīng)的質(zhì)心 ? ? ? ? ? ? objectIDs = list(self.objects.keys()) ? ? ? ? ? ? objectCentroids = list(self.objects.values()) ? ? ? ? ? ? # 分別計(jì)算每對(duì)對(duì)象質(zhì)心和輸入質(zhì)心之間的距離-我們的目標(biāo)是將輸入質(zhì)心與現(xiàn)有對(duì)象質(zhì)心匹配 ? ? ? ? ? ? D = dist.cdist(np.array(objectCentroids), inputCentroids) ? ? ? ? ? ? # 為了執(zhí)行此匹配,我們必須(1)在每行中找到最小值,然后(2)根據(jù)行索引的最小值對(duì)行索引進(jìn)行排序,以使具有最小值的行位于索引列表的* front *處 ? ? ? ? ? ? rows = D.min(axis=1).argsort() ? ? ? ? ? ? # 接下來,我們?cè)诹猩蠄?zhí)行類似的過程,方法是在每一列中找到最小值,然后使用先前計(jì)算的行索引列表進(jìn)行排序 ? ? ? ? ? ? cols = D.argmin(axis=1)[rows] ? ? ? ? ? ? # 為了確定是否需要更新,注冊(cè)或注銷對(duì)象,我們需要跟蹤已經(jīng)檢查過的行索引和列索引 ? ? ? ? ? ? usedRows = set() ? ? ? ? ? ? usedCols = set() ? ? ? ? ? ? # 循環(huán)遍歷(行,列)索引元組的組合 ? ? ? ? ? ? for (row, col) in zip(rows, cols): ? ? ? ? ? ? ? ? # 如果我們之前已經(jīng)檢查過行或列的值,請(qǐng)忽略它 ? ? ? ? ? ? ? ? if row in usedRows or col in usedCols: ? ? ? ? ? ? ? ? ? ? continue ? ? ? ? ? ? ? ? # 否則,獲取當(dāng)前行的對(duì)象ID,設(shè)置其新的質(zhì)心,然后重置消失的計(jì)數(shù)器 ? ? ? ? ? ? ? ? objectID = objectIDs[row] ? ? ? ? ? ? ? ? self.objects[objectID] = inputCentroids[col] ? ? ? ? ? ? ? ? self.disappeared[objectID] = 0 ? ? ? ? ? ? ? ? # 表示我們已經(jīng)分別檢查了行索引和列索引 ? ? ? ? ? ? ? ? usedRows.add(row) ? ? ? ? ? ? ? ? usedCols.add(col) ? ? ? ? ? ? # 計(jì)算我們尚未檢查的行和列索引 ? ? ? ? ? ? unusedRows = set(range(0, D.shape[0])).difference(usedRows) ? ? ? ? ? ? unusedCols = set(range(0, D.shape[1])).difference(usedCols) ? ? ? ? ? ? # 如果對(duì)象質(zhì)心的數(shù)量等于或大于輸入質(zhì)心的數(shù)量 ? ? ? ? ? ? # 我們需要檢查一下其中的某些對(duì)象是否已潛在消失 ? ? ? ? ? ? if D.shape[0] >= D.shape[1]: ? ? ? ? ? ? ? ? # loop over the unused row indexes ? ? ? ? ? ? ? ? for row in unusedRows: ? ? ? ? ? ? ? ? ? ? # 抓取相應(yīng)行索引的對(duì)象ID并增加消失的計(jì)數(shù)器 ? ? ? ? ? ? ? ? ? ? objectID = objectIDs[row] ? ? ? ? ? ? ? ? ? ? self.disappeared[objectID] += 1 ? ? ? ? ? ? ? ? ? ? # 檢查是否已將該對(duì)象標(biāo)記為“消失”的連續(xù)幀數(shù)以用于注銷該對(duì)象的手令 ? ? ? ? ? ? ? ? ? ? if self.disappeared[objectID] > self.maxDisappeared: ? ? ? ? ? ? ? ? ? ? ? ? self.deregister(objectID) ? ? ? ? ? ? # 否則,如果輸入質(zhì)心的數(shù)量大于現(xiàn)有對(duì)象質(zhì)心的數(shù)量,我們需要將每個(gè)新的輸入質(zhì)心注冊(cè)為可跟蹤對(duì)象 ? ? ? ? ? ? else: ? ? ? ? ? ? ? ? for col in unusedCols: ? ? ? ? ? ? ? ? ? ? self.register(inputCentroids[col]) ? ? ? ? # return the set of trackable objects ? ? ? ? return self.objects
update方法接受邊界框矩形列表。 rects 參數(shù)的格式假定為具有以下結(jié)構(gòu)的元組: (startX, startY, endX, endY) 。
如果沒有檢測(cè)到,我們將遍歷所有對(duì)象 ID 并增加它們的消失計(jì)數(shù)。 我們還將檢查是否已達(dá)到給定對(duì)象被標(biāo)記為丟失的最大連續(xù)幀數(shù)。 如果是,我們需要將其從我們的跟蹤系統(tǒng)中刪除。 由于沒有要更新的跟蹤信息,我們將提前返回。
否則,我們將初始化一個(gè) NumPy 數(shù)組來存儲(chǔ)每個(gè) rect 的質(zhì)心。 然后,我們遍歷邊界框矩形并計(jì)算質(zhì)心并將其存儲(chǔ)在 inputCentroids 列表中。 如果沒有我們正在跟蹤的對(duì)象,我們將注冊(cè)每個(gè)新對(duì)象。
否則,我們需要根據(jù)最小化它們之間的歐幾里得距離的質(zhì)心位置更新任何現(xiàn)有對(duì)象 (x, y) 坐標(biāo)。
接下來我們?cè)趀lse中計(jì)算所有 objectCentroids 和 inputCentroids 對(duì)之間的歐幾里德距離:
獲取 objectID 和 objectCentroid 值。
計(jì)算每對(duì)現(xiàn)有對(duì)象質(zhì)心和新輸入質(zhì)心之間的距離。距離圖 D 的輸出 NumPy 數(shù)組形狀將是 (# of object centroids, # of input centroids) 。要執(zhí)行匹配,我們必須 (1) 找到每行中的最小值,以及 (2) 根據(jù)最小值對(duì)行索引進(jìn)行排序。我們對(duì)列執(zhí)行非常相似的過程,在每列中找到最小值,然后根據(jù)已排序的行對(duì)它們進(jìn)行排序。我們的目標(biāo)是在列表的前面具有最小對(duì)應(yīng)距離的索引值。
下一步是使用距離來查看是否可以關(guān)聯(lián)對(duì)象 ID:
初始化兩個(gè)集合以確定我們已經(jīng)使用了哪些行和列索引。
然后遍歷 (row, col) 索引元組的組合以更新我們的對(duì)象質(zhì)心:
如果我們已經(jīng)使用了此行或列索引,請(qǐng)忽略它并繼續(xù)循環(huán)。
否則,我們找到了一個(gè)輸入質(zhì)心:
- 到現(xiàn)有質(zhì)心的歐幾里得距離最小
- 并且沒有與任何其他對(duì)象匹配
- 在這種情況下,我們更新對(duì)象質(zhì)心(第 113-115 行)并確保將 row 和 col 添加到它們各自的 usedRows 和 usedCols 集合中。
在我們的 usedRows + usedCols 集合中可能有我們尚未檢查的索引:
所以我們必須確定哪些質(zhì)心索引我們還沒有檢查過,并將它們存儲(chǔ)在兩個(gè)新的方便集合(unusedRows 和 usedCols)中。
最終檢查會(huì)處理任何丟失或可能消失的對(duì)象:
如果對(duì)象質(zhì)心的數(shù)量大于或等于輸入質(zhì)心的數(shù)量:
我們需要循環(huán)遍歷未使用的行索引來驗(yàn)證這些對(duì)象是否丟失或消失。
在循環(huán)中,我們將:
1. 增加他們?cè)谧值渲邢У拇螖?shù)。
2. 檢查消失計(jì)數(shù)是否超過 maxDisappeared 閾值,如果是,我們將注銷該對(duì)象。
否則,輸入質(zhì)心的數(shù)量大于現(xiàn)有對(duì)象質(zhì)心的數(shù)量,我們有新的對(duì)象要注冊(cè)和跟蹤.
循環(huán)遍歷未使用的Cols 索引并注冊(cè)每個(gè)新質(zhì)心。 最后,我們將可跟蹤對(duì)象集返回給調(diào)用方法。
實(shí)現(xiàn)對(duì)象跟蹤驅(qū)動(dòng)程序腳本
已經(jīng)實(shí)現(xiàn)了 CentroidTracker 類,讓我們將其與對(duì)象跟蹤驅(qū)動(dòng)程序腳本一起使用。
驅(qū)動(dòng)程序腳本是您可以使用自己喜歡的對(duì)象檢測(cè)器的地方,前提是它會(huì)生成一組邊界框。 這可能是 Haar Cascade、HOG + 線性 SVM、YOLO、SSD、Faster R-CNN 等。
在這個(gè)腳本中,需要實(shí)現(xiàn)的功能:
1、使用實(shí)時(shí) VideoStream 對(duì)象從網(wǎng)絡(luò)攝像頭中抓取幀
2、加載并使用 OpenCV 的深度學(xué)習(xí)人臉檢測(cè)器
3、實(shí)例化 CentroidTracker 并使用它來跟蹤視頻流中的人臉對(duì)象并顯示結(jié)果。
新建 object_tracker.py 插入代碼:
from Model.centroidtracker import CentroidTracker import numpy as np import imutils import time import cv2 # 定義最低置信度 confidence_t=0.5 # 初始化質(zhì)心跟蹤器和框架尺寸 ct = CentroidTracker() (H, W) = (None, None) # 加載檢測(cè)人臉的模型 print("[INFO] loading model...") net = cv2.dnn.readNetFromCaffe("deploy.prototxt", "res10_300x300_ssd_iter_140000_fp16.caffemodel") # 初始化視頻流并允許相機(jī)傳感器預(yù)熱 print("[INFO] starting video stream...") vs = cv2.VideoCapture('11.mp4') time.sleep(2.0) fps = 30 ? ?#保存視頻的FPS,可以適當(dāng)調(diào)整 size=(600,1066)#寬高,根據(jù)frame的寬和高確定。 fourcc = cv2.VideoWriter_fourcc(*"mp4v") videoWriter = cv2.VideoWriter('3.mp4',fourcc,fps,size)#最后一個(gè)是保存圖片的尺寸
導(dǎo)入需要的包。
定義最低置信度。
加載人臉檢測(cè)模型
初始化視頻流或者相機(jī)(設(shè)置成相機(jī)對(duì)應(yīng)的ID就會(huì)啟動(dòng)相機(jī))
接下來定義cv2.VideoWriter的參數(shù)。
# 循環(huán)播放圖像流中的幀 while True: ? ? # 從視頻流中讀取下一幀并調(diào)整其大小 ? ? (grabbed, frame) ?= vs.read() ? ? if not grabbed: ? ? ? ? break ? ? frame = imutils.resize(frame, width=600) ? ? print(frame.shape) ? ? # 如果幀中尺寸為“無”,則抓住它們 ? ? if W is None or H is None: ? ? ? ? (H, W) = frame.shape[:2] ? ? # 從幀中構(gòu)造一個(gè)Blob,將其通過網(wǎng)絡(luò), ? ? # 獲取輸出預(yù)測(cè),并初始化邊界框矩形的列表 ? ? blob = cv2.dnn.blobFromImage(frame, 1.0, (W, H), ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(104.0, 177.0, 123.0)) ? ? net.setInput(blob) ? ? detections = net.forward() ? ? rects = [] ? ? # 循環(huán)檢測(cè) ? ? for i in range(0, detections.shape[2]): ? ? ? ? # 通過確保預(yù)測(cè)的概率大于最小閾值來過濾掉弱檢測(cè) ? ? ? ? if detections[0, 0, i, 2] >0.5: ? ? ? ? ? ? # 計(jì)算對(duì)象邊界框的(x,y)坐標(biāo),然后更新邊界框矩形列表 ? ? ? ? ? ? box = detections[0, 0, i, 3:7] * np.array([W, H, W, H]) ? ? ? ? ? ? rects.append(box.astype("int")) ? ? ? ? ? ? # 在對(duì)象周圍畫一個(gè)邊界框,以便我們可視化它 ? ? ? ? ? ? (startX, startY, endX, endY) = box.astype("int") ? ? ? ? ? ? cv2.rectangle(frame, (startX, startY), (endX, endY), ? ? ? ? ? ? ? ? ? ? ? ? ? (0, 255, 0), 2) ? ? # 使用邊界框矩形的計(jì)算集更新質(zhì)心跟蹤器 ? ? objects = ct.update(rects) ? ? # 循環(huán)跟蹤對(duì)象 ? ? for (objectID, centroid) in objects.items(): ? ? ? ? # 在輸出幀上繪制對(duì)象的ID和對(duì)象的質(zhì)心 ? ? ? ? text = "ID {}".format(objectID) ? ? ? ? cv2.putText(frame, text, (centroid[0] - 10, centroid[1] - 10), ? ? ? ? ? ? ? ? ? ? cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) ? ? ? ? cv2.circle(frame, (centroid[0], centroid[1]), 4, (0, 255, 0), -1) ? ? # 顯示輸出畫面 ? ? cv2.imshow("Frame", frame) ? ? videoWriter.write(frame) ? ? key = cv2.waitKey(1) & 0xFF ? ? # 如果按下“ q”鍵,則退出循環(huán) ? ? if key == ord("q"): ? ? ? ? break videoWriter.release() cv2.destroyAllWindows() vs.release()
遍歷幀并將它們調(diào)整為固定寬度(同時(shí)保持縱橫比)。
然后將幀通過 CNN 對(duì)象檢測(cè)器以獲得預(yù)測(cè)和對(duì)象位置(。
初始化一個(gè) rects 列表,即邊界框矩形。
循環(huán)檢測(cè)detections,如果檢測(cè)超過我們的置信度閾值,表明檢測(cè)有效,然后計(jì)算邊框。
在質(zhì)心跟蹤器對(duì)象 ct 上調(diào)用 update 方法。
接下來在輸出幀上繪制對(duì)象的ID和質(zhì)心,將質(zhì)心顯示為一個(gè)實(shí)心圓圈和唯一的對(duì)象 ID 號(hào)文本。 現(xiàn)在我們將能夠可視化結(jié)果并通過將正確的 ID 與視頻流中的對(duì)象相關(guān)聯(lián)來檢查 CentroidTracker 是否正確地跟蹤對(duì)象。
限制和缺點(diǎn)
雖然質(zhì)心跟蹤器在這個(gè)例子中工作得很好,但這種對(duì)象跟蹤算法有兩個(gè)主要缺點(diǎn)。
1、它要求在輸入視頻的每一幀上運(yùn)行對(duì)象檢測(cè)步驟。對(duì)于非常快速的對(duì)象檢測(cè)器(即顏色閾值和 Haar 級(jí)聯(lián)),必須在每個(gè)輸入幀上運(yùn)行檢測(cè)器可能不是問題。但是,如果在 資源受限的設(shè)備上使用計(jì)算量大得多的對(duì)象檢測(cè)器,例如 HOG + 線性 SVM 或基于深度學(xué)習(xí)的檢測(cè)器,那么幀處理將大大減慢。
2、與質(zhì)心跟蹤算法本身的基本假設(shè)有關(guān)——質(zhì)心必須在后續(xù)幀之間靠得很近。
這個(gè)假設(shè)通常成立,但請(qǐng)記住,我們用 2D 幀來表示我們的 3D 世界——當(dāng)一個(gè)對(duì)象與另一個(gè)對(duì)象重疊時(shí)會(huì)發(fā)生什么?
答案是可能發(fā)生對(duì)象 ID 切換。如果兩個(gè)或多個(gè)對(duì)象相互重疊到它們的質(zhì)心相交的點(diǎn),而是與另一個(gè)相應(yīng)對(duì)象具有最小距離,則算法可能(在不知不覺中)交換對(duì)象 ID。重要的是要了解重疊/遮擋對(duì)象問題并非特定于質(zhì)心跟蹤 - 它也發(fā)生在許多其他對(duì)象跟蹤器中,包括高級(jí)對(duì)象跟蹤器。然而,質(zhì)心跟蹤的問題更為明顯,因?yàn)槲覀儑?yán)格依賴質(zhì)心之間的歐幾里得距離,并且沒有額外的度量、啟發(fā)式或?qū)W習(xí)模式。
原文鏈接:https://wanghao.blog.csdn.net/article/details/122547436
相關(guān)推薦
- 2022-09-16 Android?Jetpack架構(gòu)中ViewModel接口暴露的不合理探究_Android
- 2022-06-02 C++實(shí)現(xiàn)投骰子的隨機(jī)游戲_C 語(yǔ)言
- 2023-01-08 基于C#實(shí)現(xiàn)屏幕取色器的示例詳解_C#教程
- 2023-01-11 Pytorch如何把Tensor轉(zhuǎn)化成圖像可視化_python
- 2023-04-19 SQLSERVER?的?truncate?和?delete?區(qū)別解析_MsSql
- 2022-07-08 ???????C語(yǔ)言實(shí)現(xiàn)單鏈表基本操作方法_C 語(yǔ)言
- 2022-06-08 Golang原生rpc(rpc服務(wù)端源碼解讀)_Golang
- 2022-05-21 python?判斷文件或文件夾是否存在_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支