У меня есть цикл для взятия в изображениях от высокой скорости framegrabbger на уровне 250 футов в секунду.
/** Loop processes 250 video frames per second **/
while(1){
AcquireFrame();
DoProcessing();
TakeAction();
}
В то же время я хотел бы, чтобы пользователь был в состоянии контролировать то, что продолжается. Пользователь только должен видеть изображения на уровне приблизительно 30 кадр/с (или меньше). Как я настраиваю второй поток, который отображает текущий кадр время от времени?
Thread(){
cvShowImage();
Wait(30); /** Wait for 30 ms **/
}
Я нахожусь в Windows на четырехъядерном использовании машины Intel MinGW, gcc и OpenCV 1.1. Основные критерии - то, что поток дисплея должен занять как можно меньше времени далеко от моего основного цикла обработки. Каждая миллисекунда количества.
Я попытался использовать CreateThread()
создать новый поток с cvShowImage()
и cvWaitKey()
но по-видимому те функции не ориентированы на многопотоковое исполнение.
Я рассматриваю использование OpenMP, но некоторые люди сообщают о проблемах с OpenMP и OpenCV. Я также рассматриваю попытку использовать DirectX directDraw, потому что, по-видимому, это очень быстро. но это выглядит сложным и evidentally существуют проблемы с помощью Windows DLL с MinGw.
Какой из этих проспектов был бы лучшим местом для запуска?
Хорошо. Как ни странно, мой вопрос также является ответом на него.
Использование CreateThread ()
, CvShowImage ()
и CvWaitKey ()
, как описано в моем вопросе, действительно работает - вопреки некоторым сообщениям в Интернете, которые предлагаю обратное.
В любом случае я реализовал что-то вроде этого:
/** Global Variables **/
bool DispThreadHasFinished;
bool MainThreadHasFinished;
iplImage* myImg;
/** Main Loop that loops at >100fps **/
main() {
DispThreadHasFinished = FALSE;
MainThreadHasFinished = FALSE;
CreateThread(..,..,Thread,..);
while( IsTheUserDone() ) {
myImg=AcquireFrame();
DoProcessing();
TakeAction();
}
MainThreadHasFinished = TRUE;
while ( !DisplayThreadHasFinished ) {
CvWaitKey(100);
}
return;
}
/** Thread that displays image at ~30fps **/
Thread() {
while ( !MainThreadHasFinished ) {
cvShowImage(myImg);
cvWaitKey(30);
}
DispThreadHasFinished=TRUE;
return;
}
Когда я первоначально разместил этот вопрос, мой код не работал по не связанным причинам. Надеюсь, это поможет!
Так как захват кадров не требует использования пользовательского интерфейса, я бы установил вторичную нить, чтобы обрабатывать захват кадров, и чтобы оригинальная нить, которая обрабатывает пользовательский интерфейс, отображала образцы кадров. Если бы вы попытались отобразить кадр, который в настоящее время захвачен, вам пришлось бы заблокировать данные (что, как правило, довольно медленно). Чтобы избежать этого, я бы отобразил кадр один (или, возможно, два) "позади" захватываемого в данный момент кадра, так что между захватом и отображением данных нет никакой разницы. Вам все равно придется убедиться, что инкрементирование номера текущего кадра безопасно для потока, но это довольно просто - используйте InterlockedIncrement в потоке захвата.
Мне жаль, что я не могу дать вам лучший ответ прямо сейчас, но похоже, что ваш вопрос не о структуре вашей программы, а скорее об инструменте, который вы должны использовать для реализации многопоточности. Для этого я бы рекомендовал Qt. Я использую Qt уже некоторое время, но только сейчас начинаю разбираться с многопоточностью.
Мне кажется, что лучшим вариантом для вас будет QReadWriteLock. Это позволит вам читать с изображения, но поток чтения отдаст свою блокировку, когда появится поток записи. В этом случае вы можете сохранить копию изображения, которое вы отображали последним, и отобразить его, если изображение заблокировано для записи.
Еще раз извините, что не могу быть более подробным, но, как я уже сказал, я только начинаю разбираться в этом. В принципе, я пытаюсь сделать то же самое, что и вы, но не так быстро :). Удачи!