欢迎关注『OpenCV DNN @ Youcans』系列,持续更新中
【OpenCV DNN】Flask 视频监控目标检测教程 09
- 3.9 OpenCV+Flask多线程处理实时监控人脸识别
- 新建 Flask 项目 cvFlask09
- Python程序文件
- 视频流的网页模板
- 程序运行
本系列从零开始,详细讲解使用 Flask 框架构建 OpenCV DNN 模型的 Web 应用程序。本节使用多线程或者异步框架来处理视频帧的获取和人脸识别。
本例程使用一个线程实时获取视频帧,在主线程中处理视频帧,进行人脸识别和图像编码。因此,人脸识别就不会阻止视频帧的读取。
3.9 OpenCV+Flask多线程处理实时监控人脸识别
由于人脸识别是一个计算密集型任务,可能会减慢视频流的处理速度。为了解决这个问题,可以使用多线程或者异步框架来处理视频帧的获取和人脸识别。
本例程使用一个线程实时获取视频帧,在主线程中处理视频帧,进行人脸识别和图像编码。因此,人脸识别就不会阻止视频帧的读取。
我们为 VideoStream类添加了一个新的方法 update_frame,并在类初始化时开启了一个新的线程来运行这个方法。视频更新函数update_frame() 实时获取新的视频帧,并存储为类的一个属性。
在主线程中,生成器函数get_frame()只负责进行人脸识别和图像编码。gen_frames()逐帧获取图片,使用Haar 级联分类器 预训练模型进行人脸检测,将图像编码后返回给客户端。客户端浏览器收到视频流以后,在img标签定义的图片中逐帧显示,从而实现视频播放。即使人脸识别和图像编码需要一些时间,也不会阻塞视频刷更新。
新建 Flask 项目 cvFlask09
新建一个Flask项目cvFlask09,本项目的框架与cvFlask08相同。
cvFlask09项目的文件树如下。
---文件名\
|---models\
| |---haarcascade_frontalface_alt2.xml
|---templates\
| |---index4.html
| |---index5.html
|--- cvFlask09.py
|--- vedio_01.mp4
Python程序文件
任务逻辑由Python程序文件cvFlask09.py实现,完整代码如下。
# cvFlask09.py
# OpenCV+Flask 图像处理例程 09
# 通过浏览器播放摄像头实时监控视频+人脸识别,多线程处理
# Copyright 2023 Youcans, XUPT
# Crated:2023-5-18
# coding:utf-8
from flask import Flask, Response, request, render_template
import threading
import cv2
app = Flask(__name__) # 实例化 Flask 对象
# 定义视频流类
class VideoStream:
def __init__(self, source): # 传入视频源
self.video_cap = cv2.VideoCapture(0) # 创建视频读取对象
# 加载 Haar 级联分类器 预训练模型
model_path = "./models/haarcascade_frontalface_alt2.xml"
# 加载人脸检测级联分类器
self.face_cascade = cv2.CascadeClassifier(model_path)
self.success, self.frame = self.video_cap.read() # 读取视频帧
threading.Thread(target=self.update_frame, args=()).start()
def __del__(self):
self.video_cap.release() # 释放视频流
def update_frame(self):
while True:
self.success, self.frame = self.video_cap.read()
def get_frame(self):
gray = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY)
# 使用级联分类器检测人脸
faces = self.face_cascade.detectMultiScale(gray, scaleFactor=1.2,
minNeighbors=5, minSize=(30, 30), maxSize=(300, 300))
# 绘制人脸检测框
for (x, y, w, h) in faces:
cv2.rectangle(self.frame, (x, y), (x+w, y+h), (255,0,0), 2)
ret, buffer = cv2.imencode('.jpg', self.frame) # 编码为 jpg 格式
frame_byte = buffer.tobytes() # 转换为 bytes 类型
return frame_byte
# 生成视频流的帧
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') # 从网页获取视频源
# 通过将一帧帧的图像返回,就达到了看视频的目的。multipart/x-mixed-replace是单次的http请求-响应模式,如果网络中断,会导致视频流异常终止,必须重新连接才能恢复
return Response(gen_frames(video_source), mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/')
def index_camera(): # 实时视频监控
# <img src="{{ url_for('video_feed', video_source='camera') }}">
return render_template('index4.html')
@app.route('/vidfile')
def index_vidfile(): # 播放视频文件
# <img src="{{ url_for('video_feed', video_source='vedio_01.mp4') }}">
return render_template('index5.html')
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 地址和端口号
视频流的网页模板
视频流的网页模板index4.html和index5.html位于templates文件夹,内容与cvFlask08项目完全相同。
网页index4.html位于templates文件夹,具体内容如下。
<!DOCTYPE html>
<html>
<head>
<title>Video Streaming Demonstration</title>
</head>
<body>
<h2 align="center">OpenCV+Flask 例程:实时视频监控</h2>
<div style="text-align:center; padding-top:inherit">
<img src="{{ url_for('video_feed', video_source='camera') }}" width="600"; height="360">
</div>
</body>
</html>
网页index5.html位于templates文件夹,具体内容如下。
<!DOCTYPE html>
<html>
<head>
<title>Video Streaming Demonstration</title>
</head>
<body>
<h2 align="center">OpenCV+Flask 例程:播放视频文件</h2>
<div style="text-align:center; padding-top:inherit">
<img src="{{ url_for('video_feed', video_source='vedio_01.mp4') }}" width="600"; height="360">
</div>
</body>
</html>
程序运行
进入cvFlask09项目的根目录,运行程序cvFlask09.py,启动流媒体服务器。
在局域网内设备(包括移动手机)的浏览器打开http://192.168.3.249:5000就可以播放实时视频监控画面。
【本节完】
下节我们将讨论,使用OpenCV DNN对实时视频进行目标检测。
版权声明:
欢迎关注『OpenCV DNN @ Youcans』系列
youcans@xupt 原创作品,转载必须标注原文链接:
【OpenCV DNN】Flask 视频监控目标检测教程 09
(https://blog.csdn.net/youcans/article/details/131270693)
Copyright 2023 youcans, XUPT
Crated:2023-06-18