Add rotation invariance option for BRIEF descriptor.

pull/207/head
cbalint13 10 years ago
parent ae7e5a5489
commit df7abb94c0
  1. 5
      modules/xfeatures2d/include/opencv2/xfeatures2d.hpp
  2. 74
      modules/xfeatures2d/src/brief.cpp
  3. 2
      modules/xfeatures2d/src/generated_16.i
  4. 2
      modules/xfeatures2d/src/generated_32.i
  5. 2
      modules/xfeatures2d/src/generated_64.i
  6. 27
      modules/xfeatures2d/test/test_rotation_and_scale_invariance.cpp

@ -118,6 +118,9 @@ public:
/** @brief Class for computing BRIEF descriptors described in @cite calon2010 .
@param bytes legth of the descriptor in bytes, valid values are: 16, 32 (default) or 64 .
@param use_orientation sample patterns using keypoints orientation, disabled by default.
@note
- A complete BRIEF extractor sample can be found at
opencv_source_code/samples/cpp/brief_match_test.cpp
@ -126,7 +129,7 @@ public:
class CV_EXPORTS BriefDescriptorExtractor : public DescriptorExtractor
{
public:
static Ptr<BriefDescriptorExtractor> create( int bytes = 32 );
static Ptr<BriefDescriptorExtractor> create( int bytes = 32, bool use_orientation = false );
};
/** @overload */

