車位數(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)用于視頻以檢查可用的可用空間
過程
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ǔ)位置,并通過 pickel 在我們的 main.py 中使用這些位置
2. 繪制方框
在此圖像中,我們可以看到空間分布不均,并且間隔各不相同。
我們稍后將使用的視頻的相機(jī)處于靜態(tài)狀態(tài),因此我們可以通過在框上手動(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è)問題:
在錯(cuò)誤的位置繪制框加載圖像后只生成一幀,因此對(duì)該圖像的任何修改都不會(huì)顯示
對(duì)于第 1 個(gè)問題的解決方案,我修改了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ì)于問題2-因?yàn)槲覀兊膱D像只被導(dǎo)入一次,所以無(wú)論在其上繪制什么都將保持不變,我們?cè)诰W(wǎng)絡(luò)攝像頭或相機(jī)中不會(huì)遇到此問題,并且我們正在處理的是靜態(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ū)域有汽車。
我們可以通過查看像素計(jì)數(shù)來(lái)做到這一點(diǎn),在圖像處理中,我們可以使用邊緣和角點(diǎn)檢測(cè)算法來(lái)將圖像轉(zhuǎn)換為二進(jìn)制形式,并計(jì)算出圖像中的邊緣和角點(diǎn)數(shù)量。在二值化后的圖像中,黑色像素表示背景,白色像素表示前景。通過分析這些二值化后的圖像中的邊緣和角點(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ù)傳遞,通過嘗試不同的值來(lái)獲得,現(xiàn)在我們將這個(gè)處理過的圖像傳遞給我們的裁剪函數(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,則表明沒有汽車,如果大于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)更多
-
即日-10.29立即報(bào)名>> 2024德州儀器嵌入式技術(shù)創(chuàng)新發(fā)展研討會(huì)
-
10月31日立即下載>> 【限時(shí)免費(fèi)下載】TE暖通空調(diào)系統(tǒng)高效可靠的組件解決方案
-
即日-11.13立即報(bào)名>>> 【在線會(huì)議】多物理場(chǎng)仿真助跑新能源汽車
-
11月14日立即報(bào)名>> 2024工程師系列—工業(yè)電子技術(shù)在線會(huì)議
-
12月19日立即報(bào)名>> 【線下會(huì)議】OFweek 2024(第九屆)物聯(lián)網(wǎng)產(chǎn)業(yè)大會(huì)
-
即日-12.26火熱報(bào)名中>> OFweek2024中國(guó)智造CIO在線峰會(huì)
推薦專題
- 1 Intel宣布40年來(lái)最重大轉(zhuǎn)型:年底前裁員15000人、拋掉2/3房產(chǎn)
- 2 因美封殺TikTok,字節(jié)股價(jià)骨折!估值僅Meta1/5
- 3 宏山激光重磅發(fā)布行業(yè)解決方案,助力智能制造產(chǎn)業(yè)新飛躍
- 4 國(guó)產(chǎn)AI芯片公司破產(chǎn)!白菜價(jià)拍賣
- 5 具身智能火了,但規(guī)模落地還需時(shí)間
- 6 國(guó)產(chǎn)英偉達(dá)們,抓緊沖刺A股
- 7 三次錯(cuò)失風(fēng)口!OpenAI前員工殺回AI編程賽道,老東家捧金相助
- 8 英特爾賦能智慧醫(yī)療,共創(chuàng)數(shù)字化未來(lái)
- 9 英偉達(dá)的麻煩在后頭?
- 10 將“網(wǎng)紅”變成“商品”,AI“爆改”實(shí)力拉滿
- 高級(jí)軟件工程師 廣東省/深圳市
- 自動(dòng)化高級(jí)工程師 廣東省/深圳市
- 光器件研發(fā)工程師 福建省/福州市
- 銷售總監(jiān)(光器件) 北京市/海淀區(qū)
- 激光器高級(jí)銷售經(jīng)理 上海市/虹口區(qū)
- 光器件物理工程師 北京市/海淀區(qū)
- 激光研發(fā)工程師 北京市/昌平區(qū)
- 技術(shù)專家 廣東省/江門市
- 封裝工程師 北京市/海淀區(qū)
- 結(jié)構(gòu)工程師 廣東省/深圳市