手把手教你实现—基于OpenCV的车流量统计和车速检测代码

news2024/11/24 3:13:50

         本章将实现了一个简单的车辆速度估计和车流量统计的GUI应用,它使用了Haar级联检测器和相关跟踪器来检测和跟踪视频中的车辆,并通过图像处理和数学计算来估计车辆的速度。

        1.首先,该代码需要cv2:用于图像处理和计算机视觉任务;dlib:用于对象跟踪和检测;time:用于计算帧率和时间间隔;threading:用于处理多线程操作;math:用于数学计算等。

        2.然后,定义了全局变量video_path和highest_speed,用于存储选择的视频文件路径和最高时速度。

        3.接下来,通过carCascade = cv2.CascadeClassifier('myhaar.xml')导入车辆检测器模型。然后定义了全局变量video和一些常量,如视频的宽度和高度。

carCascade = cv2.CascadeClassifier('myhaar.xml')
video = None
WIDTH = 1280
HEIGHT = 720

        3.实现estimateSpeed(location1, location2, fps)函数用于估计车辆速度,根据两个位置点的像素距离、像素每米比例和帧率来计算车辆的速度。

def estimateSpeed(location1, location2, fps):
    d_pixels = math.sqrt(math.pow(location2[0] - location1[0], 2) + math.pow(location2[1] - location1[1], 2))
    ppm = 8.8
    d_meters = d_pixels / ppm
    if fps == 0.0:
        fps = 18
    speed = d_meters * fps * 3.6
    return speed

        代码中:location1和location2是表示车辆位置的参数。它们是包含两个元素的元组或列表,分别表示车辆在图像中的坐标(x,y)。fps是帧率(Frames Per Second),表示视频播放的帧速率。d_pixels是计算两个位置之间像素距离的变量。通过使用两个位置的x和y坐标差值计算欧氏距离。ppm是每像素米数(Pixels Per Meter)的值。它表示图像中的像素距离与实际距离之间的比例关系。在这里,假设每个像素代表8.8厘米。d_meters是将像素距离转换为米的值。通过将像素距离除以ppm得到。如果帧率fps为0.0(未提供或无效值),将其设置为默认值18。speed是估计的速度,以千米/小时为单位。通过将距离(以米为单位)乘以帧率(以秒为单位)再乘以3.6(将小时转换为秒)计算得到。返回估计的速度。
        综上所述,该函数根据两个位置之间的像素距离、帧率和像素到米的比例关系,估计车辆的速度(以千米/小时为单位)。 

        4.实现track_multiple_objects()函数是实现多目标跟踪的核心部分。它使用Haar级联检测器来检测图像中的车辆,并使用dlib的相关跟踪器来跟踪每个车辆。函数使用一个无限循环,从视频中读取帧,然后进行车辆检测和跟踪。在每一帧中,函数更新已跟踪车辆的位置和质量,并计算车辆的速度。还更新了最高时速度和实时车流量的标签,并显示跟踪结果的图像。

