Disconnect Capture Device Discovery (OpenCV)

I am trying to determine if my capture camera is disabled. My guess was that a call to cvQueryFrame would return NULL , however, it continues to return the last valid frame.

Does anyone know how to detect camera connections / disable OpenCV events? It seems so rudimentary ... what am I missing?

+7
c ++ opencv
source share
4 answers

Unfortunately, there is no API function for this.

However, my suggestion is that you create another thread that just calls cvCaptureFromCAM () and checks its result (inside the loop). If the camera is disabled, it should return NULL.

I will insert the code 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); } 
+6
source share

Thanks @karlphillip for pointing me in the right direction. cvCaptureFromCAM calls are cvCaptureFromCAM in a separate thread. When the camera turns off, the return value is NULL .

However, this feature does not seem to be thread safe. But a simple mutex to block concurrent calls to cvCaptureFromCAM seems to do the trick. I used boost::thread for this example, but you could easily configure it.

On a global scale:

 // 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 sake bool done = false; 

The entry point looks 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; } 

Workflow is simple. The only caveat is that you need to block mutexes so that you do not receive concurrent 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 flow suggested by @karlphillip, with the exception of a blocked call to cvCaptureFromCAM . In my tests, calls to cvReleaseCapture were pretty slow. I put the cvWaitKey call at the end of the loop because I don't want to eavesdrop on the constant check.

 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 that can detect if the camera is connected again. But this is beyond the scope of this example. Hope someone finds this helpful. Thanks again @karlphillip.

+5
source share

This still seems to be a problem. Another solution would be to compare the returned data with the previous one. For the working chamber should always flicker. if the data is identical, you can be sure that the cam has been disconnected. Martin

+1
source share

I think I have a good way around the problem. I am creating an auxiliary Mat matrix with zeros with the same resolution as the camera output. I assign it to the Mat array, which is immediately assigned a frame taken from the camera, and in the end I check the norm of this array. If it is equal to zero, this means that the new frame was not taken from the camera.

 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; } 
0
source share

All Articles