OpenCV 運動檢測
在本文中,我們將學習如何在 OpenCV 和 Python 的幫助下建立運動檢測專案。
使用 OpenCV 和 Python 建立運動檢測專案
首先說一下這個專案的需求。顯然,第一個要求是安裝 Python,我們還需要安裝一個名為 opencv
的外部包。
我們需要開啟命令提示符並執行此命令以在你的 PC 上安裝此軟體包。讓我們跳到我們的編輯器並開始編寫我們的程式碼。
我們將匯入的第一件事是我們需要的庫,cv2
和 time
,接下來我們將使用 OpenCV 的 VideoCapture()
方法從我們的網路攝像頭獲取資料。
讓我們建立一個名為 Video
的物件,我們必須將 0
傳遞給 VideoCapture()
,因為我們正在為網路攝像頭使用 0 通道。
import cv2
import time
Video = cv2.VideoCapture(0)
First_Frame = None
現在我們將建立一個 while True
迴圈或無限迴圈,因為我們將提取視訊,而視訊是影象幻燈片上的連續移動。
現在我們將在 while
迴圈中定義幾條指令,在第一行中,我們將建立兩個變數 Check
和 frame
,並讀取 VideoCapture()
方法提取的資料。在下一條指令中,我們將把這個提取的影象轉換成灰度圖。
但是為什麼我們要把它轉換成灰度呢?我們這樣做是因為我們想提高特徵檢測的準確性。
我們使用 cvtColor()
方法來改變灰度並且有兩個引數。首先是幀
或我們要轉換為灰度的影象,然後是 COLOR_BGR2GRAY
,它將影象轉換為灰度。
現在我們將使影象模糊或平滑,這就是為什麼物體檢測或物體運動會容易得多的原因。我們使用 GaussianBlur()
方法來應用平滑並將灰度影象、核心大小和 sigma 傳遞給它。
while True:
Check, frame = Video.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)
我們將建立一個 if
語句來檢查幀是否到來,我們這樣做是因為我們希望 First_Frame
作為我們的參考幀。
讓我們來看看物理學對運動的看法?運動是從一個參考點識別出來的,我們用一個例子來解釋這一點。
假設你坐在火車上,對你來說,樹木在移動,但它們並沒有移動;它們仍然是,但你正在從你的參考點移動。在這種情況下,樹是參考點,但在我們的例子中,框架是參考。
我們將 First_Frame
固定為我們的參考框架;如果參考系發生任何變化,那麼我們可以說運動存在。
現在我們將設定一個語句,如果 First_Frame
變數為 None
(在第一種情況下為 true
),那麼我們將使 First_Frame
變數等於作為 gray
變數的灰度影象。
if First_Frame is None:
First_Frame = gray
continue
我們將使用 absdiff()
方法來查詢幀之間的差異。讓我們建立一個增量幀變數並將兩個引數傳遞給 absdiff()
方法進行比較。
我們需要設定一個閾值或限制,我們希望檢測到運動,因為我們不希望噪聲被檢測為運動。
為此,我們使用 threshold()
方法,它有幾個引數,第一個是 delta_frame
,第二個是強度,第三個是顏色陰影,在這種情況下是白色,然後是下一個是 THRESH_BINARY
,因為它是一個元組,所以我們需要選擇第一個元素。
我們還需要在下一條指令中再應用一個平滑層。為此,我們需要使用另一個稱為 dilate()
的平滑函式,它接受三個引數,第一個是 threshold
,第二個是 None
,第三個引數是 iterations
。
iterations
引數定義了平滑的精確度;如果你增加此引數值,你的程式也會捕獲噪聲。
這次我們將建立輪廓,那麼輪廓是什麼?輪廓是運動發生的點。
如果框架靜止並且手在移動,那麼手的部分就是輪廓。
findContours()
方法有助於查詢輪廓,它接受三個引數,第一個是幀,我們使用 copy()
方法建立幀陣列的副本。
delta_frame = cv2.absdiff(First_Frame, gray)
Threshold_frame = cv2.threshold(delta_frame, 50, 255, cv2.THRESH_BINARY)[1]
Threshold_frame = cv2.dilate(Threshold_frame, None, iterations=2)
(cntr, _) = cv2.findContours(
Threshold_frame.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
現在我們將通過迭代獲得輪廓並將近似區域定義為運動。如果我們不定義區域,我們將得到一個非常嘈雜的運動檢測。
首先我們會檢查,如果輪廓區域小於一千,那麼我們不認為這是一個運動區域,我們會繼續迭代,如果大於一千,那麼我們就畫一個三角形。
for contour in cntr:
if cv2.contourArea(contour) < 1000:
continue
findContours()
方法給出了四個值(x、y、高度、寬度),我們將使用 boundingRect()
方法提取這些點,該方法將繫結矩形的區域。現在我們將在 rectangle()
方法的幫助下建立矩形。
第一個引數是我們要在其上繪製矩形的 frame
或影象。接下來是 (x,y)
座標點,接下來是高度和寬度,接下來是邊框的顏色,最後一個引數是選擇畫矩形的筆的大小。
(x, y, w, h) = cv2.boundingRect(contour)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)
完整的原始碼:
import cv2
import time
Video = cv2.VideoCapture(0)
First_Frame = None
while True:
Check, frame = Video.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)
if First_Frame is None:
First_Frame = gray
continue
delta_frame = cv2.absdiff(First_Frame, gray)
Threshold_frame = cv2.threshold(delta_frame, 50, 255, cv2.THRESH_BINARY)[1]
Threshold_frame = cv2.dilate(Threshold_frame, None, iterations=2)
(cntr, _) = cv2.findContours(
Threshold_frame.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
for contour in cntr:
if cv2.contourArea(contour) < 1000:
continue
(x, y, w, h) = cv2.boundingRect(contour)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)
cv2.imshow("Frame", frame)
Key = cv2.waitKey(1)
if Key == ord("q"):
break
Video.release()
cv2.destroyAllWindows()
現在我們可以看到運動檢測發生在手移動時。
Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.
LinkedIn