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

news/2024/11/17 9:53:38/

欢迎关注『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 cv2app = 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 Noneret, buffer = cv2.imencode('.jpg', frame)  # 编码为 jpg 格式frame_byte = buffer.tobytes()  # 转换为 bytes 类型return frame_bytedef __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__()  # 释放视频流breakyield (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 cv2app = 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 = Falsedef __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_byteelse:return Nonedef 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 = Truereturn ('', 204)@app.route('/stop', methods=['POST'])
def stop():video_stream.is_streaming = Falsereturn ('', 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.ppmy.cn/news/144432.html

相关文章

波司登云原生微服务治理探索

作者&#xff1a;曾孟琪&#xff08;山猎&#xff09; 背景 波司登创始于1976年&#xff0c;专注于羽绒服的研发、设计、制作&#xff0c;是全球知名的羽绒服生产商。波司登用一系列世人瞩目的辉煌成绩证明了自己的实力&#xff1a;连续26年全国销量领先&#xff0c;连续22年…

CTP 4097错误

这天开发ctp&#xff0c;在运行程序的时候老师出现4097错误&#xff0c;不能连接&#xff0c;让我很无奈。可是不知道为什么鬼使神差的让我发现通过这样可以解决。 我的方法是&#xff1a; 1、先把自己的BrokerID和Password赋空值&#xff0c;运行一次程序。 即是&#xff1…

VC6.0编译时出现:error C2660: 'VarCmp' : function does not take 4 parameters

VC6.0编译时出现&#xff1a;error C2660: VarCmp : function does not take 4 parameters&#xff0c;全部重建一下就好啦&#xff01; build all

C++ Visual Studio报错:error C4430

属性->C/C->高级->禁用特定警告&#xff0c;输入4430

YUYV(YUV422)转I420(YUV420)C++代码

int YUV422To420(unsigned char yuv422[], unsigned char yuv420[], int width, int height) {int ynum width * height;int i, j, k 0;//得到Y分量for (i 0; i < ynum; i) {yuv420[i] yuv422[i * 2];}//得到U分量for (i 0; i < height; i) {if ((i % 2) ! 0)contin…

vc++6.0(Visual C++)中文企业版

名称;vc6.0(Visual C)中文企业版 版本&#xff1a;6.0 软件大小&#xff1a;234M 软件语言&#xff1a;简体中文 软件授权&#xff1a;免费版 应用平台&#xff1a;Win2000/WinXP/Win2003/Vista/Win7/Win8 Visual C是一个功能强大的可视化软件开发工具。自1993年Microsoft公司…

联想V470C 禁用触摸板

联想V470C 禁用触摸板 去联想官网下载对应型号的驱动&#xff1a;驱动链接 解压安装包后&#xff1a;删除解压文件的Synaptics文件夹 进入ELAN文件夹&#xff0c;双击Setup文件 进入“控制面板->硬件和声音->鼠标”&#xff0c;选择ELAN &#xff0c;选择停滞设备&#…

ov7740 vl4c驱动

ov7740 vl4c驱动 cmos_ov7740_drv 部分代码cmos_ov7740_dev 部分代码 cmos_ov7740_drv 部分代码 #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/i2c.h> #include <linux/err.h> #i…