使用flask将Yolov5部署到前端页面实现视频检测(保姆级)

这篇具有很好参考价值的文章主要介绍了使用flask将Yolov5部署到前端页面实现视频检测(保姆级)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、创建一个flask项目

首先,开发工具我们选择jetbrains公司的Pycharm,打开Pycharm,选择new Project,flask,路径根据自己的自身情况改,最好点击create创建成功!

yolov5(pytorch)目标检测实战:flask web部署,YOLO,python,flask,pycharm

此时,新建好的flask工程目录长这样

yolov5(pytorch)目标检测实战:flask web部署,YOLO,python,flask,pycharm

static文件夹下存放一些文件,比如css,js,images等,templates文件夹存放一些html的文件,便于日后flask部署。

app.py文件

from flask import Flask  #导入项目库

app = Flask(__name__)  #实例化flask


@app.route('/')  #flask的路由
def hello_world():  # put application's code here
    return 'Hello World!'


if __name__ == '__main__':   #主函数
    app.run()

其中,app = Flask(__name__)用于实例化flask项目,@app.route('/')是flask的路由,括号中‘/’表示网址使用根目录,app.run()用于启动flask项目。

二、解读yolov5代码

YOLOv5是一种计算机视觉的目标检测算法,全称是"You Only Look Once version 5"。它是由美国加州大学伯克利分校的研究者开发的,相较于之前的YOLO版本,YOLOv5具有更快的检测速度和更高的精度。其优点有

  1. YOLOv5采用了一个名为CSPNet的新的骨干网络,可以更好地提取特征。
  2. YOLOv5使用了更高效的训练技术,如自适应训练、数据增强和多尺度训练,从而在实际应用中具有更好的性能表现。
  3. YOLOv5是一种端到端的深度学习模型,可以直接从原始图像中检测和定位目标。它使用卷积神经网络(CNN)来学习图像中物体的特征,并使用多尺度预测和网格分割来检测和定位目标,因此可以在高速运行的同时保持高精度。

YOLOv5的代码就在GitHub上,这是其地址GitHub - ultralytics/yolov5: YOLOv5 🚀 in PyTorch > ONNX > CoreML > TFLite

在YOLOv5中,最核心的就是权重文件,当模型训练完成之后,会在run目录下的train文件夹里面的exp文件夹中的weights文件夹生成两个pt文件,best.pt顾名思义就是最好的一次,last.pt就是最后一次

yolov5(pytorch)目标检测实战:flask web部署,YOLO,python,flask,pycharm

其中训练文件我就不多描述了,主要讲解一下检测文件

