title: OpenCV - linker error when implementing a new descriptor - rotation invariant BRIEF
body: <p>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). </p>
  
  <p>Now, I'm having linking problems with the function:</p>
  
  <pre><code>AlgorithmInfo* info() const;
  </code></pre>
  
  <p>I'm getting "unresolved external symbol" with the function's name.</p>
  
  <p>Here is my code: in features2d.hpp":</p>
  
  <pre><code>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&amp;);
      virtual void write(FileStorage&amp;) const;
  
      virtual int descriptorSize() const;
      virtual int descriptorType() const;
  
  
      AlgorithmInfo* info() const;
  
  protected:
      virtual void computeImpl(const Mat&amp; image, vector&lt;KeyPoint&gt;&amp; keypoints, Mat&amp; descriptors) const;
      typedef void(*PixelTestFn)(const Mat&amp;, const vector&lt;KeyPoint&gt;&amp;,  const int *, Mat&amp;);
  
      int bytes_;
      PixelTestFn test_fn_;
      static int bit_pattern_64_[512 * 4];
  };
  </code></pre>
  
  <p>And the file BriefRI.cpp (which contains the implementation):</p>
  
  <pre><code>#include "precomp.hpp"
  #include &lt;algorithm&gt;
  #include &lt;vector&gt;
  
  #include &lt;iostream&gt;
  #include &lt;iomanip&gt;
  
  using namespace cv;
  
  static void calculateSums(const Mat &amp;sum, const int &amp;count, const int *pattern, float &amp;cos_theta, float &amp;sin_theta, KeyPoint pt);
  
  inline int smoothedSum(const Mat&amp; sum, const KeyPoint&amp; 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&lt;int&gt;(img_y + HALF_KERNEL + 1, img_x + HALF_KERNEL + 1)
          - sum.at&lt;int&gt;(img_y + HALF_KERNEL + 1, img_x - HALF_KERNEL)
          - sum.at&lt;int&gt;(img_y - HALF_KERNEL, img_x + HALF_KERNEL + 1)
          + sum.at&lt;int&gt;(img_y - HALF_KERNEL, img_x - HALF_KERNEL);
  }
  
  static void pixelTests16(const Mat&amp; sum, const std::vector&lt;KeyPoint&gt;&amp; keypoints, const int *pattern, Mat&amp; descriptors)
  {
      for (int i = 0; i &lt; (int)keypoints.size(); ++i)
      {
          uchar* desc = descriptors.ptr(i);
          const KeyPoint&amp; 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 &lt; 16; ix++){
              for (int jx = 7; jx &gt;= 0; jx--){
  
                  int suma, sumb;
                  calculateSums(sum, count, pattern,cos_theta, sin_theta, pt);
                  desc[ix] += (uchar)((suma&lt; sumb) &lt;&lt; jx);
                  count += 4;
              }
          }
      }
  }
  
  static void pixelTests32(const Mat&amp; sum, const std::vector&lt;KeyPoint&gt;&amp; keypoints, const int *pattern, Mat&amp; descriptors)
  {
      for (int i = 0; i &lt; (int)keypoints.size(); ++i)
      {
          uchar* desc = descriptors.ptr(i);
          const KeyPoint&amp; 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 &lt; 32; ix++){
              for (int jx = 7; jx &gt;= 0; jx--){
  
                  int suma, sumb;
                  calculateSums(sum, count, pattern,cos_theta, sin_theta, pt);
                  desc[ix] += (uchar)((suma&lt; sumb) &lt;&lt; jx);
                  count += 4;
              }
          }
  
  
      }
  }
  
  static void pixelTests64(const Mat&amp; sum, const std::vector&lt;KeyPoint&gt;&amp; keypoints, const int *pattern, Mat&amp; descriptors)
  {
      for (int i = 0; i &lt; (int)keypoints.size(); ++i)
      {
          uchar* desc = descriptors.ptr(i);
          const KeyPoint&amp; 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 &lt; 64; ix++){
              for (int jx = 7; jx &gt;= 0; jx--){
  
                  int suma, sumb;
                  calculateSums(sum, count,pattern, cos_theta, sin_theta, pt);
                  desc[ix] += (uchar)((suma&lt; sumb) &lt;&lt; jx);
                  count += 4;
              }
          }
  
      }
  }
  
  static void calculateSums(const Mat &amp;sum, const int &amp;count, const int *pattern, float &amp;cos_theta, float &amp;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&amp; 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&amp; fs) const
      {
          fs &lt;&lt; "descriptorSize" &lt;&lt; bytes_;
      }
  
      void InvariantBriefDescriptorExtractor::computeImpl(const Mat&amp; image, std::vector&lt;KeyPoint&gt;&amp; keypoints, Mat&amp; 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)
  </code></pre>
  
  <p>Thanks in advance!</p>
  
  <p>Gil</p>