使用 Python 和 OpenCV 进行实时目标检测的详解

        使用到的模型文件我已经上传了,但是不知道能否通过审核,无法通过审核的话,就只能 靠大家自己发挥实力了,^_^

目录

简介

代码介绍

代码拆解讲解

1.首先,让我们导入需要用到的库:

2.然后,设置两个阈值:conf_threshold 和 nms_threshold,以及图片的宽度和高度:

3.接下来,我们加载预训练的 YOLOv3 模型,并加载识别的类名:

4.然后,我们创建一个颜色列表,以在最后的目标检测结果中为不同的类别绘制不同的颜色:

5.下一步,我们定义两个函数 fetch_frame 和 process_frame

6.在主循环中,我们使用 ThreadPoolExecutor 实现了并行处理读取帧和模型推理的操作。

7.退出程序

总体代码

效果展示

​编辑

使用GPU说明

如何操作

1.在读取模型时启用 CUDA:

2.其它代码不需要做太多修改:

总结        


简介

        这段程序是一个Python脚本,它使用了OpenCV库和预训练的YOLOv3模型来实现实时视频流的目标检测。它首先从摄像头捕获视频流,并使用线程池处理每一帧图像。在每一帧中,程序都会检测和识别不同的对象,并用不同的颜色显示结果。使用了非极大值抑制技术删除重复的检测框,并利用了并发处理技术以提高性能。最后,他还显示了每秒处理的帧数(FPS)。我们可以通过按'q'键来结束程序。这个程序展示了一种有效的使用深度学习模型进行实时视觉任务的方法。        


代码介绍

        这段代码是使用OpenCV和Python编写的,主要用于实时视频流处理和目标检测。代码的核心是使用训练好的YOLOv3模型来识别和定位视频帧中的对象。下面是对整个流程的详细解释:

  1. 导入库:首先,导入所需的库,包括cv2(OpenCV),numpy(用于科学计算),time(时间管理),以及concurrent.futures(用于并发执行)。

  2. 初始化参数:设置检测参数,包括置信度阈值(用于过滤掉那些置信度低于阈值的检测结果),非极大值抑制(NMS)阈值(用于去除重复的检测框),以及输入图像的宽和高。

  3. 加载模型和类别:通过使用cv2.dnn.readNet加载预训练的YOLOv3模型,并从coco.names文件中加载可以识别的类名列表。

  4. 颜色列表:为每个可识别的类别创建一个随机颜色列表,这用于在检测到的对象周围绘制彩色的边界框。

  5. 视频捕获:打开摄像头进行视频流的捕获。

  6. 多线程处理:初始化ThreadPoolExecutor以并发执行多个任务。这里定义了两个函数fetch_frameprocess_framefetch_frame用于从视频流中获取一帧图像,而process_frame则用于处理图像并执行目标检测。

  7. 目标检测流程

    • 转换输入帧:将输入帧转换为模型所需要的格式(blob),包括缩放、颜色空间转换等。
    • 执行检测:调用神经网络模型执行前向传播,获取检测结果。
    • 过滤结果:根据置信度阈值和NMS阈值过滤掉一部分检测结果,消除低置信度以及重复的检测框。
    • 绘制边界框和类别标签:在原图上绘制检测到的对象的边界框,并显示类别名称和置信度。
  8. 显示结果:在屏幕上实时显示处理后的视频帧,并计算显示FPS(每秒帧数)。

  9. 程序退出:等待我们按q键退出,并在退出前释放资源,包括摄像头和窗口。

        这段代码的设计利用了异步处理技术(通过ThreadPoolExecutor)来提高处理视频流的效率,使得帧的捕获和处理能够并行执行,从而尽可能提高FPS。

        为什么这样做,主要是我的电脑没有独立GPU,所以,呃,只能动点这中方法了,但是说实话并没有什么实质性的提升,难受了。


代码拆解讲解

        我们将使用预训练的 YOLOv3 模型进行目标检测,并使用 Python 的 concurrent.futures 库来并行处理视频帧的读取和模型推理,以优化程序的执行速度。

        感谢YOLO,虽然现在已经发展到v8了,但是我们这里使用v3还是足够了。