@ -61,7 +61,7 @@ public:
enum { PATCH_SIZE = 48, KERNEL_SIZE = 9 };
// bytes is a length of descriptor in bytes. It can be equal 16, 32 or 64 bytes.
BriefDescriptorExtractorImpl( int bytes = 32 );
BriefDescriptorExtractorImpl( int bytes = 32, bool use_orientation = false );
virtual void read( const FileNode& );
virtual void write( FileStorage& ) const;
@ -73,67 +73,103 @@ public:
virtual void compute(InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors);
protected:
typedef void(*PixelTestFn)(InputArray, const std::vector<KeyPoint>&, OutputArray);
typedef void(*PixelTestFn)(InputArray, const std::vector<KeyPoint>&, OutputArray, bool use_orientation );
int bytes_;
bool use_orientation_;
PixelTestFn test_fn_;
};
Ptr<BriefDescriptorExtractor> BriefDescriptorExtractor::create( int bytes )
Ptr<BriefDescriptorExtractor> BriefDescriptorExtractor::create( int bytes, bool use_orientation )
{
return makePtr<BriefDescriptorExtractorImpl>(bytes);
return makePtr<BriefDescriptorExtractorImpl>(bytes, use_orientation );
}
inline int smoothedSum(const Mat& sum, const KeyPoint& pt, int y, int x)
inline int smoothedSum(const Mat& sum, const KeyPoint& pt, int y, int x, bool use_orientation, Matx21f R)
{
static const int HALF_KERNEL = BriefDescriptorExtractorImpl::KERNEL_SIZE / 2;
int img_y = (int)(pt.pt.y + 0.5) + y;
int img_x = (int)(pt.pt.x + 0.5) + x;
if ( use_orientation )
{
int rx = (int)(((float)x)*R(1,0) - ((float)y)*R(0,0));
int ry = (int)(((float)x)*R(0,0) + ((float)y)*R(1,0));
if (rx > 24) rx = 24; if (rx < -24) rx = -24;
if (ry > 24) ry = 24; if (ry < -24) ry = -24;
x = rx; y = ry;
}
const int img_y = (int)(pt.pt.y + 0.5) + y;
const 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(InputArray _sum, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors)
static void pixelTests16(InputArray _sum, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, bool use_orientation )
{
Matx21f R;
Mat sum = _sum.getMat(), descriptors = _descriptors.getMat();
for (int i = 0; i < (int)keypoints.size(); ++i)
for (size_t i = 0; i < keypoints.size(); ++i)
{
uchar* desc = descriptors.ptr(i);
uchar* desc = descriptors.ptr(static_cast<int>(i));
const KeyPoint& pt = keypoints[i];
if ( use_orientation )
{
float angle = pt.angle;
angle *= (float)(CV_PI/180.f);
R(0,0) = sin(angle);
R(1,0) = cos(angle);
}
#include "generated_16.i"
}
}
static void pixelTests32(InputArray _sum, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors)
static void pixelTests32(InputArray _sum, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, bool use_orientation)
{
Matx21f R;
Mat sum = _sum.getMat(), descriptors = _descriptors.getMat();
for (int i = 0; i < (int)keypoints.size(); ++i)
for (size_t i = 0; i < keypoints.size(); ++i)
{
uchar* desc = descriptors.ptr(i);
uchar* desc = descriptors.ptr(static_cast<int>(i));
const KeyPoint& pt = keypoints[i];
if ( use_orientation )
{
float angle = pt.angle;
angle *= (float)(CV_PI / 180.f);
R(0,0) = sin(angle);
R(1,0) = cos(angle);
}
#include "generated_32.i"
}
}
static void pixelTests64(InputArray _sum, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors)
static void pixelTests64(InputArray _sum, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors, bool use_orientation)
{
Matx21f R;
Mat sum = _sum.getMat(), descriptors = _descriptors.getMat();
for (int i = 0; i < (int)keypoints.size(); ++i)
for (size_t i = 0; i < keypoints.size(); ++i)
{
uchar* desc = descriptors.ptr(i);
uchar* desc = descriptors.ptr(static_cast<int>(i));
const KeyPoint& pt = keypoints[i];
if ( use_orientation )
{
float angle = pt.angle;
angle *= (float)(CV_PI/180.f);
R(0,0) = sin(angle);
R(1,0) = cos(angle);
}
#include "generated_64.i"
}
}
BriefDescriptorExtractorImpl::BriefDescriptorExtractorImpl(int bytes) :
BriefDescriptorExtractorImpl::BriefDescriptorExtractorImpl(int bytes, bool use_orientation) :
bytes_(bytes), test_fn_(NULL)
{
use_orientation_ = use_orientation;
switch (bytes)
{
case 16:
@ -212,7 +248,7 @@ void BriefDescriptorExtractorImpl::compute(InputArray image,
descriptors.create((int)keypoints.size(), bytes_, CV_8U);
descriptors.setTo(Scalar::all(0));
test_fn_(sum, keypoints, descriptors);
test_fn_(sum, keypoints, descriptors, use_orientation_);
}
}

@ -1,5 +1,5 @@
// Code generated with '$ scripts/generate_code.py src/test_pairs.txt 16'
#define SMOOTHED(y,x) smoothedSum(sum, pt, y, x)
#define SMOOTHED(y,x) smoothedSum(sum, pt, y, x, use_orientation, R)
desc[0] = (uchar)(((SMOOTHED(-2, -1) < SMOOTHED(7, -1)) << 7) + ((SMOOTHED(-14, -1) < SMOOTHED(-3, 3)) << 6) + ((SMOOTHED(1, -2) < SMOOTHED(11, 2)) << 5) + ((SMOOTHED(1, 6) < SMOOTHED(-10, -7)) << 4) + ((SMOOTHED(13, 2) < SMOOTHED(-1, 0)) << 3) + ((SMOOTHED(-14, 5) < SMOOTHED(5, -3)) << 2) + ((SMOOTHED(-2, 8) < SMOOTHED(2, 4)) << 1) + ((SMOOTHED(-11, 8) < SMOOTHED(-15, 5)) << 0));
desc[1] = (uchar)(((SMOOTHED(-6, -23) < SMOOTHED(8, -9)) << 7) + ((SMOOTHED(-12, 6) < SMOOTHED(-10, 8)) << 6) + ((SMOOTHED(-3, -1) < SMOOTHED(8, 1)) << 5) + ((SMOOTHED(3, 6) < SMOOTHED(5, 6)) << 4) + ((SMOOTHED(-7, -6) < SMOOTHED(5, -5)) << 3) + ((SMOOTHED(22, -2) < SMOOTHED(-11, -8)) << 2) + ((SMOOTHED(14, 7) < SMOOTHED(8, 5)) << 1) + ((SMOOTHED(-1, 14) < SMOOTHED(-5, -14)) << 0));
desc[2] = (uchar)(((SMOOTHED(-14, 9) < SMOOTHED(2, 0)) << 7) + ((SMOOTHED(7, -3) < SMOOTHED(22, 6)) << 6) + ((SMOOTHED(-6, 6) < SMOOTHED(-8, -5)) << 5) + ((SMOOTHED(-5, 9) < SMOOTHED(7, -1)) << 4) + ((SMOOTHED(-3, -7) < SMOOTHED(-10, -18)) << 3) + ((SMOOTHED(4, -5) < SMOOTHED(0, 11)) << 2) + ((SMOOTHED(2, 3) < SMOOTHED(9, 10)) << 1) + ((SMOOTHED(-10, 3) < SMOOTHED(4, 9)) << 0));

@ -1,5 +1,5 @@
// Code generated with '$ scripts/generate_code.py src/test_pairs.txt 32'
#define SMOOTHED(y,x) smoothedSum(sum, pt, y, x)
#define SMOOTHED(y,x) smoothedSum(sum, pt, y, x, use_orientation, R)
desc[0] = (uchar)(((SMOOTHED(-2, -1) < SMOOTHED(7, -1)) << 7) + ((SMOOTHED(-14, -1) < SMOOTHED(-3, 3)) << 6) + ((SMOOTHED(1, -2) < SMOOTHED(11, 2)) << 5) + ((SMOOTHED(1, 6) < SMOOTHED(-10, -7)) << 4) + ((SMOOTHED(13, 2) < SMOOTHED(-1, 0)) << 3) + ((SMOOTHED(-14, 5) < SMOOTHED(5, -3)) << 2) + ((SMOOTHED(-2, 8) < SMOOTHED(2, 4)) << 1) + ((SMOOTHED(-11, 8) < SMOOTHED(-15, 5)) << 0));
desc[1] = (uchar)(((SMOOTHED(-6, -23) < SMOOTHED(8, -9)) << 7) + ((SMOOTHED(-12, 6) < SMOOTHED(-10, 8)) << 6) + ((SMOOTHED(-3, -1) < SMOOTHED(8, 1)) << 5) + ((SMOOTHED(3, 6) < SMOOTHED(5, 6)) << 4) + ((SMOOTHED(-7, -6) < SMOOTHED(5, -5)) << 3) + ((SMOOTHED(22, -2) < SMOOTHED(-11, -8)) << 2) + ((SMOOTHED(14, 7) < SMOOTHED(8, 5)) << 1) + ((SMOOTHED(-1, 14) < SMOOTHED(-5, -14)) << 0));
desc[2] = (uchar)(((SMOOTHED(-14, 9) < SMOOTHED(2, 0)) << 7) + ((SMOOTHED(7, -3) < SMOOTHED(22, 6)) << 6) + ((SMOOTHED(-6, 6) < SMOOTHED(-8, -5)) << 5) + ((SMOOTHED(-5, 9) < SMOOTHED(7, -1)) << 4) + ((SMOOTHED(-3, -7) < SMOOTHED(-10, -18)) << 3) + ((SMOOTHED(4, -5) < SMOOTHED(0, 11)) << 2) + ((SMOOTHED(2, 3) < SMOOTHED(9, 10)) << 1) + ((SMOOTHED(-10, 3) < SMOOTHED(4, 9)) << 0));

@ -1,5 +1,5 @@
// Code generated with '$ scripts/generate_code.py src/test_pairs.txt 64'
#define SMOOTHED(y,x) smoothedSum(sum, pt, y, x)
#define SMOOTHED(y,x) smoothedSum(sum, pt, y, x, use_orientation, R)
desc[0] = (uchar)(((SMOOTHED(-2, -1) < SMOOTHED(7, -1)) << 7) + ((SMOOTHED(-14, -1) < SMOOTHED(-3, 3)) << 6) + ((SMOOTHED(1, -2) < SMOOTHED(11, 2)) << 5) + ((SMOOTHED(1, 6) < SMOOTHED(-10, -7)) << 4) + ((SMOOTHED(13, 2) < SMOOTHED(-1, 0)) << 3) + ((SMOOTHED(-14, 5) < SMOOTHED(5, -3)) << 2) + ((SMOOTHED(-2, 8) < SMOOTHED(2, 4)) << 1) + ((SMOOTHED(-11, 8) < SMOOTHED(-15, 5)) << 0));
desc[1] = (uchar)(((SMOOTHED(-6, -23) < SMOOTHED(8, -9)) << 7) + ((SMOOTHED(-12, 6) < SMOOTHED(-10, 8)) << 6) + ((SMOOTHED(-3, -1) < SMOOTHED(8, 1)) << 5) + ((SMOOTHED(3, 6) < SMOOTHED(5, 6)) << 4) + ((SMOOTHED(-7, -6) < SMOOTHED(5, -5)) << 3) + ((SMOOTHED(22, -2) < SMOOTHED(-11, -8)) << 2) + ((SMOOTHED(14, 7) < SMOOTHED(8, 5)) << 1) + ((SMOOTHED(-1, 14) < SMOOTHED(-5, -14)) << 0));
desc[2] = (uchar)(((SMOOTHED(-14, 9) < SMOOTHED(2, 0)) << 7) + ((SMOOTHED(7, -3) < SMOOTHED(22, 6)) << 6) + ((SMOOTHED(-6, 6) < SMOOTHED(-8, -5)) << 5) + ((SMOOTHED(-5, 9) < SMOOTHED(7, -1)) << 4) + ((SMOOTHED(-3, -7) < SMOOTHED(-10, -18)) << 3) + ((SMOOTHED(4, -5) < SMOOTHED(0, 11)) << 2) + ((SMOOTHED(2, 3) < SMOOTHED(9, 10)) << 1) + ((SMOOTHED(-10, 3) < SMOOTHED(4, 9)) << 0));

@ -651,6 +651,33 @@ TEST(Features2d_RotationInvariance_Descriptor_SIFT, regression)
test.safe_run();
}
TEST(Features2d_RotationInvariance_Descriptor_BRIEF_64, regression)
{
DescriptorRotationInvarianceTest test(SURF::create(),
BriefDescriptorExtractor::create(64,true),
NORM_L1,
0.98f);
test.safe_run();
}
TEST(Features2d_RotationInvariance_Descriptor_BRIEF_32, regression)
{
DescriptorRotationInvarianceTest test(SURF::create(),
BriefDescriptorExtractor::create(32,true),
NORM_L1,
0.97f);
test.safe_run();
}
TEST(Features2d_RotationInvariance_Descriptor_BRIEF_16, regression)
{
DescriptorRotationInvarianceTest test(SURF::create(),
BriefDescriptorExtractor::create(16,true),
NORM_L1,
0.85f);
test.safe_run();
}
/*
* Detector's scale invariance check
*/

Loading…
Cancel
Save