用OpenCV和OpenGL读取MP4

41zrol4v  于 2022-09-26  发布在  其他
关注(0)|答案(1)|浏览(224)

我在一个C++/OpenGL交互应用程序中工作,我决定使用OpenCV来阅读视频,这样我就可以将它们作为纹理从主机传输到GPU中。到目前为止,我成功地使用了像网络摄像头一样持久的输入,但我在处理MP4文件方面遇到了麻烦,因为它们的持续时间不是永久的。我不知道该怎么处理。我在Main的渲染循环中获取帧,所以如果我决定在视频流传输结束时停止迭代,我的应用程序将关闭,我不希望发生这种情况,我猜肯定有解决方法,比如循环视频(我尝试了检查Frao.Empty(),然后重载VideoCapture或重置视频帧,但在cv::cvtColor中只得到了(!_src.Empty(),我认为另一个解决方案是在渲染循环之前执行另一个循环来进行解码,但这不是我使用以下代码的最具性能的决策:

// Import openCV.

# include <opencv2/core/core.hpp>

# include <opencv2/videoio.hpp>

# include <opencv2/imgproc/imgproc.hpp>

# include <opencv2/highgui.hpp>

using namespace cv;

// Open the MP4 and its attributes.
std::string videoName = "D:\SomeVideo\Video.mp4";

    VideoCapture cap( videoName  );
    if( !cap.isOpened() )
    {

        std::cout << "Video file not loaded!" << std::endl;
        return -1;

    }

Mat frame;
cap >> frame;
int videoWidth = frame.rows;
int videoHeight = frame.cols;
unsigned char* image = cvMat2TexInput( frame );

// We create the texture that will store our video.
unsigned int video;
glGenTextures( 1, &video );
glBindtexture( GL_TEXTURE_2D, video );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

// Render Loop.
while( !glfwWindowShouldClose( window ) )
{

    glfwGetFramebufferSize( window, &WIDTH, &HEIGHT );

    // We set our video.
    try
    {

        cap >> frame;

        if( frame.empty() )
        {

            break;

        }

        else
        {

            image = cvMat2TexInput( frame );

        }

    }

    catch( Exception& e )
    {

        std::cout << e.msg << std::endl;

    }

    if( image )
    {

        glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, videoWidth, videoHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image );

    }

    else
    {

        std::cout << "Failed to load video texture." << std::endl;

    }

    // Input.
    processInput( window );

    // Go on until I bind it to my program, here:
    glActiveTexture( GL_TEXTURE0 );
    glBindTexture( GL_TEXTURE_2D, video );

    // Finish all the boilerplate...

下面是我的实用函数,用于将cvMat链接到OpenGL的无符号字符*:

// Utility function to link OpenCV.
unsigned char* cvMat2TexInput( Mat& img )
{

    cvtColor( img, img, COLOR_BGR2RGB );
    transpose( img, img );
    flip( img, img, 1 );
    flip( img, img, 0 );
    return img.data;

}
f0brbegy

f0brbegy1#

您可以使用以下命令重置下一步要读取的帧索引:

cap.set(cv::CAP_PROP_POS_FRAMES, 0);

(来自下面链接的文档):CAP_PROP_POS_FRAMES:接下来要解码/捕获的帧的基于0的索引

这样做一次

frame.empty()

返回true应该就足够了。

Cv::VideoCapture.set()和cv::VideoCaptureProperties标志的文档

相关问题