【问题标题】:cvWaitKey() slowing capture process significantly - workaround?cvWaitKey() 显着减慢捕获过程 - 解决方法?
【发布时间】:2013-09-09 15:00:52
【问题描述】:

我正在将 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());
            }
        }
    }

【问题讨论】:

    标签: c++ opencv computer-vision


    【解决方案1】:

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

    其次,如果你在运行windows,你可以使用_getch(和_kbhit)来替换cvWaitKey,如果它更快的话。

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

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

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

    【讨论】:

    • 嗨,Jacob,我的视频不是视频,而是捕获的帧,大约 5-10 分钟长,所以我怀疑缓冲是一种选择。多线程这并没有提高速度,因为外包保存过程实际上并没有太大帮助,因为我获得了大约 3-5 毫秒的速度增益。如果我不显示并且只保存我会获得大约 40 毫秒的速度增益。至于测量 - 我看到在一段时间内保存的图像,也以客观的方式查看视频,所以差异对我来说是可以测量的。你将如何用 cvWaitKey 交换 _getch ?
    • 对不起,对于@jakob 的反对意见,但它要么放弃 waitkey 和 showImage,要么将两者都保留在这里。 waitkey 所做的不仅仅是等待按键,它包含窗口的消息泵,并触发实际的 blitting(这可能解释了为什么它需要时间)。还 getch 阻塞了主线程,这非常糟糕。
    • @berak:没问题; _getch() 单独是个坏主意。它需要像往常一样与_kbhit()结合。
    • 嘿,真的。但除了完全不可移植外,它还等待控制台窗口中的事件,而不是显示图像的事件。
    • 嘿,让我们在这里解决,我们都尽力提供帮助;)
    【解决方案2】:

    我还没有找到 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-50hz(或 fps)。这是对速度的改进,但它不是精确帧速率的精确解决方案。我还尝试将精度提高到 40hz,但像 cvWaitKey(20) 一样为 cvWaitKey() 提供更高的参数只会降低帧率,但不会增加任何帧率稳定性。

    【讨论】:

      猜你喜欢
      • 2014-10-08
      • 1970-01-01
      • 2022-11-23
      • 2016-05-04
      • 2013-11-29
      • 1970-01-01
      • 2018-11-02
      • 2020-03-24
      • 1970-01-01
      相关资源
      最近更新 更多