Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QvideoFrame to cv::Mat -> Solved
Forum Updated to NodeBB v4.3 + New Features

QvideoFrame to cv::Mat -> Solved

Scheduled Pinned Locked Moved Solved General and Desktop
1 Posts 1 Posters 477 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • I Offline
    I Offline
    Ivan_Rubianes
    wrote on last edited by Ivan_Rubianes
    #1

    Re: Convert QvideoFrame to Mat image

    1- Configure profile (if Qt vesrion < 5.15.0)
    in profile (.pro or .pri) add:

    QT += gui-private
    

    2- create functions:
    in your class functions add: example: MyFunctions.h

    #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
        #include "private/qvideoframe_p.h"
    #endif
    #include <QOpenGLContext>
    #include <QOpenGLFunctions>
    #include <QVideoFrame>
    #include <QDebug>
    #include <QImage>
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/imgproc/types_c.h"
    
    static QImage QVideoFrameToQImage( const QVideoFrame& videoFrame ){
    	if ( videoFrame.handleType() == QAbstractVideoBuffer::NoHandle )
    	{
    	    #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
    		QImage image = videoFrame.image();
    	    #else
    		QImage image = qt_imageFromVideoFrame( videoFrame );
    	    #endif
    	    if ( image.isNull() ) return QImage();
    	    if ( image.format() != QImage::Format_ARGB32 ) return image.convertToFormat( QImage::Format_ARGB32 );
    	    return image;
    	}
    	if ( videoFrame.handleType() == QAbstractVideoBuffer::GLTextureHandle )
    	{
    	    QImage image( videoFrame.width(), videoFrame.height(), QImage::Format_ARGB32 );
    	    GLuint textureId = static_cast<GLuint>( videoFrame.handle().toInt() );
    	    QOpenGLContext* ctx = QOpenGLContext::currentContext();
    	    QOpenGLFunctions* f = ctx->functions();
    	    GLuint fbo;
    	    f->glGenFramebuffers( 1, &fbo );
    	    GLint prevFbo;
    	    f->glGetIntegerv( GL_FRAMEBUFFER_BINDING, &prevFbo );
    	    f->glBindFramebuffer( GL_FRAMEBUFFER, fbo );
    	    f->glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,  GL_TEXTURE_2D, textureId, 0 );
    	    f->glReadPixels( 0, 0,  videoFrame.width(),  videoFrame.height(), GL_RGBA, GL_UNSIGNED_BYTE, image.bits() );
    	    f->glBindFramebuffer( GL_FRAMEBUFFER, static_cast<GLuint>( prevFbo ) );
    	    return image.rgbSwapped();
    	}
    	return QImage();
    }
    
    static cv::Mat QImageToCvMat(QImage inImage, bool inCloneImageData = true)
    {
        switch ( inImage.format() )
        {
        // 8-bit, 4 channel
        case QImage::Format_ARGB32:
        case QImage::Format_ARGB32_Premultiplied:
        {
            cv::Mat  mat( inImage.height(), inImage.width(),
                          CV_8UC4,
                          const_cast<uchar*>(inImage.bits()),
                          static_cast<size_t>(inImage.bytesPerLine())
                          );
    
            return (inCloneImageData ? mat.clone() : mat);
        }
    
            // 8-bit, 3 channel
        case QImage::Format_RGB32:
        {
            if ( !inCloneImageData )
            {
                qWarning() << "QImageToCvMat() - Conversion requires cloning so we don't modify the original QImage data";
            }
    
            cv::Mat  mat( inImage.height(), inImage.width(),
                          CV_8UC4,
                          const_cast<uchar*>(inImage.bits()),
                          static_cast<size_t>(inImage.bytesPerLine())
                          );
    
            cv::Mat  matNoAlpha;
    
            cv::cvtColor( mat, matNoAlpha, cv::COLOR_BGRA2BGR );   // drop the all-white alpha channel
    
            return matNoAlpha;
        }
    
            // 8-bit, 3 channel
        case QImage::Format_RGB888:
        {
            if ( !inCloneImageData )
            {
                qWarning() << "QImageToCvMat() - Conversion requires cloning so we don't modify the original QImage data";
            }
    
            QImage   swapped = inImage.rgbSwapped();
    		
            cv::Mat mat( swapped.height(), swapped.width(),
                            CV_8UC3,
                            const_cast<uchar*>(swapped.bits()),
                            static_cast<size_t>(swapped.bytesPerLine())
                            );
           return (inCloneImageData ? mat.clone() : mat);
        }
    
            // 8-bit, 1 channel
        case QImage::Format_Grayscale8:
        case QImage::Format_Indexed8:
        {
            cv::Mat  mat( inImage.height(), inImage.width(),
                          CV_8UC1,
                          const_cast<uchar*>(inImage.bits()),
                          static_cast<size_t>(inImage.bytesPerLine())
                          );
    
            return (inCloneImageData ? mat.clone() : mat);
        }
    
    
    #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
        case QImage::Format_Grayscale16:
        {
            cv::Mat mat(cv::Size(inImage.width(),inImage.height()),CV_16U,const_cast<uchar*>(inImage.bits()),cv::Mat::AUTO_STEP);
    // or
    //        cv::Mat  mat( inImage.height(), inImage.width(),
    //                    CV_16U,
    //                    const_cast<uchar*>(inImage.bits()),
    //                    static_cast<size_t>(inImage.bytesPerLine())
    //                    );
            return (inCloneImageData ? mat.clone() : mat);
        }
    #endif
    
        default:
            qWarning() << "QImageToCvMat() - QImage format not handled in switch:" << inImage.format();
            break;
        }
    
        return cv::Mat();
    }
    

    3- test
    in your code .cpp:
    // vFrame is a QVideoFrame to convert

    QImage img = QVideoFrameToQImage(vFrame);
    cv::Mat videoFrame = QImageToCvMat(img);
    

    or

    cv::Mat videoFrame = QImageToCvMat(QVideoFrameToQImage(vFrame))
    
    1 Reply Last reply
    0
    • I Ivan_Rubianes marked this topic as a regular topic on
    • I Ivan_Rubianes deleted this topic on
    • I Ivan_Rubianes restored this topic on
    • I Ivan_Rubianes marked this topic as a question on
    • I Ivan_Rubianes has marked this topic as solved on
    • I Ivan_Rubianes marked this topic as a regular topic on
    • I Ivan_Rubianes marked this topic as a question on
    • I Ivan_Rubianes has marked this topic as solved on

    • Login

    • Login or register to search.
    • First post
      Last post
    0
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Get Qt Extensions
    • Unsolved