【OpenCV DNN】Flask 视频监控目标检测教程 05

news2024/11/28 18:36:20

欢迎关注『OpenCV DNN @ Youcans』系列,持续更新中

【OpenCV DNN】Flask 视频监控目标检测教程 05

    • 3.5 浏览器播放视频服务器上的视频文件
      • cvFlask05 项目文件树
      • cvFlask05 项目程序文件
      • cvFlask05 项目网页模版
      • cvFlask05 项目运行
    • 3.6 浏览器播放视频文件+控制按钮
      • cvFlask05c 项目文件树
      • cvFlask05c 项目程序文件
      • cvFlask05c 项目网页模版


本系列从零开始,详细讲解使用 Flask 框架构建 OpenCV DNN 模型的 Web 应用程序。

本节介绍用 Flask 构建流媒体服务器,向服务器发送请求可以播放本地视频文件。


3.5 浏览器播放视频服务器上的视频文件

本例程使用Flask框架构建一个视频流服务器,通过OpenCV读取本地视频文件,向服务器发送请求可以播放视频流。

本项目的框架与cvFlask04相同,主要区别在于从网页获取视频文件路径名称和使用OpenCV读取视频文件。


cvFlask05 项目文件树

新建一个Flask项目。cvFlask05项目的文件树如下。

---文件名\
    |---templates\
    |    |---index2.html
|--- cvFlask05.py
|--- vedio_01.mp4

cvFlask05 项目程序文件

任务逻辑由Python程序文件cvFlask05.py实现,完整代码如下。

# cvFlask05.py
# OpenCV+Flask 图像处理例程 05
# 通过浏览器播放视频服务器上的视频文件
# Copyright 2023 Youcans, XUPT
# Crated:2023-4-30

# coding:utf-8
from flask import Flask, Response, render_template, request
import cv2

app = Flask(__name__)

# 定义视频流类
class VideoStream:
    def __init__(self, source):  # 传入视频源
        self.video_capture = cv2.VideoCapture(source)  # 使用视频文件

    def get_frame(self):
        success, frame = self.video_capture.read()  # 读取视频帧
        if not success:
            return None
        ret, buffer = cv2.imencode('.jpg', frame)  # 编码为 jpg 格式
        frame_byte = buffer.tobytes()  # 转换为 bytes 类型
        return frame_byte

    def __del__(self):
        self.video_capture.release()  # 释放视频流

# 视频流的网页 HTML 模板
@app.route('/')
def index():
    return render_template('index2.html')

# 生成视频流的帧
def gen_frames(video_source):
    video_stream = VideoStream(video_source)  # 从视频文件获取视频流
    while True:
        frame = video_stream.get_frame()  # 获取视频帧
        if frame is None:
            # video_stream.__del__()  # 释放视频流
            break
        yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n'
               + frame + b'\r\n')  # 生成视频流的帧

# 视频流的传输路由:从网页获取视频源,返回视频流
@app.route('/video_feed')
def video_feed():
    video_source = request.args.get('video_source', 'camera')  # 从网页获取视频源
    return Response(gen_frames(video_source),
                    content_type='multipart/x-mixed-replace; boundary=frame')

if __name__ == '__main__':
    # 启动一个本地开发服务器,激活该网页
    print("URL: http://127.0.0.1:5000")
    app.run(host='0.0.0.0', port=5000, debug=True, threaded=True)  # 绑定 IP 地址和端口号

程序cvFlask05.py与cvFlask04.py的区别在于:
(1)定义的视频流类VideoStream接受视频源参数source,使用OpenCV创建视频读取对象,逐帧读取视频帧。
(2)子程序video_feed()从网页模板index2.html获取视频文件的路径和文件名’vedio_01.mp4’,作为视频源。


cvFlask05 项目网页模版

在子程序index()中指定了视频流的网页模板index2.html。网页index2.html位于templates文件夹,具体内容如下。

<!DOCTYPE html>
<html>
  <head>
    <title>Video Streaming Demonstration</title>
  </head>
  <body>
    <h2  align="center">OpenCV+Flask 例程:视频传输</h2>
    <img src="{{ url_for('video_feed', video_source='vedio_01.mp4') }}" alt="Video stream">
  </body>
</html>

类似地,img标签定义了图片使用的url,由url_for()函数向前端返回。网页模板index2.html与index1.html的区别仅在于,利用视图函数的名字和查询字符串动态获取url。'video_feed’是视图函数的名字,而视频文件的路径和文件名’vedio_01.mp4’以关键字实参的形式放在url_for()里作为参数。

/video_feed路径由video_feed()方法提供服务,返回一个multipart应答。生成器函数gen_frames()不断地从VideoStream逐帧获取图片,通过生成器返回给客户端。客户端浏览器收到流媒体时,在img标签定义的图片中逐帧显示,从而实现视频播放。


