2013-06-13 6 views
3

Я пытаюсь записать видео с веб-камеры 1080p в файл. Я держал таймер в видео, и в каждом испытании отметка времени, сообщенная видеоплеером (VLC - это то, что я использовал) не синхронизируется с временем в видео. Это всегда от нескольких секунд (обычно таймер в видео быстрее, чем время, указанное игроком).OpenCV VideoWriter Framerate Issue

Как показано ниже, я настраиваю программу на C++ для захвата видео в одном потоке и записи в другой поток. Это нормально работает, так как мой процессор составляет ~ 200% (возможно, max out?). Я нахожусь в Macbook Air с OS X 10.8 и 1.8 ГГц Intel Core i7.

Я попытался изменить частоту кадров до 15 кадров в секунду, что приводит к очень прерывистому/медленному видео. Я также попытался установить CV_CAP_PROP_FRAME_WIDTH & CV_CAP_PROP_FRAME_HEIGHT на более низкое разрешение, и это приводит к медленному видео. Похоже, что 1080p @ 30fps приводит к хорошему устойчивому видео, но он все равно всегда играет быстрее, чем предполагалось. Я также попытался ввести waitKey(10); после record << frame;, но это ни на что не повлияло.

Любые рекомендации о том, как сделать видеоролик своевременным?

Спасибо! Aakash

#include "opencv/cv.h" 
#include "opencv/highgui.h" 
#include <boost/thread.hpp> 

using namespace cv; 

void captureFunc(Mat *frame, VideoCapture *capture){ 
    for(;;){ 
     // get a new frame from camera 
     (*capture) >> (*frame); 
    } 
} 

int main(int, char**) 
{ 
    VideoCapture capture(0); // open the default camera 
    if(!capture.isOpened()) { 
     printf("Camera failed to open!\n"); 
     return -1; 
    } 

    capture.set(CV_CAP_PROP_FPS,30); //set capture rate to 30fps 
    Mat frame; 
    capture >> frame; // get first frame for size 

    // initialize recording of video 
    VideoWriter record("test.avi", CV_FOURCC('D','I','V','X'), 30, frame.size(), true); 
    if(!record.isOpened()) { 
     printf("VideoWriter failed to open!\n"); 
     return -1; 
    } 

    boost::thread captureThread(captureFunc, &frame, &capture); //start capture thread 

    sleep(1); //just to make sure capture thread is ready 

    for(;;) 
    { 
     // add frame to recorded video 
     record << frame; 
    } 

    return 0; 
} 
+0

Попробуйте использовать различные кодеки и с различными fps (25 может быть хорошим вариантом). – cyriel

+0

Я пробовал 25 FPS и использовал XVID в качестве кодека. Для видеороликов около 1,5 минут он отлично работает (некоторые части на несколько секунд быстрее, а другие замедляются, поэтому они усредняют), но в любом случае, чем короче или длиннее VLC будет воспроизводить видео на 3-6 секунд дольше, чем на самом деле (например, таймер в видео показываются 5 минут, но VLC будет играть в течение 5 минут и 6 секунд). –

+0

В моей тестовой записи 5-минутного видео время синхронизировалось до примерно 3 минут и 10 секунд. Впоследствии промежуток времени увеличивался до 6 секунд, заканчиваясь примерно на 5 секунд после синхронизации. –

ответ

7

я решил мою проблему после того, как немного отладки; это была проблема с тем, что VideoWriter был придирчив к скорости, с которой к ним были добавлены фреймы.

+1

+1 для ответа на свой вопрос; помогая остальным из нас. – RyanfaeScotland

+0

+1 снова для ответа на вопрос. Но я заметил, что у вас может быть состояние гонки на вашем решении, так как поток, связанный с камерой, может обновить кадр «Mat» одновременно, когда VideoWriter обращается к нему. – Alex

+2

Запись замечательная, но было бы лучше, если бы вы могли написать ее здесь и просто дать ссылку на свой сайт. Если у вас есть изменение URL-адреса, информация теряется! –

1

Вам необходимо синхронизировать свои функции чтения и записи. Ваш код читается как можно быстрее и записывается также как можно быстрее. Ваше выходное видео, вероятно, выглядит медленным, потому что запись вывода происходит быстрее, чем чтение ввода (поскольку capture >> ждет вашу камеру), и записывается несколько одинаковых кадров.

Запись без ожидания или синхронизации означает, что вы можете написать один и тот же контент несколько раз (что, я думаю, здесь происходит), или потерять кадры.

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

Так же, чтобы избежать потери кадров или записи поврежденных кадров, вам необходимо прочитать процесс, чтобы дождаться, когда будет выполнена запись, чтобы можно было перезаписать frame.

Поскольку нитки в любом случае должны ждать друг друга, в потоках вообще нет точки.

Я предпочел бы рекомендовать это гораздо более простой способ:

for (;;) { 
    capture >> frame; 
    process(frame); // whatever smart you need 
    record << frame; 
} 

Если вам нужен параллелизм, вам потребуется гораздо более сложный механизм синхронизации, и, возможно, какое-то ФИФО для ваших кадров.

+1

Это правильный ответ. Как писал Готье, в коде нет механизма показанный для обеспечения наличия одной и только одной записи на чтение, чтобы каждый кадр i записывался непредсказуемым числом раз. – GroovyDotCom

Смежные вопросы