涉及的知识点
(1)窗口的展示
(2)图像,视频的加载
(3)基本图像的绘制
(4)车辆识别 基本图像运算与处理,形态学,轮廓查找
主要步骤
(1)加载视频
import cv2
import numpy as np
cap = cv2.VideoCapture('E:\\pycharm\\PycharmFile\\opencv\\video\\car.mp4')
while True:
ret, frame = cap.read()
if (ret == True):
cv2.imshow('video', frame)
key = cv2.waitKey(30)
if (key == 27): # 对应键盘上的esc
break
cap.release()
cv2.destroyAllWindows()
(2)去除背景(认为运动的是主体,而不动的是背景)
#用cv2.bgsegm,createBackgroundSubtractorMOG() 效果可能会好一点
bgsubmog=cv2.createBackgroundSubtractorMOG2()
# 灰度
cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 高斯滤波去噪
blur = cv2.GaussianBlur(frame, (3, 3), 5)
# 去背影
mask = bgsubmog.apply(blur)
(3) 形态学处理
# 心态学kernel
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 腐蚀+膨胀 将视频帧中的小白点先去除
# 腐蚀
erode = cv2.erode(mask, kernel, iterations=10)
# 膨胀
dilate = cv2.dilate(erode, kernel, iterations=10)
# 闭操作,膨胀掉内部的黑色斑点
close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)
close = cv2.morphologyEx(close, cv2.MORPH_CLOSE, kernel)
# 查找轮廓
contours, hierarchy = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 根据查找的轮廓,进行绘制外接最大矩阵
for (i, c) in enumerate(contours):
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 3)
(4)统计过程
首先,我们在上一个部分已经绘制出了最大矩阵。那我们就需要对最大矩阵进行判断,看是否是我们需要的车,就用矩阵大小进行判断。
# 对车的宽高判断,判断是否是有效的车
isValid = (w >= min_w) and (h >= min_h)
if (not isValid):
continue
# 到这全是有效的车
判断完是否是车后,需要对车进行判断是否经过了“斑马线”。这是就需要我们先画出一条线(设置线的时候需要对视频大小进行分析,设置一个合适的值),然后以车的中心点代表车,看车辆是否通过了这条线。
# 设置一条线
# 检测线的高度
line_high = 600 # 这个与视频的大小有关,可以打出视频的shape得到大小信息
def center(x, y, w, h):
x1 = int(w / 2)
y1 = int(h / 2)
cx = x + x1
cy = y + y1
return cx, cy
# 存放有效汽车中心点位置的数组
cars = []
# 存车辆中心的点
cpoint = center(x, y, w, h)
cars.append(cpoint)
判断车是否通过(看车的中心点是否经过设置的线的范围)并对车的数目+1 还要将计算后的车从数组中拿走。
for (x, y) in cars:
# 要有一条线,并需要一个范围(只要在这个范围的像素点中,就代表车通过了) 通过了就将这个xy从数组中减去
if (y >= line_high - offset) and (y <= line_high + offset):
carno += 1
cars.remove((x, y))
print(carno)
(5)收尾,完善细节(在视频中显示车辆的数目)(如果发现车辆重复计数,就说明线的范围大了)(如果发现从下往上的车没有被检测到,就应该稍微调整线的高度)
#在视频中显示车辆数
cv2.putText(frame, "cars count:" + str(carno), (500, 60), cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 0, 0), 5)