首頁 > 軟體

Python中使用Opencv開發停車位計數器功能

2022-04-04 16:00:18

在這個專案中,我們將建立一個停車位計數器。我們會發現總共有多少輛車,以及有多少停車位是空的。關於本教學最好的一點是,我們將使用基本的影象處理技術來解決這個問題,沒有使用機器學習、深度學習進行訓練來識別。

1. 環境安裝

1.1 安裝並啟用虛擬環境

python -m venv venv
cd venvScripts
.activate.bat

1.2 python包安裝

pip install opencv-python

2. 繪製停車位矩形框

2.1 匯入停車場圖片

import cv2
import pickle
img=cv2.imread('carParkImg.png')
cv2.imshow("image",img)

2.2 繪製矩形框 定位停車位

import cv2
import pickle
img=cv2.imread('carParkImg.png')
cv2.rectangle(img,(50,192),(157,240),(255,0,255),2)  #座標位置可以多次嘗試確定
cv2.imshow("image",img)
cv2.waitKey(0)

可以看出,每個停車位的估計寬、高為:

width=107  # 157-102
height = 48 # 240 - 192

2.3 滑鼠新增、刪除停車位

import cv2
import pickle
img=cv2.imread('carParkImg.png')
width,height = 107,48
posList = []   # 滑鼠點選的座標集合
def mouseClick(events,x,y,flags,params):
	if events == cv2.EVENT_LBUTTONDOWN:
		posList.append((x,y))
while True:
	img = cv2.imread("carParkImg.png")
	cv2.imshow("images",img)
	for pos in posList:
		cv2.rectangle(img,pos,(pos[0]+width,pos[1]+height),(255,0,255),2)  #座標位置可以多次嘗試確定
	cv2.imshow("image",img)
	cv2.setMouseCallback("images",mouseClick)
	if cv2.waitKey(10) & 0xFF== ord('q'):
		break

通過滑鼠點選在任何位置新增矩形框,但當矩形框位置出錯時,無法進行刪除。因此通過新增滑鼠右鍵的事件,刪除錯誤的矩形框。

def mouseClick(events,x,y,flags,params):
	if events == cv2.EVENT_LBUTTONDOWN:
		posList.append((x,y))
	if events == cv2.EVENT_RBUTTONDOWN:
		for i,pos in enumerate(posList):
			x1,y1=pos
		if x1 < x < x1 +width and y1 < y <y1 +height:
			posList.pop(i)

通過pickle.dump()保持儲存滑鼠點選的位置資訊。

with open('CarParkPos','wb') as f:
	pickle.dump(posList,f)

通過pickle.load()載入儲存好的位置資訊,即在原有的停車位新增或刪除停車位,而不是每一幀畫面重新繪製。

with open('CarParkPos','wb') as f:
	posList = pickle.load(f)

完整程式碼如下:

import cv2
import pickle
img=cv2.imread('carParkImg.png')
width,height = 107,48
try:
	with open('CarParkPos','rb') as f:
		posList = pickle.load(f)
except:
	posList = []
# posList = []   # 滑鼠點選的座標集合
def mouseClick(events,x,y,flags,params):
	if events == cv2.EVENT_LBUTTONDOWN:
		posList.append((x,y))
	
	if events == cv2.EVENT_RBUTTONDOWN:
		for i,pos in enumerate(posList):
			x1,y1=pos
		if x1 < x < x1 +width and y1 < y <y1 +height:
			posList.pop(i)
	
	with open('CarParkPos','wb') as f:
		pickle.dump(posList,f)
while True:
	img = cv2.imread("carParkImg.png")
	for pos in posList:
		cv2.rectangle(img,pos,(pos[0]+width,pos[1]+height),(255,0,255),2)  #座標位置可以多次嘗試確定
	cv2.imshow("image",img)
	cv2.setMouseCallback("image",mouseClick)
	
	if cv2.waitKey(10) & 0xFF== ord('q'):
		break

3. 停車位視訊分析

3. 1 停車監控視訊

import cv2
import pickle
import cvzone
import numpy as np
# Video feed
cap = cv2.VideoCapture('carPark.mp4')
while True:
    success,img= cap.read()
    cv2.imshow("Image",img)
    if cv2.waitKey(10) & 0xFF== ord('q'):
        break

視訊時間比較短,為了讓視訊迴圈播放,新增如下程式碼:

if cap.get(cv2.CAP_PROP_POS_FRAMES) == cap.get(cv2.CAP_PROP_FRAME_COUNT):  
	cap.set(cv2.CAP_PROP_POS_FRAMES,0)
  • cv2.CAP_PROP_POS_FRAMES :視訊播放當前幀
  • cv2.CAP_PROP_FRAME_COUNT :視訊總幀數

即:當前視訊播放到結尾時,重新播放

