OpenCV 運動檢測

Salman Mehmood 2022年6月7日
OpenCV 運動檢測

在本文中,我們將學習如何在 OpenCV 和 Python 的幫助下建立運動檢測專案。

使用 OpenCV 和 Python 建立運動檢測專案

首先說一下這個專案的需求。顯然,第一個要求是安裝 Python,我們還需要安裝一個名為 opencv 的外部包。

我們需要開啟命令提示符並執行此命令以在你的 PC 上安裝此軟體包。讓我們跳到我們的編輯器並開始編寫我們的程式碼。

我們將匯入的第一件事是我們需要的庫,cv2time,接下來我們將使用 OpenCV 的 VideoCapture() 方法從我們的網路攝像頭獲取資料。

讓我們建立一個名為 Video 的物件,我們必須將 0 傳遞給 VideoCapture(),因為我們正在為網路攝像頭使用 0 通道。

import cv2,time

Video=cv2.VideoCapture(0)
First_Frame=None

現在我們將建立一個 while True 迴圈或無限迴圈,因為我們將提取視訊,而視訊是影象幻燈片上的連續移動。

現在我們將在 while 迴圈中定義幾條指令,在第一行中,我們將建立兩個變數 Checkframe,並讀取 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,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()

現在我們可以看到運動檢測發生在手移動時。

使用 OpenCV 和 Python 建立運動檢測專案

Salman Mehmood avatar Salman Mehmood avatar

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

相關文章 - OpenCV Video