def track_multiple_objects():
    rectangleColor = (0, 255, 0)
    frameCounter = 0
    currentCarID = 0
    fps = 0

    carTracker = {}
    carLocation1 = {}
    carLocation2 = {}
    speed = [None] * 1000

    def update_highest_speed(speed):
        global highest_speed
        highest_speed = max(highest_speed, speed)
        speed_label.config(text="最高时速度:{} km/hr".format(highest_speed))

    def update_video_frame(image):
        image = Image.fromarray(image)
        image = image.resize((640, 480))
        photo = ImageTk.PhotoImage(image)
        video_label.config(image=photo)
        video_label.image = photo

        # 其他代码...

    total_cars = 0  # 车辆总数
    prev_total_cars = 0  # 上一帧的车辆总数

    while True:
        start_time = time.time()
        rc, image = video.read()
        if not rc:
            break

        image = cv2.resize(image, (WIDTH, HEIGHT))
        resultImage = image.copy()

        frameCounter = frameCounter + 1

        carIDtoDelete = []

        # 更新已跟踪车辆的位置和质量
        for carID in carTracker.keys():
            trackingQuality = carTracker[carID].update(image)

            if trackingQuality < 7:
                carIDtoDelete.append(carID)

        for carID in carIDtoDelete:
            carTracker.pop(carID, None)
            carLocation1.pop(carID, None)
            carLocation2.pop(carID, None)

        if not (frameCounter % 10):
            gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
            cars = carCascade.detectMultiScale(gray, 1.1, 13, 18, (24, 24))

            for (_x, _y, _w, _h) in cars:
                x = int(_x)
                y = int(_y)
                w = int(_w)
                h = int(_h)

                x_bar = x + 0.5 * w
                y_bar = y + 0.5 * h

                matchCarID = None

                for carID in carTracker.keys():
                    trackedPosition = carTracker[carID].get_position()

                    t_x = int(trackedPosition.left())
                    t_y = int(trackedPosition.top())
                    t_w = int(trackedPosition.width())
                    t_h = int(trackedPosition.height())

                    t_x_bar = t_x + 0.5 * t_w
                    t_y_bar = t_y + 0.5 * t_h

                    if (
                            (t_x <= x_bar <= (t_x + t_w))
                            and (t_y <= y_bar <= (t_y + t_h))
                            and (x <= t_x_bar <= (x + w))
                            and (y <= t_y_bar <= (y + h))
                    ):
                        matchCarID = carID

                if matchCarID is None:
                    tracker = dlib.correlation_tracker()
                    tracker.start_track(image, dlib.rectangle(x, y, x + w, y + h))

                    carTracker[currentCarID] = tracker
                    carLocation1[currentCarID] = [x, y, w, h]

                    currentCarID = currentCarID + 1

        for carID in carTracker.keys():
            trackedPosition = carTracker[carID].get_position()

            t_x = int(trackedPosition.left())
            t_y = int(trackedPosition.top())
            t_w = int(trackedPosition.width())
            t_h = int(trackedPosition.height())

            cv2.rectangle(resultImage, (t_x, t_y), (t_x + t_w, t_y + t_h), rectangleColor, 4)

            carLocation2[carID] = [t_x, t_y, t_w, t_h]

        end_time = time.time()

        if not (end_time == start_time):
            fps = 1.0 / (end_time - start_time)

        for i in carLocation1.keys():
            if frameCounter % 1 == 0:
                [x1, y1, w1, h1] = carLocation1[i]
                [x2, y2, w2, h2] = carLocation2[i]

                carLocation1[i] = [x2, y2, w2, h2]

                if [x1, y1, w1, h1] != [x2, y2, w2, h2]:
                    if speed[i] is None or speed[i] == 0:
                        speed[i] = estimateSpeed([x1, y1, w1, h1], [x2, y2, w2, h2], fps)

                    if speed[i] != 0 and speed[i] < 150:
                        update_highest_speed(speed[i])

                    cv2.putText(resultImage,str(int(speed[i])) + " km/hr", (int(x1 + w1 / 2), int(y1 - 10)),cv2.FONT_HERSHEY_SIMPLEX, 0.75,(0, 255, 0),2,)

        # 更新车流量
        prev_total_cars = total_cars
        total_cars = len(carTracker)

        # 更新实时车流量标签
        traffic_label.config(text="实时车流量:{}".format(total_cars))

        update_video_frame(resultImage)

    video.release()

        该代码中首先,定义了一些变量和数据结构用于跟踪车辆。rectangleColor是绘制车辆边界框的颜色,frameCounter用于计算帧数,currentCarID表示当前车辆的ID,fps表示帧率。carTracker是一个字典,用于存储每辆车的追踪器对象。carLocation1和carLocation2分别是字典,用于存储每辆车的当前和上一帧的位置信息。speed是一个列表,用于存储每辆车的速度。update_highest_speed()是一个内部函数,用于更新最高速度的显示。update_video_frame()是一个内部函数,用于更新视频帧的显示。total_cars和prev_total_cars是用于计算车流量的变量。进入主循环,首先读取视频的一帧图像。如果无法读取到图像,就退出循环。对读取到的图像进行预处理,包括调整图像大小和创建一个副本。增加帧计数器的值。创建一个空列表carIDtoDelete,用于存储需要删除的车辆的ID。遍历已跟踪的车辆,更新其位置信息和质量。如果某辆车的跟踪质量低于阈值(7),则将其ID添加到carIDtoDelete列表中。遍历carIDtoDelete列表,从carTracker、carLocation1和carLocation2中删除对应的车辆。每隔10帧,检测图像中的车辆。使用级联分类器(carCascade)对灰度图像进行目标检测,并返回检测到的车辆的边界框。遍历检测到的车辆边界框,与已跟踪的车辆进行匹配。如果找到匹配的车辆,更新该车辆的追踪器对象,位置信息和ID。如果没有找到匹配的车辆,创建一个新的追踪器对象,将其添加到carTracker中,并更新位置信息和ID。遍历carTracker中的每辆车,获取其位置信息,并在结果图像上绘制车辆边界框。根据每辆车的位置信息和帧率,估计车辆的速度,并将其存储在speed列表中。如果速度不为0且小于150,更新最高速度。在结果图像上显示每辆车的速

        5.实现open_file()函数用于打开文件对话框并选择视频文件。选择视频文件后,将启动一个新线程来处理视频。

