首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >用OpenCV (Python)从Flask服务器读取MJPEG流

用OpenCV (Python)从Flask服务器读取MJPEG流
EN

Stack Overflow用户
提问于 2018-02-21 23:04:28
回答 5查看 5K关注 0票数 9

我正在使用Flask和flask-restful生成一个MJPEG流。出于某些原因,我想在另一个Python程序中捕获这个流,为此我使用了OpenCV(3)。问题是,请求的第一个帧传入得很好。另一方面,请求的第二个帧(在延迟之后)未被正确接收,并抛出错误:

代码语言:javascript
复制
[mpjpeg @ 0000017a86f524a0] Expected boundary '--' not found, instead found a line of 82 bytes

很多次。

我相信这是因为框架的边界是手动设置的。我将把有问题的代码放在下面。

MJPEG流生成:

代码语言:javascript
复制
## Controller for the streaming of content.
class StreamContent(Resource):
    @classmethod
    def setVis(self, vis):
        self.savedVis = vis

    def get(self):
        return Response(gen(VideoCamera(self.savedVis)),
                        mimetype='multipart/x-mixed-replace; boundary=frame')


## Generate a new VideoCamera and stream the retrieved frames.    
def gen(camera):
    frame = camera.getFrame()
    while frame != None:
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
        time.sleep(0.07)
        frame = camera.getFrame()

## Allows for the reading of video frames.
class VideoCamera(object):
    def __init__(self, vis):
        #object we retrieve the frame from.
        self.vis = vis

    ## Get the current frame.
    def getFrame(self):
        image = self.vis.mat_frame_with_overlay
        # We are using Motion JPEG, but OpenCV defaults to capture raw images,
        # so we must encode it into JPEG in order to correctly display the
        # video/image stream.
        ret, jpeg = cv2.imencode('.jpg', image)
        return jpeg.tobytes()

MJPEG流检索:

代码语言:javascript
复制
"""
Get a single frame from the camera.
"""        
class Image(Resource):
    def get(self):
        camera = VideoCamera()
        return Response(camera.getSingleFrame(), mimetype='image/jpeg')

"""
Contains methods for retrieving video information from a source.
"""
class VideoCamera(object):
    def __del__(self):
        self.video.release()

    @classmethod
    def setVideo(self, video):
        self.video = video

    ## Get the current frame.
    def getSingleFrame(self):
        self.startVideoFromSource(self.video)
        ret, image = self.video.read()
        time.sleep(0.5)
        ret, image = self.video.read()
        # We are using Motion JPEG, but OpenCV defaults to capture raw images,
        # so we must encode it into JPEG in order to correctly display the
        # video/image stream.
        ret, jpeg = cv2.imencode('.jpg', image)
        self.stopVideo()
        return jpeg.tobytes()

    def stopVideo(self):
        self.video.release()
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2018-05-31 18:05:53

对于Anabad (和其他人):

哦,这个问题已经有一段时间了。如果我没记错的话,简短的答案是:不,我从来没有让它正常工作过。

摄像头通过这种方式同时被多个程序访问(当一个请求多次发送到API时,多个线程开始读取摄像头),而摄像头无法处理。正确处理这种情况的最好方法(在我看来)是在相机自己的线程上读取单独类中的相机,并使用API的观察者模式。每次从客户端收到读取摄像头的新请求时,一旦新帧可用,观察者就会发送这些帧。

这解决了摄像头被多个类实例/线程访问的问题,这就是为什么它不能工作的原因。绕过这个问题,它应该工作得很好。

票数 1
EN

Stack Overflow用户

发布于 2020-04-29 20:34:00

更改帧生成器对我来说很有效:

代码语言:javascript
复制
yield (b'--frame\r\n'
       b'Content-Type:image/jpeg\r\n'
       b'Content-Length: ' + f"{len(frame)}".encode() + b'\r\n'
       b'\r\n' + frame + b'\r\n')
票数 7
EN

Stack Overflow用户

发布于 2019-11-24 09:21:48

也许现在回答已经太晚了,但我也遇到了同样的问题,并找到了解决方案。

error [mpjpeg @ 0000017a86f524a0] Expected boundary '--' not found, instead found a line of 82 bytes是来自ffmpeg的错误消息,OpenCV将其用作mjpeg图像解码器作为后端。

这意味着图像被流式传输为mpjpeg (=多部分jpeg数据),但没有找到分隔每个jpeg图像的边界(因此解码器无法解码图像)。

边界应以--开头,但是问题中编写的服务器声明边界仅为framemimetype='multipart/x-mixed-replace; boundary=frame')此部分应类似于mimetype='multipart/x-mixed-replace; boundary=--frame')

此外,我还发现边界和图像数据之间的线分隔是强制性的。(从Ubuntu18.04及更高版本提供的ffmpeg开始?)请看mjpg服务器的另一个实现。( https://github.com/ros-drivers/video_stream_opencv/blob/e6ab82a88dca53172dc2d892cd3decd98660c447/test/mjpg_server.py#L75 )

希望这能有所帮助。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48909132

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档