我正试图检测我的捕捉相机是否被拔掉。我的假设是对cvQueryFrame
的调用将返回NULL
,但它会继续返回最后一个有效帧。
有谁知道如何使用OpenCV检测相机插拔事件?这看起来很简陋......我错过了什么?
答案 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;
}