OpenCV - Brox Optical Flow - Exception in opencv_core244d!cv::GlBuffer::unbind

2

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
c++
opencv
image-processing
cuda
opticalflow
asked on Stack Overflow Feb 25, 2013 by gpdaniels • edited Apr 17, 2015 by gpdaniels

2 Answers

1

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.

answered on Stack Overflow Apr 17, 2013 by paul
0

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
    //...
}
answered on Stack Overflow Mar 15, 2013 by gpdaniels • edited Apr 23, 2013 by gpdaniels

User contributions licensed under CC BY-SA 3.0