cvFlask05 项目运行

进入cvFlask05项目的根目录,运行程序cvFlask05.py,启动流媒体服务器。

 * Running on all addresses (0.0.0.0)  
 * Running on http://127.0.0.1:5000
 * Running on http://192.168.3.249:5000

在局域网内设备(包括移动手机)的浏览器打开http://192.168.3.249:5000,就可以播放视频服务器上的视频文件 vedio_01.mp4。

在这里插入图片描述


3.6 浏览器播放视频文件+控制按钮

进一步地,我们添加两个控制按钮“Start”和“Stop”,用来控制开始和停止播放视频流。
在 Flask 应用中添加控制按钮需要修改前端和后端代码。前端需要添加按钮以及发送请求的 JavaScript 代码,后端则需要添加处理这些请求的路由。

我们在前端添加 “start” 和 “stop” 按钮,这两个按钮在被点击时会发送请求到 “/start” 和 “/stop” 路由。

我们修改 VideoCamera 类以及gen函数,使其能够根据请求开始或停止生成视频帧。VideoCamera 类中添加了新的方法set_path,用来改变视频源。我们添加了新的路由"/set_path",它接受 POST 请求和一个表单参数 ‘video_path’,然后使用这个参数来设置视频源。添加了新的路由"/start"和"/stop",控制视频流的开关状态。


cvFlask05c 项目文件树

新建一个Flask项目。cvFlask05c项目的文件树如下。

---文件名\
    |---templates\
    |    |---index2c.html
|--- cvFlask05c.py
|--- vedio_01.mp4

cvFlask05c 项目程序文件

任务逻辑由Python程序文件cvFlask05c.py实现,完整代码如下。

# cvFlask05c.py
# OpenCV+Flask 图像处理例程 05b
# 通过浏览器播放视频服务器上的视频文件+控制按钮
# Copyright 2023 Youcans, XUPT
# Crated:2023-4-30

# coding:utf-8
from flask import Flask, Response, render_template, request
import cv2

app = Flask(__name__)

# 定义视频流类
class VideoStream:
    def __init__(self, video_path=None):  # 传入视频源
        if video_path is None:
            self.video_cap = cv2.VideoCapture(0)  # 创建视频设备读取对象
        else:
            self.video_cap = cv2.VideoCapture(video_path)  # 创建视频文件读取对象
        self.is_streaming = False

    def __del__(self):
        self.video_cap.release()  # 释放视频流

    def get_frame(self):
        success, frame = self.video_cap.read()  # 读取视频帧
        if success and self.is_streaming:
            ret, buffer = cv2.imencode('.jpg', frame)  # 编码为 jpg 格式
            frame_byte = buffer.tobytes()  # 转换为 bytes 类型
            return frame_byte
        else:
            return None

    def set_path(self, video_path):
        self.video_cap.release()
        self.video_cap = cv2.VideoCapture(video_path)

video_stream = VideoStream()  # 实例化视频流对象

# 生成视频流的帧
def gen_frames():
    while True:
        frame = video_stream.get_frame()  # 获取视频帧
        if frame is not None:
            yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n'
               + frame + b'\r\n')  # 生成视频流的帧

# 视频流的网页 HTML 模板
@app.route('/')
def index():
    return render_template('index2c.html')

# 视频流的传输路由:从网页获取视频源,返回视频流
@app.route('/video_feed')
def video_feed():
    return Response(gen_frames(),
                    content_type='multipart/x-mixed-replace; boundary=frame')

@app.route('/start', methods=['POST'])
def start():
    video_stream.is_streaming = True
    return ('', 204)

@app.route('/stop', methods=['POST'])
def stop():
    video_stream.is_streaming = False
    return ('', 204)

@app.route('/set_path', methods=['POST'])
def set_path():
    video_path = request.form.get('video_path')
    video_stream.set_path(video_path)
    return ('', 204)

if __name__ == '__main__':
    # 启动一个本地开发服务器,激活该网页
    print("URL: http://127.0.0.1:5000")
    app.run(host='0.0.0.0', port=5000, debug=True, threaded=True)  # 绑定 IP 地址和端口号

cvFlask05c 项目网页模版

在子程序index()中指定了视频流的网页模板index2c.html。我们在前端添加 “start” 和 “stop” 按钮,并指定了按钮的格式。网页index2c.html位于templates文件夹,具体内容如下。

