OpenCV - linker error when implementing a new descriptor - rotation invariant BRIEF

GilLevi

As part of my research on binary descriptor, I'm implementing a rotation invariant version of BRIEF. Basically, I rotate the sampling points by the angle of the patch (given from the detector).

Now, I'm having linking problems with the function:

AlgorithmInfo* info() const;

I'm getting "unresolved external symbol" with the function's name.

Here is my code: in features2d.hpp":

class CV_EXPORTS InvariantBriefDescriptorExtractor : public DescriptorExtractor
{
public:
    static const int PATCH_SIZE = 48;
    static const int KERNEL_SIZE = 9;
    // bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes.
    InvariantBriefDescriptorExtractor(int bytes = 32);

    virtual void read(const FileNode&);
    virtual void write(FileStorage&) const;

    virtual int descriptorSize() const;
    virtual int descriptorType() const;


    AlgorithmInfo* info() const;

protected:
    virtual void computeImpl(const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors) const;
    typedef void(*PixelTestFn)(const Mat&, const vector<KeyPoint>&,  const int *, Mat&);

    int bytes_;
    PixelTestFn test_fn_;
    static int bit_pattern_64_[512 * 4];
};

And the file BriefRI.cpp (which contains the implementation):

#include "precomp.hpp"
#include <algorithm>
#include <vector>

#include <iostream>
#include <iomanip>

using namespace cv;

static void calculateSums(const Mat &sum, const int &count, const int *pattern, float &cos_theta, float &sin_theta, KeyPoint pt);

inline int smoothedSum(const Mat& sum, const KeyPoint& pt, int y, int x)
{
    static const int HALF_KERNEL = BriefDescriptorExtractor::KERNEL_SIZE / 2;

    int img_y = (int)(pt.pt.y + 0.5) + y;
    int img_x = (int)(pt.pt.x + 0.5) + x;
    return   sum.at<int>(img_y + HALF_KERNEL + 1, img_x + HALF_KERNEL + 1)
        - sum.at<int>(img_y + HALF_KERNEL + 1, img_x - HALF_KERNEL)
        - sum.at<int>(img_y - HALF_KERNEL, img_x + HALF_KERNEL + 1)
        + sum.at<int>(img_y - HALF_KERNEL, img_x - HALF_KERNEL);
}

static void pixelTests16(const Mat& sum, const std::vector<KeyPoint>& keypoints, const int *pattern, Mat& descriptors)
{
    for (int i = 0; i < (int)keypoints.size(); ++i)
    {
        uchar* desc = descriptors.ptr(i);
        const KeyPoint& pt = keypoints[i];

        float angle = pt.angle;
        angle *= (float)(CV_PI / 180.f);
        float cos_theta = cos(angle);
        float sin_theta = sin(angle);
        int count = 0;

        for (int ix = 0; ix < 16; ix++){
            for (int jx = 7; jx >= 0; jx--){

                int suma, sumb;
                calculateSums(sum, count, pattern,cos_theta, sin_theta, pt);
                desc[ix] += (uchar)((suma< sumb) << jx);
                count += 4;
            }
        }
    }
}

static void pixelTests32(const Mat& sum, const std::vector<KeyPoint>& keypoints, const int *pattern, Mat& descriptors)
{
    for (int i = 0; i < (int)keypoints.size(); ++i)
    {
        uchar* desc = descriptors.ptr(i);
        const KeyPoint& pt = keypoints[i];

        float angle = pt.angle;
        angle *= (float)(CV_PI / 180.f);
        float cos_theta = cos(angle);
        float sin_theta = sin(angle);
        int count = 0;

        for (int ix = 0; ix < 32; ix++){
            for (int jx = 7; jx >= 0; jx--){

                int suma, sumb;
                calculateSums(sum, count, pattern,cos_theta, sin_theta, pt);
                desc[ix] += (uchar)((suma< sumb) << jx);
                count += 4;
            }
        }


    }
}

static void pixelTests64(const Mat& sum, const std::vector<KeyPoint>& keypoints, const int *pattern, Mat& descriptors)
{
    for (int i = 0; i < (int)keypoints.size(); ++i)
    {
        uchar* desc = descriptors.ptr(i);
        const KeyPoint& pt = keypoints[i];

        float angle = pt.angle;
        angle *= (float)(CV_PI / 180.f);
        float cos_theta = cos(angle);
        float sin_theta = sin(angle);
        int count = 0;

        for (int ix = 0; ix < 64; ix++){
            for (int jx = 7; jx >= 0; jx--){

                int suma, sumb;
                calculateSums(sum, count,pattern, cos_theta, sin_theta, pt);
                desc[ix] += (uchar)((suma< sumb) << jx);
                count += 4;
            }
        }

    }
}

static void calculateSums(const Mat &sum, const int &count, const int *pattern, float &cos_theta, float &sin_theta, KeyPoint pt){
    int ax = pattern[count];
    int ay = pattern[count + 1];

    int bx = pattern[count + 2];
    int by = pattern[count + 3];

    int ax2 = ((float)ax)*cos_theta - ((float)ay)*sin_theta;
    int ay2 = ((float)ax)*sin_theta + ((float)ay)*cos_theta;
    int bx2 = ((float)bx)*cos_theta - ((float)by)*sin_theta;
    int by2 = ((float)bx)*sin_theta + ((float)by)*cos_theta;

    int suma = smoothedSum(sum, pt, ay, ax);
    int sumb = smoothedSum(sum, pt, by, bx);
}

