项目总体分为四大步:
- 加载视频
- 车辆识别
- 车辆统计
- 信息显示
1. 加载视频
import cv2
import numpy as np# 读取视频
cap = cv2.VideoCapture('video/cars.mp4')while True:# 读取帧ret, frame = cap.read()if (ret == True):cv2.imshow('video', frame)else:breakkey = cv2.waitKey(1)if (key == 27):breakcap.release()cv2.destroyAllWindows()
2. 车辆识别
形态学处理
import cv2
import numpy as np# 读取视频
cap = cv2.VideoCapture('video/cars.mp4')bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()#
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))while True:# 读取帧ret, frame = cap.read()if (ret == True):# 灰度cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 去噪blur = cv2.GaussianBlur(frame, (3, 3), 5)# 去背影mask = bgsubmog.apply(blur)# 腐蚀 去掉小方块erode = cv2.erode(mask, kernel)# 膨胀 还原放大dilate = cv2.dilate(erode, kernel, iterations=3)# 闭操作 去掉物体内部方块close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)# cnts, h = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)for (i, c) in enumerate(cnts):(x, y, w, h) = cv2.boundingRect(c)cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 2)cv2.imshow('video', mask)cv2.imshow('erode', close)else:print("Error")breakkey = cv2.waitKey(1)if (key == 27):breakcap.release()cv2.destroyAllWindows()
3. 车辆统计
最小合法车宽高和检测线高度根据实际情况需要调整。
import cv2
import numpy as np# 最小合法车宽高
min_w = 50
min_h = 60# 检测线高度
line_high = 600# 存放有效车辆数组
cars = []# 线的偏移量
offset = 6# 统计车的数量
carno = 0def center(x, y, w, h):x1 =int(w/2)y1 = int(h/2)cx = x + x1cy = y + y1return cx, cy# 读取视频
cap = cv2.VideoCapture('video/cars.mp4')bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()#
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))while True:# 读取帧ret, frame = cap.read()if (ret == True):# 灰度cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 去噪blur = cv2.GaussianBlur(frame, (3, 3), 5)# 去背影mask = bgsubmog.apply(blur)# 腐蚀 去掉小方块erode = cv2.erode(mask, kernel)# 膨胀 还原放大dilate = cv2.dilate(erode, kernel, iterations=3)# 闭操作 去掉物体内部方块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), (255, 255, 0), 3)for (i, c) in enumerate(cnts):(x, y, w, h) = cv2.boundingRect(c)cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 2)# 对车辆的宽高进行判断# 以验证是否是有效车辆isValid = (w >= min_w) and (h >= min_h)if (not isValid):continue# 到这里都是有效车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 += 1cars.remove((x, y))print(carno)cv2.imshow('video', frame)else:print("Error")breakkey = cv2.waitKey(1)if (key == 27):breakcap.release()cv2.destroyAllWindows()
4. 显示信息(完整代码)
这部分我根据视频的实际情况,对形态学操作做了一些调整。
但识别效果仍然不是太好,还需要进一步调整。
import cv2
import numpy as np# 最小合法车宽高
min_w = 50
min_h = 60# 检测线高度
line_high = 600# 存放有效车辆数组
cars = []# 线的偏移量
offset = 6 # 统计车的数量
carno = 0def center(x, y, w, h):x1 =int(w/2)y1 = int(h/2)cx = x + x1cy = y + y1return cx, cy# 读取视频
cap = cv2.VideoCapture('video/cars.mp4')bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()#
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))while True:# 读取帧ret, frame = cap.read()if (ret == True):# 灰度cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 去噪blur = cv2.GaussianBlur(frame, (5, 5), 5)# 去背影mask = bgsubmog.apply(blur)# 膨胀 还原放大dilate = cv2.dilate(mask , kernel, iterations=5)# 腐蚀 去掉小方块erode = cv2.erode(dilate, kernel, iterations=3)# 闭操作 去掉物体内部方块close = cv2.morphologyEx(erode, cv2.MORPH_CLOSE, kernel, iterations=6)# cnts, h = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 绘制检测线cv2.line(frame, (10, line_high), (1200, line_high), (255, 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# 到这里都是有效车cpoint = center(x, y, w, h)cars.append(cpoint)cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 0, 255), 2)for (x, y) in cars:if ((y > line_high - offset) and (y < line_high + offset)):carno += 1cars.remove((x, y))print(carno)cv2.putText(frame, "Cars Count:" + str(carno), (500, 60), cv2.FONT_HERSHEY_SCRIPT_SIMPLEX, 2, (255, 0, 0), 5)cv2.imshow('video', frame)cv2.imshow('1', close)else:print("Error")breakkey = cv2.waitKey(1)if (key == 27):breakcap.release()cv2.destroyAllWindows()