基于OpenCV-车辆检测项目(简易版)

车辆检测

  • 1.项目介绍
  • 2. 读取一段视频
  • 3.通过形态学处理识别车辆
  • 4.描画轮廓
  • 5. 车辆计数并显示

本项目使用的视频地址链接

1.项目介绍

对一个视频进行车辆数量的检测,用到的知识有视频的读取,滤波器,形态学,添加直线、文本;项目流程为:1.读取一段视频。2.通过形态学处理识别车辆。3.对车辆进行计数。4.显示车辆统计信息。

2. 读取一段视频

在进行车辆检测之前,首先要把视频读进来。
代码如下:

import cv2
import numpy as np

# 创建视频帧对象
cap = cv2.VideoCapture('./video/video.mp4')
# 检测视频是否被打开
if not cap.isOpened():
    print('video open failed')
    exit(0)
# 循环读取图片
while True:
    ret, frame = cap.read()
    # 检测是否正确读取视频帧
    if not ret:
        print('视频帧读取有误')
        break
    # 读取正确
    cv2.imshow('frame', frame)
    # 视频播放速度过快,该成正常速度
    # key = cv2.waitKey(1) & 0xff 播放过快
    key = cv2.waitKey(int(1000/cap.get(cv2.CAP_PROP_FPS))) & 0xff
    if key == 27:
        break # 按ESC退出


# 释放资源
cap.release()
cv2.destroyAllWindows()

3.通过形态学处理识别车辆

先将彩色图像转化为灰度图,然后高斯滤波,接着去背景获得前景,接着通过腐蚀腐蚀图中小斑点,然后再膨胀,用闭运算去除图案里面的小方块。得到一个可以识别的图像。

def bodyResize(img):
    # 将图像转化为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 使用高斯滤波去噪
    blur = cv2.GaussianBlur(gray, (5, 5), 0)
    # 去背景
    mask = bgsubmog.apply(blur)
    # 腐蚀去掉图中的小方块
    erode = cv2.erode(mask, kernel, iterations=1)
    # 膨胀放大
    dilate = cv2.dilate(erode, kernel, iterations=3)
    # 闭操作,去掉物体内部的小方块
    close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)
    close = cv2.morphologyEx(close, cv2.MORPH_CLOSE, kernel)
    return close



处理过后如图所示:白色的为车辆。
在这里插入图片描述

4.描画轮廓

首先要检测出轮廓,然后根据得到的轮廓画矩形,为了防止矩形太多,过滤掉太小的矩形。

def drawContours(img, points):

    # 根据轮廓画矩形
    for (i, points) in enumerate(contours):
        #print(i, points)
        # 画最大外接矩形,太小就不画
        x, y, w, h = cv2.boundingRect(points)
        if w < min_w and h < min_h:
            continue
        cv2.rectangle(frame, (x, y), (x+w, y+h),(255, 0, 0), 2)



5. 车辆计数并显示

首先把车辆看成一个个矩形,然后算出矩形的中心点,中心点过直线就统计成一辆车,最后将计数打印在图片上。完整版代码如下。

import cv2
import numpy as np

# 矩形最小宽高
min_w = 90
min_h = 90

# 存储有效车辆的数组
cars = []
# 设置线高
line_high = 600
# 偏移量
offest = 9

# 车的数量
count = 0


def center(x, y, w, h):
    x1 = x+w/2
    y1 = y+h/2
    return x1, y1


def bodyResize(img):
    # 将图像转化为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 使用高斯滤波去噪
    blur = cv2.GaussianBlur(gray, (5, 5), 0)
    # 去背景
    mask = bgsubmog.apply(blur)
    # 腐蚀去掉图中的小方块
    erode = cv2.erode(mask, kernel, iterations=1)
    # 膨胀放大
    dilate = cv2.dilate(erode, kernel, iterations=3)
    # 闭操作,去掉物体内部的小方块
    close = cv2.morphologyEx(dilate, cv2.MORPH_CLOSE, kernel)
    close = cv2.morphologyEx(close, cv2.MORPH_CLOSE, kernel)
    return close


def drawContours(img, points):

    # 根据轮廓画矩形
    for (i, points) in enumerate(contours):
        #print(i, points)
        # 画最大外接矩形,太小就不画
        x, y, w, h = cv2.boundingRect(points)
        if w < min_w and h < min_h:
            continue
        cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2)




# 创建视频帧对象
cap = cv2.VideoCapture('./video/video.mp4')
# 创建去背景的对象
bgsubmog = cv2.bgsegm.createBackgroundSubtractorMOG()
# 卷积核大小
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 检测视频是否被打开
if not cap.isOpened():
    print('video open failed')
    exit(0)
