簡體   English   中英

如何將 python OpenCV 輸出流式傳輸到 HTML 畫布?

[英]How do I stream python OpenCV output to HTML canvas?

我正在嘗試使用 Flask 為我的 python OpenCV 代碼制作一個 Web 界面,目的是使用畫布 HTML 元素繪制“裁剪區域”以從幀流中提取細節。以下是我在此處找到的一些示例Stackoverflow 我能夠將 OpenCV 代碼的輸出流式傳輸到 img 元素,但不能流式傳輸到畫布或視頻元素。 Python代碼:(最小)

import cv2

from flask import Flask, render_template,Response

app = Flask(__name__)

video_capture = cv2.VideoCapture(0)

def gen():    

    while True:
        ret, image = video_capture.read()
        cv2.imwrite('t.jpg', image)
        yield (b'--frame\r\n'
           b'Content-Type: image/jpeg\r\n\r\n' + open('t.jpg', 'rb').read() + b'\r\n')
    video_capture.release()


@app.route('/')
def index():
    """Video streaming"""
    return render_template('index.html')

@app.route('/video_feed')
def video_feed():
    """Video streaming route. Put this in the src attribute of an img tag."""
    return Response(gen(),
                mimetype='multipart/x-mixed-replace; boundary=frame')


if __name__ == '__main__':
    app.run()

HTML代碼:

<html>
<head>
    <title>Video Streaming </title>
</head>
<body>
    <div>
        <h1>Live Video Streaming </h1>
        <img id="img" src = "{{ url_for('video_feed') }}">
    </div>
</body>
</html>

為了將來對遇到此問題的任何人的參考,盡管@furas 提供的答案按預期工作,但我發現對於我的用例,也可以使用 CSS 將輸出幀分配給畫布背景,從而允許顯示僅視頻,並在其上自由繪制。

HTML代碼

<html>
<head>
    <title>Video Streaming </title>
</head>
<style>
    .myCanvas{
       background-image: url("{{ url_for('video_feed') }}"); 
    }
</style>
<body>
    <div>
        <h1>Live Video Streaming </h1>
        <img id="img" src = "{{ url_for('video_feed') }}">
        <canvas class="myCanvas" height="600" width="480">
    </div>
</body>
</html>

這個帶有 JavaScript 的 HTML 同時在 Canvas 和<img>中顯示流。

對於單個靜態圖像,它需要運行onload() 對於流MJPEG它需要使用setInterval()定期重繪圖像。

它在Chrome上對我Chrome但我的FirefoxCanvas上只顯示第一幀。 我想我以前遇到過這個問題。 可能它需要更多的東西才能正常工作,但我不記得是什么了。

<html>
<head>
    <title>Video Streaming </title>
</head>
<body>

    <div width="640px" height="480px" style="display:inline-block">
        <h1>Image</h1>
        <img id="img" src="{{ url_for('video_feed') }}">
    </div>

    <div width="640px" height="480px" style="display:inline-block">
        <h1>Canvas</h1>
        <canvas id="canvas" width="640px" height="480px"></canvas>
    </div>

<script >

    var ctx = document.getElementById("canvas").getContext('2d');
    var img = new Image();
    img.src = "{{ url_for('video_feed') }}";

    // need only for static image
    //img.onload = function(){   
    //    ctx.drawImage(img, 0, 0);
    //};

    // need only for animated image
    function refreshCanvas(){
        ctx.drawImage(img, 0, 0);
    };
    window.setInterval("refreshCanvas()", 50);

</script>

</body>
</html>

我發現舊的信息mjpeg HTML5 視頻不能與流一起傳輸,而且<video>似乎不支持mjpeg格式,因此它可能不適用於此流。


完整的工作代碼。

我使用render_template_string而不是render_template這樣每個人都可以將所有代碼放在一個文件中並進行測試。

import cv2
from flask import Flask, render_template, render_template_string, Response

app = Flask(__name__)
video_capture = cv2.VideoCapture(0)

def gen():    
    while True:
        ret, image = video_capture.read()
        cv2.imwrite('t.jpg', image)
        yield (b'--frame\r\n'
           b'Content-Type: image/jpeg\r\n\r\n' + open('t.jpg', 'rb').read() + b'\r\n')
    video_capture.release()


@app.route('/')
def index():
    """Video streaming"""
    #return render_template('index.html')
    return render_template_string('''<html>
<head>
    <title>Video Streaming </title>
</head>
<body>
    <div>
        <h1>Image</h1>
        <img id="img" src="{{ url_for('video_feed') }}">
    </div>
    <div>
        <h1>Canvas</h1>
        <canvas id="canvas" width="640px" height="480px"></canvas>
    </div>

<script >
    var ctx = document.getElementById("canvas").getContext('2d');
    var img = new Image();
    img.src = "{{ url_for('video_feed') }}";

    // need only for static image
    //img.onload = function(){   
    //    ctx.drawImage(img, 0, 0);
    //};

    // need only for animated image
    function refreshCanvas(){
        ctx.drawImage(img, 0, 0);
    };
    window.setInterval("refreshCanvas()", 50);

</script>

</body>
</html>''')

@app.route('/video_feed')
def video_feed():
    """Video streaming route. Put this in the src attribute of an img tag."""
    return Response(gen(),
                mimetype='multipart/x-mixed-replace; boundary=frame')


if __name__ == '__main__':
    app.run()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM