Показать изображение во второй теме, OpenCV? - PullRequest
13 голосов
/ 12 января 2010

У меня есть цикл для получения изображений с высокоскоростного фрейм-граббера со скоростью 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, потому что, по-видимому, это очень быстро. но выглядит сложным и, очевидно, существуют проблемы с использованием Windows DLL с MinGw .

С какого из этих направлений лучше всего начать?

Ответы [ 4 ]

10 голосов
/ 23 февраля 2010

Хорошо. Так что смущающе, мой вопрос также является его собственным ответом.

Использование 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;
}

Когда я первоначально разместил этот вопрос, мой код не работал по несвязанным причинам. Надеюсь, это поможет!

4 голосов
/ 12 января 2010

Поскольку при захвате кадров не нужно использовать пользовательский интерфейс, я бы настроил дополнительный поток для обработки захвата кадров, а исходный поток, который обрабатывает пользовательский интерфейс, отображает примеры кадров. Если вы попытаетесь отобразить кадр, который в настоящее время захватывается, вам придется заблокировать данные (что обычно довольно медленно). Чтобы избежать этого, я бы отображал кадр один (или, возможно, два) «позади» того, который в настоящее время захватывается, так что нет никакого противоречия между захватом и отображением данных. Вам все равно придется убедиться, что увеличение текущего номера кадра является поточно-ориентированным, но это довольно просто - используйте InterlockedIncrement в потоке захвата.

0 голосов
/ 13 июня 2011

Я не уверен, почему это происходит, но я добавил cvWaitKey после каждого cvShowImage, и картинка отображалась правильно.

cvShowImage(myImage);
cvWaitKey(1);
0 голосов
/ 22 февраля 2010

Извините, я не могу дать вам лучший ответ прямо сейчас, но, похоже, ваш вопрос не о структуре вашей программы, а скорее об инструменте, который вы должны использовать для реализации многопоточности. Для этого я бы порекомендовал Qt . Некоторое время я использовал Qt, но сейчас только начинаю многопоточность.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...