1.首先,让我们导入需要用到的库:

import cv2
import numpy as np
import time
from concurrent.futures import ThreadPoolExecutor

2.然后,设置两个阈值:conf_threshold 和 nms_threshold,以及图片的宽度和高度:

conf_threshold = 0.5
nms_threshold = 0.4
Width = 416
Height = 416

3.接下来,我们加载预训练的 YOLOv3 模型,并加载识别的类名:

net = cv2.dnn.readNet('../needFiles/yolov3.weights', '../needFiles/yolov3.cfg')
with open('../needFiles/coco.names', 'r') as f:classes = f.read().strip().split('\n')

4.然后,我们创建一个颜色列表,以在最后的目标检测结果中为不同的类别绘制不同的颜色:

color_list = np.random.uniform(0, 255, size=(len(classes), 3))

5.下一步,我们定义两个函数 fetch_frame 和 process_frame

        fetch_frame 用于从视频对象读取一帧;而 process_frame 则将读取到的帧输入到 YOLOv3 模型中,然后处理获得的输出结果,并在帧上绘制物体检测结果:

def fetch_frame(cap):...
def process_frame(frame):...

6.在主循环中,我们使用 ThreadPoolExecutor 实现了并行处理读取帧和模型推理的操作。

        这样可以使读取下一帧的操作和模型推理操作同时进行,从而显著地加快了处理速度:

executor = ThreadPoolExecutor(max_workers=2)
frame_future = executor.submit(fetch_frame, cap)while True:...ret, frame, height, width, channels = frame_future.result()frame_future = executor.submit(fetch_frame, cap)processed_frame = executor.submit(process_frame, frame).result()...

7.退出程序

        在这段代码的最后,如果你按下 q 键退出主循环,视频读取对象将会被释放,所有的窗口也将被销毁:

if cv2.waitKey(1) & 0xFF == ord('q'):break
...
cap.release()
cv2.destroyAllWindows()

总体代码

# 导入必要的库
import cv2
import numpy as np
import time
from concurrent.futures import ThreadPoolExecutor# 设置置信度阈值和非极大值抑制(NMS)阈值
conf_threshold = 0.5
nms_threshold = 0.4
Width = 416
Height = 416# 加载预训练的 YOLOv3 模型
net = cv2.dnn.readNet('../needFiles/yolov3.weights', '../needFiles/yolov3.cfg')# 加载可识别的类名
with open('../needFiles/coco.names', 'r') as f:classes = f.read().strip().split('\n')# 为不同的类别创建一个颜色列表
color_list = np.random.uniform(0, 255, size=(len(classes), 3))# 打开摄像头进行视频帧的捕获
cap = cv2.VideoCapture(0)# 初始化一个ThreadPoolExecutor用于多线程处理
executor = ThreadPoolExecutor(max_workers=2)# 定义fetch_frame函数,从视频流中获取视频帧
def fetch_frame(cap):ret, frame = cap.read()  # 读取一帧图像height, width, channels = frame.shape  # 获取图像的尺寸和通道信息return ret, frame, height, width, channels# 定义process_frame函数,处理每帧图像并进行目标检测
def process_frame(frame):# 将帧转换为模型的输入格式blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416), swapRB=True, crop=False)net.setInput(blob)output_layers = net.getUnconnectedOutLayersNames()  # 获取输出层的名字layer_outputs = net.forward(output_layers)  # 进行前向传播,获取检测结果boxes = []  # 用于存储检测到的边界框confidences = []  # 用于存储边界框的置信度class_ids = []  # 用于存储边界框的类别ID# 循环每个输出层的检测结果for output in layer_outputs:for detection in output:scores = detection[5:]  # 获取类别的得分class_id = np.argmax(scores)  # 获取得分最高的类别IDconfidence = scores[class_id]  # 获取得分最高的置信度# 过滤低置信度的检测结果if confidence > conf_threshold:center_x = int(detection[0] * width)center_y = int(detection[1] * height)w = int(detection[2] * width)h = int(detection[3] * height)# 计算边界框的位置和尺寸x = int(center_x - w / 2)y = int(center_y - h / 2)# 将边界框的位置、尺寸、置信度和类别ID添加到列表中boxes.append([x, y, w, h])confidences.append(float(confidence))class_ids.append(class_id)# 使用非极大值抑制去除重叠的边界框indices = cv2.dnn.NMSBoxes(boxes, confidences, conf_threshold, nms_threshold)# 在原图上绘制边界框和类别标签for i in indices.flatten():box = boxes[i]x = box[0]y = box[1]w = box[2]h = box[3]label = str(classes[class_ids[i]])color = color_list[class_ids[i]]cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)cv2.putText(frame, label, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)return frame# 在进入循环前,先读取一帧以开始异步处理
frame_future = executor.submit(fetch_frame, cap)# 主循环
while True:start = time.time()  # 记录开始处理的时间点# 获取当前帧和相应信息ret, frame, height, width, channels = frame_future.result()# 异步读取下一帧frame_future = executor.submit(fetch_frame, cap)# 如果当前帧读取成功,则继续处理if ret:# 使用线程池异步处理当前帧processed_frame = executor.submit(process_frame, frame).result()# 计算FPSend = time.time()fps = 1 / (end - start)# 在处理好的帧上显示FPScv2.putText(processed_frame, "FPS: " + str(round(fps, 2)), (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0),2)# 显示处理好的帧cv2.imshow('frame', processed_frame)# 如果我们按下 ‘q’ 键,退出循环if cv2.waitKey(1) & 0xFF == ord('q'):breakelse:break  # 如果帧没有被成功读取,退出循环# 释放视频捕获对象和销毁所有OpenCV窗口
cap.release()
cv2.destroyAllWindows()

