有人设法让OpenCV中的Brox密集光流算法工作吗?
这里有一些代码:
{
// Load images
cv::Mat PreviousFrameGrayFloat; // Has an image in format CV_32FC1
cv::Mat CurrentFrameGrayFloat; // Has an image in format CV_32FC1
// Upload images to GPU
cv::gpu::GpuMat PreviousFrameGPU(PreviousFrameGrayFloat);
cv::gpu::GpuMat CurrentFrameGPU(CurrentFrameGrayFloat);
// Prepare receiving variables
cv::gpu::GpuMat FlowXGPU;
cv::gpu::GpuMat FlowYGPU;
// Create optical flow object
cv::gpu::BroxOpticalFlow OpticalFlowGPU = cv::gpu::BroxOpticalFlow(0.197f, 0.8f, 50.0f, 10, 77, 10);
// Perform optical flow
OpticalFlowGPU(PreviousFrameGPU, CurrentFrameGPU, FlowXGPU, FlowYGPU); // EXCEPTION
// Exception in opencv_core244d!cv::GlBuffer::unbind
// Download flow from GPU
cv::Mat FlowX;
cv::Mat FlowY;
FlowXGPU.download(FlowX);
FlowYGPU.download(FlowY);
}
如上所述,我遇到了一个异常,当我尝试使用cv::gpu::BroxOpticalFlow
对象时,我对cv::gpu::PyrLKOpticalFlow
有同样的问题,但只有密集版本而不是稀疏版本,并且cv::gpu::FarnebackOpticalFlow
工作得很好。。。
奇怪。
整个例外是:
Exception at 0x7c812fd3, code: 0xe06d7363: C++ exception, flags=0x1 (execution cannot be continued) in opencv_core244d!cv::GlBuffer::unbind
我使用的是带有调试库的调试构建,使用的是OpenCV 2.4.4,但该代码在OpenCV 2.4.3中也引发了一个异常。
当我使用OpenCV 2.4.3时,我得到了这个异常:
Exception at 0x7c812fd3, code: 0xe06d7363: C++ exception, flags=0x1 (execution cannot be continued) in opencv_core243d!cv::SparseMat::erase
OpenGL是必需的,但您的缩放参数(50.0f(可能也有问题。它似乎太大了。据我所知,这应该小于1。如果它是一个大数字,算法会很快填满GPU内存。此外,使用一个正在扩展(倒置?(的图像金字塔可能没有意义。但还不完全确定。
在试用其他版本的OpenCV并遵循此处包含的信息后:http://stuartjames.info/Journal/opencv-brox-optical-flow-sample-possible-fix.aspx
看起来我需要用OpenGL重新编译OpenCV。
您似乎可以通过运行命令cv::gpu::setGlDevice(0);
来测试OpenCV的安装是否具有OpenGL。如果出现类似上面的奇怪异常而失败,则需要重新编译。
OpenGL是必需的,因为OpenCV中较新的光流算法将数据映射到OpenGL纹理,以(我认为(加快操作,或者可能只是为了简化代码。
因此,在所有这些之后,解决方案是使用OpenGL重新编译OpenCV。这可以通过在使用CMake配置构建时勾选WITH_OPENGL
框来实现。
如果你想使用GPU版本的视频阅读器,请确保你也勾选WITH_NVCUVID
,这包括在CUDA中,但除非你要求,否则不包括…
--编辑--
在paul的评论之后,我已经从问题中更正了代码中的比例因子。
以下是我正在测试的完整代码,适用于nkit:
{
// Load images
cv::Mat PreviousFrameGray = cv::imread("Input1.png", 0);
cv::Mat CurrentFrameGray = cv::imread("Input2.png", 0);
cv::Mat PreviousFrameGrayFloat; // Has an image in format CV_32FC1
cv::Mat CurrentFrameGrayFloat; // Has an image in format CV_32FC1
PreviousFrameGray.convertTo(PreviousFrameGrayFloat, CV_32FC1, 1.0/255.0);
CurrentFrameGray.convertTo(CurrentFrameGrayFloat, CV_32FC1, 1.0/255.0);
// Upload images to GPU
cv::gpu::GpuMat PreviousFrameGPU(PreviousFrameGrayFloat);
cv::gpu::GpuMat CurrentFrameGPU(CurrentFrameGrayFloat);
// Prepare receiving variables
cv::gpu::GpuMat FlowXGPU;
cv::gpu::GpuMat FlowYGPU;
// Create optical flow object
cv::gpu::BroxOpticalFlow OpticalFlowGPU = cv::gpu::BroxOpticalFlow(0.197f, 50.0f, 0.8f, 10, 77, 10);
// Perform optical flow
OpticalFlowGPU(PreviousFrameGPU, CurrentFrameGPU, FlowXGPU, FlowYGPU);
// Download flow from GPU
cv::Mat FlowX;
cv::Mat FlowY;
FlowXGPU.download(FlowX);
FlowYGPU.download(FlowY);
// Use FlowX and FlowY in further processing
//...
}