Подтвердить что ты не робот

Как написать видеофайл с OpenCV?

Я пытаюсь написать программу для анализа эмоциональных выражений, таких как слезы. В качестве части моего трекера я использую OpenCV для записи примеров видео. В частности, я не уверен, как правильно выбрать FPS (похоже, что 10FPS должен работать). Я также не уверен, какой Codec, который я должен использовать на OS X, я также пробовал все возможные CV_FOURCC из здесь, но возвратил следующую ошибку:

Stream #0.0: Video: rawvideo, yuv420p, 640x480, q=2-31, 19660 kb/s, 90k tbn, 10 tbc
Assertion failed: (image->imageSize == avpicture_get_size( (PixelFormat)input_pix_fmt, image->width, image->height )), function writeFrame, file /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_graphics_opencv/work/OpenCV-2.2.0/modules/highgui/src/cap_ffmpeg.cpp, line 1085.

У вас есть рабочий код с cvWriteFrame? Спасибо, что нашли время, чтобы посмотреть на мою проблему!

Для тех, кого интересует вся программа:

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

int main (int argc, const char * argv[]) 
{
    CvCapture *capture;
    IplImage  *img;
    int       key = 0;
    CvVideoWriter *writer;

    // initialize camera
    capture = cvCaptureFromCAM( 0 );
    // capture = cvCaptureFromAVI("AVIFile");

    // always check
    assert( capture );

    // create a window
    cvNamedWindow( "video", 1 );

    int color = 1; // 0 for black and white

    // get the frame size
    CvSize size = cvSize((int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH),(int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT));

    writer = cvCreateVideoWriter(argv[1], -1 , 10 , size, color);

    while( key != 'q' ) {
        // get a frame
        img = cvQueryFrame( capture );

        // always check
        if( !img ) break;

        cvWriteFrame( writer, img );        
        cvShowImage("video", img );

        // quit if user press 'q'
        key = cvWaitKey( 5 );
    }

    // free memory
    cvReleaseVideoWriter( &writer );
    cvReleaseCapture( &capture );
    cvDestroyWindow( "video" );

    return 0;   
}
4b9b3361

Ответ 1

Посмотрите здесь для использования рекомендуемых кодеков.

В принципе:

  • Вы можете использовать -1 вместо CV_FOURCC(...) , только если вы находитесь в Windows (см. руководство ). Поскольку вы находитесь на OSX, , вы не можете его использовать.
  • Используйте CV_FOURCC('I', 'Y', 'U', 'V') для кодирования с помощью yuv420p в несжатый контейнер AVI - это рекомендуемый подход
  • Если вам требуется сжатое видео, вы можете использовать такие инструменты, как ffmpeg, для сжатия вывода AVI с помощью OpenCV

Причина, по которой OpenCV не рекомендует использовать компрессионные кодеки, вероятно, потому, что каждый кодек имеет большое количество специфичных для кодека опций, и все их проблемы через простой интерфейс записи видео с OpenCV были бы невозможны.

ИЗМЕНИТЬ

У меня есть плохие новости:

К сожалению, у нас по-прежнему нет рабочего (то есть собственного) видеоредактора для Mac OS X. Если вам нужна видеозапись, в настоящее время вы должны настроить ffmpeg или xine и отключить QuickTime.

Похоже, вам может понадобиться перенастроить и перекомпилировать вашу библиотеку.

РЕДАКТИРОВАТЬ 2

В качестве альтернативы вы можете просто записать каждый кадр в файл JPEG, а затем сшить эти файлы JPEG в фильм, используя ffmpeg (который должен работать на OS/X). В любом случае, это MJPEG. Вероятно, вы получите лучшие коэффициенты сжатия с кодеками, которые используют временную избыточность (например, MPEG4, H.264 и т.д.).

Ответ 2

Утверждение предполагает, что существует несоответствие размера между изображением, отправляемым видеовидео, и размером, указанным при инициализации видеопиксера. Я бы предложил добавить некоторые операторы отладки следующим образом:

cout << "Video Size: " << size.width << "," << size.height << endl;
cout << "Image Size: " << img.cols << "," << img.rows << endl;

Это поможет вам узнать, отличаются ли размеры.