# 循环读取图片
while True:
    ret, frame = cap.read()
    # 检测是否正确读取视频帧
    if not ret:
        print('视频帧读取有误')
        break
    # 下面都是读取正确的车辆
    # 画直线,用来统计车
    cv2.line(frame, (10, line_high), (1270, line_high), (0, 0, 255), 2)
    # 进行形态学处理
    close = bodyResize(frame)
    # 检测轮廓
    contours, hier = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    # 根据轮廓画矩形
    for (i, points) in enumerate(contours):
        # print(i, points)
        # 画最大外接矩形,太小就不画
        x, y, w, h = cv2.boundingRect(points)
        if w < min_w and h < min_h:
            continue
        cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)

        # 统计车辆数量
        # 求出车的中心点
        cen_point = center(x, y, w, h)
        cars.append(cen_point)

        # 统计过直线的车的数量
        for (x, y) in cars:
            if(y > line_high - offest) and (y < line_high + offest):
                count = count + 1
                cars.remove((x, y))
                # print(count)
    # 将count打印在屏幕上
    cv2.putText(frame, "count = "+str(count), (500, 60), cv2.FONT_HERSHEY_SIMPLEX, 2, (255,0,0), 5)
    cv2.imshow('frame', frame)
    # cv2.imshow('resize', close)
    # 视频播放速度过快,该成正常速度
    # key = cv2.waitKey(1) & 0xff 播放过快
    key = cv2.waitKey(int(1000/cap.get(cv2.CAP_PROP_FPS))) & 0xff
    if key == 27:
        break  # 按ESC退出


