Python中使用Opencv开发停车位计数器功能

 更新时间:2022年04月04日 11:43:48   作者:@BangBang  
这篇文章主要介绍了Python中使用Opencv开发停车位计数器,本教程最好的一点就是我们将使用基本的图像处理技术来解决这个问题,没有使用机器学习、深度学习进行训练来识别,感兴趣的朋友跟随小编一起看看吧

在这个项目中,我们将创建一个停车位计数器。我们会发现总共有多少辆车,以及有多少停车位是空的。关于本教程最好的一点是,我们将使用基本的图像处理技术来解决这个问题,没有使用机器学习、深度学习进行训练来识别。

1. 环境安装

1.1 安装并激活虚拟环境

python -m venv venv
cd venv\Scripts
.\activate.bat

1.2 python包安装

pip install opencv-python

2. 绘制停车位矩形框

2.1 导入停车场图片

import cv2
import pickle
img=cv2.imread('carParkImg.png')
cv2.imshow("image",img)

2.2 绘制矩形框 定位停车位

import cv2
import pickle
img=cv2.imread('carParkImg.png')
cv2.rectangle(img,(50,192),(157,240),(255,0,255),2)  #坐标位置可以多次尝试确定
cv2.imshow("image",img)
cv2.waitKey(0)

可以看出,每个停车位的估计宽、高为:

width=107  # 157-102
height = 48 # 240 - 192

2.3 鼠标添加、删除停车位

import cv2
import pickle
img=cv2.imread('carParkImg.png')
width,height = 107,48
posList = []   # 鼠标点击的坐标集合
def mouseClick(events,x,y,flags,params):
	if events == cv2.EVENT_LBUTTONDOWN:
		posList.append((x,y))
while True:
	img = cv2.imread("carParkImg.png")
	cv2.imshow("images",img)
	for pos in posList:
		cv2.rectangle(img,pos,(pos[0]+width,pos[1]+height),(255,0,255),2)  #坐标位置可以多次尝试确定
	cv2.imshow("image",img)
	cv2.setMouseCallback("images",mouseClick)
	if cv2.waitKey(10) & 0xFF== ord('q'):
		break

通过鼠标点击在任何位置添加矩形框,但当矩形框位置出错时,无法进行删除。因此通过添加鼠标右键的事件,删除错误的矩形框。

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)

通过pickle.dump()保持保存鼠标点击的位置信息。

with open('CarParkPos','wb') as f:
	pickle.dump(posList,f)

通过pickle.load()加载保存好的位置信息,即在原有的停车位添加或删除停车位,而不是每一帧画面重新绘制。

with open('CarParkPos','wb') as f:
	posList = pickle.load(f)

完整代码如下:

import cv2
import pickle
img=cv2.imread('carParkImg.png')
width,height = 107,48
try:
	with open('CarParkPos','rb') as f:
		posList = pickle.load(f)
except:
	posList = []
# 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:
		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)
	
	if cv2.waitKey(10) & 0xFF== ord('q'):
		break

3. 停车位视频分析

3. 1 停车监控视频

import cv2
import pickle
import cvzone
import numpy as np
# Video feed
cap = cv2.VideoCapture('carPark.mp4')
while True:
    success,img= cap.read()
    cv2.imshow("Image",img)
    if cv2.waitKey(10) & 0xFF== ord('q'):
        break

视频时间比较短,为了让视频循环播放,添加如下代码:

if cap.get(cv2.CAP_PROP_POS_FRAMES) == cap.get(cv2.CAP_PROP_FRAME_COUNT):  
	cap.set(cv2.CAP_PROP_POS_FRAMES,0)
  • cv2.CAP_PROP_POS_FRAMES :视频播放当前帧
  • cv2.CAP_PROP_FRAME_COUNT :视频总帧数

即:当前视频播放到结尾时,重新播放

3. 2 截取停车位

截取停车位,回来对每个停车位进行图像处理,从而分析该停车位是否被占用

def checkParkingSpace():
    for pos in posList:
        x,y = pos
        imgCrop=img[y:y+height,x:x+width]
        cv2.imshow(str(x*y),imgCrop)

3. 3 图像处理

对图像二值化、高斯模糊处理

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)

cv2.adaptiveThreshold 参数的选择可以通过TrackBar拖到滚动条,直到选择合适的数值。

可以看出停车位上有车辆时白色像素点比较多,停车位没有车辆时,白色像素点很少甚至没有,因此我们可以基于白色像素点数量来确定该车为是否被占用。同时可以看到当停车位为空时存在一些椒盐噪声,通过medianBlur来处理椒盐噪声

imgMedian = cv2.medianBlur(imgThreshold,5)

