Воспроизведение видео в QTCreator GUI - PullRequest
2 голосов
/ 07 декабря 2011

В настоящее время я использую QTCreator версии 4.7.4 для написания приложения с графическим интерфейсом, которое воспроизводит AVI-файлы внутри приложения.

Я делаю это, устанавливая каждый кадр как QPixmap внутри QLabel.

         video.load("lk",video.EXT_AVI);
         if(video.hasLoaded()){
              while(!video.hasFinished()){
                  frame = video.getCurrentFrame();
                  cv::cvtColor(frame, frame, CV_BGR2RGB);
                  QImage myImage = QImage( (const unsigned char*) (frame.data),frame.cols, frame.rows, frame.step1(),QImage::Format_RGB888 );
                  ui->displayLabel->setPixmap((QPixmap::fromImage(myImage)));
                  video.nextFrame();
    }
}

Поскольку я использую класс VideoCapture из API opencv для получения каждого кадра, кадры первоначально извлекаются как объекты CV :: MAT, поэтому я преобразую их в QImages.

Я могу нормально воспроизводить файлы, если использую функции CV :: imshow () из opencv API в простой консольной программе, но когда я запускаю приведенный выше код в цикле, моя программа по существу происходит сбой до последнего кадра, где он затем возвращается в стабильное состояние, показывая самый последний кадр.

Я довольно новичок в C ++, но имею хороший опыт работы с Java, поэтому мое первоначальное предположение для этой проблемы будет состоять в том, что все делается в потоке событий и, следовательно, занимает все ресурсы, вызывая остановку приложения отвечая на некоторое время.

Любая помощь будет оценена.

Примечание: video - это мой собственный класс, который инкапсулирует класс VideoCapture из API opencv.

1 Ответ

5 голосов
/ 08 декабря 2011

Короче говоря:

Ваш код не обновляет пользовательский интерфейс во время воспроизведения видео, поэтому программа работает.

Подробно

Основная проблема в том, что Qt не обновляет пользовательский интерфейс сразу после того, как вы внесете какие-либо изменения состояний виджета в код. Qt использует events для обновления виджетов. И вся обработка событий в общем случае выполняется в одном потоке. Ваш код также является обработчиком событий (вероятно, это обработчик события нажатия кнопки). Ваш код изменяет состояния виджетов внутри цикла, но только изменения будут отображаться после обработки событиями виджетов. Но виджеты могут обрабатывать события только после обработки текущего события, то есть вашего кода. Итак, ваш код действительно блокирует обработку, пока она не закончится. И когда это закончено, вы видите последний кадр.

Что делать

Вы не можете использовать цикл здесь (хорошо, вы действительно можете, но не обязательно) Вы должны создать функцию, которая показывает один кадр и затем завершает, чтобы позволить Qt обрабатывать события. И Qt должен вызывать эту функцию с некоторым фиксированным интервалом времени, который определяется по частоте кадров. Лучший способ заставить Qt вызывать какую-либо функцию с указанным интервалом времени - это использовать timer .

Итак, чтобы начать воспроизведение, вы должны инициализировать video stream и запустить таймер. После показа последнего кадра следует остановить таймер.

...