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


Posted in Python onApril 04, 2022

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

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)

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

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)

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

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

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

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

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

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)

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

3. 3 图像处理

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

imgGray =cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
imgBlur =cv2.GaussianBlur(imgGray,(3,3),1)

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

利用自适应二值化对图像进行处理

imgThreshold=cv2.adaptiveThreshold(imgBlur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,25,16)

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

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

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

imgMedian = cv2.medianBlur(imgThreshold,5)

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

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

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

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

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

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)

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

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

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

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

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

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

加上文字描述

代码

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

最终效果如下:

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

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

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

Python 相关文章推荐
python定时执行指定函数的方法
May 27 Python
详解在Python程序中解析并修改XML内容的方法
Nov 16 Python
Python实现FTP上传文件或文件夹实例(递归)
Jan 16 Python
python实现聚类算法原理
Feb 12 Python
Python FTP两个文件夹间的同步实例代码
May 25 Python
python使用scrapy发送post请求的坑
Sep 04 Python
python GUI实现小球满屏乱跑效果
May 09 Python
django ManyToManyField多对多关系的实例详解
Aug 09 Python
Pytorch之Variable的用法
Dec 31 Python
Django关于admin的使用技巧和知识点
Feb 10 Python
利用Python的folium包绘制城市道路图的实现示例
Aug 24 Python
深度学习小工程练习之垃圾分类详解
Apr 14 Python
Python采集股票数据并制作可视化柱状图
python疲劳驾驶困倦低头检测功能的实现
Python实现自动玩连连看的脚本分享
Apr 04 #Python
Python利用Turtle绘制哆啦A梦和小猪佩奇
Python必备技巧之函数的使用详解
Python批量解压&压缩文件夹的示例代码
Apr 04 #Python
Python调用腾讯API实现人脸身份证比对功能
You might like
APACHE的AcceptPathInfo指令使用介绍
2013/01/18 PHP
php cli模式学习(PHP命令行模式)
2013/06/03 PHP
php生成不重复随机数、数组的4种方法分享
2015/03/30 PHP
PHP 生成微信红包代码简单
2016/03/25 PHP
PHP模板引擎Smarty之配置文件在模板变量中的使用方法示例
2016/04/11 PHP
基于jQuery的弹出消息插件 DivAlert之旅(一)
2010/04/01 Javascript
javascript客户端解决方案 缓存提供程序
2010/07/14 Javascript
jQuery动态添加的元素绑定事件处理函数代码
2011/08/02 Javascript
jquery动画2.元素坐标动画效果(创建一个图片走廊)
2012/08/24 Javascript
js 使用form表单select类实现级联菜单效果
2012/12/19 Javascript
javascript中interval与setTimeOut的区别示例介绍
2014/03/14 Javascript
JS不能跨域借助jquery获取IP地址的方法
2014/08/20 Javascript
JQuery中DOM事件绑定用法详解
2015/06/13 Javascript
BootStrap中Tab页签切换实例代码
2016/05/30 Javascript
微信小程序 wxapp画布 canvas详细介绍
2016/10/31 Javascript
AngularJS 异步解决实现方法
2017/06/12 Javascript
Angular实现双向折叠列表组件的示例代码
2017/11/21 Javascript
详解mpvue scroll-view自动回弹bug解决方案
2018/10/01 Javascript
webpack dll打包重复问题优化的解决
2018/10/10 Javascript
支付宝小程序自定义弹窗dialog插件的实现代码
2018/11/30 Javascript
vue中img src 动态加载本地json的图片路径写法
2019/04/25 Javascript
elementUI select组件使用及注意事项详解
2019/05/29 Javascript
jquery中为什么能用$操作
2019/06/18 jQuery
Python中http请求方法库汇总
2016/01/06 Python
Django数据库表反向生成实例解析
2018/02/06 Python
对Pyhon实现静态变量全局变量的方法详解
2019/01/11 Python
基于Python爬取爱奇艺资源过程解析
2020/03/02 Python
Python使用pyyaml模块处理yaml数据
2020/04/14 Python
基于Python测试程序是否有错误
2020/05/16 Python
解决pycharm修改代码后第一次运行不生效的问题
2021/02/06 Python
全球性的在线鞋类品牌:Public Desire
2019/04/03 全球购物
如何理解委托
2012/01/06 面试题
治理商业贿赂工作总结
2015/08/10 职场文书
升职自荐书
2019/05/09 职场文书
如何利用STAR法则制作留学文书?
2019/08/26 职场文书
nginx配置文件使用环境变量的操作方法
2021/06/02 Servers