<!DOCTYPE html>
<html>
  <head>
    <title>Video Streaming Demonstration</title>
    <style>
      #video {
          display: block;
          margin: 0 auto;
          width: 600px;
          height: 300px;
      }
      #button-container {
          display: flex;
          justify-content: center;
          gap: 100px;
          margin-top: 10px;  /* 新增:设置按钮与视频画面的间距 */
      }
      button {
          width: 60px;
          height: 30px;
      }
      </style>
  </head>
  <body>
    <h2  align="center">OpenCV+Flask 例程:播放视频文件</h2>
    <div style="text-align:center; padding-top:inherit">
      <img id="video" src="{{ url_for('video_feed') }}" style="display: none">
    </div>
    <div id="button-container">
      <button id="start">Start</button>
      <button id="stop">Stop</button>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script>
      $(document).ready(function(){
          var video_path = "vedio_01.mp4"; // 替换为你的视频文件路径
          $("#start").click(function(){
              $.post("/set_path", {"video_path": video_path}, function() {
                  $.post("/start", function() {
                      $("#video").show();
                  });
              });
          });
          $("#stop").click(function(){
              $.post("/stop", function() {
                  $("#video").hide();
              });
          });
      });
      </script>
  </body>
</html>

进入cvFlask05c项目根目录,运行程序cvFlask05c.py,启动流媒体服务器。

在局域网内设备(包括移动手机)的浏览器打开http://192.168.3.249:5000,页面中有“Start”和“Stop”两个动作按钮。点击“Start”按钮,开始播放视频服务器上的视频文件vedio_01.mp4,点击“Stop”按钮结束播放。

在这里插入图片描述


【本节完】

下节我们将讨论:OpenCV+Flask实时监控和视频播放。


