前言
本节完成了车辆识别的小项目。涉及到的知识点主要有;
- 视频的加载
- 通过形态学识别车辆
- 对车辆进行统计
- 显示车辆统计信息
下面的车辆检测程序主要实现的功能:将视频中的车辆用方框选中,并对其进行计数,然后将数量实时显示在视频上方。
代码示例:
import cv2
import numpy as np
# 车辆检测最小值
min_w = 60
min_h = 60
# 检测线位置
line_high = 550
# 存放有效车辆的数组
cars = []
# 偏移量
offset = 7
# 车辆计数
carno = 0
# 求矩形中心点函数
def center(x,y,w,h):
x1 = int(w/2)
y1 = int(h/2)
cx = x+x1
cy = y+y1
return cx, cy
cap = cv2.VideoCapture('./video/car.mp4')
bgsubmog = cv2.createBackgroundSubtractorMOG2()
# 形态学kernel
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
while True:
ret, frame = cap.read()
if (ret == True):
# 图像转化为单通道
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 高斯滤波
blur = cv2.GaussianBlur(frame_gray, (3, 3), 5)
#去背景
mask = bgsubmog.apply(blur)
# 腐蚀(去掉前景中的白色小噪点)
erode = cv2.erode(mask, kernel)
# 膨胀还原
dilate = cv2.dilate(erode, kernel, iterations = 2)
#闭操作,填补汽车内部的黑色斑块
close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)
# 查找轮廓
cnts, h = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 画一条检测线
cv2.line(frame, (10, line_high), (1200, line_high), (0, 255, 0), 3)
# 框选车辆
for (i, c) in enumerate(cnts):
(x,y,w,h) = cv2.boundingRect(c)
# 对选中方框宽高进行判断,是否为车辆
isValid = (w >= min_w) and (h >= min_h)
if (not isValid):
continue
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 2)
cpoint = center(x, y, w, h)
cars.append(cpoint)
for (x,y) in cars:
if((y > line_high - offset) and (y < line_high + offset)):
carno += 1
cars.remove((x, y))
print(carno)
cv2.putText(frame, "Cars Count:" + str(carno), (500,60), cv2.FONT_HERSHEY_TRIPLEX, 1, (255, 0, 0))
cv2.imshow('frame', frame)
cv2.imshow('close', close)
key = cv2.waitKey(20)
if(key == 27):
break
cap.release()
cv2.destroyAllWindows()
结果展示:
小结:
虽然大致实现了车辆检测的功能,但是车辆计数的功能还有较大缺点,通过调节参数不能很好地改善。要么漏计数,要么多计数。例如:一辆车刚好停在绿线上,那么程序会一直计数,主要原因是:电脑无法将视频两帧之间同一辆车关联起来,因此计数之后还会再次计数。要解决这一问题,就必须能分辨出两帧画面里是同一辆车,需要引入深度学习。