效果展示

        这个效果还是不错的哈,就是这个硬件性能跟不上,要是有独显就好了。 


使用GPU说明

        当然了,为了在大学时期狠狠的奖励自己四年游戏,很多同学应该都是购买的游戏本,那么恭喜你,你的硬件非常的完美,那么这里你可以看一下。

如何操作

        如果你想利用 GPU 加速你的目标检测代码,主要更改会集中在如何让 OpenCV 利用你的 GPU。不幸的是,OpenCV 的 dnn 模块默认使用 CPU 进行计算。想要使用 GPU,首要条件是你需要有一个支持 CUDA 的 NVIDIA GPU。

        从 OpenCV 4.2 版本开始,dnn 模块添加了对 CUDA 的支持,但实现这一点需要确保你的 OpenCV 是用 CUDA 支持构建的。如果你自己编译 OpenCV,确保在编译时启用了 CUDA 支持。

以下是如何更改你的代码以利用 CUDA 的基本步骤:

1.在读取模型时启用 CUDA:

替换代码中的 readNet 调用,使用 readNetFromDarknet 并添加代码来设置网络的首选后端和目标为 CUDA。

   # 加载预训练的 YOLOv3 模型net = cv2.dnn.readNetFromDarknet('../needFiles/yolov3.cfg', '../needFiles/yolov3.weights')# 启用 CUDAnet.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)
2.其它代码不需要做太多修改:

        使用CUDA优化后,主要是模型推理过程(即net.forward()的调用)会更快。数据准备和后处理(例如非极大值抑制)的代码不需要太多修改,因为它们仍然在 CPU 上执行。

        这些改动仅在你已有 OpenCV 版本支持 CUDA,并且你的系统拥有合适的 NVIDIA GPU 时有效。如果你的环境满足这些条件,这样的更改可以显著加快模型推理的速度,尤其是在进行视频流处理时。

        最后,你一定要确定你的环境(包括 NVIDIA 驱动程序和 CUDA Toolkit)被正确设置以支持 GPU 加速。如果你对如何编译支持 CUDA 的 OpenCV 或如何配置你的系统环境有任何疑问,我建议查阅 OpenCV 官方文档和 NVIDIA 的 CUDA 安装指导,因为我真的没有仔细研究过。

总结        

        希望这篇博客对你有所帮助。最后我想说,虽然NVIDIA对我们的学习有帮助,但是我还是想说。

