1、前言

在学了一些opencv的基础知识之后,开始上手了一些小项目,本次就记录一下关于opencv停车场车位检测的学习过程。技术点包括高斯去噪、自适应阈值、灰度转换、中值滤波、腐蚀膨胀、pickle记录车位坐标等。
最终实现效果


1670209557719


2、车位标记

这里提供一个灰度图测试车位标记,并将各车位的坐标利用pickle保存到文件中,以便后面视频检测车位读取使用。

opencv 仪表识别库 opencv 车辆识别_opencv 仪表识别库


首先我们需要利用cv2.rectangle()一步一步测试出一个车位的长宽是多少,一开始我们可以给一个随意值,然后根据情况调参。这里我最终确定一个车位的宽高是850,550。

ImageWidth,ImageHeight = 850,550

获取到一个车位的宽高后,我们就需要手动框出来每一个车位,记录在文件中。

opencv 仪表识别库 opencv 车辆识别_Image_02

标记车位源码如下:

import pickle

import cv2

############################################

ImageWidth,ImageHeight = 850,550
width, height = 80, 36


############################################

# 如果文件中已有坐标点,则在原坐标点更改
try:
    with open('./CarParkingPos','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))
    # 监听鼠标右键,删除坐标点
    elif 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('./CarParkingPos', 'wb') as f:
        pickle.dump(posList,f)

while True:
	# 读取图片
    img = cv2.imread("./carParkImg.png")
    img = cv2.resize(img,(ImageWidth,ImageHeight))
	
	# 读取上次保存的坐标点,并显示出来
    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)
    cv2.waitKey(1)

3、视频流车位监控

重头戏来了!!!
检测是思路为

  • 调取摄像头读取本地视频,并循环播放
cap = cv2.VideoCapture('./carPark.mp4')
	
	# 循环播放
    if cap.get(cv2.CAP_PROP_POS_FRAMES) == cap.get(cv2.CAP_PROP_FRAME_COUNT):
        cap.set(cv2.CAP_PROP_POS_FRAMES,0)
  • 高斯去噪
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)
  • 膨胀
kenel = np.ones((3,3),np.uint8)
 imgDialate = cv2.dilate(imgMedian,kenel,iterations=1)

opencv 仪表识别库 opencv 车辆识别_Image_03

  • 记录每个 车位黑白像素点
x, y = pos
imgCrop = imgPro[y:y+height,x:x+width]

count = cv2.countNonZero(imgCrop)
  • 计数,标记空车位
if count < 640:
	color = (0,255,0)
	spaceCount += 1
	tickness = 5
else:
	color = (0,0,255)
	tickness = 2
	cv2.rectangle(img, pos, (pos[0] + width, pos[1] + height), color,tickness)

源码如下:

import cv2
import pickle
import cvzone
import numpy as np

##################################################
ImageWidth,ImageHeight = 850,550
width, height = 80, 36

############################################3#####
cap = cv2.VideoCapture('./carPark.mp4')
with open('./CarParkingPos', 'rb') as f:
    posList = pickle.load(f)


def checkParkingspace(imgPro):
    spaceCount = 0
    for pos in posList:
        x, y = pos
        imgCrop = imgPro[y:y+height,x:x+width]

        count = cv2.countNonZero(imgCrop)
        cvzone.putTextRect(img, str(count), (x, y + height - 5), scale=1, thickness=2, offset=0)
        if count < 640:
            color = (0,255,0)
            spaceCount += 1
            tickness = 5
        else:
            color = (0,0,255)
            tickness = 2
        cv2.rectangle(img, pos, (pos[0] + width, pos[1] + height), color,tickness)
    cvzone.putTextRect(img, f'Free: {spaceCount}/{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)

    sucess,img = cap.read()
    img = cv2.resize(img,(ImageWidth,ImageHeight))
    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)
    kenel = np.ones((3,3),np.uint8)
    imgDialate = cv2.dilate(imgMedian,kenel,iterations=1)

    checkParkingspace(imgDialate)
    # for pos in posList:


    cv2.imshow("Image",img)
    cv2.imshow("imgDialate",imgDialate)
    cv2.waitKey(1)

4、结语

这个项目虽然有些简单,但是大家有兴趣可以调参,提升识别率,应用到实际的环境中。

当然这是我学习的一个项目,图片和视频资源来源于网上,代码也不全是自己的
大家需要图片和原视频的话,可以在评论区留下自己的邮箱。

侵删致歉!!!