可以看出椒盐噪声少了一部分。
使用dilate(膨胀)增强白色像素值,便于更好区分每个停车位是否被占用

 kernel=np.ones((3,3),np.uint8);
 imgDilate=cv2.dilate(imgMedian,kernel,iterations=1)

可以看出白色的轮廓比之前加厚了

3. 4 判断停车位是否被占用

截取每个停车位,经过处理后的图像,统计白色像素的数量
修改checkParkingSpace函数,将处理好的图像传入函数

def checkParkingSpace(imgProc):
    for pos in posList:
        x,y = pos  
        imgCrop=imgProc[y:y+height,x:x+width]
        count=cv2.countNonZero(imgCrop)
        cvzone.putTextRect(img,str(count),(x,y+height-3,scale =1.5,thickness=2,offset=0)	

对比可以看出,占有车位的数值比较大1000-2000,空车位的200-500,数值的差距比较大。

画出所有停车位,对比找出合适的阈值,区分停车位为空还是被占用了。

可以看出停车位为空时,值为0-600,而停车位被占用,值为:960-2300,因此我们设定阈值为750。所以低于750此时停车位没有车,高于950则停车位有车。

加上文字描述

代码

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(imgProc):
    spaceCounter=0
    for pos in posList:
        x,y = pos  
        imgCrop=imgProc[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=thickness)
        cvzone.putTextRect(img,str(count),(x,y+height-5),scale =1.5,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))
            
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)
    # for pos in posList:
    #     cv2.rectangle(img,pos,(pos[0]+width,pos[1]+height),(255,0,255),2)
    cv2.imshow("Image",img)
    # cv2.imshow("imgBlur",imgBlur)
    # cv2.imshow("imgThreshold",imgThreshold)
    # cv2.imshow("imgMedian",imgMedian)
    # cv2.imshow("imgDilate",imgDilate)
    if cv2.waitKey(10) & 0xFF== ord('q'):
        break

最终效果如下:

源码链接:https://github.com/yuanxinshui/Opencv-project/tree/main/39%20Parking%20Space%20Counter

到此这篇关于Python中使用Opencv开发停车位计数器的文章就介绍到这了,更多相关python Opencv停车位计数器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python实现数组平移K位问题

    python实现数组平移K位问题

    这篇文章主要介绍了python实现数组平移K位问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • python调用pymssql包操作SqlServer数据库的实现

    python调用pymssql包操作SqlServer数据库的实现

    本文主要介绍了python调用pymssql包操作SqlServer数据库的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • Python-OpenCV深度学习入门示例详解

    Python-OpenCV深度学习入门示例详解

    深度学习已经成为机器学习中最受欢迎和发展最快的领域。深度学习的常见应用包括语音识别、图像识别、自然语言处理、推荐系统等等。本文将通过一些示例代码,带你详细了解深入学习
    2021-12-12
  • Flask中sqlalchemy模块的实例用法

    Flask中sqlalchemy模块的实例用法

    在本篇文章里小编给大家整理了关于Flask中sqlalchemy模块的实例用法,需要的朋友们可以学习下。
    2020-08-08
  • python调用OpenCV实现人脸识别功能

    python调用OpenCV实现人脸识别功能

    这篇文章主要为大家详细介绍了python调用OpenCV实现人脸识别功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • Python groupby函数图文详解

    Python groupby函数图文详解

    pandas中DataFrame提供了一个灵活高效的groupby功能,它使你能以一种自然的方式对数据集进行切片、切块、摘要等操作,下面这篇文章主要给大家介绍了关于Python groupby函数详解的相关资料,需要的朋友可以参考下
    2022-07-07
  • 新年快乐! python实现绚烂的烟花绽放效果

    新年快乐! python实现绚烂的烟花绽放效果

    这篇文章主要为大家详细介绍了python利用可视化技巧实现烟花绽放效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • Python线性点运算数字图像处理示例详解

    Python线性点运算数字图像处理示例详解

    这篇文章主要为大家介绍了数字图像处理基本运算如何用Python详细点运算来处理数字图像有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-09-09
  • Python进程池log死锁问题分析及解决

    Python进程池log死锁问题分析及解决

    最近线上运行的一个python任务负责处理一批数据,为提高处理效率,使用了python进程池,并会打印log,本文给大家分析了Python进程池log死锁问题以及解决方法,需要的朋友可以参考下
    2024-01-01
  • Python socket如何实现服务端和客户端数据传输(TCP)

    Python socket如何实现服务端和客户端数据传输(TCP)

    这篇文章主要介绍了Python socket如何实现服务端和客户端数据传输(TCP),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05

最新评论