Чтение видео с openCV


У меня есть видео движок2.avi , который я хочу прочитать и показать с помощью openCV. Вот мой код:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace cv;

int main(int argc, char** argv)
{
    string filename = "D:\BMDvideos\engine2.avi";
    VideoCapture capture(filename);
    Mat frame;

    if( !capture.isOpened() )
        throw "Error when reading steam_avi";

    namedWindow("w", 1);
    for( ; ; )
    {
        capture >> frame;
        //if(!frame)
        //    break;
        imshow("w", frame);
        waitKey(20); // waits to display frame
    }
    waitKey(0);
}
Этот код не работает, если в моем файле есть кодек YUV 4:2:2 (UYVY) (я записал видео с помощью Direct-Show), но работает, когда я использую видео, которое я захватил с помощью openCV!! Есть ли у кого-нибудь идеи, как это может работать ?

Обновление:

После прочтения некоторых ссылок, предполагающих, что перехват исключения решит проблему, я изменил свой код. Это не помогло, но вот модифицированный код:
cv::VideoCapture cap("d:\BMDvideos\engine2.avi");
cv::Mat frame;

try
{
    cap >> frame;
}
catch(cv::Exception ex)
{
    std::cout << ex.what() << std::endl;
}
catch(...)
{
    std::cout << "Unknown exception" << std::endl;  
}

Программа завершает работу в cap>>frame. Я читал подобные вопросы, но они используют кадр в YUV (4:2:0), в то время как мое видео имеет UYVY (4:2:2). Как я могу преобразовать это в цветовую модель RGB?

Обновление 2:

После предложения карлфиллипа я использовал OpenCV2. 4. 3, но я все равно получил ту же ошибку, используя код ниже:

#include <opencv2corecore.hpp>
#include <opencv2highguihighgui.hpp>
#include <opencv2opencv.hpp>
using namespace cv;
using namespace std;

int main(){
    cv::Mat frame;
    cv::VideoCapture cap("d:\BMDvideos\B\Aufnahme.avi");
    if(!cap.isOpened())
    {
        cout << "Error can't find the file"<<endl;
    }

    while(1){
        if(!cap.read(frame))
            imshow("",frame);

        cv::waitKey(33);
    }
    return 0;
}
3 6

3 ответа:

Вот несколько ссылок, которые могут вам помочь:

Edit:

Сначала я должен кое-что прояснить: OpenCV способен считывать кадры YUV из видеофайла, потому что это базовая библиотека (FFmpeg/GStreamer), которая выполняет эту работу. OpenCV также поддерживает преобразование между определенным типом YUV и RGB через cvCvtColor() с CV_YCrCb2RGB или CV_RGBYCrCb.

Изучив ваш вопрос еще раз, я заметил, что вы не указали вид ошибки, которая произошла. Вы могли бы сделать лучшую работу в , имея дело С возможным сбой из интерфейса захвата путем печати сообщения на экран вместо throw его ввода.

Я протестировал видео файл, которым вы поделились, и у меня не было проблем с воспроизведением его в окне используя следующий код:

#include <cv.h>
#include <highgui.h>

#include <iostream>

int main(int argc, char* argv[])
{
    cv::VideoCapture cap(argv[1]);
    if (!cap.isOpened())
    {
        std::cout << "!!! Failed to open file: " << argv[1] << std::endl;
        return -1;
    }

    cv::Mat frame;
    for(;;)
    {

        if (!cap.read(frame))             
            break;

        cv::imshow("window", frame);

        char key = cvWaitKey(10);
        if (key == 27) // ESC
            break;
    }

    return 0;
}

Если по какой-либо причине интерфейс capture не сможет открыть файл, он немедленно завершит работу приложения, вместо того чтобы продолжить работу, чтобы просто завершить работу в cap.read(frame).

Если вы просто ищете для отображения видео, Вот код, который работал для меня, Пожалуйста, проверьте, если это поможет вам в любом случае.

#include <stdio.h>
#include <opencv2/opencv.hpp>
int main(){
CvCapture *camera=cvCaptureFromFile("C:\\test.avi");
if (camera==NULL)
    printf("camera is null\n");
else
    printf("camera is not null");

cvNamedWindow("img");
while (cvWaitKey(10)!=atoi("q")){
    double t1=(double)cvGetTickCount();
    IplImage *img=cvQueryFrame(camera);
    /*if(img){
        cvSaveImage("C:/opencv.jpg",img);
    }*/
    double t2=(double)cvGetTickCount();
    printf("time: %gms  fps: %.2g\n",(t2-t1)/(cvGetTickFrequency()*1000.), 1000./((t2-t1)/(cvGetTickFrequency()*1000.)));
    cvShowImage("img",img);
}
cvReleaseCapture(&camera);
}

Надеюсь, это поможет вам.

Я понял, что объект VideoCapture нуждается в opencv_ffmpeg310_64.файл DLL. После того как вы скопировать эту DLL в свой двоичный папку ваш объект захватить видео должны быть в состоянии читать видео файлы.