智慧交通day02-车流量检测实现13:基于虚拟线圈法的车辆统计+视频中的车流量统计原理解析

1.基于虚拟线圈法的车辆统计

基于虚拟线圈的车流量统计算法原理与交通道路上的常见的传统的物理线圈类似,由于物理线圈需要埋设在路面之下,因此会有安装、维护费用高,造成路面破坏等问题,而采用基于视频的虚拟线圈的车辆计数方法完全避免了以上问题,且可以针对多个感兴趣区域进行检测。

虚拟线圈车辆计数法的原理是在采集到的交通流视频中,在需要进行车辆计数的道路或路段上设置一条或一条以上的检测线对通过车辆进行检测,从而完成计数工作。检测线的设置原则一般是在检测车道上设置一条垂直于车道线,居中的虚拟线段,通过判断其与通过车辆的相对位置的变化,完成车流量统计的工作。如下图所示,绿色的线就是虚拟检测线:

在该项目中我们进行检测的方法是,计算前后两帧图像的车辆检测框的中心点连线,若该连线与检测线相交,则计数加一,否则计数不变。

那怎么判断两条线段是否相交呢?

假设有两条线段AB,CD,若AB,CD相交,我们可以确定:

1.线段AB与CD所在的直线相交,即点A和点B分别在直线CD的两边;

2.线段CD与AB所在的直线相交,即点C和点D分别在直线AB的两边;

上面两个条件同时满足是两线段相交的充要条件,所以我们只需要证明点A和点B分别在直线CD的两边,点C和点D分别在直线AB的两边,这样便可以证明线段AB与CD相交了。

在上图中,线段AB与线段CD相交,于是我们可以得到两个向量AC,AD,C和D分别在AB的两边,向量AC在向量AB的逆时针方向,AB×AC > 0;向量AD在向量AB的顺时针方向,AB×AD < 0,两叉乘结果异号。

这样,方法就出来了:如果线段CD的两个端点C和D,与另一条线段的一个端点(A或B,只能是其中一个)连成的向量,与向量AB做叉乘,若结果异号,表示C和D分别在直线AB的两边,若结果同号,则表示CD两点都在AB的一边,则肯定不相交。

所以我们利用叉乘的方法来判断车辆是否经过检测线。

2.基于虚拟线圈法的实现

实现车流量检测的代码如下:

1.检测AB和CD两条直线是否相交

# 检测AB和CD两条直线是否相交
def intersect(A, B, C, D):return ccw(A, C, D) != ccw(B, C, D) and ccw(A, B, C) != ccw(A, B, D)# 计算有A,B,C三点构成的向量CA,BA之间的关系,
def ccw(A, B, C):return (C[1] - A[1]) * (B[0] - A[0]) > (B[1] - A[1]) * (C[0] - A[0])
  1. 遍历跟踪框判断其与检测线是否相交,并进行车辆计数

# 遍历跟踪框
for box in boxes:(x, y) = (int(box[0]), int(box[1]))  # 计算跟踪框的左上角坐标(w, h) = (int(box[2]), int(box[3]))  # 计算跟踪框的宽和高color = [int(c) for c in COLORS[indexIDs[i] % len(COLORS)]]  # 对方框的颜色进行设定cv2.rectangle(frame, (x, y), (w, h), color, 2)  # 将方框绘制在画面上"""根据当前帧的检测结果,与上一帧检测的检测结过,进行虚拟线圈完成车辆计数:车流量统计"""if indexIDs[i] in previous:previous_box = previous[indexIDs[i]]  # 获取上一帧识别的目标框(x2, y2) = (int(previous_box[0]), int(previous_box[1]))  # 获取上一帧画面追踪框的左上角坐标(w2, h2) = (int(previous_box[2]), int(previous_box[3]))  # 获取上一帧画面追踪框的宽和高p0 = (int(x + (w - x) / 2), int(y + (h - y) / 2))  # 获取当前帧检测框的中心点p1 = (int(x2 + (w2 - x2) / 2), int(y2 + (h2 - y2) / 2))  # 获取上一帧检测框的中心点cv2.line(frame, p0, p1, color, 3)  # 将前后两帧图像的检测结果中心连接起来"""进行碰撞检测-前后两帧检测框中心点的连线穿过基准线,则进行计数"""if intersect(p0, p1, line[0], line[1]):# 总计数加1counter += 1# 判断行进的方向if y2 < y:counter_down += 1  # 逆向行驶+1else:counter_up += 1  # 正向行驶+1

总结

  1. 基于虚拟线圈的目标检测,是设置一个垂直于车道的检测线,判断跟踪车辆与检测线之间的关系,完成车辆计数
  2. 利用叉乘的方法来检验车辆是否与检测线相交

前面我们已经完成了视频中车辆的检测功能,下面我们对车辆进行跟踪,并将跟踪结果绘制在视频中。

2.视频中的车流量统计

主要分为以下步骤:

  • 对目标进行追踪
  • 绘制车辆计数结果
  • 将检测结果绘制在视频中并进行保存