def parse_opt():
    """
       weights: 训练的权重路径,可以使用自己训练的权重,也可以使用官网提供的权重
       默认官网的权重yolov5s.pt(yolov5n.pt/yolov5s.pt/yolov5m.pt/yolov5l.pt/yolov5x.pt/区别在于网络的宽度和深度以此增加)
       source: 测试数据,可以是图片/视频路径,也可以是'0'(电脑自带摄像头),也可以是rtsp等视频流, 默认data/images
       data: 配置数据文件路径, 包括image/label/classes等信息, 训练自己的文件, 需要作相应更改, 可以不用管
       如果设置了只显示个别类别即使用了--classes = 0 或二者1, 2, 3等, 则需要设置该文件,数字和类别相对应才能只检测某一个类
       imgsz: 网络输入图片大小, 默认的大小是640
       conf-thres: 置信度阈值, 默认为0.25
       iou-thres:  做nms的iou阈值, 默认为0.45
       max-det: 保留的最大检测框数量, 每张图片中检测目标的个数最多为1000类
       device: 设置设备CPU/CUDA, 可以不用设置
       view-img: 是否展示预测之后的图片/视频, 默认False, --view-img 电脑界面出现图片或者视频检测结果
       save-txt: 是否将预测的框坐标以txt文件形式保存, 默认False, 使用--save-txt 在路径runs/detect/exp*/labels/*.txt下生成每张图片预测的txt文件
       save-conf: 是否将置信度conf也保存到txt中, 默认False
       save-crop: 是否保存裁剪预测框图片, 默认为False, 使用--save-crop 在runs/detect/exp*/crop/剪切类别文件夹/ 路径下会保存每个接下来的目标
       nosave: 不保存图片、视频, 要保存图片,不设置--nosave 在runs/detect/exp*/会出现预测的结果
       classes: 设置只保留某一部分类别, 形如0或者0 2 3, 使用--classes = n, 则在路径runs/detect/exp*/下保存的图片为n所对应的类别, 此时需要设置data
       agnostic-nms: 进行NMS去除不同类别之间的框, 默认False
       augment: TTA测试时增强/多尺度预测
       visualize: 是否可视化网络层输出特征
       update: 如果为True,则对所有模型进行strip_optimizer操作,去除pt文件中的优化器等信息,默认为False
       project:保存测试日志的文件夹路径
       name:保存测试日志文件夹的名字, 所以最终是保存在project/name中
       exist_ok: 是否重新创建日志文件, False时重新创建文件
       line-thickness: 画框的线条粗细
       hide-labels: 可视化时隐藏预测类别
       hide-conf: 可视化时隐藏置信度
       half: 是否使用F16精度推理, 半进度提高检测速度
       dnn: 用OpenCV DNN预测
       """
    parser = argparse.ArgumentParser()
    parser.add_argument('--weights', nargs='+', type=str, default=ROOT / 'weights/best.pt', help='model path(s)')
    # parser.add_argument('--source', type=str, default=ROOT / 'data/images', help='file/dir/URL/glob, 0 for webcam')  #图片检测
    parser.add_argument('--source', type=str, default=ROOT / '0', help='file/dir/URL/glob, 0 for webcam')  #视频检测
    parser.add_argument('--data', type=str, default=ROOT / 'data/Amy.yaml', help='(optional) dataset.yaml path')
    parser.add_argument('--imgsz', '--img', '--img-size', nargs='+', type=int, default=[640], help='inference size h,w')
    parser.add_argument('--conf-thres', type=float, default=0.25, help='confidence threshold')
    # conf-thres  置信度阈值,越低框越多
    parser.add_argument('--iou-thres', type=float, default=0.45, help='NMS IoU threshold')
    parser.add_argument('--max-det', type=int, default=1000, help='maximum detections per image')
    parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--view-img', action='store_true', help='show results')
    parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
    parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
    parser.add_argument('--save-crop', action='store_true', help='save cropped prediction boxes')
    parser.add_argument('--nosave', action='store_true', help='do not save images/videos')
    parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --classes 0, or --classes 0 2 3')
    parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
    parser.add_argument('--augment', action='store_true', help='augmented inference')
    parser.add_argument('--visualize', action='store_true', help='visualize features')
    parser.add_argument('--update', action='store_true', help='update all models')
    parser.add_argument('--project', default=ROOT / 'runs/detect', help='save results to project/name')
    parser.add_argument('--name', default='exp', help='save results to project/name')
    parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
    parser.add_argument('--line-thickness', default=3, type=int, help='bounding box thickness (pixels)')
    parser.add_argument('--hide-labels', default=False, action='store_true', help='hide labels')
    parser.add_argument('--hide-conf', default=False, action='store_true', help='hide confidences')
    parser.add_argument('--half', action='store_true', help='use FP16 half-precision inference')
    parser.add_argument('--dnn', action='store_true', help='use OpenCV DNN for ONNX inference')
    opt = parser.parse_args()
    opt.imgsz *= 2 if len(opt.imgsz) == 1 else 1  # expand
    print_args(vars(opt))
    return opt

检测代码中最重要的部分就是pare_opt函数,各种参数的注释我全部写在代码中,大家可以进行参考,其中weights是训练出来的权重best.pt的路径,source就是检测数据的来源,default=ROOT/'0'代表调用本地摄像头,default=ROOT/'data/images'代表是检测的data目录下的images里面的图片

使用flask肯定不能直接调用,需要根据需求来进行调用

