機器視覺——python實現追蹤物體軌跡

import numpy as np 
import argparse
import time
import cv2

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video",
help = "path to the (optional) video file")
args = vars(ap.parse_args())
# define the upper and lower boundaries for a color
# to be considered "blue"
blueLower = np.array([100,67,0],dtype="uint8")
blueUpper = np.array([255,128,50],dtype="uint8")
# load the video
if not args.get("video"):
camera = cv2.VideoCapture(0)
else:
camera = cv2.VideoCapture(args["video"])

我們將使用NumPy進行數值處理,使用argparse解析命令行參數,使用cv2進行OpenCV綁定。time包是可選的。

我們只需要一個命令行參數,--video,也就是我們視頻的路徑。

我們將在視頻中追蹤的對象是藍色物體。由於除了該物體外,藍色在視頻中的任何其他位置都不常見,因此我們希望跟蹤藍色陰影。為了完成這種顏色跟蹤,我們定義了藍色陰影的下限和上限。請記住,OpenCV表示RGB顏色空間中的像素,但順序相反。

在這種情況下,如果大於R=0,G=67,B=100且小於R=50,G=128,B=255,則將顏色定義為“藍色”。

最後,我們打開視頻文件並使用cv2.VideoCapture函數獲取對它的引用。我們將此引用賦值給變量camera。

# keep looping  

while True:
# grab the current frame
(grabbed,frame) = camera.read()
# check to see if we have reached the end of the video
if args.get("video") and not grabbed:
break
# determine which pixels fall within the blue boundaries
# and then blur the binary image
blue = cv2.inRange(frame,blueLower,blueUpper)
blue = cv2.GaussianBlur(blue,(3,3),0)

現在我們有了對視頻的引用,便可以開始處理幀。

我們開始循環遍歷幀,一次一個。調用read()方法的調用抓取視頻中的下一幀,返回具有兩個值的元組。第一個是grabbed,是一個布爾值,表示是否從視頻文件中成功讀取了幀。第二個frame,是幀本身。

然後,我們檢查frame是否成功讀取。如果未讀取框架,則表示已到達視頻的末尾,我們break掉while循環。

為了在frame中找到藍色陰影,我們必須使用cv2.inRange函數。該函數有三個參數。第一個是我們想要檢查的frame。第二個是RGB像素的lower threshold,第三個是上限閾值(upper threshold)。調用此函數的結果是閾值圖像,像素落在上下範圍內設置為白色,像素不屬於此範圍 設為黑色。

最後,我們對閾值圖像進行高斯模糊處理,以使查找輪廓更準確。

 # find contours in the image  

(_,cnts,_) = cv2.findContours(blue.copy(),cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
# check to see if any contours were found
if len(cnts) > 0:
# sort the contours and find the largest one --
# we will assume this contour coorespondes to the
# area of my phone
cnt = sorted(cnts,key=cv2.contourArea,reverse=True)[0]
# compute the (rotated) bounding box around then
# contour and then draw it
rect = np.int32(cv2.boxPoints(cv2.minAreaRect(cnt)))
cv2.drawContours(frame,[rect],-1,(0,255,0),2)
# show the frame and the binary image
cv2.imshow("Traccking",frame)
cv2.imshow("Binary",blue)
# if your machine is fast, it may display the frames in
# what appears to be 'fast forward' since more than 32
# frames per second are being displayed -- a simple hack
# is just to sleep for a tiny bit in between frames;
# however, if your computer is slow, you probably want to
# comment out this line
time.sleep(0.025)
# if the 'q' key is pressed, stop the loop
if cv2.waitKey(1) & 0xFF == ord("q"):
break
# cleanup the camera and close any open windows
camera.release()
cv2.destroyAllWindows()

現在我們有了閾值圖像,那麼我們需要找到圖像中最大的輪廓,假設最大輪廓對應於我們想要跟蹤的藍色物體輪廓。

我們調用cv2.findContours會在閾值圖像中找到輪廓。我們使用copy()方法克隆閾值圖像,因為cv2.findContour函數對傳入的NumPy數組具有破壞性。

然後檢查以確保實際發現輪廓。如果輪廓列表的長度為零,則沒有找到藍色區域。如果輪廓列表的長度大於零,那麼我們需要找到最大的輪廓。這裡,輪廓按相反的順序排序(最大的第一個),使用cv2.contourArea函數來 計算輪廓的面積。具有較大區域的輪廓存儲在列表的前面。在這種情況下,抓住具有最大面積的輪廓,再次假設該輪廓對應於藍色物體的輪廓。

現在我們有了藍色的輪廓,但我們需要在它周圍繪製一個邊界框。

調用cv2.minAreaRect計算輪廓周圍的最小邊界框。然後,cv2.boxPoints將邊界框重新定義為點列表。

注意:在OpenCV 2.4.X中,我們將使用cv2.BoxPoints函數來計算輪廓的旋轉邊界框。但是,在OpenCV 3.0+中,此函數已移至cv2.boxPoints。兩個函數執行相同的任務,只是略有不同的命名空間。

最後,我們使用cv2.drawContours函數繪製邊界框。

具有檢測到的藍色物體的frame顯示在第一個imshow,並且閾值圖像(落入藍色像素的下/上範圍的像素)顯示在第二個imshow。

上面,time.sleep(0.025)可選的。在許多較新型號的機器上,系統可能足夠快以處理>32幀/秒。如果是這種情況,找到可接受的睡眠時間將減慢處理速度並將其降低到更正常的速度。

執行我們的腳本

python track.py

結果:

機器視覺——python實現追蹤物體軌跡

或者指定視頻路徑

python track.py --video "video\2018-11-27 18-38-15-927.mp4"

也是可以的。

博客地址(有完整代碼):https://0leo0.github.io/2018/case_study_03.html

關注不迷路哦!!


分享到:


相關文章: