如何实现停车位自动计数?对于这个问题,第一个回答就是使用深度学习,构建卷积神经网络,通过使用大量的数据进行训练,使得程序具有识别停车位的能力。
当然,这是一个方法。很显然,这个方法比较复杂,需要大量的数据集。对于,一般电脑的GPU,处理时间太长。在这里,我将从另一个角度——图像角度,准确来说,应该是像素角度来进行这项工作。
前期准备:确保计算机中已安装下列第三方库
1,opencv-python
2,pickle
3,cvzone
4,numpy
5,pycharm或其它IDE(建议使用pycharm)
安装方法,通过命令行窗口安装(pip install 库名),对于pycharm,则可以通过file菜单,setting目录下的python Interpreter 窗口安装。(安装成功与否与网络好坏有较大关系)
本项目分为两大部分
第一部分:检测位置标注(这里用的是手动标注,当然,要实现自动标注有较大的难度)
要标注的场景图片:
标注后的图片:
也就是把要检测停车位都标注出来(用框框圈起来就行,大小要合适,不然影响检测)
代码实现:
import cv2
import pickle
width, height = 107, 48#经过标注尝试,得出的停车位大小
try:
with open('CarParkPos', 'rb') as f:#rb,只读模式
posList = pickle.load(f)
except:
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:#wb,覆盖写模式,文件不存在则创建,存在则完全覆盖
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)#监测鼠标函数
cv2.waitKey(1)
注意:车位的高度和宽度,是通过数次标注实验来确定的,也就是不断通过改变width和height的值,如果发现框框非常合适时,那么这时的width和height就比较合适。
标注过程:
第二部分:
有了第一部分的标注,准备工作也就完全做好了,接下来,就是如何判断,车位有车,和无车了。下面看一个视频,
不难发现,在车位上有车时,该车位的像素点多,而无车时,像素点相当少。于是基本思想就是:
将视频进行转化,(原视频不变)再计算每个车位的像素数量,通过像素数量(设定一个阈值)的多少来判断车辆的有无。
代码如下:
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(imgPro):
spaceCounter = 0
for pos in posList:
x, y = pos
imgCrop = imgPro[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)
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,255,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)
cv2.imshow("Image", img)
#cv2.imshow("ImageBlur", imgBlur)
#cv2.imshow("ImageThres", imgMedian)
cv2.waitKey(10)
结果:
车位空余量与总量清晰的显示在了视频上。当然,由于这个视频拍摄时存在抖动,而实际中,大多都是固定的,所以检测效果会更好。
这也启发我们,在考虑问题时,一定要从多方面来考虑。尽量运用较为简单的知识去做出较为准确的结果。有时,简单反而是更加有效的!