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随手笔记之标准类型内建函数
Dec 02 Python
详解Python pygame安装过程笔记
Jun 05 Python
酷! 程序员用Python带你玩转冲顶大会
Jan 17 Python
python实现图片彩色转化为素描
Jan 15 Python
对Python 检查文件名是否规范的实例详解
Jun 10 Python
详解pyinstaller selenium python3 chrome打包问题
Oct 18 Python
win10下python2和python3共存问题解决方法
Dec 23 Python
Python加密模块的hashlib,hmac模块使用解析
Jan 02 Python
Python 生成VOC格式的标签实例
Mar 10 Python
PyCharm上安装Package的实现(以pandas为例)
Sep 18 Python
python爬虫使用scrapy注意事项
Nov 23 Python
selenium判断元素是否存在的两种方法小结
Dec 07 Python
Python采集股票数据并制作可视化柱状图
python疲劳驾驶困倦低头检测功能的实现
Python实现自动玩连连看的脚本分享
Apr 04 #Python
Python利用Turtle绘制哆啦A梦和小猪佩奇
Python必备技巧之函数的使用详解
Python批量解压&压缩文件夹的示例代码
Apr 04 #Python
Python调用腾讯API实现人脸身份证比对功能
You might like
PHP+DBM的同学录程序(5)
2006/10/09 PHP
php 定界符格式引起的错误
2011/05/24 PHP
10 个经典PHP函数
2013/10/17 PHP
PHP exif扩展方法开启详解
2014/07/28 PHP
PHP实现根据银行卡号判断银行
2015/04/29 PHP
Thinkphp5.0 框架的请求方式与响应方式分析
2019/10/14 PHP
jQuery dialog 异步调用ashx,webservice数据的代码
2010/08/03 Javascript
jQuery aminate方法定位到页面具体位置
2013/12/26 Javascript
删除条目时弹出的确认对话框
2014/06/05 Javascript
jquery向上向下取整适合分页查询
2014/09/06 Javascript
使用jsonp完美解决跨域问题
2014/11/27 Javascript
原生js实现模拟滚动条
2015/06/15 Javascript
如何实现JavaScript动态加载CSS和JS文件
2020/12/28 Javascript
xtemplate node.js 的使用方法实例解析
2016/08/22 Javascript
JavaScript中如何使用cookie实现记住密码功能及cookie相关函数介绍
2016/11/10 Javascript
Vue.js实现简单ToDoList 前期准备(一)
2016/12/01 Javascript
探索Vue高阶组件的使用
2018/01/08 Javascript
微信小程序MUI导航栏透明渐变功能示例(通过改变rgba的a值实现)
2019/01/24 Javascript
vue.js 打包时出现空白页和路径错误问题及解决方法
2019/06/26 Javascript
解决nuxt 自定义全局方法,全局属性,全局变量的问题
2020/11/05 Javascript
vue中实现点击空白区域关闭弹窗的两种方法
2020/12/30 Vue.js
python使用socket向客户端发送数据的方法
2015/04/29 Python
西班牙汉普顿小姐:购买帆布鞋和太阳镜
2016/10/23 全球购物
印尼太阳百货公司网站:Matahari
2018/02/04 全球购物
创建服务型党组织实施方案
2014/02/25 职场文书
中国梦演讲稿范文
2014/08/28 职场文书
师德师风个人自我剖析材料
2014/09/27 职场文书
初中生旷课检讨书范文
2014/10/06 职场文书
大国崛起日本观后感
2015/06/02 职场文书
高三毕业感言
2015/07/30 职场文书
防溺水主题班会教案
2015/08/12 职场文书
MySQL8.0.24版本Release Note的一些改进点
2021/04/22 MySQL
解析Java异步之call future
2021/06/14 Java/Android
vue+element ui实现锚点定位
2021/06/29 Vue.js
Vue的过滤器你真了解吗
2022/02/24 Vue.js
Python字符串格式化方式
2022/04/07 Python