Что касается вопроса с четырьмя вопросами, похоже, вы используете cap_ffmpeg вместо cap_qtkit. Возможно, вы захотите попробовать перекомпилировать с помощью ffmpeg, так как версия захвата qtkit довольно хорошо работает на OS X. Вместо того, чтобы использовать macports, вы можете напрямую загрузить opencv2.2 из sourceforge и использовать ccmake для настройки opencv, чтобы не использовать ffmpeg, в этом case qtkit будет по умолчанию.

Если вы используете qtkit, тогда вам нужно использовать четыре точки ( "j", "p", "e", "g" );

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

Вот пример, основанный на файле starter_video.cpp, который будет работать с qtkit:

/*
* starter_video_write.cpp
*
*  Created on: Nov 23, 2010
*      Author: Ethan Rublee
*  Modified on: Aug 3, 2011 by David Cooper
*
* A starter sample for using opencv, get a video stream and display the images
* easy as CV_PI right?
* edited to add writing capability for OS X using qtkit.
*/
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <vector>
#include <stdio.h>

using namespace cv;
using namespace std;



//hide the local functions in an anon namespace
namespace {
    void help(char** av) {
        cout << "\nThis program justs gets you started reading images from video\n"
            "Usage:\n./" << av[0] << " <video device number>\n"
            << "q,Q,esc -- quit\n"
            << "space   -- save frame\n\n"
            << "\tThis is a starter sample, to get you up and going in a copy pasta fashion\n"
            << "\tThe program captures frames from a camera connected to your computer.\n"
            << "\tTo find the video device number, try ls /dev/video* \n"
            << "\tYou may also pass a video file, like my_vide.avi instead of a device number"
            << endl;
    }

    int process(VideoCapture& capture) {
        int n = 0;
        char filename[200];
        string window_name = "video | q or esc to quit";
        cout << "press space to save a picture. q or esc to quit" << endl;
        namedWindow(window_name, CV_WINDOW_KEEPRATIO); //resizable window;
        Mat frame;
    double frameRate = 15.0;
    capture >> frame;
    VideoWriter* writer = NULL;
    // FIXME: need to change this to an absolute path that exists on this system
    string outputFile = "/tmp/test.mov";
    writer = new VideoWriter(outputFile,
                 CV_FOURCC('j','p','e','g'),
                 frameRate,Size(frame.cols,frame.rows));


        for (;;) {
            capture >> frame;
            if (frame.empty())
                continue;
            imshow(window_name, frame);
        writer->write(frame);
            char key = (char)waitKey(5); //delay N millis, usually long enough to display and capture input
            switch (key) {
        case 'q':
        case 'Q':
        case 27: //escape key
          if(writer != NULL) {
        delete writer;
          }
          return 0;
        case ' ': //Save an image
          sprintf(filename,"filename%.3d.jpg",n++);
          imwrite(filename,frame);
          cout << "Saved " << filename << endl;
          break;
        default:
          break;
            }
        }
        return 0;
    }

}

int main(int ac, char** av) {

    if (ac != 2) {
        help(av);
        return 1;
    }
    std::string arg = av[1];
    VideoCapture capture(arg); //try to open string, this will attempt to open it as a video file
    if (!capture.isOpened()) //if this fails, try to open as a video camera, through the use of an integer param
        capture.open(atoi(arg.c_str()));
    if (!capture.isOpened()) {
        cerr << "Failed to open a video device or video file!\n" << endl;
        help(av);
        return 1;
    }
    return process(capture);
}

Ответ 3

У меня была та же проблема. Я решил это, используя Planar RGB Codec.

outputVideo.open(PathName, CV_FOURCC('8','B','P','S'), myvideo.get(CV_CAP_PROP_FPS),CvSize(outputframe.size()));

Размер вывода важен, но он работает без установки.

Ответ 4

Я думаю, что строка CV_FOURCC может быть неправильной. A аналогичный вопрос предлагает использовать -1 в качестве значения теста CV_FOURCC для запроса рабочих параметров в вашей системе.

Можете ли вы попытаться скомпилировать программу из этого вопроса и сказать нам, что если значение -1 вместо V_FOURCC('M', 'J', 'P', 'G') записывает файл AVI?

Ответ 5

Я думаю, что из-за размера видео - попробуйте другие, более распространенные, например 640X480 или 320X240.

Это работает для меня.

Ответ 6

Прочитав ответ Миши. Я решил эту проблему в Mac OS 10.9 Mavericks и XCode 5, переустановив opencv с помощью Homebrew.

brew установить opencv --with-ffmpeg