我有一个循环从250fps的高速framegrabbger中获取图像。
/** Loop processes 250 video frames per second **/
while(1){
AcquireFrame();
DoProcessing();
TakeAction();
}
与此同时,我希望用户能够监控正在发生的事情。用户只需要以大约30 fps(或更低)的速度查看图像。如何设置第二个线程,每隔一段时间显示当前帧?
Thread(){
cvShowImage();
Wait(30); /** Wait for 30 ms **/
}
我在使用MinGW,gcc和OpenCV 1.1的四核Intel机器的Windows上。主要标准是显示线程必须尽可能少地离开主处理循环。每毫秒都很重要。
我尝试使用CreateThread()
创建一个包含cvShowImage()
和cvWaitKey()
但apparently those functions are not threadsafe的新主题。
我正在考虑使用OpenMP,但有些人report problems with OpenMP and OpenCV。我也正在考虑尝试使用DirectX directDraw,因为它显然非常快。但它looks complicated,显然有problems using Windows DLL's with MinGw。
这些途径中哪一个是最好的起点?
答案 0 :(得分:10)
确定。令人尴尬的是,我的问题也是它自己的答案。
使用我的问题中描述的CreateThread()
,CvShowImage()
和CvWaitKey()
实际上是有效的 - 与网络上的一些帖子相反,这些信息表明不然。
无论如何,我实施了这样的事情:
/** Global Variables **/
bool DispThreadHasFinished;
bool MainThreadHasFinished;
iplImage* myImg;
/** Main Loop that loops at >100fps **/
main() {
DispThreadHasFinished = FALSE;
MainThreadHasFinished = FALSE;
CreateThread(..,..,Thread,..);
while( IsTheUserDone() ) {
myImg=AcquireFrame();
DoProcessing();
TakeAction();
}
MainThreadHasFinished = TRUE;
while ( !DisplayThreadHasFinished ) {
CvWaitKey(100);
}
return;
}
/** Thread that displays image at ~30fps **/
Thread() {
while ( !MainThreadHasFinished ) {
cvShowImage(myImg);
cvWaitKey(30);
}
DispThreadHasFinished=TRUE;
return;
}
当我最初发布此问题时,我的代码因无关原因而失败。我希望这有帮助!
答案 1 :(得分:4)
由于帧抓取不需要使用UI,我设置了一个辅助线程来处理帧抓取,并让处理UI的原始线程显示示例帧。如果您尝试显示当前被抓取的帧,则必须锁定数据(通常相当慢)。为了避免这种情况,我会在当前被抓取的框架后面显示一个(或可能两个)框架,因此抓取和显示数据之间没有争用。您仍然必须确保递增当前帧编号是线程安全的,但这很简单 - 在捕获线程中使用InterlockedIncrement。
答案 2 :(得分:0)
对不起,我现在无法给你一个更好的答案,但似乎你的问题不是你的程序结构,而是你应该用来实现多线程的工具。为此我建议Qt。我已经使用Qt了一段时间,但我刚刚进入多线程。
在我看来,你最好的选择可能是QReadWriteLock。这允许您从图像中读取,但读取器线程将在编写器线程出现时放弃锁定。在这种情况下,您可以保留上次显示的图像的副本,并在图像被锁定以进行写入时显示。
再次抱歉,我不能更详细,但就像我说的那样,我也只是进入了这个。我基本上试图做同样的事情,但不是那么快:)。祝你好运!
答案 3 :(得分:0)
我不确定为什么会这样,但我在每个cvShowImage之后添加了一个cvWaitKey并且图片显示正确。
cvShowImage(myImage);
cvWaitKey(1);