重磅干貨,第一時(shí)間送達(dá) 跟蹤對(duì)象是計(jì)算機(jī)視覺領(lǐng)域的重要應(yīng)用。這在監(jiān)控系統(tǒng)、國防、自動(dòng)駕駛汽車等方面都有用例。在本文中,我們將討論一種稱為均值漂移算法的基本跟蹤算法,并將通過在視頻中跟蹤汽車來了解其應(yīng)用。 在進(jìn)入均值漂移跟蹤之前,讓我們了解直方圖及其應(yīng)用,以創(chuàng)建均值漂移跟蹤的預(yù)處理輸入。圖像由不同值的像素組成。像素的分布是每幅圖像的一個(gè)重要特征。直方圖對(duì)于通過計(jì)算每個(gè)像素的值數(shù)量來表征圖像內(nèi)容非常有用。要為圖像生成直方圖,我們可以使用 opencv 庫。以下代碼片段將為給定圖像創(chuàng)建直方圖。 img = cv2.imread('image.jpg’) color = {'b','g','r'} for i,col in enumerate(color): hist = cv2.calcHist([img],[i],None,[256],[0,256]) 上面的代碼將為每個(gè)通道創(chuàng)建一個(gè)直方圖。 如果我們想檢測一個(gè)特定的物體或區(qū)域,那個(gè)位置的像素值將是一個(gè)重要的特征。因?yàn)樗c不同的對(duì)象不同。例如,狗和汽車的像素值會(huì)不同。 某個(gè)區(qū)域的直方圖可以看作是一個(gè)函數(shù),它給出了一個(gè)特定像素屬于某個(gè)對(duì)象的概率。通過對(duì)獲得的圖像直方圖進(jìn)行歸一化,我們可以得到給定強(qiáng)度值屬于我們感興趣區(qū)域的概率。獲得直方圖后,我們可以將其反投影到我們想要測試對(duì)象是否存在的任何圖像上。 在反向投影的情況下,我們用我們?yōu)楦信d趣的對(duì)象計(jì)算的歸一化直方圖的相應(yīng)概率值替換輸入圖像的每個(gè)像素值。與感興趣區(qū)域相似的位置的強(qiáng)度值比不相似的區(qū)域具有更高的概率值。簡而言之,我們可以說反投影表示我們的測試圖像包含參考圖像對(duì)象的概率。 Mean-shift 是我們將用來跟蹤視頻中對(duì)象的算法。考慮一個(gè)區(qū)域中的一組點(diǎn),如下所示。 初始窗口顯示為名稱為 C1 的藍(lán)色圓圈?,F(xiàn)在,當(dāng)我們計(jì)算窗口的質(zhì)心與中心 C1 不匹配時(shí)。所以我們移動(dòng)窗口,使 c1_r 成為窗口的新中心。現(xiàn)在我們的窗口已經(jīng)移動(dòng)了,讓我們?cè)俅斡?jì)算質(zhì)心并繼續(xù)相同的過程。這樣我們的窗口就會(huì)移動(dòng)到點(diǎn)數(shù)較多的部分。這將一直持續(xù)到質(zhì)心停止移動(dòng)或任何特定的停止標(biāo)準(zhǔn)。 因此,我們需要一個(gè)指示函數(shù),它可以為我們正在跟蹤的對(duì)象的像素值輸出更高的概率值,并為所有其他像素輸出更低的值。Meanshift 將在每次迭代中進(jìn)行加權(quán)質(zhì)心計(jì)算,因此它會(huì)偏向具有更高權(quán)重(概率)的像素,這正是我們想要的,因?yàn)榕c roi 相似的像素將具有更高的概率值。 我們的目標(biāo)是跟蹤視頻中出現(xiàn)的黃色汽車。為此,讓我們首先加載視頻。 這里我們將使用 opencv 庫。我們將創(chuàng)建一個(gè)視頻捕捉對(duì)象。視頻應(yīng)作為參數(shù)傳遞。以下代碼片段為我們完成了工作。 import cv2 cap = cv2.VideoCapture('6.mp4’) 如前所述,我們必須從應(yīng)用均值平移算法的地方隨機(jī)初始化 roi。我手動(dòng)計(jì)算了初始位置,因?yàn)?meanshift 本身無法做到。 frame_h,frame_w = frame.shape[:2] size = (frame_h,frame_w) w =frame_w//8 h =frame_h//8 x =600 y =320 track_window = (x,y,w,h) 從視頻中可以看出,汽車的顏色是黃色,很容易與其他物體的顏色區(qū)分開來。因此,我們想將 RGB 色彩空間轉(zhuǎn)換為 HSV。HSV 模型的色調(diào)成分幫助我們更好地理解物體的顏色??紤]下面的代碼片段。 roi =frame[y:y+h, x-w:x] hsv_roi = cv2.cvtColor(roi,cv2.COLOR_BGR2HSV) mask = None roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0,180]) cv2.normalize(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX) 在第一行中,我們定義了感興趣的區(qū)域。然后我們將幀從bgr 顏色空間轉(zhuǎn)換為 hsv 顏色空間。Mask 被聲明為 none,因?yàn)槲覀円?jì)算整個(gè)幀的直方圖。在第 4 行中,我們計(jì)算了感興趣區(qū)域的直方圖。為此,我們僅考慮了第 4 行的第二個(gè)參數(shù)中隱含的色調(diào)通道。Opencv 通常有 180 個(gè)色調(diào)值(盡管也可以有 360 個(gè)),我們?cè)谶@里考慮了 180 個(gè) bin(每個(gè)值 1 個(gè) bin)。最后一個(gè)參數(shù)是我們考慮了所有 180 個(gè)色調(diào)值的范圍。在下一步中,我們將 roi 歸一化在 0-255 范圍內(nèi)。 term_crit =(cv2.TERM_CRITERIA_COUNT | cv2.TERM_CRITERIA_EPS,10,1) 表示均值漂移算法的終止標(biāo)準(zhǔn)也很重要。我們將在 10 次迭代后或當(dāng)偏移不超過 1 個(gè)像素時(shí)停止計(jì)算質(zhì)心。 true,frame = cap.read() while true: hsv =cv2.cvtColor(frame,cv2.COLOR_BGR2HSV) back_project = cv2.calcBackProject([hsv], [0],roi_hist, [0,180],1) num_iters,window = cv2.meanShift(back_proj,track_window,term_crit) x,y,w,h =window cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2) cv2.imshow('back-projection’,back_project) cv2.imshow('meanshift',frame) cap.read() 返回一個(gè)布爾值。如果幀被正確讀取,它將是真的。獲得幀后,我們會(huì)將其轉(zhuǎn)換為 hsv 顏色空間。將幀轉(zhuǎn)換為 hsv 顏色空間后,我們將使用預(yù)先計(jì)算的直方圖進(jìn)行反向投影,以了解幀的哪一部分具有我們感興趣的對(duì)象。然后我們應(yīng)用了meanshift算法來跟蹤對(duì)象。然后我們的工作是將結(jié)果可視化,這是由 imshow 函數(shù)完成的。 盡管該算法在這種情況下表現(xiàn)出色,但仍然幾乎沒有缺點(diǎn)。例如,我們必須手動(dòng)給出我們感興趣的對(duì)象的位置,這對(duì)于任何現(xiàn)實(shí)生活中的實(shí)現(xiàn)都是不可取的。此外,窗口大小不會(huì)隨著被跟蹤幀中對(duì)象的大小而改變。 |
|