Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting an unplugged capture device (OpenCV)

Tags:

c++

opencv

I'm attempting to detect if my capture camera gets unplugged. My assumption was that a call to cvQueryFrame would return NULL, however it continues to return the last valid frame.

Does anyone know of how to detect camera plug/unplug events with OpenCV? This seems so rudimentary...what am I missing?

like image 869
Courtney Christensen Avatar asked Oct 26 '10 22:10

Courtney Christensen


3 Answers

There is no API function to do that, unfortunately.

However, my suggestion is that you create another thread that simply calls cvCaptureFromCAM() and check it's result (inside a loop). If the camera get's disconnected then it should return NULL.

I'll paste some code just to illustrate my idea:

// 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); 
}
like image 123
karlphillip Avatar answered Oct 18 '22 19:10

karlphillip


Thanks @karlphillip for pointing me in the right direction. Running calls to cvCaptureFromCAM in a separate thread works. When the camera gets unplugged, the return value is NULL.

However, it appears that this function is not thread-safe. But a simple mutex to lock simultaneous calls to cvCaptureFromCAM seems to do the trick. I used boost::thread, for this example, but one could tweak this easily.

At global scope:

// 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;

Entry point goes something like this:

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;
}

The work thread is simple. The only caveat is that you need to lock the mutex so you don't get simultaneous calls to 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);
}

And finally, the capture monitoring thread, as suggested by @karlphillip, except with a locked call to cvCaptureFromCAM. In my tests, the calls to cvReleaseCapture were quite slow. I put a call to cvWaitKey at the end of the loop because I don't want the overheard of constantly checking.

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);
}

I will probably end up implementing a ready-state flag which will be able to detect if the camera gets plugged back in. But that's out of the scope of this example. Hope someone finds this useful. Thanks again, @karlphillip.

like image 29
Courtney Christensen Avatar answered Oct 18 '22 21:10

Courtney Christensen


This still seems to be an issue. Another solution would be to compare the returned data with the previous one. For a working camera there should always be flickering. if the data is identical you can be sure, the cam was unplugged. Martin

like image 1
matlantis Avatar answered Oct 18 '22 19:10

matlantis