namespace cv
{

    InvariantBriefDescriptorExtractor::InvariantBriefDescriptorExtractor(int bytes) :
        bytes_(bytes), test_fn_(NULL)
    {
        switch (bytes)
        {
        case 16:
            test_fn_ = pixelTests16;
            break;
        case 32:
            test_fn_ = pixelTests32;
            break;
        case 64:
            test_fn_ = pixelTests64;
            break;
        default:
            CV_Error(CV_StsBadArg, "bytes must be 16, 32, or 64");
        }
    }

    int InvariantBriefDescriptorExtractor::descriptorSize() const
    {
        return bytes_;
    }

    int InvariantBriefDescriptorExtractor::descriptorType() const
    {
        return CV_8UC1;
    }

    void InvariantBriefDescriptorExtractor::read(const FileNode& fn)
    {
        int dSize = fn["descriptorSize"];
        switch (dSize)
        {
        case 16:
            test_fn_ = pixelTests16;
            break;
        case 32:
            test_fn_ = pixelTests32;
            break;
        case 64:
            test_fn_ = pixelTests64;
            break;
        default:
            CV_Error(CV_StsBadArg, "descriptorSize must be 16, 32, or 64");
        }
        bytes_ = dSize;
    }

    void InvariantBriefDescriptorExtractor::write(FileStorage& fs) const
    {
        fs << "descriptorSize" << bytes_;
    }

    void InvariantBriefDescriptorExtractor::computeImpl(const Mat& image, std::vector<KeyPoint>& keypoints, Mat& descriptors) const
    {
        // Construct integral image for fast smoothing (box filter)
        Mat sum;

        Mat grayImage = image;
        if (image.type() != CV_8U) cvtColor(image, grayImage, CV_BGR2GRAY);

        ///TODO allow the user to pass in a precomputed integral image
        //if(image.type() == CV_32S)
        //  sum = image;
        //else

        integral(grayImage, sum, CV_32S);

        //Remove keypoints very close to the border
        KeyPointsFilter::runByImageBorder(keypoints, image.size(), PATCH_SIZE / 2 + KERNEL_SIZE / 2);

        descriptors = Mat::zeros((int)keypoints.size(), bytes_, CV_8U);
        test_fn_(sum, keypoints, bit_pattern_64_,descriptors);
    }


    int InvariantBriefDescriptorExtractor::  bit_pattern_64_[512 * 4] =
    { -1, -2, -1, 7
    , -1, -14, 3, -3
    , -2, 1, 2, 11
    , 6, 1, -7, -10
    , 2, 13, 0, -1
    , 5, -14, -3, 5
    , 8, -2, 4, 2
    , 8, -11, 5, -15
(LONG LIST)

Thanks in advance!

Gil

berak

there is a CV_INIT_ALGORITHM macro available (within, but not outside) the opencv libs. it is used to implement the Algorithm::init() method. you set the class name for create, and expose member vars of your algo to get() and set() functions, and to write()/read() serialization.

here is an example for KAZE (taken from features2d_init.cpp):

 CV_INIT_ALGORITHM(KAZE, "Feature2D.KAZE",
              obj.info()->addParam(obj, "upright", obj.upright);
              obj.info()->addParam(obj, "extended", obj.extended))

so , to add to the features2d lib, you will have to add some similar code for your extractor there.

also, adding a line to bool cv::initModule_features2d(void) (at the end of features2d_init.cpp) might be nessecary


in the meantime, as a preliminary duct-tape-fix (also, while you're trying your code outside the features2d module), you could as well do a dummy impl:

class CV_EXPORTS InvariantBriefDescriptorExtractor : public DescriptorExtractor
{
public:

    // ...

    AlgorithmInfo* info() const { return 0; }

(btw, imho your computeImpl function does not match the inherited one from DescriptorExtractor, might be the next problem.)

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Bad file descriptor error when implementing piping in C

Rotation invariant multiple template occurrence in image Opencv

opencv 3.0.0 linker error when instantiating Mat object

Cocoapods OpenCV 2.4.10 Linker Error

is Faster RCNN rotation invariant?

Rotation Invariant Number Recognition

Linker error when inlining function

Assertion Error while implementing SIFT algorithm :opencv

Linker Error when compiling with static library

Linker Error when calling operator<<, how to fix this?

Linker error with glew when library is statically linked

Linker error when adding QAxWidget to empty project

Linker error when function definition is in cpp file

Linker error not finding destructor when a function is templated

linker error when linking libcrypto.dylib

Python error when implementing class

Error when implementing havingRaw() with max()

Linker error in Text Recognition (OCR) using Tesseract and OpenCV?

Linker error in OpenCV C++ binaries after anaconda reinstall

Linker Error on a simple OpenCV program in an alpine docker container

Linker error not related to Linker

Invariant Violation error when returning a Link as dataFormatter in react

Why do I get an 'Invariant Violation' error when using KeyboardAvoidView?

React / Enzyme: Invariant Violation error when running Jest / Enzyme test

405 error after implementing new search view

KeyPoint descriptor OpenCV

How is the RestKit related to the new Watson Conversation SDK? Linker Error?

Why my PCA is not invariant to rotation and axis swap?

Linker errors when trying to install new Google Analytics 3.0 Beta