1

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

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

没有等待键和显示的测量时间约为 20 毫秒,显示的时间约为 60 毫秒(需要等待键)。调整大小不会增加这么多时间。

谢谢你的帮助。

// 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());
            }
        }
    }
4

2 回答 2

0

我还没有找到 cvWaitKey(1) 的解决方法,但我想出了另一种使用窗口处理程序调整图像大小的方法,这让我可以在大约 20 毫秒内渲染图像,而不是使用

 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);
}

这样做我在每次迭代大约 20 毫秒到 30 毫秒之间完成了相当高的帧速率,这相当于大约 30-50 赫兹(或 fps)。这是对速度的改进,但它不是精确帧速率的精确解决方案。我还尝试将精度提高到 40hz,但像 cvWaitKey(20) 一样为 cvWaitKey() 提供更高的参数只会降低帧率,但不会增加任何帧率稳定性。

于 2013-09-10T10:03:54.910 回答
0

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

其次,如果您正在运行 Windows,则可以使用_getch(with _kbhit) 来替换cvWaitKey它是否更快。

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

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

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

于 2013-09-09T15:16:05.530 回答