理论知识见上一节,最终效果如下
涉及到的内容
(1)窗口的展示
(2)图像/视频的加载
(3)基本图形的绘制
(4)车辆识别
基本图像运算与处理、形态学处理、轮廓查找
涉及到的知识点
加载视频
通过形态学识别车辆
对车辆进行统计
显示车辆统计信息
加载视频
-
import cv2
-
import numpy
as np
-
-
cap = cv2.VideoCapture(
'E:\\video.mp4')
#加载视频
-
-
while
True:
-
ret, frame = cap.read()
-
-
if (ret ==
True) :
-
cv2.imshow(
'video',frame)
-
key = cv2.waitKey(
1)
-
if(key ==
27) :
#esc键
-
break
-
-
cap.release()
-
cv2.destroyAllWindows()
去除背景(关键)
运动的物体为前景,静止的物体为背景。将前景提取出来,把背景去除。
createBackgroundSubtractorMOG()
history:缓冲,表示多少毫秒,可不指定参数,用默认的即可;
具体实现原理比较复杂,用到了一些视频序列关联信息,把像素值不变的认为是背景;
注意:在opencv中已经不支持该函数,而是用createBackgroundSubtractorMOG2()替代;如果需要使用可以安装opencv_contrib模块,在其中的bgsegm中保留了该函数;
API使用默认参数即可,调整比较多的是history,
在视频中,以时间轴为顺序。如果像素在整个时间轴内不发生变化,则认为是背景,如果发生变化且很频繁,则认为是前景。
去除背景参考论文:
An Improved Adaptive Background Mixture Model for Real-time Tracking with Shadow Detection
在去除背景之前去噪:首先将原始图像进行灰度化,然后经过高斯滤波进行去噪
-
import cv2
-
import numpy
as np
-
-
cap = cv2.VideoCapture(
'E:\\video.mp4')
#加载视频
-
-
bgsubmog = cv2.createBackgroundSubtractorMOG2()
-
test = cv2.createBackgroundSubtractorMOG2()
#测试未经过高斯去噪的图像效果
-
while
True:
-
ret, frame = cap.read()
-
-
if (ret ==
True) :
-
-
# 灰度化处理
-
cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
-
# 去噪(高斯)
-
blur = cv2.GaussianBlur(frame, (
7,
7),
5)
-
# 去背景
-
mask = bgsubmog.apply(blur)
-
-
test1 = test.apply(frame)
-
cv2.imshow(
'video', mask)
-
cv2.imshow(
'test1', test1)
-
-
key = cv2.waitKey(
1)
-
if(key ==
27) :
#esc键
-
break
-
-
cap.release()
-
cv2.destroyAllWindows()
形态学处理
腐蚀、膨胀、开运算、闭运算、顶帽、黑帽
-
import cv2
-
from cv2
import erode
-
from cv2
import dilate
-
import numpy
as np
-
-
cap = cv2.VideoCapture(
'E:\\video.mp4')
#加载视频
-
-
bgsubmog = cv2.createBackgroundSubtractorMOG2()
-
-
# 形态学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, (
7,
7),
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)
-
# 对所有轮廓进行遍历
-
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)
-
# cv2.imshow('close', close)
-
-
key = cv2.waitKey(
1)
-
if(key ==
27) :
# esc键
-
break
-
-
cap.release()
-
cv2.destroyAllWindows()
逻辑处理
通过宽和高去除小的矩形
绘制检测线,计算车的中心点
如果车的中心点落在检测线的有效区域内,则计数加1
显示车辆统计信息
将统计的信息显示在视频中,车辆被重复计数产生的原因:检测线过宽,车辆还未完全出去就又被统计一次,还有一个原因是检测线的位置
传统的车辆检测方法弊端:车速过慢容易造成重复检测,车速过快造成漏检
目前用的较多的方法为深度学习,对车辆进行跟踪
完整程序如下:
-
from asyncio
import CancelledError
-
import cv2
-
from cv2
import erode
-
from cv2
import dilate
-
import numpy
as np
-
-
# 滤除的最小矩形的范围
-
min_w =
90
-
min_h =
90
-
-
# 定义检测线的高度,与视频大小有关,视频左上角为(0,0)
-
line_high =
550
-
# 线的偏移量
-
offset =
7
-
-
# 统计车的数量
-
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(
'E:\\video.mp4')
#加载视频
-
-
bgsubmog = cv2.createBackgroundSubtractorMOG2()
-
-
# 形态学kernel
-
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (
5,
5))
-
-
while
True:
-
ret, frame = cap.read()
-
-
if (ret ==
True) :
-
-
# 灰度化处理
-
cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
-
# print(frame.shape) # 获取视频大小的信息
-
# exit() # 该命令之后的所有程序都不执行
-
# 去噪(高斯)
-
blur = cv2.GaussianBlur(frame, (
7,
7),
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),(
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
-
# 到这里都是有效的车,绘制车的矩形
-
cv2.rectangle(frame, (x,y),(x+w,y+h),(
0,
0,
255),
2)
-
# 存储车的中心点
-
cpoint = center(x,y,w,h)
# 计算车的中心点
-
cars.append(cpoint)
# 将中心点数据存储到cars这个数组中
-
-
for (x,y)
in cars :
# 遍历数组,如果车的中心点落在检测线的有效区域内,则计数+1,然后去除该数组
-
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_SIMPLEX,
2, (
255,
0,
0),
5)
-
cv2.imshow(
'video', frame)
-
# cv2.imshow('close', close)
-
key = cv2.waitKey(
1)
-
if(key ==
27) :
# esc键
-
break
-
-
cap.release()
-
cv2.destroyAllWindows()
转载:https://blog.csdn.net/qq_45355603/article/details/125286992