3. 2 擷取停車位

擷取停車位,回來對每個停車位進行影象處理,從而分析該停車位是否被佔用

def checkParkingSpace():
    for pos in posList:
        x,y = pos
        imgCrop=img[y:y+height,x:x+width]
        cv2.imshow(str(x*y),imgCrop)

3. 3 影象處理

對影象二值化、高斯模糊處理

imgGray =cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
imgBlur =cv2.GaussianBlur(imgGray,(3,3),1)

利用自適應二值化對影象進行處理

imgThreshold=cv2.adaptiveThreshold(imgBlur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,25,16)

cv2.adaptiveThreshold 引數的選擇可以通過TrackBar拖到卷軸,直到選擇合適的數值。

可以看出停車位上有車輛時白色畫素點比較多,停車位沒有車輛時,白色畫素點很少甚至沒有,因此我們可以基於白色畫素點數量來確定該車為是否被佔用。同時可以看到當停車位為空時存在一些椒鹽噪聲,通過medianBlur來處理椒鹽噪聲

imgMedian = cv2.medianBlur(imgThreshold,5)

可以看出椒鹽噪聲少了一部分。
使用dilate(膨脹)增強白色畫素值,便於更好區分每個停車位是否被佔用

 kernel=np.ones((3,3),np.uint8);
 imgDilate=cv2.dilate(imgMedian,kernel,iterations=1)

可以看出白色的輪廓比之前加厚了

3. 4 判斷停車位是否被佔用

擷取每個停車位,經過處理後的影象,統計白色畫素的數量
修改checkParkingSpace函數,將處理好的影象傳入函數

def checkParkingSpace(imgProc):
    for pos in posList:
        x,y = pos  
        imgCrop=imgProc[y:y+height,x:x+width]
        count=cv2.countNonZero(imgCrop)
        cvzone.putTextRect(img,str(count),(x,y+height-3,scale =1.5,thickness=2,offset=0)	

對比可以看出,佔有車位的數值比較大1000-2000,空車位的200-500,數值的差距比較大。

畫出所有停車位,對比找出合適的閾值,區分停車位為空還是被佔用了。

可以看出停車位為空時,值為0-600,而停車位被佔用,值為:960-2300,因此我們設定閾值為750。所以低於750此時停車位沒有車,高於950則停車位有車。

加上文字描述

程式碼

import cv2
import pickle
import cvzone
import numpy as np
# Video feed
cap = cv2.VideoCapture('carPark.mp4')
with open('CarParkPos','rb') as f:
    posList = pickle.load(f)
width,height=107,48
def checkParkingSpace(imgProc):
    spaceCounter=0
    for pos in posList:
        x,y = pos  
        imgCrop=imgProc[y:y+height,x:x+width]
        count=cv2.countNonZero(imgCrop)
        
        if count < 950:
            color = (0,255,0)
            thickness = 5
            spaceCounter +=1
        else:
            color = (0,0,255)
            thickness = 2
        cv2.rectangle(img,pos,(pos[0]+width,pos[1]+height),color,thickness=thickness)
        cvzone.putTextRect(img,str(count),(x,y+height-5),scale =1.5,thickness=2,offset=0,colorR=color)
    cvzone.putTextRect(img,f'Free{spaceCounter}/{len(posList)}',(100,50),scale =3,thickness=5,offset=20,colorR=(0,200,0))
            
while True:
    if cap.get(cv2.CAP_PROP_POS_FRAMES) == cap.get(cv2.CAP_PROP_FRAME_COUNT):  
        cap.set(cv2.CAP_PROP_POS_FRAMES,0)
    
    success,img= cap.read()  
    imgGray =cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    imgBlur =cv2.GaussianBlur(imgGray,(3,3),1)  
    imgThreshold=cv2.adaptiveThreshold(imgBlur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,25,16)
    imgMedian = cv2.medianBlur(imgThreshold,5)
    kernel=np.ones((3,3),np.uint8);
    imgDilate=cv2.dilate(imgMedian,kernel,iterations=1)
    checkParkingSpace(imgDilate)
    # for pos in posList:
    #     cv2.rectangle(img,pos,(pos[0]+width,pos[1]+height),(255,0,255),2)
    cv2.imshow("Image",img)
    # cv2.imshow("imgBlur",imgBlur)
    # cv2.imshow("imgThreshold",imgThreshold)
    # cv2.imshow("imgMedian",imgMedian)
    # cv2.imshow("imgDilate",imgDilate)
    if cv2.waitKey(10) & 0xFF== ord('q'):
        break

最終效果如下:

原始碼連結:https://github.com/yuanxinshui/Opencv-project/tree/main/39%20Parking%20Space%20Counter

到此這篇關於Python中使用Opencv開發停車位計數器的文章就介紹到這了,更多相關python Opencv停車位計數器內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com