如何实现停车位自动计数?对于这个问题,第一个回答就是使用深度学习,构建卷积神经网络,通过使用大量的数据进行训练,使得程序具有识别停车位的能力。当然,这是一个方法。很显然,这个方法比较复杂,需要大量的数据集。对于,一般电脑的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就比较合适。
标注过程:
,时长00:47
第二部分:
有了第一部分的标注,准备工作也就完全做好了,接下来,就是如何判断,车位有车,和无车了。下面看一个视频,
,时长00:17
不难发现,在车位上有车时,该车位的像素点多,而无车时,像素点相当少。于是基本思想就是:
将视频进行转化,(原视频不变)再计算每个车位的像素数量,通过像素数量(设定一个阈值)的多少来判断车辆的有无。
代码如下:
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)
结果:
,时长00:25
(后期加工过,配上了音乐和一些字)
车位空余量与总量清晰的显示在了视频上。当然,由于这个视频拍摄时存在抖动,而实际中,大多都是固定的,所以检测效果会更好。
这也启发我们,在考虑问题时,一定要从多方面来考虑。尽量运用较为简单的知识去做出较为准确的结果。有时,简单反而是更加有效的!