Python中使用Opencv開發(fā)停車位計數(shù)器功能
在這個項目中,我們將創(chuàng)建一個停車位計數(shù)器。我們會發(fā)現(xiàn)總共有多少輛車,以及有多少停車位是空的。關(guān)于本教程最好的一點是,我們將使用基本的圖像處理技術(shù)來解決這個問題,沒有使用機器學習、深度學習進行訓練來識別。
1. 環(huán)境安裝
1.1 安裝并激活虛擬環(huán)境
python -m venv venv
cd venv\Scripts .\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 停車監(jiān)控視頻
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
視頻時間比較短,為了讓視頻循環(huán)播放,添加如下代碼:
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 :視頻總幀數(shù)
即:當前視頻播放到結(jié)尾時,重新播放
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 參數(shù)的選擇可以通過TrackBar拖到滾動條,直到選擇合適的數(shù)值。

可以看出停車位上有車輛時白色像素點比較多,停車位沒有車輛時,白色像素點很少甚至沒有,因此我們可以基于白色像素點數(shù)量來確定該車為是否被占用。同時可以看到當停車位為空時存在一些椒鹽噪聲,通過medianBlur來處理椒鹽噪聲
imgMedian = cv2.medianBlur(imgThreshold,5)

可以看出椒鹽噪聲少了一部分。
使用dilate(膨脹)增強白色像素值,便于更好區(qū)分每個停車位是否被占用
kernel=np.ones((3,3),np.uint8); imgDilate=cv2.dilate(imgMedian,kernel,iterations=1)

可以看出白色的輪廓比之前加厚了
3. 4 判斷停車位是否被占用
截取每個停車位,經(jīng)過處理后的圖像,統(tǒng)計白色像素的數(shù)量
修改checkParkingSpace函數(shù),將處理好的圖像傳入函數(shù)
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)

對比可以看出,占有車位的數(shù)值比較大1000-2000,空車位的200-500,數(shù)值的差距比較大。
畫出所有停車位,對比找出合適的閾值,區(qū)分停車位為空還是被占用了。

可以看出停車位為空時,值為0-600,而停車位被占用,值為:960-2300,因此我們設(shè)定閾值為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
到此這篇關(guān)于Python中使用Opencv開發(fā)停車位計數(shù)器的文章就介紹到這了,更多相關(guān)python Opencv停車位計數(shù)器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python?OpenCV超詳細講解調(diào)整大小與圖像操作的實現(xiàn)
- Python?OpenCV超詳細講解讀取圖像視頻和網(wǎng)絡攝像頭
- 關(guān)于python3?opencv?圖像二值化的問題(cv2.adaptiveThreshold函數(shù))
- Python?OpenCV實現(xiàn)圖形檢測示例詳解
- Python?OpenCV實現(xiàn)3種濾鏡效果實例
- python?OpenCV?圖像通道數(shù)判斷
- 巧妙使用python?opencv庫玩轉(zhuǎn)視頻幀率
- python+opencv實現(xiàn)堆疊圖片
- python?使用OpenCV進行曝光融合
相關(guān)文章
python調(diào)用pymssql包操作SqlServer數(shù)據(jù)庫的實現(xiàn)
本文主要介紹了python調(diào)用pymssql包操作SqlServer數(shù)據(jù)庫的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-06-06
python調(diào)用OpenCV實現(xiàn)人臉識別功能
這篇文章主要為大家詳細介紹了python調(diào)用OpenCV實現(xiàn)人臉識別功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-05-05
Python socket如何實現(xiàn)服務端和客戶端數(shù)據(jù)傳輸(TCP)
這篇文章主要介紹了Python socket如何實現(xiàn)服務端和客戶端數(shù)據(jù)傳輸(TCP),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-05-05