AMDyes!!!

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

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

相关文章

ansible-playbook离线升级centos内核

目录 概述实践ansible目录结构关键代码执行效果 结束 概述 内核离线包官网下载地址如下: 地址 实践 ansible目录结构 如对 ansible 不熟悉,离线包下载有问题,请至此地址下载,按本文操作可直接使用。 相关文章链接如下 文章地…

水电气能耗管理云平台

安科瑞薛瑶瑶18701709087/17343930412 能耗管理云平台采用泛在物联、云计算、大数据、移动通讯、智能传感器等技术手段可为用户提供能源数据采集、统计分析、能效分析、用能预警、设备管理等服务,平台可以广泛应用于多种领域。

Centos的一些基础命令

CentOS是一个基于开源代码构建的免费Linux发行版,它由Red Hat Enterprise Linux (RHEL) 的源代码重新编译而成。由于 CentOS是基于RHEL构建的,因此它与RHEL具有非常类似的特性和功能,包括稳定性、安全性和可靠性。并且大部分的 Linux 命令在C…

基于H.264的RTP打包中的组合封包以及分片封包结构图简介及抓包分析;FU-A FU-B STAP-A STAP-B简介;

H.264视频流的RTP封装类型分析: 前言: 1.RTP打包原则: RTP的包长度必须要小于MTU(最大传输单元),IP协议中MTU的最大长度为1500字节。除去IP报头(20字节)、UDP报头(8字节)、RTP头&a…

ZISUOJ 高级语言程序设计实训-基础C(部分题)

说明&#xff1a; 有几个题是不会讲的&#xff0c;我只能保证大家拿保底分。 题目列表&#xff1a; 问题 A: 求平均数1 思路&#xff1a; 送分题…… 参考题解&#xff1a; #include <iostream> #include <iomanip> using std::cin; using std::cout;int main(…

Django后台项目开发实战二

我们的需求是开发职位管理系统 三个功能&#xff1a; 管理员发布职位候选人能浏览职位用户能投递职位 第二阶段 创建应用 jobs&#xff0c;实现职位数据的建模 python manage.py startapp jobs 然后再 setting .py 注册应用&#xff0c;只需添加应用名称到最后一行 INST…

git 的迁移

现象是gitlab经常会挂掉&#xff0c;linux会显示磁盘空间不足&#xff0c;实际上&#xff0c;我们linux某个目录的空间是4T。这个空间应该是足够的。猜测是gitlab的安装目录不对导致的空间不足。 1、查找原因 用rpm 安装gitlab会有自己的目录&#xff0c;很多安装文件会在opt…

【华为】华为防火墙双机热备

【华为】华为防火墙双机热备 实验需求实验拓扑配置FW5-M前骤单臂路由和VRRP划分防火墙基本区域部署HRP&#xff08;华为心跳协议&#xff09; FW6-B前骤单臂路由和VRRP划分防火墙基本区域部署HRP&#xff08;华为心跳协议&#xff09; LSW2PC NATSNAT &#xff1a;Easy IPDNAT&…

DSP实时分析平台设计方案:924-6U CPCI振动数据DSP实时分析平台

6U CPCI振动数据DSP实时分析平台 一、产品概述 基于CPCI结构完成40路AD输入&#xff0c;30路DA输出的信号处理平台&#xff0c;处理平台采用双DSPFPGA的结构&#xff0c;DSP采用TI公司新一代DSP TMS320C6678&#xff0c;FPGA采用Xilinx V5 5VLX110T-1FF1136芯片&#xff…

如何在Spring Boot中配置数据库密码加密

如何在Spring Boot中配置数据库密码加密&#xff1f; alibaba/druid Wiki GitHub 使用ConfigFilter alibaba/druid Wiki GitHub 巧用Druid数据源实现数据库连接密码的加密解密功能 import com.alibaba.druid.filter.config.ConfigTools;public class Testttt {public stat…

【IDEA】IDEA自带Maven/JDK,不需要下载

