1、前言
在学了一些opencv的基础知识之后,开始上手了一些小项目,本次就记录一下关于opencv停车场车位检测的学习过程。技术点包括高斯去噪、自适应阈值、灰度转换、中值滤波、腐蚀膨胀、pickle记录车位坐标等。
最终实现效果
1670209557719
2、车位标记
这里提供一个灰度图测试车位标记,并将各车位的坐标利用pickle保存到文件中,以便后面视频检测车位读取使用。
首先我们需要利用cv2.rectangle()一步一步测试出一个车位的长宽是多少,一开始我们可以给一个随意值,然后根据情况调参。这里我最终确定一个车位的宽高是850,550。
ImageWidth,ImageHeight = 850,550
获取到一个车位的宽高后,我们就需要手动框出来每一个车位,记录在文件中。
标记车位源码如下:
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)
- 记录每个 车位黑白像素点
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、结语
这个项目虽然有些简单,但是大家有兴趣可以调参,提升识别率,应用到实际的环境中。
当然这是我学习的一个项目,图片和视频资源来源于网上,代码也不全是自己的
大家需要图片和原视频的话,可以在评论区留下自己的邮箱。
侵删致歉!!!