class VideoCamera(object):
    def __init__(self):
        # 通过opencv获取实时视频流
        self.img_size = 640
        self.threshold = 0.4
        self.max_frame = 160
        self.video = cap  #视频流
        self.weights = 'weights/best.pt'   #yolov5权重文件
        self.device = 'cuda:0' if torch.cuda.is_available() else 'cpu'
        self.device = select_device(self.device)
        model = attempt_load(self.weights)
        model.to(self.device).eval()
        model.half()
        # torch.save(model, 'test.pt')
        self.m = model
        self.names = model.module.names if hasattr(
            model, 'module') else model.names
        self.colors = [
            (randint(0, 255), randint(0, 255), randint(0, 255)) for _ in self.names
        ]


    def __del__(self):
        if self.video is None:
            # 没有上传视频时,不执行读取帧的操作
            return None
        self.video.release()

    def get_frame(self):
        if self.video is None:
            # 没有上传视频时,不执行读取帧的操作
            return None

        ret, frame = self.video.read()  # 读视频

        if not ret:
            # 视频已经播放完毕,没有更多的帧可供处理
            return None

        im0, img = self.preprocess(frame)  # 转到处理函数

        pred = self.m(img, augment=False)[0]  # 输入到模型
        pred = pred.float()
        pred = non_max_suppression(pred, self.threshold, 0.3)

        pred_boxes = []
        image_info = {}
        count = 0
        for det in pred:
            if det is not None and len(det):
                det[:, :4] = scale_coords(
                    img.shape[2:], det[:, :4], im0.shape).round()

                for *x, conf, cls_id in det:
                    lbl = self.names[int(cls_id)]
                    x1, y1 = int(x[0]), int(x[1])
                    x2, y2 = int(x[2]), int(x[3])
                    pred_boxes.append(
                        (x1, y1, x2, y2, lbl, conf))
                    count += 1
                    key = '{}-{:02}'.format(lbl, count)
                    image_info[key] = ['{}×{}'.format(
                        x2 - x1, y2 - y1), np.round(float(conf), 3)]

        frame = self.plot_bboxes(frame, pred_boxes)

        ret, jpeg = cv2.imencode('.jpg', frame)
        return jpeg.tobytes()

    def preprocess(self, img):

        img0 = img.copy()
        img = letterbox(img, new_shape=self.img_size)[0]
        img = img[:, :, ::-1].transpose(2, 0, 1)
        img = np.ascontiguousarray(img)
        img = torch.from_numpy(img).to(self.device)
        img = img.half()  # 半精度
        img /= 255.0  # 图像归一化
        if img.ndimension() == 3:
            img = img.unsqueeze(0)

        return img0, img

    def plot_bboxes(self, image, bboxes, line_thickness=None):
        tl = line_thickness or round(
            0.002 * (image.shape[0] + image.shape[1]) / 2) + 1  # line/font thickness
        for (x1, y1, x2, y2, cls_id, conf) in bboxes:
            color = self.colors[self.names.index(cls_id)]
            c1, c2 = (x1, y1), (x2, y2)
            cv2.rectangle(image, c1, c2, color,
                          thickness=tl, lineType=cv2.LINE_AA)
            tf = max(tl - 1, 1)  # font thickness
            t_size = cv2.getTextSize(
                cls_id, 0, fontScale=tl / 3, thickness=tf)[0]
            c2 = c1[0] + t_size[0], c1[1] - t_size[1] - 3
            cv2.rectangle(image, c1, c2, color, -1, cv2.LINE_AA)  # filled
            cv2.putText(image, '{}-{:.2f} '.format(cls_id, conf), (c1[0], c1[1] - 2), 0, tl / 3,
                        [225, 255, 255], thickness=tf, lineType=cv2.LINE_AA)
        return image

这里是封装了一个类名为VideoCamera,其中__init__(self)方法用于初始化类的实例,里面设置了一些参数包括图片的大小,权重的路径,视频的地址,是否使用GPU等,__del__(self)方法用于释放资源,如果视频播放完毕,则关闭视频流,get_frame(self)方法获取视频流的帧,对帧进行预处理,使用YOLOv5进行目标检测,处理检测结果,提取预测框的信息,绘制带有预测框的图像并返回其 JPEG 编码,preprocess(self, img) 方法对图像进行预处理,复制原始图像,调整图像尺寸、通道顺序,将图像转换为 PyTorch 张量,并移动到设备上,对图像进行归一化处理,plot_bboxes(self, image, bboxes, line_thickness=None) 方法在图像上绘制检测框,为每个类别进行随机分配颜色。

