Обнаружение отключенного устройства захвата (OpenCV) - PullRequest
7 голосов
/ 27 октября 2010

Я пытаюсь определить, не отключена ли моя камера захвата.Я предполагал, что вызов cvQueryFrame вернет NULL, однако он продолжает возвращать последний действительный кадр.

Кто-нибудь знает, как обнаруживать события подключения / отключения камеры с помощью OpenCV?Это кажется таким рудиментарным ... что мне не хватает?

Ответы [ 4 ]

6 голосов
/ 27 октября 2010

К сожалению, API-функции для этого не существует.

Однако я предлагаю вам создать другой поток , который просто вызывает cvCaptureFromCAM () и проверяет его результат (внутри цикла). Если камера отключена, она должна вернуть NULL.

Я вставлю код, чтобы проиллюстрировать мою идею:

// This code should be executed on another thread!
while (1)
{
  CvCapture* capture = NULL;
  capture = cvCaptureFromCAM(-1); // or whatever parameter you are already using
  if (!capture)
  {
    std::cout << "!!! Camera got disconnected !!!!" << std::endl;
    break;
  }

  // I'm not sure if releasing it will have any affect on the other thread
  cvReleaseCapture(&capture); 
}
5 голосов
/ 28 октября 2010

Спасибо @karlphillip за то, что указал мне правильное направление. Выполнение звонков на cvCaptureFromCAM в отдельном потоке работает. Когда камера отключается, возвращаемое значение равно NULL.

Однако, похоже, что эта функция не является поточно-ориентированной. Но простой мьютекс для блокировки одновременных вызовов на cvCaptureFromCAM, кажется, делает свое дело. Я использовал boost::thread, для этого примера, но можно легко настроить это.

В глобальном масштабе:

// Create a mutex used to prevent simultaneous calls to cvCaptureFromCAM
boost::shared_mutex mtxCapture;

// Flag to notify when we're done.
// NOTE: not bothering w/mutex for this example for simplicity's sake
bool done = false;

Точка входа выглядит примерно так:

int main()
{
  // Create the work and the capture monitoring threads
  boost::thread workThread(&Work);
  boost::thread camMonitorThread(&CamMonitor);

  while (! done)
  {
    // Do whatever
  }

  // Wait for threads to close themselves
  workThread.join();
  camMonitorThread.join();

  return 0;
}

Рабочий поток прост. Единственное предостережение в том, что вам нужно заблокировать мьютекс, чтобы вы не получали одновременные звонки на cvCaptureFromCAM.

// Work Thread
void Work()
{
  Capture * capture = NULL;

  mtxCapture.lock();              // Lock calls to cvCaptureFromCAM   
  capture = cvCaptureFromCAM(-1); // Get the capture object
  mtxCapture.unlock();            // Release lock on calls to cvCaptureFromCAM

  //TODO: check capture != NULL...
  while (! done)
  {
    // Do work
  }

  // Release capture
  cvReleaseCapture(&capture);
}

И, наконец, поток мониторинга захвата, предложенный @karlphillip, за исключением заблокированного вызова cvCaptureFromCAM. В моих тестах звонки на cvReleaseCapture были довольно медленными. Я положил вызов cvWaitKey в конце цикла, потому что не хочу, чтобы его постоянно слышали.

void CamMonitor()
{
  while (! done)
  {
    CvCapture * capture = NULL;

    mtxCapture.lock();              // Lock calls to cvCaptureFromCAM   
    capture = cvCaptureFromCAM(-1); // Get the capture object
    mtxCapture.unlock();           // Release lock on calls to cvCaptureFromCAM

    if (capture == NULL)
        done = true;                // NOTE: not a thread-safe write...
    else
        cvReleaseCapture(&capture);

    // Wait a while, we don't need to be constantly checking.
    cvWaitKey(2500);
}

Я, вероятно, в конечном итоге реализую флаг готовности, который сможет определить, не подключена ли камера обратно. Но это выходит за рамки этого примера. Надеюсь, кто-то найдет это полезным. Еще раз спасибо, @ karlphillip.

1 голос
/ 24 сентября 2015

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

0 голосов
/ 16 марта 2016

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

VideoCapture cap(0);
if(!cap.isOpened()) return -1;

Mat frame;
cap >> frame;
Mat emptyFrame = Mat::zeros(CV_CAP_PROP_FRAME_WIDTH,     , CV_32F);

for(;;)
{
   frame = emptyFrame;
   cap >> frame;
   if (norm(frame) == 0) break;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...