利用flask将opencv实时视频流输出到浏览器
opencv通过webcam可以获取本地实时视频流,但是如果需要将视频流共享给其他机器调用,就可以将利用flask框架构建一个实时视频流服务器,然后其他机器可以通过向这个服务器发送请求来获取这台机器上的实时视频流。[这篇文章](https://blog.miguelgrinberg.com/post/video-streaming-with-flask)包含非常详细的理论介绍和具体实现,力荐!
首先需要说明的是这里flask提供视频流是通过generator函数进行的,不了解的可以去查下文档这里就不具体讲了。flask通过将一连串独立的jpeg图片输出来实现视频流,这种方法叫做motion JPEG,好处是延迟很低,但是成像质量一般,因为jpeg压缩图片的质量对motion stream不太够用。
multipart 模式
想要将后一次请求得到的图片覆盖到前一次从而达到动画的效果就需要使用在response的时候使用multipart模式。Multipart response由以下几部分组成:包含multipart content类型的header,分界符号分隔的各个part,每个part都具有特定的content类型。multipart视频流的结构如下:
HTTP/1.1 200 OK
Content-Type: multipart/x-mixed-replace; boundary=frame
--frame
Content-Type: image/jpeg
<jpeg data here>
--frame
Content-Type: image/jpeg
<jpeg data here>
...
flask server
具体实现代码:main.py
from flask import Flask, render_template, Response
import opencv
class VideoCamera(object):
def __init__(self):
# 通过opencv获取实时视频流
self.video = cv2.VideoCapture(0)
def __del__(self):
self.video.release()
def get_frame(self):
success, image = self.video.read()
# 因为opencv读取的图片并非jpeg格式,因此要用motion JPEG模式需要先将图片转码成jpg格式图片
ret, jpeg = cv2.imencode('.jpg', image)
return jpeg.tobytes()
app = Flask(__name__)
@app.route('/') # 主页
def index():
# jinja2模板,具体格式保存在index.html文件中
return render_template('index.html')
def gen(camera):
while True:
frame = camera.get_frame()
# 使用generator函数输出视频流, 每次请求输出的content类型是image/jpeg
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')
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True, port=5000)
index.html
<html>
<head>
<title>Video Streaming Demonstration</title>
</head>
<body>
<h1>Video Streaming Demonstration</h1>
<img src="{{ url_for('video_feed') }}">
</body>
</html>
注:图片地址由大括号内的字典给出,指向app的第二个地址video_feed,在multipart模式下浏览器会将每次请求得到的地址对大括号进行更新。
局限性
如果视频流一直存在的话,这个app能输出视频流的的客户端的数量和web worker的数量相同,在debug模式下,这个数量是1,也就是说只有一个浏览器上能够看到视频流输出。
如果要克服这种局限的话,使用基于协同网络服务的框架比如gevent,可以用一个worker线程服务多个客户端。
参考
https://blog.miguelgrinberg.com/post/video-streaming-with-flask
https://github.com/mattmakai/video-service-flask
http://www.chioka.in/python-live-video-streaming-example/
利用flask将opencv实时视频流输出到浏览器的更多相关文章
- opencv获取IP摄像头(IP-camera)实时视频流
之前这篇文章讲了如何通过网络摄像头(web camera)获取实时视频流,但是这种方法的缺陷就是摄像头和主机必须连在一起,那这种在室外部署的时候就会非常麻烦并且不安全,所以后来找了下用海康威视或者大华 ...
- 人脸检测及识别python实现系列(6)——终篇:从实时视频流识别出“我”
人脸检测及识别python实现系列(6)——终篇:从实时视频流识别出“我” 终于到了最后一步,激动时刻就要来临了,先平复一下心情,把剩下的代码加上,首先是为Model类增加一个预测函数: #识别人脸 ...
- 人脸检测及识别python实现系列(1)——配置、获取实时视频流
人脸检测及识别python实现系列(1)——配置.获取实时视频流 1. 前言 今天用多半天的时间把QQ空间里的几篇年前的旧文搬到了这里,算是完成了博客搬家.QQ空间里还剩下一些记录自己数学学习路线的学 ...
- 在WEB显示实时视频流
转载自:https://www.jianshu.com/p/7ef5490fbef7 安装摄像头 这里使用的是树莓派的官方摄像头,使用普通的 USB 摄像头也可以,但前提是你能够搞的定它的驱动. 大概 ...
- 利用javascript实现文本的自动输出
主要利用了setTimeout(),递归和String.substring(); 做出的效果就像是有一个打字员在打字. <!doctype html> <html lang=&quo ...
- opencv学习_15 (利用cmake查看opencv的源码)
当我们有时想查看opencv自带的函数的源代码,比如函数cvCreateImage, 此时我们选中cvCreateImage, 点击鼠标右键->转到定义,我们会很惊讶的发现为什么只看到了cvCr ...
- 利用sql命令把结果集输出到文件
利用sql命令把结果集输出到文件 红色部分的三条命令完成把结果集输出到文件!! [root@test root]# psql -hlocalhost -Utest testWelcome to psq ...
- Python - 利用flask搭建一个共享服务器
零.概述 我利用flask搭建了一个简易的共享服务器,分享给大家 一.python代码 import os import time from flask import Flask,render_tem ...
- 利用cmake查看opencv的源码
当我们有时想查看opencv自带的函数的源代码,比如函数cvCreateImage, 此时我们选中cvCreateImage, 点击鼠标右键->转到定义,我们会很惊讶的发现为什么只看到了cvCr ...
随机推荐
- 腾讯云安装Hadoop遇到的问题
1.能正常访问bincoding.cn:50030,不能连接到9000端口 Call to bincoding.cn/123.206.212.115:9000 failed on connection ...
- Maven项目编译后classes文件中没有.xml问题
在做spring+mybatiss时,自动扫描都配置正确了,却在运行时出现了如下错误.后来查看target/classes/.../dao/文件夹下,发现只有mapper的class文件,而没有xml ...
- Could not read symbols解决方法
Could not read symbols 陈运文 Could not read symbols:Linux/UNIX系统下编译时,常见的一类报错信息. 通常情况下,该编译报错信息之前会给出出现错误 ...
- Unicode编码:保存中文cookie
中文和英文字符不同,中文属于Unicod字符,在内存中站4个字符,而英文属于ASCII字符,内存中只占2个字符.Cookie中使用Unicode字符时需要对Unicode字符进行编码,否则会乱码.编码 ...
- JVM调优总结(一):基本概念
一.数据类型 Java虚拟机中,数据类型可以分为两类:基本类型和引用类型. 基本类型的变量保存原始值,即:他代表的值就是数值本身: 而引用类型的变量保存引用值.“引用值”代表了某个对象的引用,而不是对 ...
- Map总结(HashMap, Hashtable, TreeMap, WeakHashMap等使用场景)
概要 学完了Map的全部内容,我们再回头开开Map的框架图. 本章内容包括:第1部分 Map概括第2部分 HashMap和Hashtable异同第3部分 HashMap和WeakHashMap异同 转 ...
- SwipeBackLayout侧滑返回显示桌面
SwipeBackLayout是一个很好的类库,它可以让Android实现类似iOS系统的右滑返回效果,但是很多用户在使用官方提供的Demo会发现,可能出现黑屏或者返回只是看到桌面背景而没有看到上一个 ...
- android 向服务器上传
采用数据流的格式向服务器上传. 代码如下: private void upload(String requestURL) { //参数requestU ...
- android 监听声音变化
新的项目需要监听android声音的变化,再做出对应的操作,从网上找了个demo验证.记录于此. 参考链接 https://my.oschina.net/yuanxulong/blog/372268 ...
- Java如何中断正在运行的线程?
在Java编程中,如何中断正在运行的线程? 以下示例演示如何使用Thread类的interrupt()方法中断正在运行线程,并检查线程是否使用isInterrupted()方法中断. package ...