Ask Your Question

Revision history [back]

Why is ORB algorithm border reflection necessary?

So I'm working on an implementation of OpenCV's ORB keypoint algorithm (not the descriptors, just keypoints). My implmentation produces key points VERY close to the original, but something's a bit off and I'm trying to find the problem. One thing that always puzzled me about the OpenCV implementation of the ORB algorithm is that as it is pre-computing the image pyramid, it feels to need to use the "copyMakeBorder" function to relect a mirror image of the border of the image around each level of the pyramid.

// Pre-compute the scale pyramids
for (level = 0; level < nLevels; ++level)
{
    Rect linfo = layerInfo[level];
    Size sz(linfo.width, linfo.height);
    Size wholeSize(sz.width + border*2, sz.height + border*2);
    Rect wholeLinfo = Rect(linfo.x - border, linfo.y - border, wholeSize.width, wholeSize.height);
    Mat extImg = imagePyramid(wholeLinfo), extMask;
    Mat currImg = extImg(Rect(border, border, sz.width, sz.height)), currMask;

    if( !mask.empty() )
    {
        extMask = maskPyramid(wholeLinfo);
        currMask = extMask(Rect(border, border, sz.width, sz.height));
    }

    // Compute the resized image
    if( level != firstLevel )
    {
        resize(prevImg, currImg, sz, 0, 0, INTER_LINEAR);
        if( !mask.empty() )
        {
            resize(prevMask, currMask, sz, 0, 0, INTER_LINEAR);
            if( level > firstLevel )
                threshold(currMask, currMask, 254, 0, THRESH_TOZERO);
        }

        copyMakeBorder(currImg, extImg, border, border, border, border,
                       BORDER_REFLECT_101+BORDER_ISOLATED);
        if (!mask.empty())
            copyMakeBorder(currMask, extMask, border, border, border, border,
                           BORDER_CONSTANT+BORDER_ISOLATED);
    }
    else
    {
        copyMakeBorder(image, extImg, border, border, border, border,
                       BORDER_REFLECT_101);
        if( !mask.empty() )
            copyMakeBorder(mask, extMask, border, border, border, border,
                           BORDER_CONSTANT+BORDER_ISOLATED);
    }
    prevImg = currImg;
    prevMask = currMask;
}

Does this reflected border serve any purpose in terms of generating key points? I've studied the key point section carefully and as far as I can tell, it never gets used. Can I skip that part and save some CPU cycles?

(P.S.: If you're wondering, my implementation is going to be optimized for use on video key frames. In other words, I can calculate most of the buffers once per video since the resolution between frames remains the same. I can also play with background subtraction to restrict the mask to focus only on moving objects.)