计算机视觉——停车位(可用)自动计数!

文摘   科技   2023-04-12 21:42   河南  

如何实现停车位自动计数?对于这个问题,第一个回答就是使用深度学习,构建卷积神经网络,通过使用大量的数据进行训练,使得程序具有识别停车位的能力。


当然,这是一个方法。很显然,这个方法比较复杂,需要大量的数据集。对于,一般电脑的GPU,处理时间太长。在这里,我将从另一个角度——图像角度,准确来说,应该是像素角度来进行这项工作。


前期准备:确保计算机中已安装下列第三方库

  • 1,opencv-python

  • 2,pickle

  • 3,cvzone

  • 4,numpy

  • 5,pycharm或其它IDE(建议使用pycharm)

安装方法,通过命令行窗口安装(pip install 库名),对于pycharm,则可以通过file菜单,setting目录下的python Interpreter 窗口安装。(安装成功与否与网络好坏有较大关系)


本项目分为两大部分


第一部分:检测位置标注(这里用的是手动标注,当然,要实现自动标注有较大的难度

要标注的场景图片:

标注后的图片:


也就是把要检测停车位都标注出来(用框框圈起来就行,大小要合适,不然影响检测)

代码实现:

import cv2import 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 cv2import pickleimport cvzoneimport numpy as np
# Video feedcap = 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)

结果:


车位空余量与总量清晰的显示在了视频上。当然,由于这个视频拍摄时存在抖动,而实际中,大多都是固定的,所以检测效果会更好。



这也启发我们,在考虑问题时,一定要从多方面来考虑。尽量运用较为简单的知识去做出较为准确的结果。有时,简单反而是更加有效的!








math and code
计算机专业研究生在读,拥有深厚的计算机科学和数学背景,对编程、算法、数据结构、深度学习等领域都有着深入的了解和实践经验。对编程语言的掌握熟练而全面,无论是主流的Python、Java,还是强大的C++、Go,都能轻松驾驭。