# 释放资源
cap.release()
cv2.destroyAllWindows(

在这里插入图片描述


此项目仅供个人练习使用,目的是加强对OpenCV的各种API的理解,本项目是基于传统图像处理,还存在较大缺陷,比如极端情况计数不准等问题,后续优化还可以依据深度学习等模型来训练,如有问题,欢迎在评论区讨论。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/32756.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

实战-基于Jenkins+K8s构建DevOps平台(九)

实验步骤如下&#xff1a; 第一部分&#xff1a;安装持久化存储nfs 1、在k8s-master和k8s-node1上安装nfs服务 [rootk8s-master ~]# yum install nfs-utils -y [rootk8s-master ~]# systemctl start nfs [rootk8s-master ~]# systemctl enable nfs [rootk8s-node1 ~]# yum …

Java 集合继承关系图

Java 容器类库的用途是“保存对象”&#xff0c;并划分为两大类,序列Collection和健值对 Map Collection接口&#xff1a;一个独立元素的序列&#xff0c;衍生的2个子类接口 List接口&#xff1a;存储有序的、可重复的数据 实现类: ArrayList、LinkedList、Vector Set接口&am…

华为MateBook 16 2021款锐龙版R7(CREM-WFD9)(CREM-WFG9)原装出厂Win11系统工厂模式,恢复原厂系统

HUAWEI华为笔记本电脑&#xff0c;MateBook 16 2021款 锐龙版 R7(CREM-WFD9) (CREM-WFG9) 原厂Windows11系统&#xff0c;带F10恢复功能&#xff0c;原装OEM专用系统&#xff0c;恢复出厂状态 系统自带所有驱动、出厂主题壁纸LOGO、Office办公软件、华为电脑管家等预装程序 …

网络安全自学秘籍

前言 想学网络安全但是无从下手的小白看过来&#xff0c;非常系统的学习资料&#xff0c;无数小白看了这份资料都已经成功入门&#xff0c;涵盖多个网络安全知识点&#xff0c;我愿称之为网络安全自学宝典。 一、概念性知识 1、了解什么是网络安全 2、清楚法律法规 3、网络安…

【git】idea怎么去替换git的地址

git 打开git地址添加或者修改git地址 打开git地址 右击->git->repository->remotes 添加或者修改git地址

useReducer可配合react-redux方案

接下来 我们来看 useReducer 这个属性 配合 react-redux 就会非常好用 那么 我们编写一段这样代码 import React, { useState } from react;const ContDom () > {const [count, setCount] useState(0);return (<div>cont值{ count }<button onClick {()>{ …

【模块三:职业成长】38|能力维度三:如何提升解决跨领域冲突的能力?

你好&#xff0c;我是郭东白。今天我们来讨论架构师核心能力的第三个层次——解决跨领域冲突。 上节课我们讲了从程序员到兼职架构师的跨越&#xff0c;也就是如何搭建解决横向问题的能力。 不过&#xff0c;在兼职架构师这个角色中&#xff0c;架构能力是一个加分项&#xff…

远程访问VPN配置与验证实验:构建安全的远程连接

远程访问VPN配置与验证实验&#xff1a;构建安全的远程连接 【实验目的】 理解远程访问 VPN的含义。掌握远程访问 VPN的含义。掌握VPN Client软件的使用。验证配置。 【实验拓扑】 实验拓扑如下图所示。 实验拓扑 设备参数表如下表所示。 设备参数表 设备 接口 IP地址 …

AutoGPT 英文版安装过程

自从2022年11月chatGPT的发布3.0GPT大模型&#xff0c;在中国掀起一股AI学习热潮&#xff0c;国内百度2023年4月份发布文心一言&#xff0c;把AI推上另一个高潮&#xff0c;最直接的是问答&#xff0c;我输入一句话&#xff0c;AI帮生成一段文字或一个视频&#xff0c;但是国内…

逻辑回归算法实现

目录 1.关于逻辑回归的原理解析和准备工作 2.关于激活函数 3.关于数据集 4.编写LogisticsRegression类 5.逻辑回归测试 6.结果 1.关于逻辑回归的原理解析和准备工作 逻辑回归原理相关内容&#xff0c;请参考博主的另一篇文章&#xff1a;机器学习&#xff08;二&#xff…

【Axure高保真原型】多选树穿梭框选择器

今天和大家分享多选树穿梭框的原型模板&#xff0c;左侧多选树选择子级选项后&#xff0c;可以在右侧看到对应的标签&#xff0c;取消选中也会删除对应标签。多选树可以通过选中或取消选中父级自动选中或取消选对应的子级&#xff0c;也可以选中或取消选子级自动反选父级。右侧…

SpringBoot源码分析(三):SpringBoot的事件分发机制

文章目录 通过源码明晰的几个问题Spring 中的事件Springboot 是怎么做到事件监听的另外两种注册的Listener 源码解析加载listenerSpringApplicationRunListenerEventPublishingRunListenerSimpleApplicationEventMulticaster判断 listener 是否可以接收事件Java 泛型获取 整体流…

Verilog基础之十一、移位寄存器实现

目录 一、前言 二、工程设计 ​2.1 工程代码 2.2 综合结果 2.3 仿真结果 一、前言 移位寄存器SRL在工程中属于使用频率较高个模块&#xff0c;可用于存储数据&#xff0c;实现串并转换&#xff1b;根据数据移动方向可分为左移寄存器&#xff0c;右移寄存器&#xff0c;左移…

测试岗入职第一天,老员工给我丢了这个文档!炒鸡好用!

不管新老测试员工应该都会对自己的测试工作进行一些总结&#xff0c;这个测试方法总结帮助了很多人&#xff0c;今天我再芬享一次&#xff0c;文末自取吧。 真的炒鸡好用&#xff01;这份笔记可以说陪我度过了测试试用期&#xff0c;里面包括90&#xff05;测试会遇到的问题&a…

ModaHub魔搭社区:向量数据库Milvus使用 MySQL 管理元数据教程

目录 使用 MySQL 管理元数据 常见问题 数据管理相关博客 使用 MySQL 管理元数据 Milvus 默认使用 SQLite 作为元数据后台管理服务&#xff0c;SQLite 内嵌于 Milvus 进程中&#xff0c;无需启动额外服务。但是在生产环境中&#xff0c;基于可靠性的考虑&#xff0c;我们强烈…

【Android Framework系列】第3章 Zygote进程相关

1 Zygote简介 Zygote是Android中最重要的一个进程&#xff0c;Zygote进程和Init进程、SystemServer进程是Android最重要的三大进程。Zygote是Android系统创建新进程的核心进程&#xff0c;负责启动Dalvik虚拟机&#xff0c;加载一些必要的系统资源和系统类&#xff0c;启动sys…

C#串口通信从入门到精通(26)——多个串口多个线程发送数据和接收数据

前言 我们在开发串口程序的过程中有时候会遇到多个串口,并且多个串口也需要在多个线程进行操作,本文就来讲解如何实现多个串口在多线程下的安全发送与接收。 1、操作界面与测试过程 我们首先使用虚拟串口助手虚拟COM1、COM2这一对串口;COM3、COM4这一对串口,然后使用代码…

Redis 原理

Redis 原理 动态字符串SDS Redis中保存的key时字符串&#xff0c;value往往是字符串或字符串集合&#xff0c;字符串是Redis中常见的数据结构 Redis没有直接使用C语言中的字符串&#xff0c;因为C语言字符串存在很多问题&#xff0c;使用起来不方便 Redis构建了一种新型的字…

TypeScript 【类型推断】与【类型别名】的使用解读

什么是类型推断&#xff1f; 在 TypeScript 中&#xff0c; 如果声明变量时&#xff0c;没有明确的指定类型&#xff0c;那么 TypeScript 会依照类型推论&#xff08;Type Inference&#xff09;的规则推断出一个类型。 以下代码虽然没有明确指定类型&#xff0c;但是会在编译的…

应急响应:系统入侵排查指南

目录 系统基本信息排查 Windows系统排查 Linux系统排查 CPU信息 操作系统信息 载入模块排查 用户排查 Windows系统用户排查 排查所有账户 Linux用户排查 root账户排查 查看所有可登录账户 查看用户错误的登录信息 查看所有用户最后登录信息 排查空口令账户 启…