車位數(shù)量檢測(cè)
該項(xiàng)目基于圖像處理來(lái)檢測(cè)停車場(chǎng)中的空間。
該項(xiàng)目將使用 openCV 和 CVzone 庫(kù)來(lái)執(zhí)行圖像處理任務(wù)。
如何運(yùn)行
用鼠標(biāo)單擊功能在停車場(chǎng)的靜止圖像上繪制框在這些單獨(dú)的框上裁剪和執(zhí)行 opencv 轉(zhuǎn)換結(jié)合這兩個(gè)步驟并將它們應(yīng)用于視頻以檢查可用的可用空間
過(guò)程
1. 安裝和導(dǎo)入依賴項(xiàng)
openCV 將允許我們導(dǎo)入圖像和視頻,然后我們可以對(duì)它們應(yīng)用轉(zhuǎn)換,CVzone作為基于 openCV 的庫(kù),它還允許我們使用與 openCV 相比所需語(yǔ)法更少的轉(zhuǎn)換,“Pickel”用于存儲(chǔ)在圖片上繪制的方框的位置,“numpy”用于應(yīng)用簡(jiǎn)單的轉(zhuǎn)換。
import cv2
import pickle
import cvzone
import numpy as np
我們將處理使用 parkingspacepicker.py 繪制框并存儲(chǔ)位置,并通過(guò) pickel 在我們的 main.py 中使用這些位置
2. 繪制方框
在此圖像中,我們可以看到空間分布不均,并且間隔各不相同。
我們稍后將使用的視頻的相機(jī)處于靜態(tài)狀態(tài),因此我們可以通過(guò)在框上手動(dòng)繪制框來(lái)接近它。
為此,我們需要知道單個(gè)框的高度和寬度,然后我們將不得不嘗試不同的值以獲得完美形狀的框
import cv2
import pickle
import cvzone
import numpy as np
img = cv2.imread('carParkImg.png')
while True:
cv2.rectangle(img,(50,1920),(157,240),(255,0,255),2)
cv2.imshow("image", img)
cv2.waitKey(1)
在此之后,我們得到 width 和 height = 107, 48 你也可以嘗試不同的值。
我們啟動(dòng)一個(gè)列表來(lái)存儲(chǔ)這些值并編寫一個(gè)函數(shù)來(lái)檢測(cè)鼠標(biāo)點(diǎn)擊操作,你可以在下一個(gè)片段中看到
img = cv2.imread('carParkImg.png')
width, height = 107, 48
def mouse_click(events, x, y, flags, params):
if events == cv2.EVENT_LBUTTONDOWN:
posList.append((x, y))
#and to see what we are drwaing on the screen
while True:
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", mouse_click)
cv2.waitKey(1)
在 mouse_click 函數(shù)中,我們將events, x, y, flags, params作為參數(shù)傳遞,如果events == cv2.EVENT_LBUTTONDOWN,則將值 (x, y) 附加到 posList 并查看我們?cè)谄聊簧侠L制的內(nèi)容,我們將在我們的 posList 值上編寫一個(gè) for 循環(huán)。
我在這里遇到了兩個(gè)問(wèn)題:
在錯(cuò)誤的位置繪制框加載圖像后只生成一幀,因此對(duì)該圖像的任何修改都不會(huì)顯示
對(duì)于第 1 個(gè)問(wèn)題的解決方案,我修改了mouse_click函數(shù),將右鍵單擊按鈕作為一個(gè)事件,然后我們將檢查我們的單擊點(diǎn)是否位于其中一個(gè)位置之間,我們將刪除它。
def mouse_click(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)
我們將檢查當(dāng)前的x是否在x1<x<x1+width和y1<y<y1+height之間,如果在其中,則刪除它。我們需要知道要進(jìn)行多少次迭代才能刪除它,為此我們可以使用enumerate獲取i并彈出i。
對(duì)于問(wèn)題2-因?yàn)槲覀兊膱D像只被導(dǎo)入一次,所以無(wú)論在其上繪制什么都將保持不變,我們?cè)诰W(wǎng)絡(luò)攝像頭或相機(jī)中不會(huì)遇到此問(wèn)題,并且我們正在處理的是靜態(tài)圖像,因此我們必須在循環(huán)中導(dǎo)入它以獲得刪除框。
在繪制所有框后,現(xiàn)在我們必須將它們存儲(chǔ)為pickle對(duì)象并以一種方式存儲(chǔ)它們,以便我們不必每次都進(jìn)行制作,并且我們可以使用先前的對(duì)象或修改現(xiàn)有的對(duì)象。
img = cv2.imread('carParkImg.png')
width, height = 107, 48
try:
with open('CarParkPos', 'rb') as f:
posList = pickle.load(f)
except:
posList = []
def mouse_click(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", mouse_click)
cv2.waitKey(1)
這將創(chuàng)建一個(gè)對(duì)象 CarParkPos 并檢查該對(duì)象是否已經(jīng)存在
圖像處理(main.py)
加載視頻饋送并循環(huán)進(jìn)行循環(huán),我們將對(duì)幀進(jìn)行計(jì)數(shù),當(dāng)幀到達(dá)時(shí),我們將重置它,以便獲得連續(xù)的視頻
import cv2
import pickle
import cvzone
import numpy as np
# video feed
cap = cv2.VideoCapture('carPark.mp4')
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()
cv2.imshow("Image", img)
cv2.waitKey(10)
將框位置加載到我們將使用 pickle 對(duì)象的視頻上,并定義我們之前找到的寬度和高度with open('CarParkPos', 'rb') as f:
posList = pickle.load(f)
width, height = 107, 48
我們需要裁剪這些位置以供以后轉(zhuǎn)換,為此我們將編寫一個(gè)函數(shù)def checkParkingSpace(imgPro):
for pos in posList:
x, y = pos
imgCrop = imgPro[y:y + height, x:x + width]
cv2.imshow(str(x * y), imgCrop)
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)
for pos in posList:
cv2.rectangle(img, pos, (pos[0] + width, pos[1] + height), (255, 0, 255), 2)
success, img = cap.read()
cv2.imshow("Image", img)
cv2.waitKey(10)
裁剪后繪制出方框,這將為裁剪區(qū)域提供完美的視角,現(xiàn)在我們需要找出其中哪個(gè)區(qū)域有汽車。
我們可以通過(guò)查看像素計(jì)數(shù)來(lái)做到這一點(diǎn),在圖像處理中,我們可以使用邊緣和角點(diǎn)檢測(cè)算法來(lái)將圖像轉(zhuǎn)換為二進(jìn)制形式,并計(jì)算出圖像中的邊緣和角點(diǎn)數(shù)量。在二值化后的圖像中,黑色像素表示背景,白色像素表示前景。通過(guò)分析這些二值化后的圖像中的邊緣和角點(diǎn)數(shù)目,我們可以了解到關(guān)于該圖像的一些信息,如圖像是否具有結(jié)構(gòu)性、復(fù)雜度等信息,來(lái)確定圖像的特點(diǎn)。在此基礎(chǔ)上,我們可以繼續(xù)下一步的分析或處理。
為了確定該區(qū)域是否包含汽車,我們必須首先使用 OpenCV 和 CVzone 進(jìn)行一些閾值處理,我們將圖像轉(zhuǎn)換為灰度并應(yīng)用高斯模糊,然后我們將其轉(zhuǎn)換為二值圖像,我們將使用自適應(yīng)閾值和去除椒鹽噪聲,我們使用“medianBlur”和主動(dòng)內(nèi)核來(lái)去除噪聲,有時(shí)這些像素非常小,為了更好地區(qū)分,我們將使用膨脹操作。
應(yīng)用所有濾鏡后的圖像
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)
cv2.imshow("Image", img)
# cv2.imshow("ImageBlur", imgBlur)
# cv2.imshow("ImageThres", imgMedian)
cv2.waitKey(10)
所有的值都作為參數(shù)傳遞,通過(guò)嘗試不同的值來(lái)獲得,現(xiàn)在我們將這個(gè)處理過(guò)的圖像傳遞給我們的裁剪函數(shù)
做出預(yù)測(cè)def checkParkingSpace(imgPro):
spaceCounter = 0
for pos in posList:
x, y = pos
imgCrop = imgPro[y:y + height, x:x + width]
# cv2.imshow(str(x * y), imgCrop)
count = cv2.countNonZero(imgCrop)
if count < 900:
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)
cvzone.putTextRect(img, str(count), (x, y + height - 3), scale=1,
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))
我們將處理后的圖像傳遞給此函數(shù)并計(jì)算像素,如果像素密度小于 900,則表明沒(méi)有汽車,如果大于900,則包含汽車并顯示文本,我們將使用 CVzone 庫(kù),并使用 python f string Free:{spaceCounter}/{len(posList)} 來(lái)顯示計(jì)數(shù)器。
github:https://github.com/Tejaswi-kashyap-006/computervision_projects
原文標(biāo)題 : 車位數(shù)量檢測(cè)