def open_file():
    global video_path, video
    file_types = [("视频文件", "*.mp4;*.avi;*.mkv")]  # 允许上传的视频文件类型
    video_path = filedialog.askopenfilename(title="选择视频文件", filetypes=file_types)
    if video_path:
        video = cv2.VideoCapture(video_path)
        t = threading.Thread(target=process_video)
        t.start()

       6. 实现process_video()函数在新线程中执行,它首先通过cv2.VideoCapture打开选择的视频文件,然后调用track_multiple_objects()函数对视频进行处理。

        7.实现update_highest_speed(speed)函数用于更新最高时速度的全局变量,并更新显示最高时速度的标签。

        8.实现update_video_frame(image)函数用于更新显示视频帧的标签,它将图像转换为Tkinter可用的格式并进行适当的调整。

        9.最后,代码创建了一个Tkinter窗口,并在窗口中添加了按钮、车流量标签、最高时速度标签和视频显示标签。通过window.mainloop()来启动GUI窗口的事件循环,使应用保持运行状态。实现的界面如下所示:

点击选择视频视频按钮,我们可以选择任意格式的视频进行检测:

 选择视频后的输出界面如下:

车流量检测和速度估计

 整个代码下载链接:

https://download.csdn.net/download/weixin_40651515/87882938

运行环境依赖包:

opencv-python==4.1.0.25
numpy==1.17.2
dlib==19.8.1
future==0.17.1
Pillow==8.4.0

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

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

相关文章

软件测试(功能、接口、性能、自动化)详解

一、软件测试功能测试测试用例编写是软件测试的基本技能&#xff1b;也有很多人认为测试用例是软件测试的核心&#xff1b;软件测试中最重要的是设计和生成有效的测试用例&#xff1b;测试用例是测试工作的指导&#xff0c;是软件测试的必须遵守的准则。黑盒测试常见测试用例编…

比较18个3*6尺寸差值结构的迭代次数

已发现二值化差值结构有3种相互作用&#xff0c;纵向&#xff0c;横向和斜向。纵向相互作用只与行间距有关而与数值的数量无关&#xff0c;与迭代次数成反比&#xff1b;横向相互作用只与列的数值数量有关与列间距无关&#xff0c;与迭代次数成正比&#xff1b;斜向相互作用将导…

完全免费PNG素材库,免费可商用~

推荐的这几个PNG素材网一定要收藏~免费可商用~ 菜鸟图库 https://www.sucai999.com/searchlist/66008----all-0-1.html?vNTYxMjky 菜鸟图库是一个为新手设计师提供免费素材的网站&#xff0c;站内有非常多设计相关素材&#xff0c;比如平面模板、UI素材、电商素材、免抠素材…

C++中string类的常用函数

文章目录 默认成员函数常见构造函数(constructor) string类的容量操作size()empty()capacity()reserve()clear()resize() string类对象的访问及遍历操作重载 [ ]begin()end()begin() end() 遍历字符串rbegin()rend()rbegin() rend()反向遍历字符串C11范围for string类对象修改…

客户至上 服务至极 ——优维服务流程标准化体系

◎ 如何用服务打动客户&#xff1f; 在思考这个问题之前&#xff0c;首先我们要了解做好服务最难的是什么&#xff1f; 众所周知&#xff0c;由机器作业出来的东西是一致且规范的&#xff0c;而服务不一样。服务&#xff0c;是需要人来参与的&#xff0c;当由不同的人来完成某…

web问题定位:F12,如何找到对应接口

接口查看法&#xff0c;是我们最常用的定位前后端问题的方法。即&#xff1a;一般用来查看是后端返回给前端的数据有误&#xff0c;还是前端显示有误。 主流浏览器&#xff08;如Chrome&#xff0c;FireFox&#xff0c;等&#xff09;都有自带的接口查看工具&#xff0c;可以通…

微软wsl2 + ubantu + docker + 部署本地项目

windows 操作系统版本要达到要求 开启 wsl2 安装实用工具 Windows Terminal 和 Visual Studio Code 安装 Ubuntu 子系统 安装 Docker Desktop 并让 Docker Desktop 基于 wsl2 来运行 基础环境准备可以完全参照《搭建 Laravel Sail 开发环境 - Windows》来进行&#xff0c;我跟教…

2023年的深度学习入门指南(16) - JAX和TPU加速

2023年的深度学习入门指南(16) - JAX和TPU加速 上一节我们介绍了ChatGPT的核心算法之一的人类指示的强化学习的原理。我知道大家都没看懂&#xff0c;因为需要的知识储备有点多。不过没关系&#xff0c;大模型也不是一天能够训练出来的&#xff0c;也不可能一天就对齐。我们有…

葡萄酒质量预测

本文中所有代码及数据均存放于&#xff1a;https://github.com/MADMAX110/WineQualityPrediction 本文根据酸度、残糖和酒精浓度等特征训练和调整一个随机的葡萄酒质量森林模型。 一、设置环境&#xff0c;确认你的电脑安装了以下环境 Python 3NumPyPandasScikit-Learn (a.k.a…

