使用 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模型来识别和定位视频帧中的对象。下面是对整个流程的详细解释:
-
导入库:首先,导入所需的库,包括
cv2
(OpenCV),numpy
(用于科学计算),time
(时间管理),以及concurrent.futures
(用于并发执行)。 -
初始化参数:设置检测参数,包括置信度阈值(用于过滤掉那些置信度低于阈值的检测结果),非极大值抑制(NMS)阈值(用于去除重复的检测框),以及输入图像的宽和高。
-
加载模型和类别:通过使用
cv2.dnn.readNet
加载预训练的YOLOv3模型,并从coco.names
文件中加载可以识别的类名列表。 -
颜色列表:为每个可识别的类别创建一个随机颜色列表,这用于在检测到的对象周围绘制彩色的边界框。
-
视频捕获:打开摄像头进行视频流的捕获。
-
多线程处理:初始化
ThreadPoolExecutor
以并发执行多个任务。这里定义了两个函数fetch_frame
和process_frame
。fetch_frame
用于从视频流中获取一帧图像,而process_frame
则用于处理图像并执行目标检测。 -
目标检测流程:
- 转换输入帧:将输入帧转换为模型所需要的格式(blob),包括缩放、颜色空间转换等。
- 执行检测:调用神经网络模型执行前向传播,获取检测结果。
- 过滤结果:根据置信度阈值和NMS阈值过滤掉一部分检测结果,消除低置信度以及重复的检测框。
- 绘制边界框和类别标签:在原图上绘制检测到的对象的边界框,并显示类别名称和置信度。
-
显示结果:在屏幕上实时显示处理后的视频帧,并计算显示FPS(每秒帧数)。
-
程序退出:等待我们按
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!!!
相关文章:

使用 Python 和 OpenCV 进行实时目标检测的详解
使用到的模型文件我已经上传了,但是不知道能否通过审核,无法通过审核的话,就只能 靠大家自己发挥实力了,^_^ 目录 简介 代码介绍 代码拆解讲解 1.首先,让我们导入需要用到的库: 2.然后,设…...

Android build.prop生成过程源码分析
Android的build.prop文件是在Android编译时刻收集的各种property【LCD density/语言/编译时间, etc.】;编译完成之后,文件生成在out/target/product/<board【OK1000】>/system/目录下;在Android运行时刻可以通过property_get()[c/c域] …...

计算机网络教材——谢希仁教材与配套PPT课件和《计算机网络——自顶向下方法》
教材链接: https://pan.baidu.com/s/1MUkgTVNMvhFdkGxAd0U7Ew?pwdn3g4 提取码: n3g4 ppt资源:课程包列表 (51zhy.cn) 计算机网络——自顶向下方法(资源在下面的评论区里):计算机网络自顶向下方法第7版中文PDF习题参考 - 哔哩哔…...

mysql 离线安装
package download mysql https://dev.mysql.com/downloads/mysql/ libaio http://mirror.centos.org/centos/7/os/x86_64/Packages/libaio-0.3.109-13.el7.x86_64.rpm 根据自己服务器选择下载对应的安装包及依赖 删除本机自带mysql相关 # 首先排查服务器自身是否有安装对应m…...

【C++】 string类:应用与实践
💞💞 前言 hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 💥个人主页&#x…...

巩固学习7
正则表达式 就是用来找到符合模式的字符串,这些模式包括:是什么字符,重复多少次,在什么位置,有哪些额外的约束 找某个字符串 import re text身高:178 体重:168 学号:123456 密码:9527 #在Python中,r前缀用…...

Android 右键 new AIDL 无法选择
提示 (AIDL File)Requires setting the buildFeatures.aidl to true in the build file) 解决方式: 在app的build.gradl中 adnroid{} 添加: buildFeatures{aidl true}...

使用Springboot整合Elasticsearch
全文搜索引擎 全文搜索引擎是目前广泛应用的主流搜索引擎,也称为全文检索。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序…...

Vue3+Element+TS动态菜单+按钮权限控制实现探索
1.动态获取权限并根据获取权限转换成相对应的router 根据请求获取菜单数据,对菜单数据进行转换,分别进行下面几步: /*** 组件地址前加斜杠处理*/ export function addSlashToRouteComponent(routeList: AppRouteRecordRaw[]) {routeList.fo…...

五款公司源代码加密软件推荐|代码防泄密解决方案
在当今数字化的世界中,源代码的泄露无疑是一场灾难。对于依赖加密软件保护关键信息的企业和个人来说,这种泄露不仅可能导致数据失窃,还可能损害企业的声誉和客户的信任。面对这种严峻的形势,我们迫切需要一种全面而有效的加密软件…...

【spring】Security 密码加密算法
Spring Security 提供了多种密码加密算法,用于在存储用户密码时进行加密,以增强安全性。 查看org.springframework.security.crypto.factory.PasswordEncoderFactories 以下是一些常用的密码加密算法: BCryptPasswordEncoder: 这…...

IO系列(一) -一文带你读懂 java 中的IO流!
一、摘要 说到 IO,相信大家都不陌生,英文全称:Input/Output,即输入/输出,通常指数据在内部存储器和外部存储器或其他周边设备之间的输入和输出。 比如我们常用的SD卡、U盘、移动硬盘等等存储文件的硬件设备ÿ…...

代码随想录算法训练营第六天| 242. 有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和
哈希表理论基础 [LeetCode] 242. 有效的字母异位词 [LeetCode] 242. 有效的字母异位词 文章解释 [LeetCode] 242. 有效的字母异位词 视频解释 题目: 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 注意:若 s 和 t 中每个字符出…...

【python】中的可迭代对象、迭代器、生成器
结论 凡是实现了__iter__() 方法的类都称之为可迭代对象,但 __iter__() 方法的返回值只能是迭代器和生成器for 循环的本质是先调用 __iter__() 方法,然后不断调用返回值的 __next__() 方法,直至报出异常 StopIteration,可迭代对象…...

短视频矩阵系统源码/saas--总后台端、商户端、代理端、源头开发
短视频矩阵系统源码/saas--总后台端、商户端、代理端、源头开发 搭建短视频矩阵系统源码的交付步骤可以概括为以下几个关键环节: 1. **系统需求分析**:明确系统需要支持的功能,如短视频的上传、存储、播放、分享、评论、点赞等。 2. **技术选…...

K8s:二进制安装k8s(单台master)
目录 一、安装k8s 1、拓扑图 2、系统初始化配置 2.1关闭防火墙selinx以及swap 2.2设置主机名 2.3在每台主机中添加hosts,做映射 2.4调整内核参数,将桥接的ipv4流量传递到iptables,关闭ipv6 2.4时间同步 3、部署docker引擎࿰…...

C++类和对象下——实现日期类
前言 在学习了类和对象的六大成员函数后,为了巩固我们学习的知识可以手写一个日期类来帮助我们理解类和对象,加深对于其的了解。 默认函数 构造函数 既然是写类和对象,我们首先就要定义一个类,然后根据实际需要来加入类的数据与函…...

252 基于MATLAB的自适应差分阈值法检测心电信号的QRS波
基于MATLAB的自适应差分阈值法检测心电信号的QRS波,QRS波群反映左、右心室除极电位和时间的变化,第一个向下的波为Q波,向上的波为R波,接着向下的波是S波。通过GUI进行数据处理,展示心率和QRS。程序已调通,可…...

SSIM(Structural Similarity),结构相似性及MATLAB实现
参考文献 Wang, Zhou; Bovik, A.C.; Sheikh, H.R.; Simoncelli, E.P. (2004-04-01). “Image quality assessment: from error visibility to structural similarity”. IEEE Transactions on Image Processing. 13 (4): 600–612. Bibcode:2004ITIP…13…600W. CiteSeerX 10.…...

第十六章-消费者-PUSH方式(一)
16.1 准备阶段 先从一段官方示例代码开始 public class Consumer {public static void main(String[] args) throws InterruptedException, MQClientException {// 初始化consumer,并设置consumer group nameDefaultMQPushConsumer consumer new DefaultMQPushCo…...

【C++要哮着学】初识C++,什么是C++?什么是命名空间?什么又是缺省函数?
文章目录 前言1、C简介1.1、什么是C1.2、C起源1.3、C发展 2、C关键字(C98)3、命名空间3.1、命名空间的定义及使用3.2、命名空间的嵌套3.3、命名空间的三种使用方式3.3.1、加命名空间名称及作用域限定符3.3.2、使用using将命名空间中某个成员引入3.3.3、使…...

Lua 数字格式化
在编程中,对数字进行格式化是一项常见的任务,特别是当我们需要在用户界面中显示数据或生成报告时。在 Lua 中,我们可以使用一些简单而有效的函数来实现数字的格式化。在本文中,我们将介绍一个由几个函数组成的小型 Lua 库…...

Java入门基础学习笔记13——数据类型
数据类型的分类: 基本数据类型 引用数据类型 基本数据类型:4大类8种类型: 定义整形用int,再大的数用long。 package cn.ensource.variable;public class VariableDemo2 {public static void main(String[] args) {//目标&#x…...

使用Docker+Jar方式部署微服务工程(前后端分离)看着一篇就够了
本篇教程的使用到的技术有springboot、springcloud、Nacos、Docker、Nginx部署前后端分离访问的微服务。 部署一下Nacos 首先我们需要在服务器中(或者本地部署启动一下Nacos),这里我采用服务器的方式进行部署,这里有一点不一样的…...

红外遥控和LCD1602
26.1.1 红外线简介 人的眼睛能看到的可见光按波长从长到短排列,依次为红、橙、黄、绿、青、蓝、紫。其中红光的波长范围为 0.62~0.76μm;紫光的波长范围为 0.38~0.46μm。比紫光波长还短的光叫紫外线,比红光波长还长的…...

房屋出租管理系统需求分析及功能介绍
房屋租赁管理系统适用于写字楼、办公楼、厂区、园区、商城、公寓等商办商业不动产的租赁管理及租赁营销;提供资产管理,合同管理,租赁管理, 物业管理,门禁管理等一体化的运营管理平台,提高项目方管理运营效率…...

高精度模拟算法
高精度模拟算法 高精度加法 extern string m,n; extern int a[MAX],b[MAX],ans[MAX]; void addition(){int _mmax(m.size(),n.size());reverse(m.begin(),m.end()),reverse(n.begin(),n.end());//转置原字符串for(int i0;i<m.size();i) a[i]m[i]-0;//字符型以ASCII码存储&…...

Ansible简介版
目录 架构 环境部署 一、Ansible安装部署 1.yum安装Ansible 2.修改主机清单文件 3.配置密钥对验证 4.ansible-doc 5.看被控主机 二、常用模块 1.Command模块 2.Shell模块 3.Cron模块 1.添加 2.删除 4.User模块 5.Group模块 1.创建组 编辑 编辑 编辑…...

卷积通用模型的剪枝、蒸馏---蒸馏篇--RKD关系蒸馏(以deeplabv3+为例)
本文使用RKD实现对deeplabv3+模型的蒸馏;与上一篇KD蒸馏的方法有所不同,RKD是对展平层的特征做蒸馏,蒸馏的loss分为二阶的距离损失Distance-wise Loss和三阶的角度损失Angle-wise Loss。 完整代码放在文末。 一、RKD简介 RKD算法的核心是以教师模型的多个输出为结构单元,取…...

AVL树的完全指南:平衡与性能
文章目录 AVL树简介AVL的操作建立一个AVL树插入操作删除操作 书写代码1.构造函数和析构函数2.获取最大值和最小值3.树的高度和节点个数3.前序中序和后序遍历4.判断树是否为空树5.四个旋转操作6.获取平衡因子7.插入操作8.删除操作9.搜索节点.h文件中的定义 总结 AVL树简介 AVL树…...