版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:
【OpenCV DNN】Flask 视频监控目标检测教程 05
(https://blog.csdn.net/youcans/article/details/130989608)
Copyright 2023 youcans, XUPT
Crated:2023-06-01

欢迎关注『OpenCV DNN @ Youcans』系列
【OpenCV DNN】Flask 视频监控目标检测教程 01
【OpenCV DNN】Flask 视频监控目标检测教程 02
【OpenCV DNN】Flask 视频监控目标检测教程 03
【OpenCV DNN】Flask 视频监控目标检测教程 04


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

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

相关文章

Camtasia Studio2023中文版下载安装图文教程

Camtasia Studio是TechSmith旗下的一套专业屏幕录像软件&#xff0c;同时包含Camtasia 录像器、Camtasia Studio&#xff08;编辑器&#xff09;、Camtasia 菜单制作器、Camtasia 剧场、Camtasia 播放器和Screencast的内置功能。在这里我亲测安装了Camtasia2023版本&#xff0c…

【C/C++】C语言和C++的区别 | 面向过程与面向对象

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

【AI处理器】TDA4VE88TGAALZRQ1、TDA4VL21HGAALZRQ1 Automotive 智能视觉摄像头应用

TDA4VE/TDA4VL SoC处理器基于演进Jacinto™ 7架构&#xff0c;面向智能视觉摄像头应用。这些器件基于TI过去十年在视觉处理器市场积累的广泛市场知识。DA4AL为传统和深度学习算法提供高性能计算&#xff0c;具有业界领先的功率/性能比&#xff0c;系统集成度高&#xff0c;可为…

信创办公–基于WPS的PPT最佳实践系列 (自定义版式)

信创办公–基于WPS的PPT最佳实践系列 &#xff08;自定义版式&#xff09; 目录 应用背景相关知识操作步骤 应用背景 在PPT幻灯片当中&#xff0c;拥有11种版式&#xff0c;我们可以在任何一个页面当中单击鼠标右键&#xff0c;选中【版式】功能即可看到这11种版式&#xff0c…

pmp主流培训机构推荐,pmp培训机构哪个好?

PMP 机构选择也是我报名的时候最头疼的一个问题&#xff0c;做 PMP 培训的机构太多了&#xff0c;各执一词&#xff0c;各机构互踩的人也很多&#xff0c;看的眼花缭乱叫人头大。 下面这篇文章把几个机构的优劣都写出来了&#xff0c;比较清晰和中肯&#xff0c;个人觉得可以参…

Linux Kernel RTC驱动使用hwclock调试

hwclock hwclock的源码路径&#xff1a;sys-utils/hwclock.c 源码&#xff1a; if (opt & HWCLOCK_OPT_HCTOSYS)to_sys_clock(&rtcname, utc);else if (opt & HWCLOCK_OPT_SYSTOHC)from_sys_clock(&rtcname, utc);else if (opt & HWCLOCK_OPT_SYSTZ)set_…

可加模型的一个简单示例

Additive Models to avoid the curse of dimensionality and for better interpretability we assume m ( x ) E ( Y ∣ X x ) c ∑ j 1 d g j ( x j ) m(\boldsymbol{x})E(Y|\boldsymbol{X}\boldsymbol{x})c\sum_{j1}^dg_j(x_j) m(x)E(Y∣Xx)cj1∑d​gj​(xj​) ⟹ \L…

高压放大器和示波器的关系是什么

高压放大器和示波器是电子工程领域中常见的两种设备&#xff0c;它们在实际的电路设计、测试和分析中都扮演着重要的角色。下面安泰电子将从定义、功能、应用场景等方面为您介绍高压放大器和示波器的关系。 图&#xff1a;ATA-7000系列高压放大器 一、高压放大器的定义及功能 高…

【软件测试】软件测试理论总结笔记(一)

软件测试理论总结 1.Introduction1.1 What is Software Bug1.3 Tester的职责和目标其他概念 2.软件开发生命周期Software Development ProcessSoftware Development Lifecycle Models2.1 TDD - Test-Driven Development测试驱动开发&#xff08;一种敏捷开发&#xff09;Softwa…

Chrome浏览器无痕浏览真的无痕吗?

当您启用无痕浏览后&#xff0c;设备的其他用户将不会看到您的历史记录。 Chrome 不会保存您的浏览记录或您在表单中填写的信息。当您浏览时&#xff0c;Chrome 会记住相应的 Cookie 和网站数据&#xff0c;但当您退出无痕模式时&#xff0c;Chrome 会删除这些数据。您可在打开…

【Android】Binder(一)Binder的介绍和AIDL使用Binder的实例

Binder介绍 Android 中的 Binder 是一个进程间通信机制&#xff0c;它允许不同进程之间相互调用方法和传递数据。Binder 主要用于实现系统服务和应用程序之间的通信&#xff0c;以及实现 IPC&#xff08;Inter-Process Communication&#xff0c;进程间通信&#xff09;。 Bi…

陪诊APP小程序开发 陪伴就医告别孤独

生活工作忙碌&#xff0c;很多情况下父母或者其他亲人需要去医院的时候没办法陪同&#xff0c;让其单独去又不放心成为令很多人苦恼的问题。随着移动互联网的深入到我们生活的方方面面&#xff0c;医疗行业也出现了很多陪诊服务APP小程序系统软件&#xff0c;让孤独就医者有人陪…

Android H5拉起安卓原生方案的介绍与实战(六一篇)

一、介绍 今天是6.1儿童节&#xff0c;祝大家儿童节快乐。 言归正传&#xff0c;开始介绍H5拉起原生。如今&#xff0c;在APP应用中&#xff0c;消息大多数采用推送方式比较多&#xff0c;到达率很低或者说无法满足业务的需求。在一些大型活动中&#xff0c;依然需要短信的参与…

网络安全:SQL 注入漏洞

一、漏洞描述 WordPress是一个用PHP编写的免费开源内容管理系统&#xff0c;由于clean_query函数的校验不当&#xff0c;导致了可能通过插件或主题以某种方式从而触发SQL注入的情况。这已经在WordPress5.8.3中进行了修复。影响版本可以追溯到3.7.37。 二、漏洞分析 在分析整…

平台使用篇 | 批处理(bat)脚本使用教程(四)

导读 一个开启多机软件在环仿真的批处理文件 (对应卓面RflyTools文件夹中SITLRun快捷方式)&#xff0c;双击它&#xff0c;输入想要生成的飞机数量&#xff0c;即可生成多机软件在环仿真&#xff0c;等待RflySim3D显示3DFixed 4/4&#xff0c;然后可通过QGC控制飞机起飞。运行…

Unity API详解——Time类

Time类是Unity中获取时间信息的接口类&#xff0c;只有静态属性。本博客介绍Time类的一些静态属性。 一、Time类静态属性 在Time类中&#xff0c;涉及的静态属性有realtimeSinceStartup、smoothDeltaTime和time属性&#xff0c;在介绍time属性时涉及了Time类的多个其他属性的…

学姐生日快到了~这不得用Python把她的照片做成视频当礼物送给她....

前言 这不是学姐生日快到了&#xff0c;于是我学了一手Python~ 来把学姐的照片生成为视频&#xff0c;到时候给她一个惊喜&#xff01; 好了先不说了&#xff0c;下面分享一下用python代码 实现多张图片合成MP4视频为实例&#xff0c;做下详细代码讲解。 一、需要调入的模块…

设计模式之~迭代器模式

迭代器模式&#xff1a; 迭代器&#xff08;Iterator&#xff09;模式&#xff0c;又叫做游标&#xff08;Cursor&#xff09;模式。GOF 给出的定义为&#xff1a;提供一种方法顺序访问一个容器&#xff08;container&#xff09;对象中各个元素&#xff0c;而又不需暴露该对象…

数据库DBMS并发控制(1)

pgsql&#xff08;PostgreSQL&#xff09;常用命令行操作_pgsql常用命令_石头wang的博客-CSDN博客 重要&#xff1a;事务的操作和事务的性质 操作演示 四种典型数据不一致现象: 串行调度和可串行调度 串行调度 顾名思义 就是可以进行调度的意思 可串行调度 就是 一种和串行…