Search code examples
opencvcomputer-visionsurf

SURF_CUDA error while computing descriptors and keypoints


I'm computing SURF descriptors on the Oxford dataset (5000k images) calling sequentially the following method:

void SURF_CUDAOpenCV::ComputeDescriptors(cv::Mat &img, cv::Mat1f &descriptors){
    cv::cuda::GpuMat imgGpu;
    std::vector<float> f_descriptors;
    std::vector<cv::KeyPoint> keypoints;
    imgGpu.upload(img);
    if(imgGpu.empty())
        throw std::runtime_error("Error uploading gpuImg");
    surf_cuda(imgGpu, cv::cuda::GpuMat(), keypoints, f_descriptors);
    descriptors = cv::Mat1f((int) f_descriptors.size()/surf_cuda.descriptorSize(), surf_cuda.descriptorSize(), f_descriptors[0]);
}

It computes successfully the descriptors for part of the images (I printed the descriptors rows and cols after surf_cuda(...)) but it suddenly stops with this error:

OpenCV Error: Assertion failed (layer_rows - 2 * min_margin > 0) in SURF_CUDA_Invoker, file /home/luca/ParallelOpenCV/opencv_contrib/modules/xfeatures2d/src/surf.cuda.cpp, line 134
error: /home/luca/ParallelOpenCV/opencv_contrib/modules/xfeatures2d/src/surf.cuda.cpp:134: error: (-215) layer_rows - 2 * min_margin > 0 in function SURF_CUDA_Invoker

Why this happens?

I noticed one curious thing: The image where the error presents it's the smallest one seen until that moment in terms of rows. Usually there at least more than 200 hundreds rows (but usually 300, 400), but in this case there are "only" 117 rows. Maybe is this the problem? I remember that using classic cv::xfeatures::SURF it detected 0 keypoints for one very small image, that's why I thought this could be the problem.


Solution

  • The error happens because the code checks the size of the image, and Surf does not work properly with small images.

    Actually in the file opencv/opencv_contrib/modules/xfeatures2d/src/surf.cuda.cpp, the constructor SURF_CUDA_Invoker has several asserts like the one that is shown in this error.

    Why Surf has this issue? Because, it is a design constraint. Basically working with small images means using smaller descriptor resulting into not having enough information.

    If you want to go further you can check this other question or some documentation about surf.