我正在将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(<);
// 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());
}
}
}
答案 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)只是降低帧速率但不添加任何帧速率稳定。