首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >实战 | 基于OpenCV的停车场空余车位实时监测系统(详细步骤 + 源码)

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

作者头像
Color Space
发布2022-12-22 15:53:48
发布2022-12-22 15:53:48
2.4K0
举报

导 读

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

背景介绍

介绍实现步骤之前,先来看看测试视频(小型停车场实时监控画面):http://mpvideo.qpic.cn/0b2eoaaaoaaaseafammy7vrva4gda5yaabya.f10002.mp4?

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

实现步骤

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

① 设定每个停车位ROI;

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

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

④ 实时检测输出结果。

1

设定每个停车位ROI

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

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

代码语言:javascript
复制
import cv2
import 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则为空位,否则表示停车状态。

代码与效果如下:

代码语言:javascript
复制
import cv2
import 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的状态:

代码语言:javascript
复制
with open('carParkPos','rb') as f:
    posList=pickle.load(f)
frame_counter = 0
def 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

实时检测输出结果

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

代码语言:javascript
复制
import cv2
import numpy as np
import pickle

rectW,rectH=107,48

cap=cv2.VideoCapture('carPark.mp4')

with open('carParkPos','rb') as f:
    posList=pickle.load(f)
frame_counter = 0
def 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)

5

参考链接 & 源码下载

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-12-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OpenCV与AI深度学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档