IDEA是由Java编写的&#xff0c;为了保证其运行&#xff0c;内部是自带JDK的。IDEA 2021 及 之后的版本是自带Maven的&#xff1a; 视频连接&#xff1a; https://www.bilibili.com/video/BV1Cs4y1b7JC?p4&spm_id_frompageDriver&vd_source5534adbd427e3b01c725714cd…

状态模式和策略模式对比

状态模式和策略模式都是行为型设计模式&#xff0c;它们的主要目标都是将变化的行为封装起来&#xff0c;使得程序更加灵活和可维护。之所以将状态模式和策略模式进行比较&#xff0c;主要是因为两个设计模式的类图相似度较高。但是&#xff0c;从状态模式和策略模式的应用场景…

Redisson分布式锁,重试锁和锁续命的原理

RedissonLock 锁重试原理 tryLock有三个三个参数&#xff0c;第一个是等待时间&#xff0c;第二个是锁失效后自动释放的时间,不填默认为-1&#xff0c;第三个是时间单位&#xff1b; 当设置了第一个参数&#xff0c;那这个锁就成了可重试锁&#xff1b;获取锁失败后&#xff0c…

大数据分析与内存计算学习笔记

一、Scala编程初级实践 1.计算级数&#xff1a; 请用脚本的方式编程计算并输出下列级数的前n项之和Sn&#xff0c;直到Sn刚好大于或等于q为止&#xff0c;其中q为大于0的整数&#xff0c;其值通过键盘输入。&#xff08;不使用脚本执行方式可写Java代码转换成Scala代码执行&a…

【R语言数据分析】数据类型与数据结构

R的数据类型有数值型num&#xff0c;字符型chr&#xff0c;逻辑型logi等等。 R最常处理的数据结构是&#xff1a;向量&#xff0c;数据框&#xff0c;矩阵&#xff0c;列表。 向量有数值型向量&#xff0c;字符型向量&#xff0c;逻辑型向量等&#xff0c;字符型向量就是反应…

普通屏幕已过时?裸眼3D屏幕显示效果更胜一筹!

随着多媒体技术的迅猛进步&#xff0c;我们日常生活中的内容展现方式&#xff0c;已经经历了前所未有的变革。在这其中&#xff0c;裸眼3D屏幕的应用&#xff0c;无疑是最为引人注目的亮点&#xff0c;它相较于传统屏幕&#xff0c;在显示效果上展现出了鲜明的优势&#xff0c;…

ComfyUI最新InsightFaceLoader节点无法安装的问题

最近更新一个工作流。里面有一些爆红节点&#xff0c;很正常的想到去Manager安装&#xff0c;于是乎开启Clash猫远程安装。装完了还是有一些报错&#xff0c;InsightFaceLoader也无法安装&#xff0c;很奇怪&#xff0c;很常用的节点啊。 一查是ComfyUI_IPAdapter_plus模块的。…

C#知识|汇总方法重载与静态方法应用技巧

哈喽&#xff0c;你好&#xff0c;我是雷工&#xff01; 今天学习C#方法重载与静态方法应用技巧的相关内容。 01 方法重载有什么好处&#xff1f; 1.1、可以有效的减少类的对外接口&#xff08;只显示一个方法比较简洁&#xff09;&#xff0c;从而降低类的复杂度。 1.2、方便…

java实现模板填充word,word转pdf,pdf转图片

Java实现Word转PDF及PDF转图片 在日常开发中&#xff0c;我们经常需要将文件操作&#xff0c;比如&#xff1a; 根据模板填充wordword文档中插入图片Word文档转换为PDF格式将PDF文件转换为图片。 这些转换可以帮助我们在不同的场景下展示或处理文档内容。下面&#xff0c;我将…

鹏哥C语言复习——字符函数与字符串函数

目录 一.字符函数 1.字符分类函数 2.字符转换函数 二.基础字符串函数 1.strlen函数 2.strcpy函数 3.strcat函数 4.strcmp函数 三.基础字符串函数优化 1.strncpy函数 2.strncat函数 3.strncmp函数 四.进阶字符串函数 1.strstr函数 2.strtok函数 3.strerror函数 一…