OpenCV_车辆检测实战

前言:总纲请看《计算机视觉学习路》

1.去除背景

createBackgroundSubtractorMOG2( ... ) 

history = 200  # 代表预存多少视频帧,根据这些帧里面静止的东西判断背景

 

 

可以看到树叶形成了很多噪点,所以需要在去除背景先去噪,下面是去噪后的视频

2.形态处理

去除背景通过腐蚀去掉小的噪点

 

 

腐蚀膨胀后发现有很多残缺的地方:

 

所以还要进行一次闭运算:如果加了闭运算还有物体内部还有斑块,可以再进行一次闭运算

 

3.查找轮廓

根据上面处理完的视频,可以找到一些(车和噪点的)轮廓 ,并且在原视频绘制出来,可以看到还是有一些其他的轮廓会显示出来

观察到车辆经过摄像头下方时,边框会变大,所以根据边框宽高,设置一个阈值,小于阈值的不显示。

获取到边框之后,用边框的中心点表示车辆,并且存入一个数组中,在视频底部画一条线,当车辆的中心点经过该线时,表示有车辆经过。

天空云动的时候轮廓也比较大,但是该轮廓一般静止,中心点不可能经过下面那条线!!!

 

4.车辆统计

查找到有效车辆后,需要将统计的个数显示在屏幕上,整体效果如下:

 

总结:传统目标检测的缺点: 

  1. 当车辆靠的较近时,容易漏检
  2. 当车辆行驶较慢时,容易重复计数

更准确的统计信息需要使用深度学习,后面进行介绍。 

总的代码如下:

import cv2
import numpy as np

# 加载视频
cap = cv2.VideoCapture('../img/video.mp4')

# 背景去除
bgsubmog = cv2.createBackgroundSubtractorMOG2()

# 创建腐蚀膨胀的卷积核
k = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 设置最小宽高阈值
min_w, min_h = 90, 90
# 创建一个列表存放车辆轮廓中心点
cars = []
car_n = 0  # 车辆的个数
# 检测线的高   视频的尺寸为1280*720
line_height = 550
# 线的偏移
line_offset = 6


# 定义函数,计算中心点
def center(x, y, w, h):
    x1 = int(w / 2)
    y1 = int(h / 2)
    cx = x + x1
    cy = y + y1
    return cx, cy


while True:
    ret, frame = cap.read()
    if ret:
        # 灰度化
        cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 由于一些树叶也会动,形成噪点,所以进行去噪
        blur = cv2.GaussianBlur(frame, (9, 9), 5)  # 9*9可以自己设置 3*3  5*5 7*7.。。
        mask = bgsubmog.apply(blur)  # 去除背景
        # 腐蚀
        erode = cv2.erode(mask, k)
        # 腐蚀之后变小了,要膨胀
        dilate = cv2.dilate(erode, k, iterations=2)
        # 闭操作,去掉物体内部的小块
        close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, k)
        close = cv2.morphologyEx(close, cv2.MORPH_CLOSE, k)
        # 查找轮廓
        contours, h = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        # 每一帧都要画线
        cv2.line(frame, (0, line_height), (1280, line_height), (0, 255, 0), 2)
        for (i, c) in enumerate(contours):  # 拿到索引和边界
            (x, y, w, h) = cv2.boundingRect(c)  # 绘制矩形
            if w >= min_w and h >= min_h:  # 如果是车辆,绘制轮廓
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255))
                # 存取车的轮廓的中心点,如果中心点过线,代表有车经过
                cpoint = center(x, y, w, h)  # 计算中心点
                cars.append(cpoint)
                for (x, y) in cars:
                    # 如果车在线的上下偏移量之间,表示有车辆经过
                    if (y > line_height - line_offset) and (y < line_height + line_offset):
                        car_n += 1  # 车的数量+1
                        cars.remove((x, y))
                        print(car_n)
            else:  # 如果不是车辆,跳过
                continue
        # 显示车辆的统计信息
        cv2.putText(frame, 'Cars Count:' + str(car_n), (500, 60), cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 0, 0), 5)

        cv2.imshow('video', frame)
    key = cv2.waitKey(33)
    if key == 113:  # 按‘q'退出
        break

cap.release()
cv2.destroyAllWindows()

 

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Goafan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值