三、flask后端代码

 flask项目录

yolov5(pytorch)目标检测实战:flask web部署,YOLO,python,flask,pycharm

其中data目录,models目录,runs目录,weights目录,utils目录是从yolov5的工程目录中copy过来的,其他的都是flask项目自带的。

首先导入相关库

from flask import *
from flask_cors import CORS
import torch
import numpy as np
from models.experimental import attempt_load
from utils.general import non_max_suppression, scale_coords
from utils.augmentations import letterbox
from utils.torch_utils import select_device
import cv2
from random import randint

然后

@app.route('/')
def index():
    return render_template('index.html')  #template文件夹下的index.html
def gen(camera):
    while True:
        frame = camera.get_frame()
        # 使用generator函数输出视频流, 每次请求输出的content类型是image/jpeg
        if frame is None:
            break
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')

@app.route('/video_feed')  # 这个地址返回视频流响应
def video_feed():
    return Response(gen(VideoCamera()),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

@app.route('/detect',methods=['POST'])
def vedio_stream():
    global cap
    if request.method == 'POST':
        stream = request.files['videoFile'].stream
        # 将文件流写入临时文件
        temp_video_path = 'temp_video.mp4'
        with open(temp_video_path, 'wb') as temp_video_file:
            temp_video_file.write(stream.read())
        cap = cv2.VideoCapture(temp_video_path)
    else:
        return 'request method error!'
    return redirect('/')

index()函数用于当访问url(‘/’)时,将渲染成index.html的模板,gen() 函数是一个生成器函数,用于不断地获取视频帧并生成对应的MJPEG格式数据。这个函V数作为视频流的生成器,/video_feed 路由返回一个包含视频流响应的 Response 对象。 是一个用于获取视频帧的相机类,该类的 get_frame 方法用于获取视频帧数据。

四、前端代码

我艺术细胞太少,前端很简陋,之所以写出来是因为有几个重点要强调一下

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>视频检测</title>
    <style>
      div{
        margin: 0 auto;
        text-align: center;
        width: 1200px;
        height: 800px;
      }
      img{
        width: 75%;
        height: 75%;
        border: 1px solid black;
      }
    </style>
  </head>
  <body>
    <div>
      <h1>视频检测</h1>
        <form id="uploadForm" enctype="multipart/form-data" method="post" action="http://127.0.0.1:5000/detect">

        <input type="file" name="videoFile" accept="video/*">

        <button type="submit">开始检测</button>

        </form>
    <img src="{{ url_for('video_feed') }}">
    </div>

  </body>
</html>

 其中{{url_for('video_feed')}}对应的就是上面的video_feed函数,因为video_feed函数的路由是video_feed,这样返回的视频以每帧的方式呈现,action中的网址写的就是video_steam函数,使用的是post方法,input标签里面的name="videoFile"就是对应下面

stream = request.files['videoFile'].stream

 

运行结果

最后看一下运行结果

yolov5(pytorch)目标检测实战:flask web部署,YOLO,python,flask,pycharm

下面是本帅哥的帅哥,哈哈,自恋一下,大家不要把重点放在本帅哥身上哈。  

yolov5(pytorch)目标检测实战:flask web部署,YOLO,python,flask,pycharm文章来源地址https://www.toymoban.com/news/detail-821557.html

到了这里,关于使用flask将Yolov5部署到前端页面实现视频检测(保姆级)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • yolov5部署+微信小程序前端展示

    分为yolov5项目部署和微信小程序两部分,先介绍微信小程序前端展示+flask后端,之后介绍项目部署这部分。 一、先上效果图 1. 点击选择图片,调用摄像头选择图片   2.选择图片之后,点击开始检测,然后返回结果   ​​​​​​​    二、前端代码 wxml文件: js文件,分为

    2024年02月02日
    浏览(36)
  • 基于YoloV5的使用手机行为检测及在边缘设备部署实现

    目录 一、背景 二、配置环境 三、使用手机行为检测数据集 四、租用云端GPU进行模型训练 五、PC端验证训练效果 六、Aidlux端的模型推理测试 七、改进及拓展 一、背景 现代社会“低头族”越来越多,过马路时低头玩手机,操作岗位上工作时玩手机,甚至有的骑车时也在玩手

    2024年02月08日
    浏览(116)
  • yolov5 web端部署进行图片和视频检测

    目录 1、思路 2、代码结构 3、代码运行 4、api接口代码 5、web ui界面 6、参考资料 7、代码分享  通过搭建flask微型服务器后端,以后通过vue搭建网页前端。flask是第一个第三方库。与其他模块一样,安装时可以直接使用python的pip命令实现。flask是web开发框架,简单易学,因此用

    2024年02月05日
    浏览(44)
  • 吸烟检测从零开始使用YOLOv5+PyQt5+OpenCV实现(支持图片、视频、摄像头实时检测)

    全流程 教程,从数据采集到模型使用到最终展示。若有任何疑问和建议欢迎评论区讨论。 先放上最终实现效果 检测效果 由上图我们可以看到,使用YOLOV5完成了吸烟的目标识别检测,可以达到mAP可达85.38%。通过对吸烟的自动检测可以方便商场、医院、疗养院等公共场合进行禁

    2024年02月09日
    浏览(55)
  • YOLOv5使用NCNN将模型部署到Android端教程(1)部署自己的训练模型到Android实现静态图片检测

    之前一直是在电脑端运行YOLOv5,但在户外调试的时候不太方便,因此考虑把YOLOv5的代码移植到手机端。 这个部署的流程其实很简单:原始pt权重中间onnx权重ncnn权重修改Android Studio源码得到安卓APP结束。如果你感觉博客教程太长了,那么很有可能是中间的图片太多,以及之前自

    2023年04月09日
    浏览(82)
  • YOLOv5 + Flask + Vue实现基于深度学习算法的垃圾检测系统源码+数据库

    YOLOv5🚀 :高效、准确的目标检测算法,实时识别检测图像和视频中的各种对象 PyTorch :机器学习框架,以动态计算图为基础,具有灵活性和易用性 OpenCV :计算机视觉库,提供了丰富的图像和视频处理功能 Vue3 :采用 Vue3 + script setup 最新的 Vue3 组合式 API Element Plus :Element

    2024年02月22日
    浏览(44)
  • 烟雾和火灾检测从零开始使用YOLOv5+PyQt5+OpenCV实现(支持图片、视频、摄像头实时检测)

    全流程 教程,从数据采集到模型使用到最终展示。若有任何疑问和建议欢迎评论区讨论。 先放上最终实现效果 图片检测效果 视频检测效果 针对住宅、加油站、公路、森林等火灾高发场景,可以自动检测监控区域内的烟雾和火灾,帮助相关人员及时应对,最大程度降低人员

    2024年02月11日
    浏览(60)
  • 瑞芯微RK3568/RK3588平台YOLOV5实时视频算法的部署小白教程

    本文实现整体的部署流程比较小白,首先在PC上分别实现工程中的模型仿真推理、yolov5-pytorch仿真推理、自己训练yolov5模型仿真推理,完成仿真之后再在板端分别实现rk提供模型的板端推理、yolov5-pytorch板端推理、自己训练的yolov5模型板端推理,最后实现自己训练的yolov5模型实

    2024年02月06日
    浏览(85)
  • 智能零售柜商品识别从零开始使用YOLOv5+PyQt5+OpenCV实现(支持图片、视频、摄像头实时检测)

    全流程 教程,从数据采集到模型使用到最终展示。若有任何疑问和建议欢迎评论区讨论。 先放上最终实现效果 检测效果 智能零售柜商品识别,当顾客将自己选购的商品放置在制定区域的时候,能精准地识别每一个商品,从而能够返回完整地购物清单及计算顾客应付的实际商

    2024年02月08日
    浏览(47)
  • 基于YOLOv5的视频计数 — 汽车计数实现

    在视频中计数对象可能看起来有挑战性,但借助Python和OpenCV的强大功能,变得令人意外地易于实现。在本文中,我们将探讨如何使用YOLO(You Only Look Once)目标检测模型在视频流或文件中计数对象。我们将该过程分解为简单的步骤,使初学者能够轻松跟随。 本文将分为以下几

    2024年02月04日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包