【问题标题】:How to QVideoFrame to QImage如何将 QVideoFrame 转换为 QImage
【发布时间】:2014-12-04 15:24:15
【问题描述】:

任务是从 QVideoFrame 中复制一个帧,并可能对该图像执行一些操作并在 QML 中显示处理后的图像。

...

m_lastFrame = QImage(videoFrame.width(), videoFrame.height(), QImage::Format_ARGB32);
memcpy(m_lastFrame.bits(), videoFrame.bits(),videoFrame.mappedBytes());

...

上面的代码会导致崩溃,因为 m_lastFrame 缺少 32 个字节(3686400 vs 3686432) videoFrame.mappedBytes() 报告 3686432 字节。我在这里做错了什么?或者我应该如何计算 m_lastFrame() 的大小。

代码在 Mac OSx 10.9.5 Qt 5.1.1 上运行。

一些附加代码:

... if( videoFrame.ma​​p(QAbstractVideoBuffer::ReadOnly) ){

    m_lastFrame = QImage(videoFrame.width(),videoFrame.height(),QImage::Format_ARGB32);
    memcpy(m_lastFrame.bits(), videoFrame.bits(),videoFrame.mappedBytes() - 32);

    ...

} ...

【问题讨论】:

  • 你有没有给videoFrame.map(QAbstractVideoBuffer::ReadOnly)打过电话并检查过返回值?您确定视频帧包含 ARGB32 数据吗?
  • 在调用videoFrame.bits() 之前,您是否成功地将视频帧的内容映射(通过调用map())到系统内存?在那种情况下,我认为您的问题应该通过从像素格式正确转换为图像格式来解决。
  • 是的@njahnke。我是按照上面的
    调用map()
  • 好的,@mhcuervo。谢谢你们的帮助,我检查了格式,它使用了正确的格式。我将在电脑上运行这段代码,看看结果如何。
  • 在带有 Qt 5.3.2 的 Windows 8 上测试。两个函数都返回 3686400bytes。因此,似乎是MAC上的问题。但是,在 PC 上发现了其他问题,返回的帧是颠倒的,RGB32 图像只是呈现一个白色帧。转换为 ARGB_32 并渲染图像。下一步将采取一些日志来调查实际像素值。这个想法是在多个平台上使用它,到目前为止,Qt fw 似乎没有提供良好的跨平台功能。

标签: qt


【解决方案1】:

由于这并不总是有效,请参阅convert QVideoFrame to QImage 的评论,即

QImage Camera::imageFromVideoFrame(const QVideoFrame& buffer) const
{
    QImage img;
    QVideoFrame frame(buffer);  // make a copy we can call map (non-const) on
    frame.map(QAbstractVideoBuffer::ReadOnly);
    QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(
                frame.pixelFormat());
    // BUT the frame.pixelFormat() is QVideoFrame::Format_Jpeg, and this is
    // mapped to QImage::Format_Invalid by
    // QVideoFrame::imageFormatFromPixelFormat
    if (imageFormat != QImage::Format_Invalid) {
        img = QImage(frame.bits(),
                     frame.width(),
                     frame.height(),
                     // frame.bytesPerLine(),
                     imageFormat);
    } else {
        // e.g. JPEG
        int nbytes = frame.mappedBytes();
        img = QImage::fromData(frame.bits(), nbytes);
    }
    frame.unmap();
    return img;
}

【讨论】:

    【解决方案2】:

    您可以尝试通过以下方式首先将 QVideoFrame 映射到 QAbstractVideoBuffer 来创建 QImage:

    bool CameraFrameGrabber::present(const QVideoFrame &frame)
    {
    Q_UNUSED(frame);
    if (frame.isValid()) {
        QVideoFrame cloneFrame(frame);
        cloneFrame.map(QAbstractVideoBuffer::ReadOnly);
        const QImage image(cloneFrame.bits(),
                           cloneFrame.width(),
                           cloneFrame.height(),
                          QVideoFrame::imageFormatFromPixelFormat(cloneFrame .pixelFormat()));
    
    
        emit frameAvailable(image);
        qDebug()<<cloneFrame.mappedBytes();
        cloneFrame.unmap();
        return true;
    }
    

    如果您希望 QImage 采用任何其他格式,只需在创建图像期间将最后一个参数更改为您喜欢的任何格式:

    QImage::Format_xxx ;

    而不是

    QVideoFrame::imageFormatFromPixelFormat(cloneFrame .pixelFormat()));

    【讨论】:

    • 您不能只指定您喜欢的格式。它必须是您提供的数据的格式,因此需要QVideoFrame::imageFormatFromPixelFormat
    猜你喜欢
    • 2014-11-15
    • 2015-02-05
    • 2023-03-09
    • 2018-08-27
    • 2011-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多