cvWaitKey()显着减慢捕获过程 - 解决方法?

时间:2013-09-09 15:00:52

标签: c++ opencv computer-vision

我正在将PS3 Eye Camera Video捕捉到我调整大小和显示以及将它们保存到磁盘的图像。我遇到了帧速率问题所以我用每个单独的过程测量时间。事实证明,真正减慢捕获速度的唯一过程是cvWaitKey(1),它为每个捕获循环增加了大约20毫秒。

是否有以某种方式避免cvWaitKey()的解决方法?

在没有等待键和显示器的情况下测量的时间约为20ms,显示时间为60ms(需要等待键)。调整大小不会增加这么长的时间。

感谢您的帮助。

// image capturing loop
    while(_running)
    {
        //activate cvWaitKey - this drops framerate significantly!
        cvWaitKey(1);

        //get frame from capture and put into buffer
        CLEyeCameraGetFrame(_cam, pCapBuffer);

        //get system timestamps 
        GetSystemTime(&st);
        GetLocalTime(&lt);

        // Resize image to fit screen size
        cvResize(pCapImage,resizedpCapImage,CV_INTER_NN);

        //display image
        cvShowImage(_windowName, resizedpCapImage);

        //clear string
        sstm.str(std::string());

        //complete filname      
        sstm << _folder << prefix << _participant << std::setfill('0') << std::setw(10) << i  << "-" << st.wHour << st.wMinute << st.wSecond <<  st.wMilliseconds << suffix;
        image_name = sstm.str();
        c = image_name.c_str();


        //log if enabled
        if (_logging){
            //try to save image
            try {
                cvSaveImage(c, pCapImage); //bmp = speed!
            }
            catch (runtime_error& ex) {
                fprintf(stderr, "Exception converting image to bmp format: %s\n", ex.what());
            }
        }
    }

2 个答案:

答案 0 :(得分:0)

首先,不建议抓取一个帧并立即将其写入磁盘,因为它是一个系统调用,因此所用的时间是不可预测的。对于短视频,您可以将整组未压缩帧存储在内存中。如果这不起作用,则需要两个线程:一个用于抓取帧并将其写入缓冲区,另一个用于将它们保存到磁盘。

其次,如果您正在运行Windows,则可以使用_getch_kbhit}替换cvWaitKey,如果它更快。

if(_kbhit()) ch = _getch();

但是,我对保留cvWaitKey有所保留。如果您正在使用GetSystemTime来分析您的代码,那么您的结果很可能是错误的,因为它不是很准确。

我建议您使用QueryPerformanceCounter重新分析您的代码(如果您正在使用Windows)。

答案 1 :(得分:0)

我还没有找到cvWaitKey(1)的解决方法,但我想到了另一种使用窗口处理程序调整图像大小的方法,这让我可以比使用

更少的时间渲染图像
 cvResize(pCapImage,resizedpCapImage,CV_INTER_NN);

因此,这种插值可能会减慢过程并代表瓶颈。

以下是我处理它的方式:

而不是使用

cvNamedWindow(_windowName, CV_WINDOW_AUTOSIZE);

我现在用

cvNamedWindow(_windowName, CV_WINDOW_NORMAL);

由于我仍然必须在无边框全屏幕中完成表示窗口,我添加了以下功能:

//display Window in Fullscreen depending on where the client camerawindow is at and what resolution this monitor has.
void Class::setFullscreen(){    

    cvSetWindowProperty(_windowName, CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);

    HWND win_handle = FindWindow(0, (LPCTSTR)_windowName);
    if (!win_handle)
    {
        printf("Failed FindWindow\n");
    }

    // Get monitor resolution
    HMONITOR monitor = MonitorFromWindow(win_handle, MONITOR_DEFAULTTONEAREST);
    MONITORINFO info;
    info.cbSize = sizeof(MONITORINFO);
    GetMonitorInfo(monitor, &info);
    int monitor_width = info.rcMonitor.right - info.rcMonitor.left;
    int monitor_height = info.rcMonitor.bottom - info.rcMonitor.top;

    // Resize
    unsigned int flags = (SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER);
    flags &= ~SWP_NOSIZE;

    // Set position
    unsigned int x = 0;
    unsigned int y = 0;
    SetWindowPos(win_handle, HWND_NOTOPMOST, x, y, monitor_width, monitor_height, flags);

    // Borderless
    SetWindowLong(win_handle, GWL_STYLE, 0);
    ShowWindow(win_handle, SW_SHOW);
}

这样做我在每次迭代大约20ms到30ms之间达到相当高的帧速率,大约等于30-50hz(或fps)。这是对速度的改进,但它不是精确帧率的精确解决方案。我也尝试将预测值提高到40hz,但给cvWaitKey()提供更高的分段,如cvWaitKey(20)只是降低帧速率但不添加任何帧速率稳定。