Ubuntu 18.04 交叉编译Opencv-4.6.0

环境 操作系统&#xff1a;Ubuntu 18.04 OpenCv版本&#xff1a;4.6.0 交叉工具链&#xff1a;arm-linux-gnueabihf-gcc-5.3.1 下载OpenCV源代码 这里推荐大家到网上找OpenCV的Linux版本安装包&#xff08;.tar.gz结尾&#xff09;&#xff0c;不要github上clone&#xff08…

leetcode688. 骑士在棋盘上的概率(java)

骑士在棋盘上的概率 leetcode688. 骑士在棋盘上的概率题目描述 解题思路代码演示动态规划专题 leetcode688. 骑士在棋盘上的概率 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/knight-probability-in-chessboard 题目描…

【源码篇】基于ssm+vue+微信小程序的医疗科普小程序

系统介绍 这是一个ssmvue微信小程序的医疗科普小程序&#xff0c;分为pc端和微信小程序端 pc端包括&#xff1a;管理员角色和学生角色。 管理员拥有&#xff1a;学生管理、科普知识管理、论坛管理、收藏管理、试卷管理、留言板管理、试题管理、系统管理、考试管理 学生端拥…

AI实战营第二期 第五节 《目标检测与MMDetection》——笔记6

文章目录 摘要主要特性 常用概念框、边界框交并比 (loU)感受野有效感受野置信度 目标检测的基本思路难点滑框在特征图进行密集计算边界框回归基于锚框VS无锚框NMS&#xff08;非极大值抑制&#xff09;使周密集预测模型进行推理步骤如何训练密集预测模型的训练匹配的基本思路密…

C++ 教程(01)

C 教程 C 是一种高级语言&#xff0c;它是由 Bjarne Stroustrup 于 1979 年在贝尔实验室开始设计开发的。C 进一步扩充和完善了 C 语言&#xff0c;是一种面向对象的程序设计语言。C 可运行于多种平台上&#xff0c;如 Windows、MAC 操作系统以及 UNIX 的各种版本。 本教程通过…

节省90%编译时间,这是字节跳动开源的基于Rust的前端构建工具

Rspack 是一个基于 Rust 的高性能构建引擎&#xff0c;它可以与 Webpack 生态系统交互&#xff0c;并提供更好的构建性能。 在处理具有复杂构建配置的巨石应用时&#xff0c;Rspack 可以提供 5~10 倍的编译性能提升。 字节跳动将 Rspack 开源后&#xff0c;它在 GitHub 上已有 …

Bert+FGSM/PGD实现中文文本分类(Loss=0.5L1+0.5L2)

任务目标&#xff1a;在使用FGSM/PGD来训练Bert模型进行文本分类&#xff0c;其实现原理可以简单概括为以下几个步骤&#xff1a; 对原始文本每个词转换为对应的嵌入向量。将每个嵌入向量与一个小的扰动向量相加&#xff0c;从而生成对抗样本。这个扰动向量的大小可以通过一个超…

2023年牛客网最新版大厂Java八股文面试题总结(覆盖所有面试题考点)

程序员真的是需要将终生学习贯彻到底的职业&#xff0c;一旦停止学习&#xff0c;离被淘汰&#xff0c;也就不远了。 金九银十跳槽季&#xff0c;这是一个千年不变的话题&#xff0c;每到这个时候&#xff0c;很多人都会临阵磨枪&#xff0c;相信不快也光。于是&#xff0c;大…

多业务线下,IT企业如何应对市场经济下行危机?

多业务线下&#xff0c;IT企业如何应对市场经济下行危机&#xff1f; 市场经济下行就像是一辆行驶的车子遇到了坡道&#xff0c;速度开始变慢甚至停下来。在这个情况下&#xff0c;经济的增长变得较为缓慢&#xff0c;消费减少&#xff0c;投资减少&#xff0c;也对企业会带来…

运筹说 第25期 | 对偶理论经典例题讲解

对偶理论是研究线性规划中原始问题与对偶问题之间关系的理论&#xff0c;主要研究经济学中的相互确定关系&#xff0c;涉及到经济学的诸多方面。产出与成本的对偶、效用与支出的对偶&#xff0c;是经济学中典型的对偶关系。 对偶理论中最有力的武器是影子价格&#xff0c;影子…

【MySQL】主从复制部署

文章目录 概述SQL数据库的三大范式 主从复制技术产生原因主从形式原理图主节点 binary log dump 线程从节点I/O线程作用从节点SQL线程作用 复制过程复制模式异步模式&#xff08;mysql async-mode&#xff09;半同步模式(mysql semi-sync)全同步模式 复制机制binlog记录模式GTI…