Has anyone managed to get the Brox dense optical flow algorithm in OpenCV working?
Here is some code:
{
    // 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);
}
I get an exception, as commented above, when I try and use the cv::gpu::BroxOpticalFlow object, I have the same problem with cv::gpu::PyrLKOpticalFlow but only the dense version not the sparse one, and cv::gpu::FarnebackOpticalFlow works fine...
Weird.
Entire exception is:
Exception at 0x7c812fd3, code: 0xe06d7363: C++ exception, flags=0x1 (execution cannot be continued) in opencv_core244d!cv::GlBuffer::unbind
I'm using a debug build with debug libraries, using OpenCV 2.4.4 however the code also raises an exception in OpenCV 2.4.3.
When I use OpenCV 2.4.3 I get this exception:
Exception at 0x7c812fd3, code: 0xe06d7363: C++ exception, flags=0x1 (execution cannot be continued) in opencv_core243d!cv::SparseMat::erase
OpenGL is required, but there may also be a problem with your scale parameter (50.0f). It seems too large. As I understand, this should be less than 1. If it is a large number, the algorithm fills up GPU memory quickly. Plus, it may not make sense to use an expanding (upside-down?) image pyramid. Not perfectly sure though.
After experimenting with other versions of OpenCV and following the information contained here: http://stuartjames.info/Journal/opencv-brox-optical-flow-sample-possible-fix.aspx
It looks like I need to recompile OpenCV with OpenGL.
It seems that you can test whether your install of OpenCV has OpenGL by running the command: cv::gpu::setGlDevice(0); if this fails with a weird exception like the one above then you need to recompile.
OpenGL is required as the newer optical flow algorithms in OpenCV map data to OpenGL textures to (I assume) speed up operations, or maybe to just make the code simpler.
So, after all this, the solution is to recompile OpenCV with OpenGL. This can be achieved by ticking the WITH_OPENGL box when using CMake to configure the build.
If you want to use the GPU version of the video reader make sure you also tick WITH_NVCUVID this is included with CUDA but not included unless you request it...
-- EDIT --
After the comments from paul I've corrected the scale factor in my code from the question.
Here is the complete code I'm testing, for nkint:
{
    // 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
    //...
}
User contributions licensed under CC BY-SA 3.0