利用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 ...
随机推荐
- 依赖注入(Dependency Injection)
Spring的两个核心内容为控制反转(Ioc)和面向切面(AOP),依赖注入(DI)是控制反转(Ioc)的一种方式. 依赖注入这个词让人望而生畏,现在已经演变成一项复杂的编程技巧 或设计模式理念.但事 ...
- Github ——转
Github 简明教程 分类 编程技术 如果你是一枚Coder,但是你不知道Github,那么我觉的你就不是一个菜鸟级别的Coder,因为你压根不是真正Coder,你只是一个Code搬运工. 但是你如 ...
- [算法]谷歌笔试题:Beautiful Numbers
题目描述 思路 这道题就是在说,由多个1组成的数是beautiful的,现在想求出r进制中的r,使得给出的数字转换成r进制,得到beautiful的数字,如果有多种方式转换,那么取1的个数最多的那种情 ...
- spring+dubbo整合
创建公共接口或者project用到的一些bean.我这里就仅仅是创建了一个接口.project文件夹例如以下: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQ ...
- PCL法线估计
平面的法线是垂直于它的单位向量.在点云的表面的法线被定义为垂直于与点云表面相切的平面的向量.表面法线也可以计算点云中一点的法线,被认为是一种十分重要的性质.常常在被使用在很多计算机视觉的应用里面,比如 ...
- js json处理 双引号
在数据传输流程中,json是以文本,即字符串的形式传递的,而JS操作的是JSON对象 JSON字符串: var str1 = '{ "name": "cxh", ...
- 微信小程序 --- e.currentTarget.dataset.id 获取不到值
直接代码 wxml代码片段 <view class='ranksList' wx:for="{{ranksLb}}"> <view class='ranksLis ...
- 利用函数或映射进行数据转换 (map)
先来看个数据 df = DataFrame({"food":["bacon", "pulled pork", "bacon&quo ...
- android O 蓝牙设备默认名称更改
安卓系统会首先读取BTM_DEF_LOCAL_NAME的值,如果为空,就使用"ro.product.model"作为蓝牙设备名. system/bt/btif/src/btif_d ...
- python 读写配置文件
使用python读写配置文件,写个demo测试一下. #!/usr/bin/env python import os import ConfigParser # 如果文件不存在,就穿件文件. if o ...