1.对目标进行追踪

# yolo中检测结果为0时,传入跟踪器中会出现错误,在这里判断下,未检测到目标时不进行目标追踪if np.size(dets) == 0:continueelse:tracks = tracker.update(dets)  # 将检测结果传入跟踪器中,返回当前画面中跟踪成功的目标,包含五个信息:目标框的左上角和右下角横纵坐标,目标的置信度# 对跟踪器返回的结果进行处理boxes = []  # 存放tracks中的前四个值:目标框的左上角横纵坐标和右下角的横纵坐标indexIDs = []  # 存放tracks中的最后一个值:置信度,用来作为memory中跟踪框的Keyprevious = memory.copy()  # 用于存放上一帧的跟踪结果,用于碰撞检测memory = {} # 存放当前帧目标的跟踪结果,用于碰撞检测# 遍历跟踪结果,对参数进行更新for track in tracks:boxes.append([track[0], track[1], track[2], track[3]])  # 更新目标框坐标信息indexIDs.append(int(track[4]))  # 更新置信度信息memory[indexIDs[-1]] = boxes[-1]  # 将跟踪框以key为:置信度,value为:跟踪框坐标形式存入memory中
  1. 绘制车辆计数的相关信息

 cv2.line(frame, line[0], line[1], (0, 255, 0), 3)  # 根据设置的基准线将其绘制在画面上cv2.putText(frame, str(counter), (30, 80), cv2.FONT_HERSHEY_DUPLEX, 3.0, (255, 0, 0), 3)  # 绘制车辆的总计数cv2.putText(frame, str(counter_up), (130, 80), cv2.FONT_HERSHEY_DUPLEX, 3.0, (0, 255, 0), 3)  # 绘制车辆正向行驶的计数cv2.putText(frame, str(counter_down), (230, 80), cv2.FONT_HERSHEY_DUPLEX, 3.0, (0, 0, 255), 3)  # 绘制车辆逆向行驶的计数
  1. 将结果保存在视频中

    # 未设置视频的编解码信息时,执行以下代码if writer is None:# 设置编码格式fourcc = cv2.VideoWriter_fourcc(*"mp4v")# 视频信息设置writer = cv2.VideoWriter("./output/output.mp4",fourcc,30,(frame.shape[1], frame.shape[0]),True)# 将处理后的帧写入到视频中writer.write(frame)# 显示当前帧的结果cv2.imshow("", frame)# 按下q键退出if cv2.waitKey(1) & 0xFF == ord('q'):break

    总结

    1. 对目标进行追踪

    2. 绘制车辆计数的相关信息

    3. 将结果保存在视频中

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu 12.04 eclipse 安装

方法二&#xff1a;(优点是安装内容清爽&#xff0c;缺点是配置麻烦) 1、安装JDK&#xff0c;参考 Ubuntu 12.04 下安装 JDK 7 2、下载 Eclipse 从 http://www.eclipse.org/downloads/index-developer.php下载合适版本&#xff0c;如&#xff1a;Eclipse IDE for C/C Develope…

智慧交通day02-车流量检测实现14:代码汇总+问题修正

代码权重文件资源https://download.csdn.net/download/qq_39237205/43072746https://download.csdn.net/download/qq_39237205/43072746 环境要求&#xff1a;python2.7 环境配置&#xff1a;见文末requirements.txt 1.YOLO.py # encoding:utf-8 import imutils import tim…

从资源池和管理的角度理解物理内存

早就想搞一下内存问题了&#xff01;这次正趁着搞bigmemory内核&#xff0c;可以写一篇文章了。本文旨在记录&#xff0c;不包含细节&#xff0c;细节的话&#xff0c;google&#xff0c;百度均可&#xff0c;很多人已经写了不少了。我只是按照自己的理解记录一下内存的点点滴滴…

从头开始学一个android activity

一、类层次结构&#xff1a; 二、什么是Activity&#xff0c;如何理解Activity 1、 用户与应用程序的交互的接口 2、 控件的容器&#xff0c;我们要把控件摆放在这个容器中 三、如何创建一个Activity 新建一个类&#xff1a; 1、 继承Activity类 [java] view plaincopyprint…

python3 numpy中矩阵np.dot(a,b)乘法运算

python np.dot(a,b)乘法运算 首先我们知道矩阵运算是不满足交换律的&#xff0c;np.dot(a, b)与np.dot(b, a)是不一样的 另外np.dot(a,b)和a.dot(b)果是一样的 1.numpy中数组&#xff08;矩阵&#xff09;相乘np.dot(a,b)运算&#xff1a; 对于两数组a和b &#xff1a; 示例…

ML Backpropagation算法的计算过程举例

Backpropagation计算过程举例 初始权重(initialize weights)是随机产生的(如-1~1之间) 初始化可以选择均值为0&#xff0c;方差为1/n_in的正态分布&#xff0c;n_in为输入的实例个数&#xff0c;Python中可使用np.random.normal函数来初始化权重&#xff1a; np.random.normal…

