检测未插入的捕获设备(OpenCV)

时间:2010-10-26 22:08:39

标签: c++ opencv

我正试图检测我的捕捉相机是否被拔掉。我的假设是对cvQueryFrame的调用将返回NULL,但它会继续返回最后一个有效帧。

有谁知道如何使用OpenCV检测相机插拔事件?这看起来很简陋......我错过了什么?

4 个答案:

答案 0 :(得分:6)

遗憾的是,没有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); 
}

答案 1 :(得分:5)

感谢@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所建议,除了锁定调用{​​{1}}。在我的测试中,对cvCaptureFromCAM的调用非常缓慢。我在循环结束时拨打cvReleaseCapture,因为我不想听到不断检查。

cvWaitKey

我可能最终会实现一个就绪状态标志,它可以检测相机是否重新插入。但这超出了本例的范围。希望有人觉得这很有用。再次感谢,@ karlphillip。

答案 2 :(得分:1)

这仍然是一个问题。 另一种解决方案是将返回的数据与前一个数据进行比较。对于工作相机,应始终闪烁。如果数据相同,您可以确定,凸轮已拔下。 马丁

答案 3 :(得分:0)

我认为我对此问题有一个很好的解决方法。我创建了一个带有零的辅助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;
}