笔者前期对OpenCV进行了一些了解,通过教学视频的学习,大致明白了该库的主要功能。
现将学习后期教学视频中的一组代码记录于此
OpenCV车辆检测项目
- 加载视频
- 通过形态学识别车辆
- 对车辆进行统计
- 显示车辆统计信息
视频加载
import cv2
import numpy as np
cap = cv2.VideoCapture("video.mp4")
while True:
ret, frame = cap.read()
if ret == True:
cv2.imshow("video", frame)
key = cv2.waitKey(1)
if key == 27:
break
cap.release()
cv2.destroyAllWindows()
去背景
- createBackgroundSubtractorMOG(…)
- history=200
论文:
An improved adaptive background mixture model for real-time tracking with shadow detection
import cv2
import numpy as np
cap = cv2.VideoCapture("video.mp4")
bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()
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)
cv2.imshow("video", mask)
key = cv2.waitKey(1)
if key == 27:
break
cap.release()
cv2.destroyAllWindows()
形态学处理
膨胀,腐蚀等,去除噪点,增强图像,方便轮廓提取。
import cv2
import numpy as np
cap = cv2.VideoCapture("video.mp4")
bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()
# 形态学kernel
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)
close = cv2.morphologyEx(close, 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", frame)
key = cv2.waitKey(1)
if key == 27:
break
cap.release()
cv2.destroyAllWindows()
逻辑处理
-
判断是否为车
- 通过API获取外轮廓举行
- 通过宽高进行判断:宽高大于一定值
- 是车,则绘制矩形边框
-
车辆统计
- 确定一条检测线并绘制出来
- 确定检测范围(检测线上下偏移量)
- 每一帧统计所有确定为车的矩形的中心
- 遍历中心是否位于检测范围内:是,则统计数量加一
- 课程中,清空车辆列表的地方感觉不对
import cv2
import numpy as np
min_w = 90
min_h = 90
# 检测线的高度
line_high = 600
# 线的偏移量
offset = 6
# 统计车的数量
carno = 0
# 存放有效车辆的数组
cars = []
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.mp4")
bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()
# 形态学kernel
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)
close = cv2.morphologyEx(close, 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, 0, 255), 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.imshow("video", frame)
key = cv2.waitKey(1)
if key == 27:
break
cap.release()
cv2.destroyAllWindows()
显示统计信息
- 添加统计信息
...
cv2.putText(
frame,
"Cars Count:" + str(carno),
(500, 60),
cv2.FONT_HERSHEY_SIMPLEX,
2,
(255, 0, 0),
5,
)
cv2.imshow("video", frame)
...
- 微调
- 检测范围:调整线的偏移量,防止重复计数或漏记
- 检测位置:上下移动检测线的位置,防止漏记
补充
机器学习和深度学习存在更好的识别方案,待后期学习。