OpenCV實現對象跟蹤的方法

介紹

OpenCV 是一個很好的處理圖像和視頻的工具。無論你是想讓你的照片呈現 90 年代的黑白效果,還是執行復雜的數學運算,OpenCV 都可以隨時為你服務。

如果你對計算機視覺感興趣,則必須具備 OpenCV 的知識。該庫包含 2500 多種優化算法,可用於執行各種任務。它被谷歌、微軟、IBM 等許多行業巨頭使用,並被廣泛用於研究小組。該庫支持多種語言,包括 java、c++ 和 python。

本文將向你展示如何使用 OpenCV 中的一些基本功能來執行復雜的對象跟蹤任務。

對象跟蹤

對象跟蹤是在視頻中定位移動對象的過程。你可以考慮一個足球比賽的例子。

你有正在進行的比賽的實時饋送,你的任務是隨時跟蹤球的位置。對於普通人來說,這項任務似乎很簡單,但即使是最聰明的機器,它還是太復雜瞭。

你可能知道,計算機隻能理解數字。它不瞭解圖像是什麼,但瞭解與圖像相關聯的像素值。在人眼看來完全相同的兩個圖像在計算機看來可能並不相同,因為即使像素的微小變化也會導致圖片之間的差異。因為對象跟蹤被認為是計算機視覺中最復雜的任務之一。雖然復雜,但也不是無法實現的。

可以使用機器學習以及基於深度學習的方法來執行對象跟蹤。

一方面,深度學習方法在復雜任務上提供瞭更好的結果,並且非常通用,需要大量的訓練數據。而基於 ML 的方法非常簡單,但不是通用的。

在本文中,我們將使用基於 ML 的方法以及我們將在本文後面討論的各種計算機視覺技術。

該技術廣泛應用於監控、安全、交通監控、機器人視覺、視頻通信等領域。此外,對象跟蹤有幾個用例,例如人群計數、自動駕駛汽車、人臉檢測等。你能想出更多可以在日常生活中使用對象跟蹤的示例嗎?

由於現實生活中有如此多的應用,因此該領域正在進行不斷的研究,以實現更高的準確性並使模型更加穩健。

