【问题标题】:OpenCV unable to read image frames from videoOpenCV 无法从视频中读取图像帧
【发布时间】:2020-07-10 08:25:57
【问题描述】:

我目前正在尝试使用 OpenCV 和 Python 将视频从 url 加载到 localhost 网页上。加载的视频有点断断续续,但主要问题是它会在一段时间后停止读取视频帧并显示以下错误消息。

[h264 @ 0955e140] error while decoding MB 87 29, bytestream -5
[h264 @ 0955e500] left block unavailable for requested intra4x4 mode -1
[h264 @ 0955e500] error while decoding MB 0 44, bytestream 126
Debugging middleware caught exception in streamed response at a point where response headers were already sent.
Traceback (most recent call last):
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\Lib\site-packages\werkzeug\wsgi.py", line 506, in __next__
    return self._next()
  File "C:\Users\\AppData\Local\Programs\Python\Python38-32\Lib\site-packages\werkzeug\wrappers\base_response.py", line 45, in _iter_encoded
    for item in iterable:
  File "C:\Users\\Downloads\VideoStreamingFlask\main.py", line 12, in gen
    frame = camera.get_frame()
  File "C:\Users\\Downloads\VideoStreamingFlask\camera.py", line 13, in get_frame
    ret, jpeg = cv2.imencode('.jpg', image)
cv2.error: OpenCV(4.3.0) C:\projects\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp:919: error: (-215:Assertion failed) !image.empty() in function 'cv::imencode'

代码

main.py

from flask import Flask, render_template, Response
from camera import VideoCamera

app = Flask(__name__)

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

def gen(camera):
    while True:
        frame = camera.get_frame()
        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)

camera.py

import cv2

class VideoCamera(object):
    def __init__(self):
        self.video = cv2.VideoCapture(*url*)

    def __del__(self):
        self.video.release()
    
    def get_frame(self):
        success, image = self.video.read()
        ret, jpeg = cv2.imencode('.jpg', image)
        return jpeg.tobytes()

问题

  1. 这里的问题可能是什么原因造成的?
  2. 如何减少视频的断断续续?

【问题讨论】:

    标签: python opencv flask video-streaming video-capture


    【解决方案1】:

    你的 python 崩溃是因为 video.read() 失败。因此,image 不能传递给cv2.imencode()。您应该检查get_frame(self) 中的success 值,并准备好有时camera.get_frame() 不会返回有效的Jpeg。

    现在,让我们了解一下为什么 video.read() 在这种情况下会失败。如果与相机的连接不够好并且某些数据包丢失,则可能会发生这种情况。但更有可能的是,您的 VideoCapture 速度不够快,无法处理视频流。

    如果您减少视频捕获线程正在执行的工作,这可能会得到改善。正如another discussion 中所建议的,将处理卸载到单独的线程。

    目前,您的烧瓶服务器侦听相机流,将其转换为一系列 Jpeg,并通过 HTTP 将它们发送到客户端。如果你有一个专门用于摄像头流的线程,你可能会发现你的服务器无法传递每个视频帧,因为编码器和 HTTP 传输太慢了。因此,会跳过一些帧。

    这是一篇关于使用烧瓶进行视频流传输的详细文章:https://blog.miguelgrinberg.com/post/flask-video-streaming-revisited。您可以找到一些其他将视频流式传输到浏览器的开源项目,不一定使用 opencv 和 python。

    【讨论】:

    • 那么,我应该将我的 get_frame 函数拆分为两个较小的函数并使用多线程吗?
    • 基本上是的
    • 我是opencv新手,但是imencode()不需要等待read()返回的图像来处理吗?
    猜你喜欢
    • 1970-01-01
    • 2021-01-06
    • 1970-01-01
    • 2018-02-27
    • 2018-03-01
    • 2015-12-05
    • 1970-01-01
    • 2015-05-20
    • 2018-07-22
    相关资源
    最近更新 更多