实战 | 基于OpenCV的停车场空余车位实时监测系统(详细步骤 + 源码)

83 篇文章 25 订阅
44 篇文章 9 订阅

导  读

    本文主要介绍如何使用Python和OpenCV实现一个停车场空余车位实时监测系统,并包含详细步骤和源码。

      

背景介绍

    介绍实现步骤之前,先来看看测试视频(小型停车场实时监控画面):

,时长00:28

    我们的目标是实时检测停车场剩余空位数量,以此来提示将要进入停车场的司机是否有空位。

      

实现步骤

    完成一个停车场实时空位检测系统的主要步骤如下:

    ① 设定每个停车位ROI;

    ② 设计停车与空位的判断方法;

    ③ 对每个ROI分别判断状态;

    ④ 实时检测输出结果。

1

设定每个停车位ROI

    停车位ROI的设定可以根据实际情况处理,一般停车位比较多且有规律的可以使用坐标间隔增加的方式自动设定。本文实例中停车位较少,且中间有部分特殊位置,所以采用手动框选设定方法。如下图所示:

    鼠标左键按下,标记新的停车位;鼠标右键按下且点击位置位于矩形内,删除对应矩形。实现代码如下:

import cv2import pickle
rectW,rectH=107,48
try:    with open('carParkPos','rb') as f:        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+rectW and y1<y<y1+rectH:                posList.pop(i)    with open('carParkPos','wb') as f:        pickle.dump(posList,f)

while True:    img=cv2.imread("img.png")    for pos in posList: cv2.rectangle(img,pos,(pos[0]+rectW,pos[1]+rectH),(0,0,255),2)
    cv2.imshow("Image",img)    cv2.setMouseCallback("Image",mouseClick)    if cv2.waitKey(1) == 27:        break

    直至标记好所有的停车位ROI,并写入文件,效果如下:

 

2

为设计停车与空位的判断方法

    选择停车状态和空位状态的图片各2张,做演示说明:

    判断停车状态与空位状态的具体步骤如下:

    ① 转为灰度图;

    ② 高斯滤波;

    ③ 自适应二值化;

    ④ 中值滤波 + 膨胀;

    ⑤ 计算非0像素数量;

    ⑥ 判断结果:非0像素数量 < 900则为空位,否则表示停车状态。

    代码与效果如下:

import cv2import numpy as np
img = cv2.imread('2.png')cv2.imshow('src', img)
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)blur=cv2.GaussianBlur(gray,(3,3),1)Thre=cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,25,16)blur=cv2.medianBlur(Thre,5)kernel=np.ones((3,3),np.uint8)dilate=cv2.dilate(blur,kernel,iterations=1)count=cv2.countNonZero(dilate)cv2.imshow('dilate', dilate)print(count)if count<900:    cv2.rectangle(img, (0, 0), (img.shape[1],img.shape[0]), (0, 255, 0), 5)else:    cv2.rectangle(img, (0, 0), (img.shape[1],img.shape[0]), (0, 0, 255), 5)
cv2.imshow('result', img)cv2.waitKey()cv2.destroyAllWindows()

    绿色矩形表示空位,红色矩形表示停车,数量表示非0像素数。

3

对每个ROI分别判断状态

    从坐标文件中循环读取位置信息,依次判断每个ROI的状态:​​​​​​​

with open('carParkPos','rb') as f:    posList=pickle.load(f)frame_counter = 0def check(imgPro):    spaceCount=0    for pos in posList:        x,y=pos        crop=imgPro[y:y+rectH,x:x+rectW]        count=cv2.countNonZero(crop)        if count<900:            spaceCount+=1            color=(0,255,0)            thick=5        else:            color=(0,0,255)            thick=2
        cv2.rectangle(img,pos,(x+rectW,y+rectH),color,thick)    cv2.rectangle(img,(45,30),(250,75),(180,0,180),-1)    cv2.putText(img,f'Free: {spaceCount}/{len(posList)}',(50,60),cv2.FONT_HERSHEY_SIMPLEX,0.9,(255,255,255),2)

4

实时检测输出结果

    实时检测输出结果,代码和效果如下:​​​​​​​

import cv2import numpy as npimport pickle
rectW,rectH=107,48
cap=cv2.VideoCapture('carPark.mp4')
with open('carParkPos','rb') as f:    posList=pickle.load(f)frame_counter = 0def check(imgPro):    spaceCount=0    for pos in posList:        x,y=pos        crop=imgPro[y:y+rectH,x:x+rectW]        count=cv2.countNonZero(crop)        if count<900:            spaceCount+=1            color=(0,255,0)            thick=5        else:            color=(0,0,255)            thick=2
        cv2.rectangle(img,pos,(x+rectW,y+rectH),color,thick)    cv2.rectangle(img,(45,30),(250,75),(180,0,180),-1)    cv2.putText(img,f'Free: {spaceCount}/{len(posList)}',(50,60),cv2.FONT_HERSHEY_SIMPLEX,0.9,(255,255,255),2)