Python基础知识__字符串

字符串介绍 一. 认识字符串 字符串是 Python 中最常用的数据类型。我们一般使用引号来创建字符串。创建字符串很简单&#xff0c;只要为变量分配一个值即可。 a hello world b "abcdefg" print(type(a)) print(type(b)) 注意&#xff1a;控制台显示结果为<cl…

智慧交通day03-车道线检测实现01:车道线检测概述

项目简介 汽车的日益普及在给人们带来极大便利的同时&#xff0c;也导致了拥堵的交通路况&#xff0c;以及更为频发的交通事故。而自动驾驶技术的出现可以有效的缓解了此类问题&#xff0c;减少交通事故&#xff0c;提升出行效率。 国内外检测车道线的方法主要有两类&#xf…

vsphere平台windows虚拟机克隆的小插曲(无法登陆系统)

问题&#xff1a; 1、克隆完windows虚拟化后输入法乱码。 2、开启远程的情况下远程登录输入正确的密码也无法登录。 解决&#xff1a; 1、更改管理员用户密码&#xff08;不输入原win7密码更改win7密码&#xff09;。 2、重新启用管理员。 3、重启系统 不输入当前密码改win密码…

智慧交通day03-车道线检测实现02-1:相机校正

1. 相机标定的意义 我们所处的世界是三维的&#xff0c;而照片是二维的&#xff0c;我们可以把相机认为是一个函数&#xff0c;输入量是一个场景&#xff0c;输出量是一幅灰度图。这个从三维到二维的过程的函数是不可逆的。 相机标定的一个目的是要找一个合适的数学模型&#…

把输入字符的小写转换成大写并输出

#include <stdio.h> #include <stdlib.h> #include <string.h> /******************************* *把小写字母转成大写字母 ********************************/ int main(void) { char *srcNULL;unsigned char i0;char *new_1NULL;char *new_2NULL;char *dN…

nginx服务无法启动,启动时报错1067以外终止

解决方法&#xff1a; 首先cmd命令打开&#xff0c;输入nginx -t测试配置文件是否能运行OK&#xff0c;如果报错bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a …) 则说明配置文件中的端口0.0.0.0:80被占用 可使用下面两种方法解决&#xff1a; cmd输…

智慧交通day03-车道线检测实现02-2:张氏标定法+双目标定

6.张氏标定法 张氏标定法是张正友博士在1999年发表在国际顶级会议ICCV上的论文《Flexible Camera Calibration By Viewing a Plane From Unknown Orientations》中&#xff0c;提出的一种利用平面棋盘格进行相机标定的实用方法。 该方法介于传统标定法和自标定法之间&#xff…

指针的基本操作(10.1 Basic Pointer Operations)

[This section corresponds to K&R Sec. 5.1] The first things to do with pointers are to declare a pointer variable, set it to point somewhere, and finally manipulate the value that it points to. A simple pointer declaration looks like this: 对指针的第…

HTML animate()动画更改多个元素背景颜色但不同时生效问题

问题&#xff1a; 我想点击按钮时把页面中的body颜色和button中颜色【同时】改变 这个时候出现了body颜色先变化&#xff0c;而button颜色后变化&#xff0c;似乎是因为我的代码是这样有先后顺序的&#xff1a; $("html,body").animate({backgroundColor:BGC[rando…

plt.axis()用法详解

plt.axis(‘square’) 作图为正方形&#xff0c;并且x,y轴范围相同&#xff0c;即y m a x − y m i n x m a x − x m i n y_{max}-y_{min} x_{max}-x_{min}y plt.axis(‘equal’) x,y轴刻度等长 plt.axis(‘off’) 关闭坐标轴 官网上也贴出了其他的一些选项 plt.axis([a,…

struts2学习笔记之十一:struts2的类型转换器

Struts2的类型转换器如何实现Struts2的类型转换器&#xff1f;* 继承StrutsTypeConverter* 覆盖convertFromString和convertToString注册类型转换器* 局部类型转换器&#xff0c;局部类型转换器只对当前Action起作用&#xff0c;需要提供如下配置文件&#xff1a;MyActionName-…

【Pytorch神经网络基础理论篇】 01 从零开始介绍深度学习算法和代码实现

同学你好&#xff01;本文章于2021年末编写&#xff0c;已与实际存在较大的偏差&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)…

【Pytorch神经网络基础理论篇】 02 pytorch环境的安装

同学你好&#xff01;本文章于2021年末编写&#xff0c;已与实际存在较大的偏差&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)…

JavaScript (If...Else和Switch和循环遍历) 语句以及常用消息框

If...Else 语句 JavaScript中if...else语句和Java中的语法和使用方法是一样的。 只是在JavaScript中要使用小写字母。使用大写的 IF 会出错&#xff01; 至于if...else...else if...和Java中的都是一样的。 例&#xff1a; var d new Date() var time d.getHours()if (time&l…