ffpyplayer图像到QPixmap

问题描述 投票:0回答:1

我正在寻找一种使用FfPyPlayer将视频文件流式传输到PyQt中的QPixmap的方法。该文档提供了一个将Image对象从播放器中流出来的示例,但是我不确定如何将该Image转换为QPixmap。我确实看到有一种将其转换为字节数组的方法,并且QPixmap确实具有QPixmap.loadFromData()函数,但是我无法将这两者成功地结合在一起。

这是文档中的示例:

from ffpyplayer.player import MediaPlayer
import time

player = MediaPlayer(filename)
val = ''
while val != 'eof':
    frame, val = player.get_frame()
    if val != 'eof' and frame is not None:
        img, t = frame
        # Now what?!

编辑好吧,我确实提出了一个解决方案,将FfPyPlayer图像转换为PIL图像,然后通过Pillow ImageQt.toqpixmap()方法转换为QPixmap。但是,我犹豫将其标记为答案,因为它似乎效率很低,以至于我想知道是否还有其他人有更好的解决方案。

from ffpyplayer.player import MediaPlayer
from PIL import ImageQt, Image

player = MediaPlayer(filename)
val = ''
while val != 'eof':
    frame, val = player.get_frame()
    if val != 'eof' and frame is not None:
        img, t = frame

        data = img.to_bytearray()[0]
        img2 = Image.frombytes("RGB", img.get_size(), bytes(data))

        pixmap = ImageQt.toqpixmap(img2) # <- returns a QPixmap
python pyqt
1个回答
0
投票

问题是QPixmap.loadFromData()期望实际的图像“文件”,而ffpyplayer(如ffmpeg所提供的)实际上是原始图像,这是最终出现的图像的实际表示(光栅化)。] >

由于各种原因,QPixmap无法直接处理原始数据,因为它打算在屏幕上显示图像,而QImages则可以,因为它们也与硬件无关。

QImage可以加载原始图像数据(例如,如果图像被压缩,则原始数据是未压缩图像的实际表示),但是它需要了解有关“图像格式”的知识,并且显然图像宽度/高度。当您使用QPixmap.loadFromData()时,实际上发生的是Qt“猜测”图像文件格式,将其解压缩(如有必要)以获取有关“每个像素”的数据,获取图形大小和像素格式,然后构建内部具有所有这些信息的QImage,最后将其返回为QPixmap。

在这种情况下,您已经拥有ffpyplayer提供的所有数据,因此您完全跳过了第一个“解码”段落并创建了QImage,然后从中获取QPixmap。

while val != 'eof':
    frame, val = player.get_frame()
    if val != 'eof' and frame is not None:
        img, t = frame

        data = img.to_bytearray()[0]
        width, height = img.get_size()

        # the technical name for the 'rgb24' default pixel format is RGB888,
        # which is QImage.Format_RGB888 in the QImage format enum
        qimage = QtGui.QImage(data, width, height, QtGui.QImage.Format_RGB888)
        pixmap = QtGui.QPixmap.fromImage(qimage)

[请注意,MediaPlayer的默认out_fmt为'rgb24',我怀疑您是否需要更改它,但是如果您避免使用任何基于YUV的像素格式,因为QImage不支持它们。仍然可以转换它(有some methods),但我不建议这样做。

最后,考虑宽高比,它可能在源图像和实际表示形式之间发生变化(例如,变形格式)。您可以从player.get_metadata()中获得该图像,如果它与图像纵横比不匹配,则可以使用以下方法获得正确的图像:

pixmap = pixmap.scaled(targetWidth, targetHeight, 
    QtCore.Qt.IgnoreAspectRatio, QtCore.Qt.SmoothTransformation)
© www.soinside.com 2019 - 2024. All rights reserved.