對於本文,我們將使用此視頻(https://drive.google.com/file/d/1N6NcFpveLQLc_DnFjfuMMvfuCMTAJRFm/view?usp=sharing)。

正如你將看到的,有一個紅色的球在迷宮中移動,我們的任務是檢測球的位置並找到它的質心。你還可以在背景中看到巨大的噪音(人群),使任務更具挑戰性。

91d4fea877e0d3170384998316e5ebbd.jpg

1.首先,我們導入將要使用的所需庫。

import numpy as np
import cv2

2.我們將定義一個函數來調整圖像的大小,以便它們在足夠大的情況下適合我們的屏幕。這一步是完全可選的,可以隨意跳過。

def resize(img):
        return cv2.resize(img,(512,512)) # arg1- input image, arg- output_width, output_height

3.你可能知道,視頻是由幀組成的。幀隻不過是構成整個動態畫面的眾多靜止圖像之一。下一步將使用 OpenCV 中的 VideoCapture() 函數讀取這些幀,並使用 while 循環,我們可以看到幀在移動。

你可以使用將屏幕暫停 x 毫秒的 cv2.waitKey(x) 來調整視頻的速度。

cap=cv2.VideoCapture(vid_file_path)
ret,frame=cap.read()
 
while ret==True:
    ret,frame=cap.read()
    cv2.imshow("frame",resize(frame))
    key=cv2.waitKey(1)
    if key==ord('q'):
        break
cv2.waitKey(0)
cv2.destroyAllWindows()

4.現在是時候執行一些閾值和預處理瞭。OpenCV 讀取 BGR 格式的圖像,因此我們將把色彩空間從 BGR 轉換為 HSV。

為什麼是 HSV 而不是 BGR 或任何其他格式?

我們使用 HSV 顏色格式,因為它對外部照明的微小變化更敏感。因此,它將提供更準確的蒙版,從而獲得更好的結果。

轉換色彩空間後,我們要做的是過濾掉紅色通道並創建一個蒙版框。

hsv 格式的紅色通道出現在 [0,230,170] 到 [255,255,220] 范圍內。

cap=cv2.VideoCapture(vid_file_path)
 
 
ret,frame=cap.read()
l_b=np.array([0,230,170])# lower hsv bound for red
u_b=np.array([255,255,220])# upper hsv bound to red
 
while ret==True:
    ret,frame=cap.read()
 
    hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
    mask=cv2.inRange(hsv,l_b,u_b)
 
    cv2.imshow("frame",resize(frame))
 
    cv2.imshow("mask",mask)
 
 
    key=cv2.waitKey(1)
    if key==ord('q'):
        break
cv2.waitKey(0)
cv2.destroyAllWindows()

b6decc3fd55c1004b61e133dd4bf1c9e.jpg

(此圖已調整大小)

5.到目前為止,我們已經創建瞭幀的蒙版圖像,並且我們已經過濾掉瞭大部分噪聲。接下來是獲得球的邊界。為此,我們將使用輪廓檢測的概念。

輪廓隻不過是圍繞我們球的邊界。值得慶幸的是,我們不必自己找到這些邊界,因為 OpenCV 允許我們可以將其用於我們的目的的函數 findContours()。它需要一個蒙版圖像並返回一個輪廓數組。

有關輪廓的更多信息,請訪問:https://docs.opencv.org/4.5.2/d4/d73/tutorial_py_contours_begin.html

理想情況下,在我們的例子中,輪廓的值應該是 1,因為我們隻有一個球,但由於有些人戴著紅帽子,我們會得到不止一個。你能想出一些辦法來進一步降低這種噪音嗎?

為瞭解決這個問題,我們將使用 OpenCV 中的另一個函數 cv2.contourArea()。我們知道在蒙版圖像中,球的面積最大,它的輪廓也是如此。因此,我們將得到面積最大的輪廓。

我們有球的輪廓,我們可以使用 cv2.drawContours() 函數直接繪制這些輪廓。但是對於檢測任務,我們一般做的就是用一個緊密綁定的矩形來表示對象已經被檢測到瞭。

為此,我們將使用 cv2.boundingRect() 函數。此函數將返回矩形的坐標,然後 cv2.rectangle() 函數將為我們繪制矩形。

cap=cv2.VideoCapture(vid_file_path)
 
 
ret,frame=cap.read()
l_b=np.array([0,230,170])# lower hsv bound for red
u_b=np.array([255,255,220])# upper hsv bound to red
 
while ret==True:
    ret,frame=cap.read()
 
    hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
    mask=cv2.inRange(hsv,l_b,u_b)
 
    contours,_= cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
 
    max_contour = contours[0]
         for contour in contours:
                if cv2.contourArea(contour)>cv2.contourArea(max_contour):
 
                      max_contour=contour
 
         contour=max_contour
         approx=cv2.approxPolyDP(contour, 0.01*cv2.arcLength(contour,True),True)
         x,y,w,h=cv2.boundingRect(approx)
         cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),4)
 
    cv2.imshow("frame",resize(frame))
 
    cv2.imshow("mask",mask)

d322b9afd5f1618649233b5160acc913.jpg

(此圖已調整大小)

6.此外,我們可以做的是同時檢測球的質心。為此,我們將使用 cv2.moments。cv2.moments 計算輪廓內像素強度的加權平均總和,因此允許從斑點中獲取一些更有用的信息,如其半徑、質心等。

確保在使用該函數之前將圖像轉換為二進制格式。你可以在這裡瞭解更多關於時刻的信息:https://docs.opencv.org/3.4/d0/d49/tutorial_moments.html。

cap=cv2.VideoCapture(vid_file_path)
 
 
ret,frame=cap.read()
l_b=np.array([0,230,170])# lower hsv bound for red
u_b=np.array([255,255,220])# upper hsv bound to red
 
while ret==True:
    ret,frame=cap.read()
 
    hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
    mask=cv2.inRange(hsv,l_b,u_b)
 
    contours,_= cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
 
    max_contour = contours[0]
         for contour in contours:
 
 
                if cv2.contourArea(contour)>cv2.contourArea(max_contour):
 
                  max_contour = contour
 
         approx=cv2.approxPolyDP(contour, 0.01*cv2.arcLength(contour,True),True)
         x,y,w,h=cv2.boundingRect(approx)
         cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),4)
 
         M=cv2.moments(contour)

364ad9a8e21446d83e0c2124040577f0.jpg

到此這篇關於開始使用 OpenCV 進行對象跟蹤的文章就介紹到這瞭,更多相關OpenCV 對象跟蹤內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: