yolov5实现目标检测系统(使用线程池)

一、简介

该系统包含以下几个部分:

  1. 从摄像头中读取数据
  2. 主线程将数据输出到窗口
  3. 后台线程完成计算机视觉的目标检测过程,并且将结果共享给主线程
  4. 主线程将结果画在输出图像上

下载yolvo5:

YOLOv5的源码放在 Github 地址:https://github.com/ultralytics/yolov5

我使用到的是 yolov5s.pt,yolvo5学习参考目标检测 YOLOv5使用入门

安装Yolov5所需模块

在命令行里,
输入“pip install -r requirements.txt”,等待安装完成即可。(pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple 命令会更快!!)

二、步骤

1.引入库

import cv2 as cv
import torch
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
from threading import Thread

2.打开摄像头

cap = cv.VideoCapture(0)

3.窗口输出

def show_frame(self):
        print("thread1 open!")
        while True:
            self.ret, self.frame = cap.read()
            if self.state:
                cv.imshow("res", self.a)
                if cv.waitKey(10) & 0xFF == ord('q'):# 按q退出
                    break
        self.ret = False
        self.thread_state = False
        cap.release()
        cv.destroyAllWindows()
        print("t1 finished")

4.计算机视觉的目标检测推理过程

def process_frame(self):
        print("thread2 open!")
        model = torch.hub.load(self.path, "custom",
                               self.pt_path, source="local")
        while True:
            if self.ret:
                res = model(self.frame)
                res.render()  # 打标签
                self.a = res.ims[0]
                self.state = True
            elif self.thread_state is False:
                break
        print("t2 finished")

5.用线程池管理

线程池帮助你来管理线程,不再需要每个任务都创建一个线程进行处理任务。任务需要执行时,会从线程池申请线程,有则使用线程池的线程执行任务,如果没有就等着,其他在执行的任务执行完毕后释放线程,等待的任务就可以使用释放的线程来执行操作了。线程池使用可以参考 python线程池的使用方法

concurrent.futures模块提供了高度封装的异步调用接口
ThreadPoolExecutor:线程池,提供异步调用

submit(fn, *args, **kwargs)异步提交任务

#使用类来实现多线程通信
t1 = Mythread()
#创建一个包含2条线程的线程池
pool = ThreadPoolExecutor(max_workers=2)  # 定义两个线程
#向线程池提交2个任务
thread1 = pool.submit(t1.show_frame)
thread2 = pool.submit(t1.process_frame)

这样我们就实现从摄像头中读取数据;主线程将数据输出到窗口,后台线程完成计算机视觉的目标检测过程,并且将结果共享给主线程,主线程将结果画在输出图像上。


三、完整代码

from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
from threading import Thread

import cv2 as cv
import torch

cap = cv.VideoCapture(0)


class Mythread(Thread):
    def __init__(self):
        Thread.__init__(self)
        cap = cv.VideoCapture(0)
        self.ret = {
    
    }
        self.frame = {
    
    }
        self.a = {
    
    }
        self.state = False
        self.thread_state = True
        self.project = Path(__file__).resolve().parent.parent
        self.path = self.project.joinpath("yolov5-master")
        self.pt_path = self.path.joinpath("yolov5s.pt")

    def process_frame(self):
        print("thread2 open!")
        model = torch.hub.load(self.path, "custom",
                               self.pt_path, source="local")
        while True:
            if self.ret:
                res = model(self.frame)
                res.render()  # 打标签
                self.a = res.ims[0]
                self.state = True
            elif self.thread_state is False:
                break
        print("t2 finished")

    def show_frame(self):
        print("thread1 open!")
        while True:
            self.ret, self.frame = cap.read()
            if self.state:
                cv.imshow("res", self.a)
                if cv.waitKey(10) & 0xFF == ord('q'):
                    break
        self.ret = False
        self.thread_state = False
        cap.release()
        cv.destroyAllWindows()
        print("t1 finished")


if __name__ == '__main__':
    t1 = Mythread()
    pool = ThreadPoolExecutor(max_workers=2)  # 定义两个线程
    thread1 = pool.submit(t1.show_frame)
    thread2 = pool.submit(t1.process_frame)

以上内容是我的个人总结,如有疑问,欢迎私聊,谢谢!!

猜你喜欢

转载自blog.csdn.net/m0_53256878/article/details/128120261