OpenCV не может читать кадры изображения из видео - PullRequest
1 голос
/ 10 июля 2020

В настоящее время я пытаюсь использовать 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. Как сделать видео менее прерывистым?

1 Ответ

0 голосов
/ 10 июля 2020

Cra sh в вашем python произошло, потому что video.read() не удалось. Следовательно, image нельзя передать в cv2.imencode(). Вы должны проверить значение success в get_frame(self) и быть готовым к тому, что иногда camera.get_frame() не вернет действительный Jpeg.

Теперь давайте разберемся, почему video.read() не удалось в этом случае. Это могло произойти, если соединение с камерой было недостаточно хорошим и некоторые пакеты были потеряны. Но более вероятно, что ваш VideoCapture был недостаточно быстр для обработки видеопотока.

Это можно было бы улучшить, если бы вы уменьшили объем работы, выполняемой потоком видеозахвата. Как было предложено в другом обсуждении , выгрузить обработку в отдельный поток.

В настоящее время ваш flask сервер прослушивает поток камеры, конвертирует его в серию Jpeg и отправляет их в клиент через HTTP. Если у вас есть поток, посвященный потоку с камеры, вы можете обнаружить, что ваш сервер не может передавать каждый видеокадр, потому что кодировщик и транспорт HTTP работают слишком медленно. Таким образом, некоторые кадры будут пропущены.

Вот подробная статья о потоковой передаче видео с flask: https://blog.miguelgrinberg.com/post/flask-video-streaming-revisited. Вы можете найти другие проекты с открытым исходным кодом, которые транслируют видео в браузер, не обязательно с opencv и python.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...