打印MJPEG fram

2024-10-02 00:41:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我在试着做一个mjpeg拖缆。帧前面的前5个字节表示它的大小。然后我可以提取帧。我需要检查一下我的相框是否正确。我试图将帧写入.jpeg文件;但这不起作用。 我做得对吗?在

import os
from array import array

class VideoStream:
    def __init__(self,filename):
        self.fis = open(filename,'r')
        self.frame_nb = 0

    def getnextframe(self):
        length = 0
        frame_length = bytearray(5)

        frame_length = self.fis.read(5)
        fm = array('B',frame_length[:5])

        length = fm[4]+((fm[3]<<8)&0xFF)+((fm[2]<<16)&0xFF)+((fm[1]<<24)&0xFF)+((fm[0]<<32)&0xFF)

        frame = self.fis.read(length)
        print 'len=',length

        test = open("test.jpeg",'w')
        test.write(frame)
        test.close()
        print 'frame=',frame



if __name__=='__main__':
    vs = VideoStream("Movie.mjpeg")
    vs.getnextframe()

Tags: testimportselfdefopenfilenamearrayframe
1条回答
网友
1楼 · 发布于 2024-10-02 00:41:58

代码中的长度实际上就是第五个字节的值。将所有其他求和数至少向左移动8位,然后屏蔽除最低8位之外的所有位。由于前面的移位操作,这些位都是零。在

一个简单的附加测试可以实现的是,如果帧数据以JPEG开始的图像标记(FF D8)开始,并以图像结束标记(DD D9)结束。在

下面的函数应该迭代JPEG图像,这些图像由5个ascii字符长的帧长度计数分隔,就像您要移植到Python的VideoStream.java

def iter_frames(filename):
    with open(filename, 'rb') as mjpeg_file:
        while True:
            frame_length_bytes = mjpeg_file.read(5)
            if len(frame_length_bytes) != 5:
                if frame_length_bytes:
                    raise ValueError('incomplete length')
                else:
                    break
            frame_length = int(frame_length_bytes)
            frame = mjpeg_file.read(frame_length)
            if len(frame) != frame_length:
                raise ValueError('incomplete frame data')
            if not (
                frame.startswith(b'\xff\xd8') and frame.endswith(b'\xff\xd9')
            ):
                raise ValueError('invalid jpeg')

            yield frame


def main():
    frames = iter_frames('Movie.mjpeg')
    frame = next(frames)
    with open('test.jpg', 'wb') as jpeg_file:
        jpeg_file.write(frame)



if __name__ == '__main__':
    main()

它检查字节计数值和JPEG数据是否完整,以及JPEG开始和结束标记是否存在。在

比你想象的要简单得多。但是有一个问题:这种格式很可能是由Java类的作者编写的。在

MJPEG只是一个视频编解码器,基本上只是JPEG图像的拼接。但它很少以“原始”格式出现,而是嵌入到包含元数据的容器格式中,比如MJPEG数据、帧速率、音频等等。在

其中一种格式是AVI,如您在注释中引用的example MJPEG avi。在

从这样一个文件中提取帧到单个JPEG图像要比读取以简单长度信息为前缀的JPEG图像并将其连接到一个文件中的工作量要大一些。我们需要实现一个AVI读取器,它对AVI格式有足够的了解,以获取帧数据。然后是一个JPEG读取器,它能读懂JPEG格式的全部帧,因为它们是背靠背保存的,没有任何长度信息。在

下一个问题是并非所有的mjpeg都包含可用作独立JPEG图像的帧。有些缺少解压缩图像数据所需的数据表(huffman表)。在MJPEG编解码器的AVI规范中有一个固定的表。软件使用该表进行解码,当保存为JPEG文件时,必须将其注入帧中。在

最后一件事:有一些交错的视频不包含完整的图像,但是两个连续的图像需要合并成一个。每个图像包含其他行。你给出的example MJPEG avi就是这样一个视频。在不解码、去隔行和重编码的情况下提取帧时,每个图像的高度只有视频高度的一半。在

为了更好地了解单个图像的外观,ffmpeg命令行提取帧数据并注入缺失的数据表,以便获得独立的JPEG图像:

^{pr2}$

相关问题 更多 >

    热门问题