發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
最新活動(dòng)更多
-
7月8日立即報(bào)名>> 【在線會(huì)議】英飛凌新一代智能照明方案賦能綠色建筑與工業(yè)互聯(lián)
-
7月22-29日立即報(bào)名>> 【線下論壇】第三屆安富利汽車生態(tài)圈峰會(huì)
-
7.30-8.1火熱報(bào)名中>> 全數(shù)會(huì)2025(第六屆)機(jī)器人及智能工廠展
-
7月31日免費(fèi)預(yù)約>> OFweek 2025具身智能機(jī)器人產(chǎn)業(yè)技術(shù)創(chuàng)新應(yīng)用論壇
-
免費(fèi)參會(huì)立即報(bào)名>> 7月30日- 8月1日 2025全數(shù)會(huì)工業(yè)芯片與傳感儀表展
-
即日-2025.8.1立即下載>> 《2024智能制造產(chǎn)業(yè)高端化、智能化、綠色化發(fā)展藍(lán)皮書(shū)》
推薦專題
- 1 AI 眼鏡讓百萬(wàn) APP「集體失業(yè)」?
- 2 豆包前負(fù)責(zé)人喬木出軌BP后續(xù):均被辭退
- 3 一文看懂視覺(jué)語(yǔ)言動(dòng)作模型(VLA)及其應(yīng)用
- 4 “支付+”時(shí)代,支付即生態(tài) | 2025中國(guó)跨境支付十大趨勢(shì)
- 5 中國(guó)最具實(shí)力AI公司TOP10
- 6 深圳跑出40億超級(jí)隱形冠軍:賣機(jī)器人年入6.1億,港股上市
- 7 特斯拉Robotaxi上路,馬斯克端上畫(huà)了十年的餅
- 8 “AI六小虎”到了下一個(gè)賽點(diǎn)
- 9 張勇等人退出阿里合伙人
- 10 AI的夏天:第四范式VS云從科技VS地平線機(jī)器人