while True:    _,img=cap.read()    if frame_counter == cap.get(cv2.CAP_PROP_FRAME_COUNT):        frame_counter = 0 #Or whatever as long as it is the same as next line        cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, 0)    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)    blur=cv2.GaussianBlur(gray,(3,3),1)    Thre=cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,25,16)    blur=cv2.medianBlur(Thre,5)    kernel=np.ones((3,3),np.uint8)    dilate=cv2.dilate(blur,kernel,iterations=1)    check(dilate)
    cv2.imshow("Image",img)    cv2.waitKey(10)

 

参考链接 & 源码下载

https://github.com/creativekids11/Car-Parking-Space-Counter-Detector

  • 9
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
【资源说明】 1.项目代码均经过功能验证ok,确保稳定可靠运行。欢迎下载使用体验! 2.主要针对各个计算机相关专业,包括计算机科学、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师、企业员工。 3.项目具有丰富的拓展空间,不仅可作为入门进阶,也可直接作为毕设、课程设计、大作业、初期项目立项演示等用途。 4.当然也鼓励大家基于此进行二次开发。在使用过程中,如有问题或建议,请及时沟通。 5.期待你能在项目中找到乐趣和灵感,也欢迎你的分享和反馈! 【项目介绍】 基于Opencv+Mysql+QT实现车牌识别停车场管理系统源码(含超详细注释+项目说明).zip 实现功能 `登陆`功能 `注册`功能 账户`信息管理`增删改查 停车`信息查询` 车辆`入库`和车辆`出库` 出库入库判断车牌信息判断 微信小程序调用`PHP`数据库后端查询车场车位 微信小程序预定系统 调用`摄像头`和`视频` `车牌识别` 剩余车位预定可视化展示(实时同步小程序) `优化EasyPR`过时的style,适配`Qt5.12.1`,`C++11` 前端多线程数据库初始化,与多线程循环检测更新饼图 Linux后端优化数据库和QT多次调用的TCP开销 文件解释 * 查询订阅小程序存放小程序源码(需要`修改`里面调用`IP`) * 查询订阅小程序后端PHP(存放的`PHP`供小程序`调用`的后端代码) * 论文部分(存储`开发文档`,以及和本项目相关的`书籍`和`论文`,老师要求的是完善版本,数据库文件也在里面) * 首页的`.pro`是`QT`的运行文件 * `images`是QT文件调用的图片文件夹 环境: 阅读详细[环境配置](./environment.md) 客户端 * `QT5.12.1` * `C++11` * `MySql 8.0.27` * OpenCV 3.2.0 * 安装K-Lite_Codec_Pack_1676_Standard解析视频\(安装全部默认选项即可) 微信小程序 # 后台 * `CentOS 7.6.1810 x86_64` * ``Nginx 1.18.0` * `PHP-5.6.40` # 前端 * 微信开发者工具``1.06` 环境配置 QT换将 * MySQL环境配置 > ​ 由于直接将在QT中引用MySQL`并不能`直接使用,所以需要将MySQL的动态链接库存放到QT的bin目录下,才可以调用MySQL。QT默认使用`C++11`编译 更多详情见项目说明!!
下面是一个简单的Opencv停车场空余车位检测的示例代码,仅供参考: ```python import cv2 # 读取停车场图像 img = cv2.imread('parking_lot.jpg') # 转换颜色空间为灰度 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 对图像进行高斯模糊 blur = cv2.GaussianBlur(gray, (5, 5), 0) # 进行Canny边缘检测 edges = cv2.Canny(blur, 50, 150) # 对边缘图像进行形态学操作,填充小孔洞 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel) # 查找轮廓 contours, hierarchy = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 遍历所有轮廓,判断是否为空余车位 for contour in contours: # 计算轮廓面积 area = cv2.contourArea(contour) # 如果面积小于一定阈值,则认为是噪声 if area < 1000: continue # 计算轮廓周长 perimeter = cv2.arcLength(contour, True) # 计算轮廓近似多边形 approx = cv2.approxPolyDP(contour, 0.02 * perimeter, True) # 如果近似多边形有4个顶点,则认为是矩形车位 if len(approx) == 4: # 计算车位中心坐标 M = cv2.moments(contour) cx = int(M['m10'] / M['m00']) cy = int(M['m01'] / M['m00']) # 在图像上绘制车位中心点 cv2.circle(img, (cx, cy), 5, (0, 255, 0), -1) # 显示结果图像 cv2.imshow('Parking Lot', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 注意:这只是一个简单的示例代码,实际应用中需要根据具体场景进行调整和优化。同时,由于车位的颜色和形状可能会有很大差异,因此需要进行充分的测试和训练,以确保算法的准确性和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Color Space

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值