moved nonfree and a part of features2d to opencv_contrib/xfeatures2d
This commit is contained in:
@@ -1,184 +0,0 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009-2010, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
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(InputArray _sum, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors)
|
||||
{
|
||||
Mat sum = _sum.getMat(), descriptors = _descriptors.getMat();
|
||||
for (int i = 0; i < (int)keypoints.size(); ++i)
|
||||
{
|
||||
uchar* desc = descriptors.ptr(i);
|
||||
const KeyPoint& pt = keypoints[i];
|
||||
#include "generated_16.i"
|
||||
}
|
||||
}
|
||||
|
||||
static void pixelTests32(InputArray _sum, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors)
|
||||
{
|
||||
Mat sum = _sum.getMat(), descriptors = _descriptors.getMat();
|
||||
for (int i = 0; i < (int)keypoints.size(); ++i)
|
||||
{
|
||||
uchar* desc = descriptors.ptr(i);
|
||||
const KeyPoint& pt = keypoints[i];
|
||||
|
||||
#include "generated_32.i"
|
||||
}
|
||||
}
|
||||
|
||||
static void pixelTests64(InputArray _sum, const std::vector<KeyPoint>& keypoints, OutputArray _descriptors)
|
||||
{
|
||||
Mat sum = _sum.getMat(), descriptors = _descriptors.getMat();
|
||||
for (int i = 0; i < (int)keypoints.size(); ++i)
|
||||
{
|
||||
uchar* desc = descriptors.ptr(i);
|
||||
const KeyPoint& pt = keypoints[i];
|
||||
|
||||
#include "generated_64.i"
|
||||
}
|
||||
}
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
BriefDescriptorExtractor::BriefDescriptorExtractor(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(Error::StsBadArg, "bytes must be 16, 32, or 64");
|
||||
}
|
||||
}
|
||||
|
||||
int BriefDescriptorExtractor::descriptorSize() const
|
||||
{
|
||||
return bytes_;
|
||||
}
|
||||
|
||||
int BriefDescriptorExtractor::descriptorType() const
|
||||
{
|
||||
return CV_8UC1;
|
||||
}
|
||||
|
||||
int BriefDescriptorExtractor::defaultNorm() const
|
||||
{
|
||||
return NORM_HAMMING;
|
||||
}
|
||||
|
||||
void BriefDescriptorExtractor::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(Error::StsBadArg, "descriptorSize must be 16, 32, or 64");
|
||||
}
|
||||
bytes_ = dSize;
|
||||
}
|
||||
|
||||
void BriefDescriptorExtractor::write( FileStorage& fs) const
|
||||
{
|
||||
fs << "descriptorSize" << bytes_;
|
||||
}
|
||||
|
||||
void BriefDescriptorExtractor::computeImpl(InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors) const
|
||||
{
|
||||
// Construct integral image for fast smoothing (box filter)
|
||||
Mat sum;
|
||||
|
||||
Mat grayImage = image.getMat();
|
||||
if( image.type() != CV_8U ) cvtColor( image, grayImage, COLOR_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.create((int)keypoints.size(), bytes_, CV_8U);
|
||||
descriptors.setTo(Scalar::all(0));
|
||||
test_fn_(sum, keypoints, descriptors);
|
||||
}
|
||||
|
||||
} // namespace cv
|
@@ -98,13 +98,6 @@ void DescriptorExtractor::removeBorderKeypoints( std::vector<KeyPoint>& keypoint
|
||||
|
||||
Ptr<DescriptorExtractor> DescriptorExtractor::create(const String& descriptorExtractorType)
|
||||
{
|
||||
if( descriptorExtractorType.find("Opponent") == 0 )
|
||||
{
|
||||
size_t pos = String("Opponent").size();
|
||||
String type = descriptorExtractorType.substr(pos);
|
||||
return makePtr<OpponentColorDescriptorExtractor>(DescriptorExtractor::create(type));
|
||||
}
|
||||
|
||||
return Algorithm::create<DescriptorExtractor>("Feature2D." + descriptorExtractorType);
|
||||
}
|
||||
|
||||
@@ -114,151 +107,4 @@ CV_WRAP void Feature2D::compute( InputArray image, CV_OUT CV_IN_OUT std::vector<
|
||||
DescriptorExtractor::compute(image, keypoints, descriptors);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/****************************************************************************************\
|
||||
* OpponentColorDescriptorExtractor *
|
||||
\****************************************************************************************/
|
||||
OpponentColorDescriptorExtractor::OpponentColorDescriptorExtractor( const Ptr<DescriptorExtractor>& _descriptorExtractor ) :
|
||||
descriptorExtractor(_descriptorExtractor)
|
||||
{
|
||||
CV_Assert( descriptorExtractor );
|
||||
}
|
||||
|
||||
static void convertBGRImageToOpponentColorSpace( const Mat& bgrImage, std::vector<Mat>& opponentChannels )
|
||||
{
|
||||
if( bgrImage.type() != CV_8UC3 )
|
||||
CV_Error( Error::StsBadArg, "input image must be an BGR image of type CV_8UC3" );
|
||||
|
||||
// Prepare opponent color space storage matrices.
|
||||
opponentChannels.resize( 3 );
|
||||
opponentChannels[0] = cv::Mat(bgrImage.size(), CV_8UC1); // R-G RED-GREEN
|
||||
opponentChannels[1] = cv::Mat(bgrImage.size(), CV_8UC1); // R+G-2B YELLOW-BLUE
|
||||
opponentChannels[2] = cv::Mat(bgrImage.size(), CV_8UC1); // R+G+B
|
||||
|
||||
for(int y = 0; y < bgrImage.rows; ++y)
|
||||
for(int x = 0; x < bgrImage.cols; ++x)
|
||||
{
|
||||
Vec3b v = bgrImage.at<Vec3b>(y, x);
|
||||
uchar& b = v[0];
|
||||
uchar& g = v[1];
|
||||
uchar& r = v[2];
|
||||
|
||||
opponentChannels[0].at<uchar>(y, x) = saturate_cast<uchar>(0.5f * (255 + g - r)); // (R - G)/sqrt(2), but converted to the destination data type
|
||||
opponentChannels[1].at<uchar>(y, x) = saturate_cast<uchar>(0.25f * (510 + r + g - 2*b)); // (R + G - 2B)/sqrt(6), but converted to the destination data type
|
||||
opponentChannels[2].at<uchar>(y, x) = saturate_cast<uchar>(1.f/3.f * (r + g + b)); // (R + G + B)/sqrt(3), but converted to the destination data type
|
||||
}
|
||||
}
|
||||
|
||||
struct KP_LessThan
|
||||
{
|
||||
KP_LessThan(const std::vector<KeyPoint>& _kp) : kp(&_kp) {}
|
||||
bool operator()(int i, int j) const
|
||||
{
|
||||
return (*kp)[i].class_id < (*kp)[j].class_id;
|
||||
}
|
||||
const std::vector<KeyPoint>* kp;
|
||||
};
|
||||
|
||||
void OpponentColorDescriptorExtractor::computeImpl( InputArray _bgrImage, std::vector<KeyPoint>& keypoints, OutputArray descriptors ) const
|
||||
{
|
||||
Mat bgrImage = _bgrImage.getMat();
|
||||
std::vector<Mat> opponentChannels;
|
||||
convertBGRImageToOpponentColorSpace( bgrImage, opponentChannels );
|
||||
|
||||
const int N = 3; // channels count
|
||||
std::vector<KeyPoint> channelKeypoints[N];
|
||||
Mat channelDescriptors[N];
|
||||
std::vector<int> idxs[N];
|
||||
|
||||
// Compute descriptors three times, once for each Opponent channel to concatenate into a single color descriptor
|
||||
int maxKeypointsCount = 0;
|
||||
for( int ci = 0; ci < N; ci++ )
|
||||
{
|
||||
channelKeypoints[ci].insert( channelKeypoints[ci].begin(), keypoints.begin(), keypoints.end() );
|
||||
// Use class_id member to get indices into initial keypoints vector
|
||||
for( size_t ki = 0; ki < channelKeypoints[ci].size(); ki++ )
|
||||
channelKeypoints[ci][ki].class_id = (int)ki;
|
||||
|
||||
descriptorExtractor->compute( opponentChannels[ci], channelKeypoints[ci], channelDescriptors[ci] );
|
||||
idxs[ci].resize( channelKeypoints[ci].size() );
|
||||
for( size_t ki = 0; ki < channelKeypoints[ci].size(); ki++ )
|
||||
{
|
||||
idxs[ci][ki] = (int)ki;
|
||||
}
|
||||
std::sort( idxs[ci].begin(), idxs[ci].end(), KP_LessThan(channelKeypoints[ci]) );
|
||||
maxKeypointsCount = std::max( maxKeypointsCount, (int)channelKeypoints[ci].size());
|
||||
}
|
||||
|
||||
std::vector<KeyPoint> outKeypoints;
|
||||
outKeypoints.reserve( keypoints.size() );
|
||||
|
||||
int dSize = descriptorExtractor->descriptorSize();
|
||||
Mat mergedDescriptors( maxKeypointsCount, 3*dSize, descriptorExtractor->descriptorType() );
|
||||
int mergedCount = 0;
|
||||
// cp - current channel position
|
||||
size_t cp[] = {0, 0, 0};
|
||||
while( cp[0] < channelKeypoints[0].size() &&
|
||||
cp[1] < channelKeypoints[1].size() &&
|
||||
cp[2] < channelKeypoints[2].size() )
|
||||
{
|
||||
const int maxInitIdx = std::max( 0, std::max( channelKeypoints[0][idxs[0][cp[0]]].class_id,
|
||||
std::max( channelKeypoints[1][idxs[1][cp[1]]].class_id,
|
||||
channelKeypoints[2][idxs[2][cp[2]]].class_id ) ) );
|
||||
|
||||
while( channelKeypoints[0][idxs[0][cp[0]]].class_id < maxInitIdx && cp[0] < channelKeypoints[0].size() ) { cp[0]++; }
|
||||
while( channelKeypoints[1][idxs[1][cp[1]]].class_id < maxInitIdx && cp[1] < channelKeypoints[1].size() ) { cp[1]++; }
|
||||
while( channelKeypoints[2][idxs[2][cp[2]]].class_id < maxInitIdx && cp[2] < channelKeypoints[2].size() ) { cp[2]++; }
|
||||
if( cp[0] >= channelKeypoints[0].size() || cp[1] >= channelKeypoints[1].size() || cp[2] >= channelKeypoints[2].size() )
|
||||
break;
|
||||
|
||||
if( channelKeypoints[0][idxs[0][cp[0]]].class_id == maxInitIdx &&
|
||||
channelKeypoints[1][idxs[1][cp[1]]].class_id == maxInitIdx &&
|
||||
channelKeypoints[2][idxs[2][cp[2]]].class_id == maxInitIdx )
|
||||
{
|
||||
outKeypoints.push_back( keypoints[maxInitIdx] );
|
||||
// merge descriptors
|
||||
for( int ci = 0; ci < N; ci++ )
|
||||
{
|
||||
Mat dst = mergedDescriptors(Range(mergedCount, mergedCount+1), Range(ci*dSize, (ci+1)*dSize));
|
||||
channelDescriptors[ci].row( idxs[ci][cp[ci]] ).copyTo( dst );
|
||||
cp[ci]++;
|
||||
}
|
||||
mergedCount++;
|
||||
}
|
||||
}
|
||||
mergedDescriptors.rowRange(0, mergedCount).copyTo( descriptors );
|
||||
std::swap( outKeypoints, keypoints );
|
||||
}
|
||||
|
||||
void OpponentColorDescriptorExtractor::read( const FileNode& fn )
|
||||
{
|
||||
descriptorExtractor->read(fn);
|
||||
}
|
||||
|
||||
void OpponentColorDescriptorExtractor::write( FileStorage& fs ) const
|
||||
{
|
||||
descriptorExtractor->write(fs);
|
||||
}
|
||||
|
||||
int OpponentColorDescriptorExtractor::descriptorSize() const
|
||||
{
|
||||
return 3*descriptorExtractor->descriptorSize();
|
||||
}
|
||||
|
||||
int OpponentColorDescriptorExtractor::descriptorType() const
|
||||
{
|
||||
return descriptorExtractor->descriptorType();
|
||||
}
|
||||
|
||||
int OpponentColorDescriptorExtractor::defaultNorm() const
|
||||
{
|
||||
return descriptorExtractor->defaultNorm();
|
||||
}
|
||||
|
||||
bool OpponentColorDescriptorExtractor::empty() const
|
||||
{
|
||||
return !descriptorExtractor || descriptorExtractor->empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -106,24 +106,6 @@ void FeatureDetector::removeInvalidPoints( const Mat& mask, std::vector<KeyPoint
|
||||
|
||||
Ptr<FeatureDetector> FeatureDetector::create( const String& detectorType )
|
||||
{
|
||||
if( detectorType.find("Grid") == 0 )
|
||||
{
|
||||
return makePtr<GridAdaptedFeatureDetector>(FeatureDetector::create(
|
||||
detectorType.substr(strlen("Grid"))));
|
||||
}
|
||||
|
||||
if( detectorType.find("Pyramid") == 0 )
|
||||
{
|
||||
return makePtr<PyramidAdaptedFeatureDetector>(FeatureDetector::create(
|
||||
detectorType.substr(strlen("Pyramid"))));
|
||||
}
|
||||
|
||||
if( detectorType.find("Dynamic") == 0 )
|
||||
{
|
||||
return makePtr<DynamicAdaptedFeatureDetector>(AdjusterAdapter::create(
|
||||
detectorType.substr(strlen("Dynamic"))));
|
||||
}
|
||||
|
||||
if( detectorType.compare( "HARRIS" ) == 0 )
|
||||
{
|
||||
Ptr<FeatureDetector> fd = FeatureDetector::create("GFTT");
|
||||
@@ -176,212 +158,4 @@ void GFTTDetector::detectImpl( InputArray _image, std::vector<KeyPoint>& keypoin
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* DenseFeatureDetector
|
||||
*/
|
||||
DenseFeatureDetector::DenseFeatureDetector( float _initFeatureScale, int _featureScaleLevels,
|
||||
float _featureScaleMul, int _initXyStep,
|
||||
int _initImgBound, bool _varyXyStepWithScale,
|
||||
bool _varyImgBoundWithScale ) :
|
||||
initFeatureScale(_initFeatureScale), featureScaleLevels(_featureScaleLevels),
|
||||
featureScaleMul(_featureScaleMul), initXyStep(_initXyStep), initImgBound(_initImgBound),
|
||||
varyXyStepWithScale(_varyXyStepWithScale), varyImgBoundWithScale(_varyImgBoundWithScale)
|
||||
{}
|
||||
|
||||
|
||||
void DenseFeatureDetector::detectImpl( InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask ) const
|
||||
{
|
||||
Mat image = _image.getMat(), mask = _mask.getMat();
|
||||
|
||||
float curScale = static_cast<float>(initFeatureScale);
|
||||
int curStep = initXyStep;
|
||||
int curBound = initImgBound;
|
||||
for( int curLevel = 0; curLevel < featureScaleLevels; curLevel++ )
|
||||
{
|
||||
for( int x = curBound; x < image.cols - curBound; x += curStep )
|
||||
{
|
||||
for( int y = curBound; y < image.rows - curBound; y += curStep )
|
||||
{
|
||||
keypoints.push_back( KeyPoint(static_cast<float>(x), static_cast<float>(y), curScale) );
|
||||
}
|
||||
}
|
||||
|
||||
curScale = static_cast<float>(curScale * featureScaleMul);
|
||||
if( varyXyStepWithScale ) curStep = static_cast<int>( curStep * featureScaleMul + 0.5f );
|
||||
if( varyImgBoundWithScale ) curBound = static_cast<int>( curBound * featureScaleMul + 0.5f );
|
||||
}
|
||||
|
||||
KeyPointsFilter::runByPixelsMask( keypoints, mask );
|
||||
}
|
||||
|
||||
/*
|
||||
* GridAdaptedFeatureDetector
|
||||
*/
|
||||
GridAdaptedFeatureDetector::GridAdaptedFeatureDetector( const Ptr<FeatureDetector>& _detector,
|
||||
int _maxTotalKeypoints, int _gridRows, int _gridCols )
|
||||
: detector(_detector), maxTotalKeypoints(_maxTotalKeypoints), gridRows(_gridRows), gridCols(_gridCols)
|
||||
{}
|
||||
|
||||
bool GridAdaptedFeatureDetector::empty() const
|
||||
{
|
||||
return !detector || detector->empty();
|
||||
}
|
||||
|
||||
struct ResponseComparator
|
||||
{
|
||||
bool operator() (const KeyPoint& a, const KeyPoint& b)
|
||||
{
|
||||
return std::abs(a.response) > std::abs(b.response);
|
||||
}
|
||||
};
|
||||
|
||||
static void keepStrongest( int N, std::vector<KeyPoint>& keypoints )
|
||||
{
|
||||
if( (int)keypoints.size() > N )
|
||||
{
|
||||
std::vector<KeyPoint>::iterator nth = keypoints.begin() + N;
|
||||
std::nth_element( keypoints.begin(), nth, keypoints.end(), ResponseComparator() );
|
||||
keypoints.erase( nth, keypoints.end() );
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
class GridAdaptedFeatureDetectorInvoker : public ParallelLoopBody
|
||||
{
|
||||
private:
|
||||
int gridRows_, gridCols_;
|
||||
int maxPerCell_;
|
||||
std::vector<KeyPoint>& keypoints_;
|
||||
const Mat& image_;
|
||||
const Mat& mask_;
|
||||
const Ptr<FeatureDetector>& detector_;
|
||||
Mutex* kptLock_;
|
||||
|
||||
GridAdaptedFeatureDetectorInvoker& operator=(const GridAdaptedFeatureDetectorInvoker&); // to quiet MSVC
|
||||
|
||||
public:
|
||||
|
||||
GridAdaptedFeatureDetectorInvoker(const Ptr<FeatureDetector>& detector, const Mat& image, const Mat& mask,
|
||||
std::vector<KeyPoint>& keypoints, int maxPerCell, int gridRows, int gridCols,
|
||||
cv::Mutex* kptLock)
|
||||
: gridRows_(gridRows), gridCols_(gridCols), maxPerCell_(maxPerCell),
|
||||
keypoints_(keypoints), image_(image), mask_(mask), detector_(detector),
|
||||
kptLock_(kptLock)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() (const Range& range) const
|
||||
{
|
||||
for (int i = range.start; i < range.end; ++i)
|
||||
{
|
||||
int celly = i / gridCols_;
|
||||
int cellx = i - celly * gridCols_;
|
||||
|
||||
Range row_range((celly*image_.rows)/gridRows_, ((celly+1)*image_.rows)/gridRows_);
|
||||
Range col_range((cellx*image_.cols)/gridCols_, ((cellx+1)*image_.cols)/gridCols_);
|
||||
|
||||
Mat sub_image = image_(row_range, col_range);
|
||||
Mat sub_mask;
|
||||
if (!mask_.empty()) sub_mask = mask_(row_range, col_range);
|
||||
|
||||
std::vector<KeyPoint> sub_keypoints;
|
||||
sub_keypoints.reserve(maxPerCell_);
|
||||
|
||||
detector_->detect( sub_image, sub_keypoints, sub_mask );
|
||||
keepStrongest( maxPerCell_, sub_keypoints );
|
||||
|
||||
std::vector<cv::KeyPoint>::iterator it = sub_keypoints.begin(),
|
||||
end = sub_keypoints.end();
|
||||
for( ; it != end; ++it )
|
||||
{
|
||||
it->pt.x += col_range.start;
|
||||
it->pt.y += row_range.start;
|
||||
}
|
||||
|
||||
cv::AutoLock join_keypoints(*kptLock_);
|
||||
keypoints_.insert( keypoints_.end(), sub_keypoints.begin(), sub_keypoints.end() );
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namepace
|
||||
|
||||
void GridAdaptedFeatureDetector::detectImpl( InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask ) const
|
||||
{
|
||||
if (_image.empty() || maxTotalKeypoints < gridRows * gridCols)
|
||||
{
|
||||
keypoints.clear();
|
||||
return;
|
||||
}
|
||||
keypoints.reserve(maxTotalKeypoints);
|
||||
int maxPerCell = maxTotalKeypoints / (gridRows * gridCols);
|
||||
|
||||
Mat image = _image.getMat(), mask = _mask.getMat();
|
||||
|
||||
cv::Mutex kptLock;
|
||||
cv::parallel_for_(cv::Range(0, gridRows * gridCols),
|
||||
GridAdaptedFeatureDetectorInvoker(detector, image, mask, keypoints, maxPerCell, gridRows, gridCols, &kptLock));
|
||||
}
|
||||
|
||||
/*
|
||||
* PyramidAdaptedFeatureDetector
|
||||
*/
|
||||
PyramidAdaptedFeatureDetector::PyramidAdaptedFeatureDetector( const Ptr<FeatureDetector>& _detector, int _maxLevel )
|
||||
: detector(_detector), maxLevel(_maxLevel)
|
||||
{}
|
||||
|
||||
bool PyramidAdaptedFeatureDetector::empty() const
|
||||
{
|
||||
return !detector || detector->empty();
|
||||
}
|
||||
|
||||
void PyramidAdaptedFeatureDetector::detectImpl( InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask ) const
|
||||
{
|
||||
Mat image = _image.getMat(), mask = _mask.getMat();
|
||||
Mat src = image;
|
||||
Mat src_mask = mask;
|
||||
|
||||
Mat dilated_mask;
|
||||
if( !mask.empty() )
|
||||
{
|
||||
dilate( mask, dilated_mask, Mat() );
|
||||
Mat mask255( mask.size(), CV_8UC1, Scalar(0) );
|
||||
mask255.setTo( Scalar(255), dilated_mask != 0 );
|
||||
dilated_mask = mask255;
|
||||
}
|
||||
|
||||
for( int l = 0, multiplier = 1; l <= maxLevel; ++l, multiplier *= 2 )
|
||||
{
|
||||
// Detect on current level of the pyramid
|
||||
std::vector<KeyPoint> new_pts;
|
||||
detector->detect( src, new_pts, src_mask );
|
||||
std::vector<KeyPoint>::iterator it = new_pts.begin(),
|
||||
end = new_pts.end();
|
||||
for( ; it != end; ++it)
|
||||
{
|
||||
it->pt.x *= multiplier;
|
||||
it->pt.y *= multiplier;
|
||||
it->size *= multiplier;
|
||||
it->octave = l;
|
||||
}
|
||||
keypoints.insert( keypoints.end(), new_pts.begin(), new_pts.end() );
|
||||
|
||||
// Downsample
|
||||
if( l < maxLevel )
|
||||
{
|
||||
Mat dst;
|
||||
pyrDown( src, dst );
|
||||
src = dst;
|
||||
|
||||
if( !mask.empty() )
|
||||
resize( dilated_mask, src_mask, src.size(), 0, 0, INTER_AREA );
|
||||
}
|
||||
}
|
||||
|
||||
if( !mask.empty() )
|
||||
KeyPointsFilter::runByPixelsMask( keypoints, mask );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -44,181 +44,4 @@
|
||||
namespace cv
|
||||
{
|
||||
|
||||
DynamicAdaptedFeatureDetector::DynamicAdaptedFeatureDetector(const Ptr<AdjusterAdapter>& a,
|
||||
int min_features, int max_features, int max_iters ) :
|
||||
escape_iters_(max_iters), min_features_(min_features), max_features_(max_features), adjuster_(a)
|
||||
{}
|
||||
|
||||
bool DynamicAdaptedFeatureDetector::empty() const
|
||||
{
|
||||
return !adjuster_ || adjuster_->empty();
|
||||
}
|
||||
|
||||
void DynamicAdaptedFeatureDetector::detectImpl(InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask) const
|
||||
{
|
||||
Mat image = _image.getMat(), mask = _mask.getMat();
|
||||
|
||||
//for oscillation testing
|
||||
bool down = false;
|
||||
bool up = false;
|
||||
|
||||
//flag for whether the correct threshhold has been reached
|
||||
bool thresh_good = false;
|
||||
|
||||
Ptr<AdjusterAdapter> adjuster = adjuster_->clone();
|
||||
|
||||
//break if the desired number hasn't been reached.
|
||||
int iter_count = escape_iters_;
|
||||
|
||||
while( iter_count > 0 && !(down && up) && !thresh_good && adjuster->good() )
|
||||
{
|
||||
keypoints.clear();
|
||||
|
||||
//the adjuster takes care of calling the detector with updated parameters
|
||||
adjuster->detect(image, keypoints,mask);
|
||||
|
||||
if( int(keypoints.size()) < min_features_ )
|
||||
{
|
||||
down = true;
|
||||
adjuster->tooFew(min_features_, (int)keypoints.size());
|
||||
}
|
||||
else if( int(keypoints.size()) > max_features_ )
|
||||
{
|
||||
up = true;
|
||||
adjuster->tooMany(max_features_, (int)keypoints.size());
|
||||
}
|
||||
else
|
||||
thresh_good = true;
|
||||
|
||||
iter_count--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FastAdjuster::FastAdjuster( int init_thresh, bool nonmax, int min_thresh, int max_thresh ) :
|
||||
thresh_(init_thresh), nonmax_(nonmax), init_thresh_(init_thresh),
|
||||
min_thresh_(min_thresh), max_thresh_(max_thresh)
|
||||
{}
|
||||
|
||||
void FastAdjuster::detectImpl(InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask) const
|
||||
{
|
||||
FastFeatureDetector(thresh_, nonmax_).detect(image, keypoints, mask);
|
||||
}
|
||||
|
||||
void FastAdjuster::tooFew(int, int)
|
||||
{
|
||||
//fast is easy to adjust
|
||||
thresh_--;
|
||||
}
|
||||
|
||||
void FastAdjuster::tooMany(int, int)
|
||||
{
|
||||
//fast is easy to adjust
|
||||
thresh_++;
|
||||
}
|
||||
|
||||
//return whether or not the threshhold is beyond
|
||||
//a useful point
|
||||
bool FastAdjuster::good() const
|
||||
{
|
||||
return (thresh_ > min_thresh_) && (thresh_ < max_thresh_);
|
||||
}
|
||||
|
||||
Ptr<AdjusterAdapter> FastAdjuster::clone() const
|
||||
{
|
||||
Ptr<AdjusterAdapter> cloned_obj(new FastAdjuster( init_thresh_, nonmax_, min_thresh_, max_thresh_ ));
|
||||
return cloned_obj;
|
||||
}
|
||||
|
||||
StarAdjuster::StarAdjuster(double initial_thresh, double min_thresh, double max_thresh) :
|
||||
thresh_(initial_thresh), init_thresh_(initial_thresh),
|
||||
min_thresh_(min_thresh), max_thresh_(max_thresh)
|
||||
{}
|
||||
|
||||
void StarAdjuster::detectImpl(InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask) const
|
||||
{
|
||||
StarFeatureDetector detector_tmp(16, cvRound(thresh_), 10, 8, 3);
|
||||
detector_tmp.detect(image, keypoints, mask);
|
||||
}
|
||||
|
||||
void StarAdjuster::tooFew(int, int)
|
||||
{
|
||||
thresh_ *= 0.9;
|
||||
if (thresh_ < 1.1)
|
||||
thresh_ = 1.1;
|
||||
}
|
||||
|
||||
void StarAdjuster::tooMany(int, int)
|
||||
{
|
||||
thresh_ *= 1.1;
|
||||
}
|
||||
|
||||
bool StarAdjuster::good() const
|
||||
{
|
||||
return (thresh_ > min_thresh_) && (thresh_ < max_thresh_);
|
||||
}
|
||||
|
||||
Ptr<AdjusterAdapter> StarAdjuster::clone() const
|
||||
{
|
||||
Ptr<AdjusterAdapter> cloned_obj(new StarAdjuster( init_thresh_, min_thresh_, max_thresh_ ));
|
||||
return cloned_obj;
|
||||
}
|
||||
|
||||
SurfAdjuster::SurfAdjuster( double initial_thresh, double min_thresh, double max_thresh ) :
|
||||
thresh_(initial_thresh), init_thresh_(initial_thresh),
|
||||
min_thresh_(min_thresh), max_thresh_(max_thresh)
|
||||
{}
|
||||
|
||||
void SurfAdjuster::detectImpl(InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask) const
|
||||
{
|
||||
Ptr<FeatureDetector> surf = FeatureDetector::create("SURF");
|
||||
surf->set("hessianThreshold", thresh_);
|
||||
surf->detect(image, keypoints, mask);
|
||||
}
|
||||
|
||||
void SurfAdjuster::tooFew(int, int)
|
||||
{
|
||||
thresh_ *= 0.9;
|
||||
if (thresh_ < 1.1)
|
||||
thresh_ = 1.1;
|
||||
}
|
||||
|
||||
void SurfAdjuster::tooMany(int, int)
|
||||
{
|
||||
thresh_ *= 1.1;
|
||||
}
|
||||
|
||||
//return whether or not the threshhold is beyond
|
||||
//a useful point
|
||||
bool SurfAdjuster::good() const
|
||||
{
|
||||
return (thresh_ > min_thresh_) && (thresh_ < max_thresh_);
|
||||
}
|
||||
|
||||
Ptr<AdjusterAdapter> SurfAdjuster::clone() const
|
||||
{
|
||||
Ptr<AdjusterAdapter> cloned_obj(new SurfAdjuster( init_thresh_, min_thresh_, max_thresh_ ));
|
||||
return cloned_obj;
|
||||
}
|
||||
|
||||
Ptr<AdjusterAdapter> AdjusterAdapter::create( const String& detectorType )
|
||||
{
|
||||
Ptr<AdjusterAdapter> adapter;
|
||||
|
||||
if( !detectorType.compare( "FAST" ) )
|
||||
{
|
||||
adapter = makePtr<FastAdjuster>();
|
||||
}
|
||||
else if( !detectorType.compare( "STAR" ) )
|
||||
{
|
||||
adapter = makePtr<StarAdjuster>();
|
||||
}
|
||||
else if( !detectorType.compare( "SURF" ) )
|
||||
{
|
||||
adapter = makePtr<SurfAdjuster>();
|
||||
}
|
||||
|
||||
return adapter;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -556,56 +556,3 @@ int cv::getNearestPoint( const std::vector<Point2f>& recallPrecisionCurve, float
|
||||
|
||||
return nearestPointIndex;
|
||||
}
|
||||
|
||||
void cv::evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& img2, const Mat& H1to2,
|
||||
std::vector<KeyPoint>& keypoints1, std::vector<KeyPoint>& keypoints2,
|
||||
std::vector<std::vector<DMatch> >* _matches1to2, std::vector<std::vector<uchar> >* _correctMatches1to2Mask,
|
||||
std::vector<Point2f>& recallPrecisionCurve,
|
||||
const Ptr<GenericDescriptorMatcher>& _dmatcher )
|
||||
{
|
||||
Ptr<GenericDescriptorMatcher> dmatcher = _dmatcher;
|
||||
dmatcher->clear();
|
||||
|
||||
std::vector<std::vector<DMatch> > *matches1to2, buf1;
|
||||
matches1to2 = _matches1to2 != 0 ? _matches1to2 : &buf1;
|
||||
|
||||
std::vector<std::vector<uchar> > *correctMatches1to2Mask, buf2;
|
||||
correctMatches1to2Mask = _correctMatches1to2Mask != 0 ? _correctMatches1to2Mask : &buf2;
|
||||
|
||||
if( keypoints1.empty() )
|
||||
CV_Error( Error::StsBadArg, "keypoints1 must not be empty" );
|
||||
|
||||
if( matches1to2->empty() && !dmatcher )
|
||||
CV_Error( Error::StsBadArg, "dmatch must not be empty when matches1to2 is empty" );
|
||||
|
||||
bool computeKeypoints2ByPrj = keypoints2.empty();
|
||||
if( computeKeypoints2ByPrj )
|
||||
{
|
||||
CV_Error(Error::StsNotImplemented, "");
|
||||
// TODO: add computing keypoints2 from keypoints1 using H1to2
|
||||
}
|
||||
|
||||
if( matches1to2->empty() || computeKeypoints2ByPrj )
|
||||
{
|
||||
dmatcher->clear();
|
||||
dmatcher->radiusMatch( img1, keypoints1, img2, keypoints2, *matches1to2, std::numeric_limits<float>::max() );
|
||||
}
|
||||
float repeatability;
|
||||
int correspCount;
|
||||
Mat thresholdedOverlapMask; // thresholded allOverlapErrors
|
||||
calculateRepeatability( img1, img2, H1to2, keypoints1, keypoints2, repeatability, correspCount, &thresholdedOverlapMask );
|
||||
|
||||
correctMatches1to2Mask->resize(matches1to2->size());
|
||||
for( size_t i = 0; i < matches1to2->size(); i++ )
|
||||
{
|
||||
(*correctMatches1to2Mask)[i].resize((*matches1to2)[i].size());
|
||||
for( size_t j = 0;j < (*matches1to2)[i].size(); j++ )
|
||||
{
|
||||
int indexQuery = (*matches1to2)[i][j].queryIdx;
|
||||
int indexTrain = (*matches1to2)[i][j].trainIdx;
|
||||
(*correctMatches1to2Mask)[i][j] = thresholdedOverlapMask.at<uchar>( indexQuery, indexTrain );
|
||||
}
|
||||
}
|
||||
|
||||
computeRecallPrecisionCurve( *matches1to2, *correctMatches1to2Mask, recallPrecisionCurve );
|
||||
}
|
||||
|
@@ -62,24 +62,11 @@ CV_INIT_ALGORITHM(BRISK, "Feature2D.BRISK",
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CV_INIT_ALGORITHM(BriefDescriptorExtractor, "Feature2D.BRIEF",
|
||||
obj.info()->addParam(obj, "bytes", obj.bytes_))
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CV_INIT_ALGORITHM(FastFeatureDetector, "Feature2D.FAST",
|
||||
obj.info()->addParam(obj, "threshold", obj.threshold);
|
||||
obj.info()->addParam(obj, "nonmaxSuppression", obj.nonmaxSuppression);
|
||||
obj.info()->addParam(obj, "type", obj.type))
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CV_INIT_ALGORITHM(StarDetector, "Feature2D.STAR",
|
||||
obj.info()->addParam(obj, "maxSize", obj.maxSize);
|
||||
obj.info()->addParam(obj, "responseThreshold", obj.responseThreshold);
|
||||
obj.info()->addParam(obj, "lineThresholdProjected", obj.lineThresholdProjected);
|
||||
obj.info()->addParam(obj, "lineThresholdBinarized", obj.lineThresholdBinarized);
|
||||
obj.info()->addParam(obj, "suppressNonmaxSize", obj.suppressNonmaxSize))
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -108,14 +95,6 @@ CV_INIT_ALGORITHM(ORB, "Feature2D.ORB",
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CV_INIT_ALGORITHM(FREAK, "Feature2D.FREAK",
|
||||
obj.info()->addParam(obj, "orientationNormalized", obj.orientationNormalized);
|
||||
obj.info()->addParam(obj, "scaleNormalized", obj.scaleNormalized);
|
||||
obj.info()->addParam(obj, "patternScale", obj.patternScale);
|
||||
obj.info()->addParam(obj, "nbOctave", obj.nOctaves))
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CV_INIT_ALGORITHM(GFTTDetector, "Feature2D.GFTT",
|
||||
obj.info()->addParam(obj, "nfeatures", obj.nfeatures);
|
||||
obj.info()->addParam(obj, "qualityLevel", obj.qualityLevel);
|
||||
@@ -181,23 +160,6 @@ CV_INIT_ALGORITHM(HarrisDetector, "Feature2D.HARRIS",
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CV_INIT_ALGORITHM(DenseFeatureDetector, "Feature2D.Dense",
|
||||
obj.info()->addParam(obj, "initFeatureScale", obj.initFeatureScale);
|
||||
obj.info()->addParam(obj, "featureScaleLevels", obj.featureScaleLevels);
|
||||
obj.info()->addParam(obj, "featureScaleMul", obj.featureScaleMul);
|
||||
obj.info()->addParam(obj, "initXyStep", obj.initXyStep);
|
||||
obj.info()->addParam(obj, "initImgBound", obj.initImgBound);
|
||||
obj.info()->addParam(obj, "varyXyStepWithScale", obj.varyXyStepWithScale);
|
||||
obj.info()->addParam(obj, "varyImgBoundWithScale", obj.varyImgBoundWithScale))
|
||||
|
||||
CV_INIT_ALGORITHM(GridAdaptedFeatureDetector, "Feature2D.Grid",
|
||||
obj.info()->addParam<FeatureDetector>(obj, "detector", obj.detector, false, 0, 0); // Extra params added to avoid VS2013 fatal error in opencv2/core.hpp (decl. of addParam)
|
||||
obj.info()->addParam(obj, "maxTotalKeypoints", obj.maxTotalKeypoints);
|
||||
obj.info()->addParam(obj, "gridRows", obj.gridRows);
|
||||
obj.info()->addParam(obj, "gridCols", obj.gridCols))
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CV_INIT_ALGORITHM(BFMatcher, "DescriptorMatcher.BFMatcher",
|
||||
obj.info()->addParam(obj, "normType", obj.normType);
|
||||
obj.info()->addParam(obj, "crossCheck", obj.crossCheck))
|
||||
@@ -209,19 +171,14 @@ CV_INIT_ALGORITHM(FlannBasedMatcher, "DescriptorMatcher.FlannBasedMatcher",)
|
||||
bool cv::initModule_features2d(void)
|
||||
{
|
||||
bool all = true;
|
||||
all &= !BriefDescriptorExtractor_info_auto.name().empty();
|
||||
all &= !BRISK_info_auto.name().empty();
|
||||
all &= !FastFeatureDetector_info_auto.name().empty();
|
||||
all &= !StarDetector_info_auto.name().empty();
|
||||
all &= !MSER_info_auto.name().empty();
|
||||
all &= !FREAK_info_auto.name().empty();
|
||||
all &= !ORB_info_auto.name().empty();
|
||||
all &= !GFTTDetector_info_auto.name().empty();
|
||||
all &= !KAZE_info_auto.name().empty();
|
||||
all &= !AKAZE_info_auto.name().empty();
|
||||
all &= !HarrisDetector_info_auto.name().empty();
|
||||
all &= !DenseFeatureDetector_info_auto.name().empty();
|
||||
all &= !GridAdaptedFeatureDetector_info_auto.name().empty();
|
||||
all &= !HarrisDetector_info_auto.name().empty();
|
||||
all &= !BFMatcher_info_auto.name().empty();
|
||||
all &= !FlannBasedMatcher_info_auto.name().empty();
|
||||
|
||||
|
@@ -1,733 +0,0 @@
|
||||
// freak.cpp
|
||||
//
|
||||
// Copyright (C) 2011-2012 Signal processing laboratory 2, EPFL,
|
||||
// Kirell Benzi (kirell.benzi@epfl.ch),
|
||||
// Raphael Ortiz (raphael.ortiz@a3.epfl.ch)
|
||||
// Alexandre Alahi (alexandre.alahi@epfl.ch)
|
||||
// and Pierre Vandergheynst (pierre.vandergheynst@epfl.ch)
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include <fstream>
|
||||
#include <stdlib.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <bitset>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <string.h>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
static const double FREAK_SQRT2 = 1.4142135623731;
|
||||
static const double FREAK_LOG2 = 0.693147180559945;
|
||||
static const int FREAK_NB_ORIENTATION = 256;
|
||||
static const int FREAK_NB_POINTS = 43;
|
||||
static const int FREAK_SMALLEST_KP_SIZE = 7; // smallest size of keypoints
|
||||
static const int FREAK_NB_SCALES = FREAK::NB_SCALES;
|
||||
static const int FREAK_NB_PAIRS = FREAK::NB_PAIRS;
|
||||
static const int FREAK_NB_ORIENPAIRS = FREAK::NB_ORIENPAIRS;
|
||||
|
||||
// default pairs
|
||||
static const int FREAK_DEF_PAIRS[FREAK::NB_PAIRS] =
|
||||
{
|
||||
404,431,818,511,181,52,311,874,774,543,719,230,417,205,11,
|
||||
560,149,265,39,306,165,857,250,8,61,15,55,717,44,412,
|
||||
592,134,761,695,660,782,625,487,549,516,271,665,762,392,178,
|
||||
796,773,31,672,845,548,794,677,654,241,831,225,238,849,83,
|
||||
691,484,826,707,122,517,583,731,328,339,571,475,394,472,580,
|
||||
381,137,93,380,327,619,729,808,218,213,459,141,806,341,95,
|
||||
382,568,124,750,193,749,706,843,79,199,317,329,768,198,100,
|
||||
466,613,78,562,783,689,136,838,94,142,164,679,219,419,366,
|
||||
418,423,77,89,523,259,683,312,555,20,470,684,123,458,453,833,
|
||||
72,113,253,108,313,25,153,648,411,607,618,128,305,232,301,84,
|
||||
56,264,371,46,407,360,38,99,176,710,114,578,66,372,653,
|
||||
129,359,424,159,821,10,323,393,5,340,891,9,790,47,0,175,346,
|
||||
236,26,172,147,574,561,32,294,429,724,755,398,787,288,299,
|
||||
769,565,767,722,757,224,465,723,498,467,235,127,802,446,233,
|
||||
544,482,800,318,16,532,801,441,554,173,60,530,713,469,30,
|
||||
212,630,899,170,266,799,88,49,512,399,23,500,107,524,90,
|
||||
194,143,135,192,206,345,148,71,119,101,563,870,158,254,214,
|
||||
276,464,332,725,188,385,24,476,40,231,620,171,258,67,109,
|
||||
844,244,187,388,701,690,50,7,850,479,48,522,22,154,12,659,
|
||||
736,655,577,737,830,811,174,21,237,335,353,234,53,270,62,
|
||||
182,45,177,245,812,673,355,556,612,166,204,54,248,365,226,
|
||||
242,452,700,685,573,14,842,481,468,781,564,416,179,405,35,
|
||||
819,608,624,367,98,643,448,2,460,676,440,240,130,146,184,
|
||||
185,430,65,807,377,82,121,708,239,310,138,596,730,575,477,
|
||||
851,797,247,27,85,586,307,779,326,494,856,324,827,96,748,
|
||||
13,397,125,688,702,92,293,716,277,140,112,4,80,855,839,1,
|
||||
413,347,584,493,289,696,19,751,379,76,73,115,6,590,183,734,
|
||||
197,483,217,344,330,400,186,243,587,220,780,200,793,246,824,
|
||||
41,735,579,81,703,322,760,720,139,480,490,91,814,813,163,
|
||||
152,488,763,263,425,410,576,120,319,668,150,160,302,491,515,
|
||||
260,145,428,97,251,395,272,252,18,106,358,854,485,144,550,
|
||||
131,133,378,68,102,104,58,361,275,209,697,582,338,742,589,
|
||||
325,408,229,28,304,191,189,110,126,486,211,547,533,70,215,
|
||||
670,249,36,581,389,605,331,518,442,822
|
||||
};
|
||||
|
||||
// used to sort pairs during pairs selection
|
||||
struct PairStat
|
||||
{
|
||||
double mean;
|
||||
int idx;
|
||||
};
|
||||
|
||||
struct sortMean
|
||||
{
|
||||
bool operator()( const PairStat& a, const PairStat& b ) const
|
||||
{
|
||||
return a.mean < b.mean;
|
||||
}
|
||||
};
|
||||
|
||||
void FREAK::buildPattern()
|
||||
{
|
||||
if( patternScale == patternScale0 && nOctaves == nOctaves0 && !patternLookup.empty() )
|
||||
return;
|
||||
|
||||
nOctaves0 = nOctaves;
|
||||
patternScale0 = patternScale;
|
||||
|
||||
patternLookup.resize(FREAK_NB_SCALES*FREAK_NB_ORIENTATION*FREAK_NB_POINTS);
|
||||
double scaleStep = std::pow(2.0, (double)(nOctaves)/FREAK_NB_SCALES ); // 2 ^ ( (nOctaves-1) /nbScales)
|
||||
double scalingFactor, alpha, beta, theta = 0;
|
||||
|
||||
// pattern definition, radius normalized to 1.0 (outer point position+sigma=1.0)
|
||||
const int n[8] = {6,6,6,6,6,6,6,1}; // number of points on each concentric circle (from outer to inner)
|
||||
const double bigR(2.0/3.0); // bigger radius
|
||||
const double smallR(2.0/24.0); // smaller radius
|
||||
const double unitSpace( (bigR-smallR)/21.0 ); // define spaces between concentric circles (from center to outer: 1,2,3,4,5,6)
|
||||
// radii of the concentric cirles (from outer to inner)
|
||||
const double radius[8] = {bigR, bigR-6*unitSpace, bigR-11*unitSpace, bigR-15*unitSpace, bigR-18*unitSpace, bigR-20*unitSpace, smallR, 0.0};
|
||||
// sigma of pattern points (each group of 6 points on a concentric cirle has the same sigma)
|
||||
const double sigma[8] = {radius[0]/2.0, radius[1]/2.0, radius[2]/2.0,
|
||||
radius[3]/2.0, radius[4]/2.0, radius[5]/2.0,
|
||||
radius[6]/2.0, radius[6]/2.0
|
||||
};
|
||||
// fill the lookup table
|
||||
for( int scaleIdx=0; scaleIdx < FREAK_NB_SCALES; ++scaleIdx )
|
||||
{
|
||||
patternSizes[scaleIdx] = 0; // proper initialization
|
||||
scalingFactor = std::pow(scaleStep,scaleIdx); //scale of the pattern, scaleStep ^ scaleIdx
|
||||
|
||||
for( int orientationIdx = 0; orientationIdx < FREAK_NB_ORIENTATION; ++orientationIdx )
|
||||
{
|
||||
theta = double(orientationIdx)* 2*CV_PI/double(FREAK_NB_ORIENTATION); // orientation of the pattern
|
||||
int pointIdx = 0;
|
||||
|
||||
PatternPoint* patternLookupPtr = &patternLookup[0];
|
||||
for( size_t i = 0; i < 8; ++i )
|
||||
{
|
||||
for( int k = 0 ; k < n[i]; ++k )
|
||||
{
|
||||
beta = CV_PI/n[i] * (i%2); // orientation offset so that groups of points on each circles are staggered
|
||||
alpha = double(k)* 2*CV_PI/double(n[i])+beta+theta;
|
||||
|
||||
// add the point to the look-up table
|
||||
PatternPoint& point = patternLookupPtr[ scaleIdx*FREAK_NB_ORIENTATION*FREAK_NB_POINTS+orientationIdx*FREAK_NB_POINTS+pointIdx ];
|
||||
point.x = static_cast<float>(radius[i] * cos(alpha) * scalingFactor * patternScale);
|
||||
point.y = static_cast<float>(radius[i] * sin(alpha) * scalingFactor * patternScale);
|
||||
point.sigma = static_cast<float>(sigma[i] * scalingFactor * patternScale);
|
||||
|
||||
// adapt the sizeList if necessary
|
||||
const int sizeMax = static_cast<int>(ceil((radius[i]+sigma[i])*scalingFactor*patternScale)) + 1;
|
||||
if( patternSizes[scaleIdx] < sizeMax )
|
||||
patternSizes[scaleIdx] = sizeMax;
|
||||
|
||||
++pointIdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// build the list of orientation pairs
|
||||
orientationPairs[0].i=0; orientationPairs[0].j=3; orientationPairs[1].i=1; orientationPairs[1].j=4; orientationPairs[2].i=2; orientationPairs[2].j=5;
|
||||
orientationPairs[3].i=0; orientationPairs[3].j=2; orientationPairs[4].i=1; orientationPairs[4].j=3; orientationPairs[5].i=2; orientationPairs[5].j=4;
|
||||
orientationPairs[6].i=3; orientationPairs[6].j=5; orientationPairs[7].i=4; orientationPairs[7].j=0; orientationPairs[8].i=5; orientationPairs[8].j=1;
|
||||
|
||||
orientationPairs[9].i=6; orientationPairs[9].j=9; orientationPairs[10].i=7; orientationPairs[10].j=10; orientationPairs[11].i=8; orientationPairs[11].j=11;
|
||||
orientationPairs[12].i=6; orientationPairs[12].j=8; orientationPairs[13].i=7; orientationPairs[13].j=9; orientationPairs[14].i=8; orientationPairs[14].j=10;
|
||||
orientationPairs[15].i=9; orientationPairs[15].j=11; orientationPairs[16].i=10; orientationPairs[16].j=6; orientationPairs[17].i=11; orientationPairs[17].j=7;
|
||||
|
||||
orientationPairs[18].i=12; orientationPairs[18].j=15; orientationPairs[19].i=13; orientationPairs[19].j=16; orientationPairs[20].i=14; orientationPairs[20].j=17;
|
||||
orientationPairs[21].i=12; orientationPairs[21].j=14; orientationPairs[22].i=13; orientationPairs[22].j=15; orientationPairs[23].i=14; orientationPairs[23].j=16;
|
||||
orientationPairs[24].i=15; orientationPairs[24].j=17; orientationPairs[25].i=16; orientationPairs[25].j=12; orientationPairs[26].i=17; orientationPairs[26].j=13;
|
||||
|
||||
orientationPairs[27].i=18; orientationPairs[27].j=21; orientationPairs[28].i=19; orientationPairs[28].j=22; orientationPairs[29].i=20; orientationPairs[29].j=23;
|
||||
orientationPairs[30].i=18; orientationPairs[30].j=20; orientationPairs[31].i=19; orientationPairs[31].j=21; orientationPairs[32].i=20; orientationPairs[32].j=22;
|
||||
orientationPairs[33].i=21; orientationPairs[33].j=23; orientationPairs[34].i=22; orientationPairs[34].j=18; orientationPairs[35].i=23; orientationPairs[35].j=19;
|
||||
|
||||
orientationPairs[36].i=24; orientationPairs[36].j=27; orientationPairs[37].i=25; orientationPairs[37].j=28; orientationPairs[38].i=26; orientationPairs[38].j=29;
|
||||
orientationPairs[39].i=30; orientationPairs[39].j=33; orientationPairs[40].i=31; orientationPairs[40].j=34; orientationPairs[41].i=32; orientationPairs[41].j=35;
|
||||
orientationPairs[42].i=36; orientationPairs[42].j=39; orientationPairs[43].i=37; orientationPairs[43].j=40; orientationPairs[44].i=38; orientationPairs[44].j=41;
|
||||
|
||||
for( unsigned m = FREAK_NB_ORIENPAIRS; m--; )
|
||||
{
|
||||
const float dx = patternLookup[orientationPairs[m].i].x-patternLookup[orientationPairs[m].j].x;
|
||||
const float dy = patternLookup[orientationPairs[m].i].y-patternLookup[orientationPairs[m].j].y;
|
||||
const float norm_sq = (dx*dx+dy*dy);
|
||||
orientationPairs[m].weight_dx = int((dx/(norm_sq))*4096.0+0.5);
|
||||
orientationPairs[m].weight_dy = int((dy/(norm_sq))*4096.0+0.5);
|
||||
}
|
||||
|
||||
// build the list of description pairs
|
||||
std::vector<DescriptionPair> allPairs;
|
||||
for( unsigned int i = 1; i < (unsigned int)FREAK_NB_POINTS; ++i )
|
||||
{
|
||||
// (generate all the pairs)
|
||||
for( unsigned int j = 0; (unsigned int)j < i; ++j )
|
||||
{
|
||||
DescriptionPair pair = {(uchar)i,(uchar)j};
|
||||
allPairs.push_back(pair);
|
||||
}
|
||||
}
|
||||
// Input vector provided
|
||||
if( !selectedPairs0.empty() )
|
||||
{
|
||||
if( (int)selectedPairs0.size() == FREAK_NB_PAIRS )
|
||||
{
|
||||
for( int i = 0; i < FREAK_NB_PAIRS; ++i )
|
||||
descriptionPairs[i] = allPairs[selectedPairs0.at(i)];
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_Error(Error::StsVecLengthErr, "Input vector does not match the required size");
|
||||
}
|
||||
}
|
||||
else // default selected pairs
|
||||
{
|
||||
for( int i = 0; i < FREAK_NB_PAIRS; ++i )
|
||||
descriptionPairs[i] = allPairs[FREAK_DEF_PAIRS[i]];
|
||||
}
|
||||
}
|
||||
|
||||
void FREAK::computeImpl( InputArray _image, std::vector<KeyPoint>& keypoints, OutputArray _descriptors ) const
|
||||
{
|
||||
Mat image = _image.getMat();
|
||||
if( image.empty() )
|
||||
return;
|
||||
if( keypoints.empty() )
|
||||
return;
|
||||
|
||||
((FREAK*)this)->buildPattern();
|
||||
|
||||
// Convert to gray if not already
|
||||
Mat grayImage = image;
|
||||
// if( image.channels() > 1 )
|
||||
// cvtColor( image, grayImage, COLOR_BGR2GRAY );
|
||||
|
||||
// Use 32-bit integers if we won't overflow in the integral image
|
||||
if ((image.depth() == CV_8U || image.depth() == CV_8S) &&
|
||||
(image.rows * image.cols) < 8388608 ) // 8388608 = 2 ^ (32 - 8(bit depth) - 1(sign bit))
|
||||
{
|
||||
// Create the integral image appropriate for our type & usage
|
||||
if (image.depth() == CV_8U)
|
||||
computeDescriptors<uchar, int>(grayImage, keypoints, _descriptors);
|
||||
else if (image.depth() == CV_8S)
|
||||
computeDescriptors<char, int>(grayImage, keypoints, _descriptors);
|
||||
else
|
||||
CV_Error( Error::StsUnsupportedFormat, "" );
|
||||
} else {
|
||||
// Create the integral image appropriate for our type & usage
|
||||
if ( image.depth() == CV_8U )
|
||||
computeDescriptors<uchar, double>(grayImage, keypoints, _descriptors);
|
||||
else if ( image.depth() == CV_8S )
|
||||
computeDescriptors<char, double>(grayImage, keypoints, _descriptors);
|
||||
else if ( image.depth() == CV_16U )
|
||||
computeDescriptors<ushort, double>(grayImage, keypoints, _descriptors);
|
||||
else if ( image.depth() == CV_16S )
|
||||
computeDescriptors<short, double>(grayImage, keypoints, _descriptors);
|
||||
else
|
||||
CV_Error( Error::StsUnsupportedFormat, "" );
|
||||
}
|
||||
}
|
||||
|
||||
template <typename srcMatType>
|
||||
void FREAK::extractDescriptor(srcMatType *pointsValue, void ** ptr) const
|
||||
{
|
||||
std::bitset<FREAK_NB_PAIRS>** ptrScalar = (std::bitset<FREAK_NB_PAIRS>**) ptr;
|
||||
|
||||
// extracting descriptor preserving the order of SSE version
|
||||
int cnt = 0;
|
||||
for( int n = 7; n < FREAK_NB_PAIRS; n += 128)
|
||||
{
|
||||
for( int m = 8; m--; )
|
||||
{
|
||||
int nm = n-m;
|
||||
for(int kk = nm+15*8; kk >= nm; kk-=8, ++cnt)
|
||||
{
|
||||
(*ptrScalar)->set(kk, pointsValue[descriptionPairs[cnt].i] >= pointsValue[descriptionPairs[cnt].j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
--(*ptrScalar);
|
||||
}
|
||||
|
||||
#if CV_SSE2
|
||||
template <>
|
||||
void FREAK::extractDescriptor(uchar *pointsValue, void ** ptr) const
|
||||
{
|
||||
__m128i** ptrSSE = (__m128i**) ptr;
|
||||
|
||||
// note that comparisons order is modified in each block (but first 128 comparisons remain globally the same-->does not affect the 128,384 bits segmanted matching strategy)
|
||||
int cnt = 0;
|
||||
for( int n = FREAK_NB_PAIRS/128; n-- ; )
|
||||
{
|
||||
__m128i result128 = _mm_setzero_si128();
|
||||
for( int m = 128/16; m--; cnt += 16 )
|
||||
{
|
||||
__m128i operand1 = _mm_set_epi8(pointsValue[descriptionPairs[cnt+0].i],
|
||||
pointsValue[descriptionPairs[cnt+1].i],
|
||||
pointsValue[descriptionPairs[cnt+2].i],
|
||||
pointsValue[descriptionPairs[cnt+3].i],
|
||||
pointsValue[descriptionPairs[cnt+4].i],
|
||||
pointsValue[descriptionPairs[cnt+5].i],
|
||||
pointsValue[descriptionPairs[cnt+6].i],
|
||||
pointsValue[descriptionPairs[cnt+7].i],
|
||||
pointsValue[descriptionPairs[cnt+8].i],
|
||||
pointsValue[descriptionPairs[cnt+9].i],
|
||||
pointsValue[descriptionPairs[cnt+10].i],
|
||||
pointsValue[descriptionPairs[cnt+11].i],
|
||||
pointsValue[descriptionPairs[cnt+12].i],
|
||||
pointsValue[descriptionPairs[cnt+13].i],
|
||||
pointsValue[descriptionPairs[cnt+14].i],
|
||||
pointsValue[descriptionPairs[cnt+15].i]);
|
||||
|
||||
__m128i operand2 = _mm_set_epi8(pointsValue[descriptionPairs[cnt+0].j],
|
||||
pointsValue[descriptionPairs[cnt+1].j],
|
||||
pointsValue[descriptionPairs[cnt+2].j],
|
||||
pointsValue[descriptionPairs[cnt+3].j],
|
||||
pointsValue[descriptionPairs[cnt+4].j],
|
||||
pointsValue[descriptionPairs[cnt+5].j],
|
||||
pointsValue[descriptionPairs[cnt+6].j],
|
||||
pointsValue[descriptionPairs[cnt+7].j],
|
||||
pointsValue[descriptionPairs[cnt+8].j],
|
||||
pointsValue[descriptionPairs[cnt+9].j],
|
||||
pointsValue[descriptionPairs[cnt+10].j],
|
||||
pointsValue[descriptionPairs[cnt+11].j],
|
||||
pointsValue[descriptionPairs[cnt+12].j],
|
||||
pointsValue[descriptionPairs[cnt+13].j],
|
||||
pointsValue[descriptionPairs[cnt+14].j],
|
||||
pointsValue[descriptionPairs[cnt+15].j]);
|
||||
|
||||
__m128i workReg = _mm_min_epu8(operand1, operand2); // emulated "not less than" for 8-bit UNSIGNED integers
|
||||
workReg = _mm_cmpeq_epi8(workReg, operand2); // emulated "not less than" for 8-bit UNSIGNED integers
|
||||
|
||||
workReg = _mm_and_si128(_mm_set1_epi16(short(0x8080 >> m)), workReg); // merge the last 16 bits with the 128bits std::vector until full
|
||||
result128 = _mm_or_si128(result128, workReg);
|
||||
}
|
||||
(**ptrSSE) = result128;
|
||||
++(*ptrSSE);
|
||||
}
|
||||
(*ptrSSE) -= 8;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename srcMatType, typename iiMatType>
|
||||
void FREAK::computeDescriptors( InputArray _image, std::vector<KeyPoint>& keypoints, OutputArray _descriptors ) const {
|
||||
|
||||
Mat image = _image.getMat();
|
||||
Mat imgIntegral;
|
||||
integral(image, imgIntegral, DataType<iiMatType>::type);
|
||||
std::vector<int> kpScaleIdx(keypoints.size()); // used to save pattern scale index corresponding to each keypoints
|
||||
const std::vector<int>::iterator ScaleIdxBegin = kpScaleIdx.begin(); // used in std::vector erase function
|
||||
const std::vector<cv::KeyPoint>::iterator kpBegin = keypoints.begin(); // used in std::vector erase function
|
||||
const float sizeCst = static_cast<float>(FREAK_NB_SCALES/(FREAK_LOG2* nOctaves));
|
||||
srcMatType pointsValue[FREAK_NB_POINTS];
|
||||
int thetaIdx = 0;
|
||||
int direction0;
|
||||
int direction1;
|
||||
|
||||
// compute the scale index corresponding to the keypoint size and remove keypoints close to the border
|
||||
if( scaleNormalized )
|
||||
{
|
||||
for( size_t k = keypoints.size(); k--; )
|
||||
{
|
||||
//Is k non-zero? If so, decrement it and continue"
|
||||
kpScaleIdx[k] = std::max( (int)(std::log(keypoints[k].size/FREAK_SMALLEST_KP_SIZE)*sizeCst+0.5) ,0);
|
||||
if( kpScaleIdx[k] >= FREAK_NB_SCALES )
|
||||
kpScaleIdx[k] = FREAK_NB_SCALES-1;
|
||||
|
||||
if( keypoints[k].pt.x <= patternSizes[kpScaleIdx[k]] || //check if the description at this specific position and scale fits inside the image
|
||||
keypoints[k].pt.y <= patternSizes[kpScaleIdx[k]] ||
|
||||
keypoints[k].pt.x >= image.cols-patternSizes[kpScaleIdx[k]] ||
|
||||
keypoints[k].pt.y >= image.rows-patternSizes[kpScaleIdx[k]]
|
||||
)
|
||||
{
|
||||
keypoints.erase(kpBegin+k);
|
||||
kpScaleIdx.erase(ScaleIdxBegin+k);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const int scIdx = std::max( (int)(1.0986122886681*sizeCst+0.5) ,0);
|
||||
for( size_t k = keypoints.size(); k--; )
|
||||
{
|
||||
kpScaleIdx[k] = scIdx; // equivalent to the formule when the scale is normalized with a constant size of keypoints[k].size=3*SMALLEST_KP_SIZE
|
||||
if( kpScaleIdx[k] >= FREAK_NB_SCALES )
|
||||
{
|
||||
kpScaleIdx[k] = FREAK_NB_SCALES-1;
|
||||
}
|
||||
if( keypoints[k].pt.x <= patternSizes[kpScaleIdx[k]] ||
|
||||
keypoints[k].pt.y <= patternSizes[kpScaleIdx[k]] ||
|
||||
keypoints[k].pt.x >= image.cols-patternSizes[kpScaleIdx[k]] ||
|
||||
keypoints[k].pt.y >= image.rows-patternSizes[kpScaleIdx[k]]
|
||||
)
|
||||
{
|
||||
keypoints.erase(kpBegin+k);
|
||||
kpScaleIdx.erase(ScaleIdxBegin+k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// allocate descriptor memory, estimate orientations, extract descriptors
|
||||
if( !extAll )
|
||||
{
|
||||
// extract the best comparisons only
|
||||
_descriptors.create((int)keypoints.size(), FREAK_NB_PAIRS/8, CV_8U);
|
||||
_descriptors.setTo(Scalar::all(0));
|
||||
Mat descriptors = _descriptors.getMat();
|
||||
|
||||
void *ptr = descriptors.data+(keypoints.size()-1)*descriptors.step[0];
|
||||
|
||||
for( size_t k = keypoints.size(); k--; ) {
|
||||
// estimate orientation (gradient)
|
||||
if( !orientationNormalized )
|
||||
{
|
||||
thetaIdx = 0; // assign 0° to all keypoints
|
||||
keypoints[k].angle = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// get the points intensity value in the un-rotated pattern
|
||||
for( int i = FREAK_NB_POINTS; i--; ) {
|
||||
pointsValue[i] = meanIntensity<srcMatType, iiMatType>(image, imgIntegral,
|
||||
keypoints[k].pt.x, keypoints[k].pt.y,
|
||||
kpScaleIdx[k], 0, i);
|
||||
}
|
||||
direction0 = 0;
|
||||
direction1 = 0;
|
||||
for( int m = 45; m--; )
|
||||
{
|
||||
//iterate through the orientation pairs
|
||||
const int delta = (pointsValue[ orientationPairs[m].i ]-pointsValue[ orientationPairs[m].j ]);
|
||||
direction0 += delta*(orientationPairs[m].weight_dx)/2048;
|
||||
direction1 += delta*(orientationPairs[m].weight_dy)/2048;
|
||||
}
|
||||
|
||||
keypoints[k].angle = static_cast<float>(atan2((float)direction1,(float)direction0)*(180.0/CV_PI));//estimate orientation
|
||||
thetaIdx = int(FREAK_NB_ORIENTATION*keypoints[k].angle*(1/360.0)+0.5);
|
||||
if( thetaIdx < 0 )
|
||||
thetaIdx += FREAK_NB_ORIENTATION;
|
||||
|
||||
if( thetaIdx >= FREAK_NB_ORIENTATION )
|
||||
thetaIdx -= FREAK_NB_ORIENTATION;
|
||||
}
|
||||
// extract descriptor at the computed orientation
|
||||
for( int i = FREAK_NB_POINTS; i--; ) {
|
||||
pointsValue[i] = meanIntensity<srcMatType, iiMatType>(image, imgIntegral,
|
||||
keypoints[k].pt.x, keypoints[k].pt.y,
|
||||
kpScaleIdx[k], thetaIdx, i);
|
||||
}
|
||||
|
||||
// Extract descriptor
|
||||
extractDescriptor<srcMatType>(pointsValue, &ptr);
|
||||
}
|
||||
}
|
||||
else // extract all possible comparisons for selection
|
||||
{
|
||||
_descriptors.create((int)keypoints.size(), 128, CV_8U);
|
||||
_descriptors.setTo(Scalar::all(0));
|
||||
Mat descriptors = _descriptors.getMat();
|
||||
std::bitset<1024>* ptr = (std::bitset<1024>*) (descriptors.data+(keypoints.size()-1)*descriptors.step[0]);
|
||||
|
||||
for( size_t k = keypoints.size(); k--; )
|
||||
{
|
||||
//estimate orientation (gradient)
|
||||
if( !orientationNormalized )
|
||||
{
|
||||
thetaIdx = 0;//assign 0° to all keypoints
|
||||
keypoints[k].angle = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//get the points intensity value in the un-rotated pattern
|
||||
for( int i = FREAK_NB_POINTS;i--; )
|
||||
pointsValue[i] = meanIntensity<srcMatType, iiMatType>(image, imgIntegral,
|
||||
keypoints[k].pt.x,keypoints[k].pt.y,
|
||||
kpScaleIdx[k], 0, i);
|
||||
|
||||
direction0 = 0;
|
||||
direction1 = 0;
|
||||
for( int m = 45; m--; )
|
||||
{
|
||||
//iterate through the orientation pairs
|
||||
const int delta = (pointsValue[ orientationPairs[m].i ]-pointsValue[ orientationPairs[m].j ]);
|
||||
direction0 += delta*(orientationPairs[m].weight_dx)/2048;
|
||||
direction1 += delta*(orientationPairs[m].weight_dy)/2048;
|
||||
}
|
||||
|
||||
keypoints[k].angle = static_cast<float>(atan2((float)direction1,(float)direction0)*(180.0/CV_PI)); //estimate orientation
|
||||
thetaIdx = int(FREAK_NB_ORIENTATION*keypoints[k].angle*(1/360.0)+0.5);
|
||||
|
||||
if( thetaIdx < 0 )
|
||||
thetaIdx += FREAK_NB_ORIENTATION;
|
||||
|
||||
if( thetaIdx >= FREAK_NB_ORIENTATION )
|
||||
thetaIdx -= FREAK_NB_ORIENTATION;
|
||||
}
|
||||
// get the points intensity value in the rotated pattern
|
||||
for( int i = FREAK_NB_POINTS; i--; ) {
|
||||
pointsValue[i] = meanIntensity<srcMatType, iiMatType>(image, imgIntegral,
|
||||
keypoints[k].pt.x, keypoints[k].pt.y,
|
||||
kpScaleIdx[k], thetaIdx, i);
|
||||
}
|
||||
|
||||
int cnt(0);
|
||||
for( int i = 1; i < FREAK_NB_POINTS; ++i )
|
||||
{
|
||||
//(generate all the pairs)
|
||||
for( int j = 0; j < i; ++j )
|
||||
{
|
||||
ptr->set(cnt, pointsValue[i] >= pointsValue[j] );
|
||||
++cnt;
|
||||
}
|
||||
}
|
||||
--ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// simply take average on a square patch, not even gaussian approx
|
||||
template <typename imgType, typename iiType>
|
||||
imgType FREAK::meanIntensity( InputArray _image, InputArray _integral,
|
||||
const float kp_x,
|
||||
const float kp_y,
|
||||
const unsigned int scale,
|
||||
const unsigned int rot,
|
||||
const unsigned int point) const {
|
||||
Mat image = _image.getMat(), integral = _integral.getMat();
|
||||
// get point position in image
|
||||
const PatternPoint& FreakPoint = patternLookup[scale*FREAK_NB_ORIENTATION*FREAK_NB_POINTS + rot*FREAK_NB_POINTS + point];
|
||||
const float xf = FreakPoint.x+kp_x;
|
||||
const float yf = FreakPoint.y+kp_y;
|
||||
const int x = int(xf);
|
||||
const int y = int(yf);
|
||||
|
||||
// get the sigma:
|
||||
const float radius = FreakPoint.sigma;
|
||||
|
||||
// calculate output:
|
||||
if( radius < 0.5 )
|
||||
{
|
||||
// interpolation multipliers:
|
||||
const int r_x = static_cast<int>((xf-x)*1024);
|
||||
const int r_y = static_cast<int>((yf-y)*1024);
|
||||
const int r_x_1 = (1024-r_x);
|
||||
const int r_y_1 = (1024-r_y);
|
||||
unsigned int ret_val;
|
||||
// linear interpolation:
|
||||
ret_val = r_x_1*r_y_1*int(image.at<imgType>(y , x ))
|
||||
+ r_x *r_y_1*int(image.at<imgType>(y , x+1))
|
||||
+ r_x_1*r_y *int(image.at<imgType>(y+1, x ))
|
||||
+ r_x *r_y *int(image.at<imgType>(y+1, x+1));
|
||||
//return the rounded mean
|
||||
ret_val += 2 * 1024 * 1024;
|
||||
return static_cast<imgType>(ret_val / (4 * 1024 * 1024));
|
||||
}
|
||||
|
||||
// expected case:
|
||||
|
||||
// calculate borders
|
||||
const int x_left = int(xf-radius+0.5);
|
||||
const int y_top = int(yf-radius+0.5);
|
||||
const int x_right = int(xf+radius+1.5);//integral image is 1px wider
|
||||
const int y_bottom = int(yf+radius+1.5);//integral image is 1px higher
|
||||
iiType ret_val;
|
||||
|
||||
ret_val = integral.at<iiType>(y_bottom,x_right);//bottom right corner
|
||||
ret_val -= integral.at<iiType>(y_bottom,x_left);
|
||||
ret_val += integral.at<iiType>(y_top,x_left);
|
||||
ret_val -= integral.at<iiType>(y_top,x_right);
|
||||
ret_val = ret_val/( (x_right-x_left)* (y_bottom-y_top) );
|
||||
//~ std::cout<<integral.step[1]<<std::endl;
|
||||
return static_cast<imgType>(ret_val);
|
||||
}
|
||||
|
||||
// pair selection algorithm from a set of training images and corresponding keypoints
|
||||
std::vector<int> FREAK::selectPairs(const std::vector<Mat>& images
|
||||
, std::vector<std::vector<KeyPoint> >& keypoints
|
||||
, const double corrTresh
|
||||
, bool verbose )
|
||||
{
|
||||
extAll = true;
|
||||
// compute descriptors with all pairs
|
||||
Mat descriptors;
|
||||
|
||||
if( verbose )
|
||||
std::cout << "Number of images: " << images.size() << std::endl;
|
||||
|
||||
for( size_t i = 0;i < images.size(); ++i )
|
||||
{
|
||||
Mat descriptorsTmp;
|
||||
computeImpl(images[i],keypoints[i],descriptorsTmp);
|
||||
descriptors.push_back(descriptorsTmp);
|
||||
}
|
||||
|
||||
if( verbose )
|
||||
std::cout << "number of keypoints: " << descriptors.rows << std::endl;
|
||||
|
||||
//descriptor in floating point format (each bit is a float)
|
||||
Mat descriptorsFloat = Mat::zeros(descriptors.rows, 903, CV_32F);
|
||||
|
||||
std::bitset<1024>* ptr = (std::bitset<1024>*) (descriptors.data+(descriptors.rows-1)*descriptors.step[0]);
|
||||
for( int m = descriptors.rows; m--; )
|
||||
{
|
||||
for( int n = 903; n--; )
|
||||
{
|
||||
if( ptr->test(n) == true )
|
||||
descriptorsFloat.at<float>(m,n)=1.0f;
|
||||
}
|
||||
--ptr;
|
||||
}
|
||||
|
||||
std::vector<PairStat> pairStat;
|
||||
for( int n = 903; n--; )
|
||||
{
|
||||
// the higher the variance, the better --> mean = 0.5
|
||||
PairStat tmp = { fabs( mean(descriptorsFloat.col(n))[0]-0.5 ) ,n};
|
||||
pairStat.push_back(tmp);
|
||||
}
|
||||
|
||||
std::sort( pairStat.begin(),pairStat.end(), sortMean() );
|
||||
|
||||
std::vector<PairStat> bestPairs;
|
||||
for( int m = 0; m < 903; ++m )
|
||||
{
|
||||
if( verbose )
|
||||
std::cout << m << ":" << bestPairs.size() << " " << std::flush;
|
||||
double corrMax(0);
|
||||
|
||||
for( size_t n = 0; n < bestPairs.size(); ++n )
|
||||
{
|
||||
int idxA = bestPairs[n].idx;
|
||||
int idxB = pairStat[m].idx;
|
||||
double corr(0);
|
||||
// compute correlation between 2 pairs
|
||||
corr = fabs(compareHist(descriptorsFloat.col(idxA), descriptorsFloat.col(idxB), HISTCMP_CORREL));
|
||||
|
||||
if( corr > corrMax )
|
||||
{
|
||||
corrMax = corr;
|
||||
if( corrMax >= corrTresh )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( corrMax < corrTresh/*0.7*/ )
|
||||
bestPairs.push_back(pairStat[m]);
|
||||
|
||||
if( bestPairs.size() >= 512 )
|
||||
{
|
||||
if( verbose )
|
||||
std::cout << m << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> idxBestPairs;
|
||||
if( (int)bestPairs.size() >= FREAK_NB_PAIRS )
|
||||
{
|
||||
for( int i = 0; i < FREAK_NB_PAIRS; ++i )
|
||||
idxBestPairs.push_back(bestPairs[i].idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( verbose )
|
||||
std::cout << "correlation threshold too small (restrictive)" << std::endl;
|
||||
CV_Error(Error::StsError, "correlation threshold too small (restrictive)");
|
||||
}
|
||||
extAll = false;
|
||||
return idxBestPairs;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// create an image showing the brisk pattern
|
||||
void FREAKImpl::drawPattern()
|
||||
{
|
||||
Mat pattern = Mat::zeros(1000, 1000, CV_8UC3) + Scalar(255,255,255);
|
||||
int sFac = 500 / patternScale;
|
||||
for( int n = 0; n < kNB_POINTS; ++n )
|
||||
{
|
||||
PatternPoint& pt = patternLookup[n];
|
||||
circle(pattern, Point( pt.x*sFac,pt.y*sFac)+Point(500,500), pt.sigma*sFac, Scalar(0,0,255),2);
|
||||
// rectangle(pattern, Point( (pt.x-pt.sigma)*sFac,(pt.y-pt.sigma)*sFac)+Point(500,500), Point( (pt.x+pt.sigma)*sFac,(pt.y+pt.sigma)*sFac)+Point(500,500), Scalar(0,0,255),2);
|
||||
|
||||
circle(pattern, Point( pt.x*sFac,pt.y*sFac)+Point(500,500), 1, Scalar(0,0,0),3);
|
||||
std::ostringstream oss;
|
||||
oss << n;
|
||||
putText( pattern, oss.str(), Point( pt.x*sFac,pt.y*sFac)+Point(500,500), FONT_HERSHEY_SIMPLEX,0.5, Scalar(0,0,0), 1);
|
||||
}
|
||||
imshow( "FreakDescriptorExtractor pattern", pattern );
|
||||
waitKey(0);
|
||||
}
|
||||
*/
|
||||
|
||||
// -------------------------------------------------
|
||||
/* FREAK interface implementation */
|
||||
FREAK::FREAK( bool _orientationNormalized, bool _scaleNormalized
|
||||
, float _patternScale, int _nOctaves, const std::vector<int>& _selectedPairs )
|
||||
: orientationNormalized(_orientationNormalized), scaleNormalized(_scaleNormalized),
|
||||
patternScale(_patternScale), nOctaves(_nOctaves), extAll(false), nOctaves0(0), selectedPairs0(_selectedPairs)
|
||||
{
|
||||
}
|
||||
|
||||
FREAK::~FREAK()
|
||||
{
|
||||
}
|
||||
|
||||
int FREAK::descriptorSize() const
|
||||
{
|
||||
return FREAK_NB_PAIRS / 8; // descriptor length in bytes
|
||||
}
|
||||
|
||||
int FREAK::descriptorType() const
|
||||
{
|
||||
return CV_8U;
|
||||
}
|
||||
|
||||
int FREAK::defaultNorm() const
|
||||
{
|
||||
return NORM_HAMMING;
|
||||
}
|
||||
|
||||
} // END NAMESPACE CV
|
@@ -1,19 +0,0 @@
|
||||
// Code generated with '$ scripts/generate_code.py src/test_pairs.txt 16'
|
||||
#define SMOOTHED(y,x) smoothedSum(sum, pt, y, x)
|
||||
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));
|
||||
desc[3] = (uchar)(((SMOOTHED(0, 12) < SMOOTHED(-3, 19)) << 7) + ((SMOOTHED(1, 15) < SMOOTHED(-11, -5)) << 6) + ((SMOOTHED(14, -1) < SMOOTHED(7, 8)) << 5) + ((SMOOTHED(7, -23) < SMOOTHED(-5, 5)) << 4) + ((SMOOTHED(0, -6) < SMOOTHED(-10, 17)) << 3) + ((SMOOTHED(13, -4) < SMOOTHED(-3, -4)) << 2) + ((SMOOTHED(-12, 1) < SMOOTHED(-12, 2)) << 1) + ((SMOOTHED(0, 8) < SMOOTHED(3, 22)) << 0));
|
||||
desc[4] = (uchar)(((SMOOTHED(-13, 13) < SMOOTHED(3, -1)) << 7) + ((SMOOTHED(-16, 17) < SMOOTHED(6, 10)) << 6) + ((SMOOTHED(7, 15) < SMOOTHED(-5, 0)) << 5) + ((SMOOTHED(2, -12) < SMOOTHED(19, -2)) << 4) + ((SMOOTHED(3, -6) < SMOOTHED(-4, -15)) << 3) + ((SMOOTHED(8, 3) < SMOOTHED(0, 14)) << 2) + ((SMOOTHED(4, -11) < SMOOTHED(5, 5)) << 1) + ((SMOOTHED(11, -7) < SMOOTHED(7, 1)) << 0));
|
||||
desc[5] = (uchar)(((SMOOTHED(6, 12) < SMOOTHED(21, 3)) << 7) + ((SMOOTHED(-3, 2) < SMOOTHED(14, 1)) << 6) + ((SMOOTHED(5, 1) < SMOOTHED(-5, 11)) << 5) + ((SMOOTHED(3, -17) < SMOOTHED(-6, 2)) << 4) + ((SMOOTHED(6, 8) < SMOOTHED(5, -10)) << 3) + ((SMOOTHED(-14, -2) < SMOOTHED(0, 4)) << 2) + ((SMOOTHED(5, -7) < SMOOTHED(-6, 5)) << 1) + ((SMOOTHED(10, 4) < SMOOTHED(4, -7)) << 0));
|
||||
desc[6] = (uchar)(((SMOOTHED(22, 0) < SMOOTHED(7, -18)) << 7) + ((SMOOTHED(-1, -3) < SMOOTHED(0, 18)) << 6) + ((SMOOTHED(-4, 22) < SMOOTHED(-5, 3)) << 5) + ((SMOOTHED(1, -7) < SMOOTHED(2, -3)) << 4) + ((SMOOTHED(19, -20) < SMOOTHED(17, -2)) << 3) + ((SMOOTHED(3, -10) < SMOOTHED(-8, 24)) << 2) + ((SMOOTHED(-5, -14) < SMOOTHED(7, 5)) << 1) + ((SMOOTHED(-2, 12) < SMOOTHED(-4, -15)) << 0));
|
||||
desc[7] = (uchar)(((SMOOTHED(4, 12) < SMOOTHED(0, -19)) << 7) + ((SMOOTHED(20, 13) < SMOOTHED(3, 5)) << 6) + ((SMOOTHED(-8, -12) < SMOOTHED(5, 0)) << 5) + ((SMOOTHED(-5, 6) < SMOOTHED(-7, -11)) << 4) + ((SMOOTHED(6, -11) < SMOOTHED(-3, -22)) << 3) + ((SMOOTHED(15, 4) < SMOOTHED(10, 1)) << 2) + ((SMOOTHED(-7, -4) < SMOOTHED(15, -6)) << 1) + ((SMOOTHED(5, 10) < SMOOTHED(0, 24)) << 0));
|
||||
desc[8] = (uchar)(((SMOOTHED(3, 6) < SMOOTHED(22, -2)) << 7) + ((SMOOTHED(-13, 14) < SMOOTHED(4, -4)) << 6) + ((SMOOTHED(-13, 8) < SMOOTHED(-18, -22)) << 5) + ((SMOOTHED(-1, -1) < SMOOTHED(-7, 3)) << 4) + ((SMOOTHED(-19, -12) < SMOOTHED(4, 3)) << 3) + ((SMOOTHED(8, 10) < SMOOTHED(13, -2)) << 2) + ((SMOOTHED(-6, -1) < SMOOTHED(-6, -5)) << 1) + ((SMOOTHED(2, -21) < SMOOTHED(-3, 2)) << 0));
|
||||
desc[9] = (uchar)(((SMOOTHED(4, -7) < SMOOTHED(0, 16)) << 7) + ((SMOOTHED(-6, -5) < SMOOTHED(-12, -1)) << 6) + ((SMOOTHED(1, -1) < SMOOTHED(9, 18)) << 5) + ((SMOOTHED(-7, 10) < SMOOTHED(-11, 6)) << 4) + ((SMOOTHED(4, 3) < SMOOTHED(19, -7)) << 3) + ((SMOOTHED(-18, 5) < SMOOTHED(-4, 5)) << 2) + ((SMOOTHED(4, 0) < SMOOTHED(-20, 4)) << 1) + ((SMOOTHED(7, -11) < SMOOTHED(18, 12)) << 0));
|
||||
desc[10] = (uchar)(((SMOOTHED(-20, 17) < SMOOTHED(-18, 7)) << 7) + ((SMOOTHED(2, 15) < SMOOTHED(19, -11)) << 6) + ((SMOOTHED(-18, 6) < SMOOTHED(-7, 3)) << 5) + ((SMOOTHED(-4, 1) < SMOOTHED(-14, 13)) << 4) + ((SMOOTHED(17, 3) < SMOOTHED(2, -8)) << 3) + ((SMOOTHED(-7, 2) < SMOOTHED(1, 6)) << 2) + ((SMOOTHED(17, -9) < SMOOTHED(-2, 8)) << 1) + ((SMOOTHED(-8, -6) < SMOOTHED(-1, 12)) << 0));
|
||||
desc[11] = (uchar)(((SMOOTHED(-2, 4) < SMOOTHED(-1, 6)) << 7) + ((SMOOTHED(-2, 7) < SMOOTHED(6, 8)) << 6) + ((SMOOTHED(-8, -1) < SMOOTHED(-7, -9)) << 5) + ((SMOOTHED(8, -9) < SMOOTHED(15, 0)) << 4) + ((SMOOTHED(0, 22) < SMOOTHED(-4, -15)) << 3) + ((SMOOTHED(-14, -1) < SMOOTHED(3, -2)) << 2) + ((SMOOTHED(-7, -4) < SMOOTHED(17, -7)) << 1) + ((SMOOTHED(-8, -2) < SMOOTHED(9, -4)) << 0));
|
||||
desc[12] = (uchar)(((SMOOTHED(5, -7) < SMOOTHED(7, 7)) << 7) + ((SMOOTHED(-5, 13) < SMOOTHED(-8, 11)) << 6) + ((SMOOTHED(11, -4) < SMOOTHED(0, 8)) << 5) + ((SMOOTHED(5, -11) < SMOOTHED(-9, -6)) << 4) + ((SMOOTHED(2, -6) < SMOOTHED(3, -20)) << 3) + ((SMOOTHED(-6, 2) < SMOOTHED(6, 10)) << 2) + ((SMOOTHED(-6, -6) < SMOOTHED(-15, 7)) << 1) + ((SMOOTHED(-6, -3) < SMOOTHED(2, 1)) << 0));
|
||||
desc[13] = (uchar)(((SMOOTHED(11, 0) < SMOOTHED(-3, 2)) << 7) + ((SMOOTHED(7, -12) < SMOOTHED(14, 5)) << 6) + ((SMOOTHED(0, -7) < SMOOTHED(-1, -1)) << 5) + ((SMOOTHED(-16, 0) < SMOOTHED(6, 8)) << 4) + ((SMOOTHED(22, 11) < SMOOTHED(0, -3)) << 3) + ((SMOOTHED(19, 0) < SMOOTHED(5, -17)) << 2) + ((SMOOTHED(-23, -14) < SMOOTHED(-13, -19)) << 1) + ((SMOOTHED(-8, 10) < SMOOTHED(-11, -2)) << 0));
|
||||
desc[14] = (uchar)(((SMOOTHED(-11, 6) < SMOOTHED(-10, 13)) << 7) + ((SMOOTHED(1, -7) < SMOOTHED(14, 0)) << 6) + ((SMOOTHED(-12, 1) < SMOOTHED(-5, -5)) << 5) + ((SMOOTHED(4, 7) < SMOOTHED(8, -1)) << 4) + ((SMOOTHED(-1, -5) < SMOOTHED(15, 2)) << 3) + ((SMOOTHED(-3, -1) < SMOOTHED(7, -10)) << 2) + ((SMOOTHED(3, -6) < SMOOTHED(10, -18)) << 1) + ((SMOOTHED(-7, -13) < SMOOTHED(-13, 10)) << 0));
|
||||
desc[15] = (uchar)(((SMOOTHED(1, -1) < SMOOTHED(13, -10)) << 7) + ((SMOOTHED(-19, 14) < SMOOTHED(8, -14)) << 6) + ((SMOOTHED(-4, -13) < SMOOTHED(7, 1)) << 5) + ((SMOOTHED(1, -2) < SMOOTHED(12, -7)) << 4) + ((SMOOTHED(3, -5) < SMOOTHED(1, -5)) << 3) + ((SMOOTHED(-2, -2) < SMOOTHED(8, -10)) << 2) + ((SMOOTHED(2, 14) < SMOOTHED(8, 7)) << 1) + ((SMOOTHED(3, 9) < SMOOTHED(8, 2)) << 0));
|
||||
#undef SMOOTHED
|
@@ -1,35 +0,0 @@
|
||||
// Code generated with '$ scripts/generate_code.py src/test_pairs.txt 32'
|
||||
#define SMOOTHED(y,x) smoothedSum(sum, pt, y, x)
|
||||
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));
|
||||
desc[3] = (uchar)(((SMOOTHED(0, 12) < SMOOTHED(-3, 19)) << 7) + ((SMOOTHED(1, 15) < SMOOTHED(-11, -5)) << 6) + ((SMOOTHED(14, -1) < SMOOTHED(7, 8)) << 5) + ((SMOOTHED(7, -23) < SMOOTHED(-5, 5)) << 4) + ((SMOOTHED(0, -6) < SMOOTHED(-10, 17)) << 3) + ((SMOOTHED(13, -4) < SMOOTHED(-3, -4)) << 2) + ((SMOOTHED(-12, 1) < SMOOTHED(-12, 2)) << 1) + ((SMOOTHED(0, 8) < SMOOTHED(3, 22)) << 0));
|
||||
desc[4] = (uchar)(((SMOOTHED(-13, 13) < SMOOTHED(3, -1)) << 7) + ((SMOOTHED(-16, 17) < SMOOTHED(6, 10)) << 6) + ((SMOOTHED(7, 15) < SMOOTHED(-5, 0)) << 5) + ((SMOOTHED(2, -12) < SMOOTHED(19, -2)) << 4) + ((SMOOTHED(3, -6) < SMOOTHED(-4, -15)) << 3) + ((SMOOTHED(8, 3) < SMOOTHED(0, 14)) << 2) + ((SMOOTHED(4, -11) < SMOOTHED(5, 5)) << 1) + ((SMOOTHED(11, -7) < SMOOTHED(7, 1)) << 0));
|
||||
desc[5] = (uchar)(((SMOOTHED(6, 12) < SMOOTHED(21, 3)) << 7) + ((SMOOTHED(-3, 2) < SMOOTHED(14, 1)) << 6) + ((SMOOTHED(5, 1) < SMOOTHED(-5, 11)) << 5) + ((SMOOTHED(3, -17) < SMOOTHED(-6, 2)) << 4) + ((SMOOTHED(6, 8) < SMOOTHED(5, -10)) << 3) + ((SMOOTHED(-14, -2) < SMOOTHED(0, 4)) << 2) + ((SMOOTHED(5, -7) < SMOOTHED(-6, 5)) << 1) + ((SMOOTHED(10, 4) < SMOOTHED(4, -7)) << 0));
|
||||
desc[6] = (uchar)(((SMOOTHED(22, 0) < SMOOTHED(7, -18)) << 7) + ((SMOOTHED(-1, -3) < SMOOTHED(0, 18)) << 6) + ((SMOOTHED(-4, 22) < SMOOTHED(-5, 3)) << 5) + ((SMOOTHED(1, -7) < SMOOTHED(2, -3)) << 4) + ((SMOOTHED(19, -20) < SMOOTHED(17, -2)) << 3) + ((SMOOTHED(3, -10) < SMOOTHED(-8, 24)) << 2) + ((SMOOTHED(-5, -14) < SMOOTHED(7, 5)) << 1) + ((SMOOTHED(-2, 12) < SMOOTHED(-4, -15)) << 0));
|
||||
desc[7] = (uchar)(((SMOOTHED(4, 12) < SMOOTHED(0, -19)) << 7) + ((SMOOTHED(20, 13) < SMOOTHED(3, 5)) << 6) + ((SMOOTHED(-8, -12) < SMOOTHED(5, 0)) << 5) + ((SMOOTHED(-5, 6) < SMOOTHED(-7, -11)) << 4) + ((SMOOTHED(6, -11) < SMOOTHED(-3, -22)) << 3) + ((SMOOTHED(15, 4) < SMOOTHED(10, 1)) << 2) + ((SMOOTHED(-7, -4) < SMOOTHED(15, -6)) << 1) + ((SMOOTHED(5, 10) < SMOOTHED(0, 24)) << 0));
|
||||
desc[8] = (uchar)(((SMOOTHED(3, 6) < SMOOTHED(22, -2)) << 7) + ((SMOOTHED(-13, 14) < SMOOTHED(4, -4)) << 6) + ((SMOOTHED(-13, 8) < SMOOTHED(-18, -22)) << 5) + ((SMOOTHED(-1, -1) < SMOOTHED(-7, 3)) << 4) + ((SMOOTHED(-19, -12) < SMOOTHED(4, 3)) << 3) + ((SMOOTHED(8, 10) < SMOOTHED(13, -2)) << 2) + ((SMOOTHED(-6, -1) < SMOOTHED(-6, -5)) << 1) + ((SMOOTHED(2, -21) < SMOOTHED(-3, 2)) << 0));
|
||||
desc[9] = (uchar)(((SMOOTHED(4, -7) < SMOOTHED(0, 16)) << 7) + ((SMOOTHED(-6, -5) < SMOOTHED(-12, -1)) << 6) + ((SMOOTHED(1, -1) < SMOOTHED(9, 18)) << 5) + ((SMOOTHED(-7, 10) < SMOOTHED(-11, 6)) << 4) + ((SMOOTHED(4, 3) < SMOOTHED(19, -7)) << 3) + ((SMOOTHED(-18, 5) < SMOOTHED(-4, 5)) << 2) + ((SMOOTHED(4, 0) < SMOOTHED(-20, 4)) << 1) + ((SMOOTHED(7, -11) < SMOOTHED(18, 12)) << 0));
|
||||
desc[10] = (uchar)(((SMOOTHED(-20, 17) < SMOOTHED(-18, 7)) << 7) + ((SMOOTHED(2, 15) < SMOOTHED(19, -11)) << 6) + ((SMOOTHED(-18, 6) < SMOOTHED(-7, 3)) << 5) + ((SMOOTHED(-4, 1) < SMOOTHED(-14, 13)) << 4) + ((SMOOTHED(17, 3) < SMOOTHED(2, -8)) << 3) + ((SMOOTHED(-7, 2) < SMOOTHED(1, 6)) << 2) + ((SMOOTHED(17, -9) < SMOOTHED(-2, 8)) << 1) + ((SMOOTHED(-8, -6) < SMOOTHED(-1, 12)) << 0));
|
||||
desc[11] = (uchar)(((SMOOTHED(-2, 4) < SMOOTHED(-1, 6)) << 7) + ((SMOOTHED(-2, 7) < SMOOTHED(6, 8)) << 6) + ((SMOOTHED(-8, -1) < SMOOTHED(-7, -9)) << 5) + ((SMOOTHED(8, -9) < SMOOTHED(15, 0)) << 4) + ((SMOOTHED(0, 22) < SMOOTHED(-4, -15)) << 3) + ((SMOOTHED(-14, -1) < SMOOTHED(3, -2)) << 2) + ((SMOOTHED(-7, -4) < SMOOTHED(17, -7)) << 1) + ((SMOOTHED(-8, -2) < SMOOTHED(9, -4)) << 0));
|
||||
desc[12] = (uchar)(((SMOOTHED(5, -7) < SMOOTHED(7, 7)) << 7) + ((SMOOTHED(-5, 13) < SMOOTHED(-8, 11)) << 6) + ((SMOOTHED(11, -4) < SMOOTHED(0, 8)) << 5) + ((SMOOTHED(5, -11) < SMOOTHED(-9, -6)) << 4) + ((SMOOTHED(2, -6) < SMOOTHED(3, -20)) << 3) + ((SMOOTHED(-6, 2) < SMOOTHED(6, 10)) << 2) + ((SMOOTHED(-6, -6) < SMOOTHED(-15, 7)) << 1) + ((SMOOTHED(-6, -3) < SMOOTHED(2, 1)) << 0));
|
||||
desc[13] = (uchar)(((SMOOTHED(11, 0) < SMOOTHED(-3, 2)) << 7) + ((SMOOTHED(7, -12) < SMOOTHED(14, 5)) << 6) + ((SMOOTHED(0, -7) < SMOOTHED(-1, -1)) << 5) + ((SMOOTHED(-16, 0) < SMOOTHED(6, 8)) << 4) + ((SMOOTHED(22, 11) < SMOOTHED(0, -3)) << 3) + ((SMOOTHED(19, 0) < SMOOTHED(5, -17)) << 2) + ((SMOOTHED(-23, -14) < SMOOTHED(-13, -19)) << 1) + ((SMOOTHED(-8, 10) < SMOOTHED(-11, -2)) << 0));
|
||||
desc[14] = (uchar)(((SMOOTHED(-11, 6) < SMOOTHED(-10, 13)) << 7) + ((SMOOTHED(1, -7) < SMOOTHED(14, 0)) << 6) + ((SMOOTHED(-12, 1) < SMOOTHED(-5, -5)) << 5) + ((SMOOTHED(4, 7) < SMOOTHED(8, -1)) << 4) + ((SMOOTHED(-1, -5) < SMOOTHED(15, 2)) << 3) + ((SMOOTHED(-3, -1) < SMOOTHED(7, -10)) << 2) + ((SMOOTHED(3, -6) < SMOOTHED(10, -18)) << 1) + ((SMOOTHED(-7, -13) < SMOOTHED(-13, 10)) << 0));
|
||||
desc[15] = (uchar)(((SMOOTHED(1, -1) < SMOOTHED(13, -10)) << 7) + ((SMOOTHED(-19, 14) < SMOOTHED(8, -14)) << 6) + ((SMOOTHED(-4, -13) < SMOOTHED(7, 1)) << 5) + ((SMOOTHED(1, -2) < SMOOTHED(12, -7)) << 4) + ((SMOOTHED(3, -5) < SMOOTHED(1, -5)) << 3) + ((SMOOTHED(-2, -2) < SMOOTHED(8, -10)) << 2) + ((SMOOTHED(2, 14) < SMOOTHED(8, 7)) << 1) + ((SMOOTHED(3, 9) < SMOOTHED(8, 2)) << 0));
|
||||
desc[16] = (uchar)(((SMOOTHED(-9, 1) < SMOOTHED(-18, 0)) << 7) + ((SMOOTHED(4, 0) < SMOOTHED(1, 12)) << 6) + ((SMOOTHED(0, 9) < SMOOTHED(-14, -10)) << 5) + ((SMOOTHED(-13, -9) < SMOOTHED(-2, 6)) << 4) + ((SMOOTHED(1, 5) < SMOOTHED(10, 10)) << 3) + ((SMOOTHED(-3, -6) < SMOOTHED(-16, -5)) << 2) + ((SMOOTHED(11, 6) < SMOOTHED(-5, 0)) << 1) + ((SMOOTHED(-23, 10) < SMOOTHED(1, 2)) << 0));
|
||||
desc[17] = (uchar)(((SMOOTHED(13, -5) < SMOOTHED(-3, 9)) << 7) + ((SMOOTHED(-4, -1) < SMOOTHED(-13, -5)) << 6) + ((SMOOTHED(10, 13) < SMOOTHED(-11, 8)) << 5) + ((SMOOTHED(19, 20) < SMOOTHED(-9, 2)) << 4) + ((SMOOTHED(4, -8) < SMOOTHED(0, -9)) << 3) + ((SMOOTHED(-14, 10) < SMOOTHED(15, 19)) << 2) + ((SMOOTHED(-14, -12) < SMOOTHED(-10, -3)) << 1) + ((SMOOTHED(-23, -3) < SMOOTHED(17, -2)) << 0));
|
||||
desc[18] = (uchar)(((SMOOTHED(-3, -11) < SMOOTHED(6, -14)) << 7) + ((SMOOTHED(19, -2) < SMOOTHED(-4, 2)) << 6) + ((SMOOTHED(-5, 5) < SMOOTHED(3, -13)) << 5) + ((SMOOTHED(2, -2) < SMOOTHED(-5, 4)) << 4) + ((SMOOTHED(17, 4) < SMOOTHED(17, -11)) << 3) + ((SMOOTHED(-7, -2) < SMOOTHED(1, 23)) << 2) + ((SMOOTHED(8, 13) < SMOOTHED(1, -16)) << 1) + ((SMOOTHED(-13, -5) < SMOOTHED(1, -17)) << 0));
|
||||
desc[19] = (uchar)(((SMOOTHED(4, 6) < SMOOTHED(-8, -3)) << 7) + ((SMOOTHED(-5, -9) < SMOOTHED(-2, -10)) << 6) + ((SMOOTHED(-9, 0) < SMOOTHED(-7, -2)) << 5) + ((SMOOTHED(5, 0) < SMOOTHED(5, 2)) << 4) + ((SMOOTHED(-4, -16) < SMOOTHED(6, 3)) << 3) + ((SMOOTHED(2, -15) < SMOOTHED(-2, 12)) << 2) + ((SMOOTHED(4, -1) < SMOOTHED(6, 2)) << 1) + ((SMOOTHED(1, 1) < SMOOTHED(-2, -8)) << 0));
|
||||
desc[20] = (uchar)(((SMOOTHED(-2, 12) < SMOOTHED(-5, -2)) << 7) + ((SMOOTHED(-8, 8) < SMOOTHED(-9, 9)) << 6) + ((SMOOTHED(2, -10) < SMOOTHED(3, 1)) << 5) + ((SMOOTHED(-4, 10) < SMOOTHED(-9, 4)) << 4) + ((SMOOTHED(6, 12) < SMOOTHED(2, 5)) << 3) + ((SMOOTHED(-3, -8) < SMOOTHED(0, 5)) << 2) + ((SMOOTHED(-13, 1) < SMOOTHED(-7, 2)) << 1) + ((SMOOTHED(-1, -10) < SMOOTHED(7, -18)) << 0));
|
||||
desc[21] = (uchar)(((SMOOTHED(-1, 8) < SMOOTHED(-9, -10)) << 7) + ((SMOOTHED(-23, -1) < SMOOTHED(6, 2)) << 6) + ((SMOOTHED(-5, -3) < SMOOTHED(3, 2)) << 5) + ((SMOOTHED(0, 11) < SMOOTHED(-4, -7)) << 4) + ((SMOOTHED(15, 2) < SMOOTHED(-10, -3)) << 3) + ((SMOOTHED(-20, -8) < SMOOTHED(-13, 3)) << 2) + ((SMOOTHED(-19, -12) < SMOOTHED(5, -11)) << 1) + ((SMOOTHED(-17, -13) < SMOOTHED(-3, 2)) << 0));
|
||||
desc[22] = (uchar)(((SMOOTHED(7, 4) < SMOOTHED(-12, 0)) << 7) + ((SMOOTHED(5, -1) < SMOOTHED(-14, -6)) << 6) + ((SMOOTHED(-4, 11) < SMOOTHED(0, -4)) << 5) + ((SMOOTHED(3, 10) < SMOOTHED(7, -3)) << 4) + ((SMOOTHED(13, 21) < SMOOTHED(-11, 6)) << 3) + ((SMOOTHED(-12, 24) < SMOOTHED(-7, -4)) << 2) + ((SMOOTHED(4, 16) < SMOOTHED(3, -14)) << 1) + ((SMOOTHED(-3, 5) < SMOOTHED(-7, -12)) << 0));
|
||||
desc[23] = (uchar)(((SMOOTHED(0, -4) < SMOOTHED(7, -5)) << 7) + ((SMOOTHED(-17, -9) < SMOOTHED(13, -7)) << 6) + ((SMOOTHED(22, -6) < SMOOTHED(-11, 5)) << 5) + ((SMOOTHED(2, -8) < SMOOTHED(23, -11)) << 4) + ((SMOOTHED(7, -10) < SMOOTHED(-1, 14)) << 3) + ((SMOOTHED(-3, -10) < SMOOTHED(8, 3)) << 2) + ((SMOOTHED(-13, 1) < SMOOTHED(-6, 0)) << 1) + ((SMOOTHED(-7, -21) < SMOOTHED(6, -14)) << 0));
|
||||
desc[24] = (uchar)(((SMOOTHED(18, 19) < SMOOTHED(-4, -6)) << 7) + ((SMOOTHED(10, 7) < SMOOTHED(-1, -4)) << 6) + ((SMOOTHED(-1, 21) < SMOOTHED(1, -5)) << 5) + ((SMOOTHED(-10, 6) < SMOOTHED(-11, -2)) << 4) + ((SMOOTHED(18, -3) < SMOOTHED(-1, 7)) << 3) + ((SMOOTHED(-3, -9) < SMOOTHED(-5, 10)) << 2) + ((SMOOTHED(-13, 14) < SMOOTHED(17, -3)) << 1) + ((SMOOTHED(11, -19) < SMOOTHED(-1, -18)) << 0));
|
||||
desc[25] = (uchar)(((SMOOTHED(8, -2) < SMOOTHED(-18, -23)) << 7) + ((SMOOTHED(0, -5) < SMOOTHED(-2, -9)) << 6) + ((SMOOTHED(-4, -11) < SMOOTHED(2, -8)) << 5) + ((SMOOTHED(14, 6) < SMOOTHED(-3, -6)) << 4) + ((SMOOTHED(-3, 0) < SMOOTHED(-15, 0)) << 3) + ((SMOOTHED(-9, 4) < SMOOTHED(-15, -9)) << 2) + ((SMOOTHED(-1, 11) < SMOOTHED(3, 11)) << 1) + ((SMOOTHED(-10, -16) < SMOOTHED(-7, 7)) << 0));
|
||||
desc[26] = (uchar)(((SMOOTHED(-2, -10) < SMOOTHED(-10, -2)) << 7) + ((SMOOTHED(-5, -3) < SMOOTHED(5, -23)) << 6) + ((SMOOTHED(13, -8) < SMOOTHED(-15, -11)) << 5) + ((SMOOTHED(-15, 11) < SMOOTHED(6, -6)) << 4) + ((SMOOTHED(-16, -3) < SMOOTHED(-2, 2)) << 3) + ((SMOOTHED(6, 12) < SMOOTHED(-16, 24)) << 2) + ((SMOOTHED(-10, 0) < SMOOTHED(8, 11)) << 1) + ((SMOOTHED(-7, 7) < SMOOTHED(-19, -7)) << 0));
|
||||
desc[27] = (uchar)(((SMOOTHED(5, 16) < SMOOTHED(9, -3)) << 7) + ((SMOOTHED(9, 7) < SMOOTHED(-7, -16)) << 6) + ((SMOOTHED(3, 2) < SMOOTHED(-10, 9)) << 5) + ((SMOOTHED(21, 1) < SMOOTHED(8, 7)) << 4) + ((SMOOTHED(7, 0) < SMOOTHED(1, 17)) << 3) + ((SMOOTHED(-8, 12) < SMOOTHED(9, 6)) << 2) + ((SMOOTHED(11, -7) < SMOOTHED(-8, -6)) << 1) + ((SMOOTHED(19, 0) < SMOOTHED(9, 3)) << 0));
|
||||
desc[28] = (uchar)(((SMOOTHED(1, -7) < SMOOTHED(-5, -11)) << 7) + ((SMOOTHED(0, 8) < SMOOTHED(-2, 14)) << 6) + ((SMOOTHED(12, -2) < SMOOTHED(-15, -6)) << 5) + ((SMOOTHED(4, 12) < SMOOTHED(0, -21)) << 4) + ((SMOOTHED(17, -4) < SMOOTHED(-6, -7)) << 3) + ((SMOOTHED(-10, -9) < SMOOTHED(-14, -7)) << 2) + ((SMOOTHED(-15, -10) < SMOOTHED(-15, -14)) << 1) + ((SMOOTHED(-7, -5) < SMOOTHED(5, -12)) << 0));
|
||||
desc[29] = (uchar)(((SMOOTHED(-4, 0) < SMOOTHED(15, -4)) << 7) + ((SMOOTHED(5, 2) < SMOOTHED(-6, -23)) << 6) + ((SMOOTHED(-4, -21) < SMOOTHED(-6, 4)) << 5) + ((SMOOTHED(-10, 5) < SMOOTHED(-15, 6)) << 4) + ((SMOOTHED(4, -3) < SMOOTHED(-1, 5)) << 3) + ((SMOOTHED(-4, 19) < SMOOTHED(-23, -4)) << 2) + ((SMOOTHED(-4, 17) < SMOOTHED(13, -11)) << 1) + ((SMOOTHED(1, 12) < SMOOTHED(4, -14)) << 0));
|
||||
desc[30] = (uchar)(((SMOOTHED(-11, -6) < SMOOTHED(-20, 10)) << 7) + ((SMOOTHED(4, 5) < SMOOTHED(3, 20)) << 6) + ((SMOOTHED(-8, -20) < SMOOTHED(3, 1)) << 5) + ((SMOOTHED(-19, 9) < SMOOTHED(9, -3)) << 4) + ((SMOOTHED(18, 15) < SMOOTHED(11, -4)) << 3) + ((SMOOTHED(12, 16) < SMOOTHED(8, 7)) << 2) + ((SMOOTHED(-14, -8) < SMOOTHED(-3, 9)) << 1) + ((SMOOTHED(-6, 0) < SMOOTHED(2, -4)) << 0));
|
||||
desc[31] = (uchar)(((SMOOTHED(1, -10) < SMOOTHED(-1, 2)) << 7) + ((SMOOTHED(8, -7) < SMOOTHED(-6, 18)) << 6) + ((SMOOTHED(9, 12) < SMOOTHED(-7, -23)) << 5) + ((SMOOTHED(8, -6) < SMOOTHED(5, 2)) << 4) + ((SMOOTHED(-9, 6) < SMOOTHED(-12, -7)) << 3) + ((SMOOTHED(-1, -2) < SMOOTHED(-7, 2)) << 2) + ((SMOOTHED(9, 9) < SMOOTHED(7, 15)) << 1) + ((SMOOTHED(6, 2) < SMOOTHED(-6, 6)) << 0));
|
||||
#undef SMOOTHED
|
@@ -1,67 +0,0 @@
|
||||
// Code generated with '$ scripts/generate_code.py src/test_pairs.txt 64'
|
||||
#define SMOOTHED(y,x) smoothedSum(sum, pt, y, x)
|
||||
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));
|
||||
desc[3] = (uchar)(((SMOOTHED(0, 12) < SMOOTHED(-3, 19)) << 7) + ((SMOOTHED(1, 15) < SMOOTHED(-11, -5)) << 6) + ((SMOOTHED(14, -1) < SMOOTHED(7, 8)) << 5) + ((SMOOTHED(7, -23) < SMOOTHED(-5, 5)) << 4) + ((SMOOTHED(0, -6) < SMOOTHED(-10, 17)) << 3) + ((SMOOTHED(13, -4) < SMOOTHED(-3, -4)) << 2) + ((SMOOTHED(-12, 1) < SMOOTHED(-12, 2)) << 1) + ((SMOOTHED(0, 8) < SMOOTHED(3, 22)) << 0));
|
||||
desc[4] = (uchar)(((SMOOTHED(-13, 13) < SMOOTHED(3, -1)) << 7) + ((SMOOTHED(-16, 17) < SMOOTHED(6, 10)) << 6) + ((SMOOTHED(7, 15) < SMOOTHED(-5, 0)) << 5) + ((SMOOTHED(2, -12) < SMOOTHED(19, -2)) << 4) + ((SMOOTHED(3, -6) < SMOOTHED(-4, -15)) << 3) + ((SMOOTHED(8, 3) < SMOOTHED(0, 14)) << 2) + ((SMOOTHED(4, -11) < SMOOTHED(5, 5)) << 1) + ((SMOOTHED(11, -7) < SMOOTHED(7, 1)) << 0));
|
||||
desc[5] = (uchar)(((SMOOTHED(6, 12) < SMOOTHED(21, 3)) << 7) + ((SMOOTHED(-3, 2) < SMOOTHED(14, 1)) << 6) + ((SMOOTHED(5, 1) < SMOOTHED(-5, 11)) << 5) + ((SMOOTHED(3, -17) < SMOOTHED(-6, 2)) << 4) + ((SMOOTHED(6, 8) < SMOOTHED(5, -10)) << 3) + ((SMOOTHED(-14, -2) < SMOOTHED(0, 4)) << 2) + ((SMOOTHED(5, -7) < SMOOTHED(-6, 5)) << 1) + ((SMOOTHED(10, 4) < SMOOTHED(4, -7)) << 0));
|
||||
desc[6] = (uchar)(((SMOOTHED(22, 0) < SMOOTHED(7, -18)) << 7) + ((SMOOTHED(-1, -3) < SMOOTHED(0, 18)) << 6) + ((SMOOTHED(-4, 22) < SMOOTHED(-5, 3)) << 5) + ((SMOOTHED(1, -7) < SMOOTHED(2, -3)) << 4) + ((SMOOTHED(19, -20) < SMOOTHED(17, -2)) << 3) + ((SMOOTHED(3, -10) < SMOOTHED(-8, 24)) << 2) + ((SMOOTHED(-5, -14) < SMOOTHED(7, 5)) << 1) + ((SMOOTHED(-2, 12) < SMOOTHED(-4, -15)) << 0));
|
||||
desc[7] = (uchar)(((SMOOTHED(4, 12) < SMOOTHED(0, -19)) << 7) + ((SMOOTHED(20, 13) < SMOOTHED(3, 5)) << 6) + ((SMOOTHED(-8, -12) < SMOOTHED(5, 0)) << 5) + ((SMOOTHED(-5, 6) < SMOOTHED(-7, -11)) << 4) + ((SMOOTHED(6, -11) < SMOOTHED(-3, -22)) << 3) + ((SMOOTHED(15, 4) < SMOOTHED(10, 1)) << 2) + ((SMOOTHED(-7, -4) < SMOOTHED(15, -6)) << 1) + ((SMOOTHED(5, 10) < SMOOTHED(0, 24)) << 0));
|
||||
desc[8] = (uchar)(((SMOOTHED(3, 6) < SMOOTHED(22, -2)) << 7) + ((SMOOTHED(-13, 14) < SMOOTHED(4, -4)) << 6) + ((SMOOTHED(-13, 8) < SMOOTHED(-18, -22)) << 5) + ((SMOOTHED(-1, -1) < SMOOTHED(-7, 3)) << 4) + ((SMOOTHED(-19, -12) < SMOOTHED(4, 3)) << 3) + ((SMOOTHED(8, 10) < SMOOTHED(13, -2)) << 2) + ((SMOOTHED(-6, -1) < SMOOTHED(-6, -5)) << 1) + ((SMOOTHED(2, -21) < SMOOTHED(-3, 2)) << 0));
|
||||
desc[9] = (uchar)(((SMOOTHED(4, -7) < SMOOTHED(0, 16)) << 7) + ((SMOOTHED(-6, -5) < SMOOTHED(-12, -1)) << 6) + ((SMOOTHED(1, -1) < SMOOTHED(9, 18)) << 5) + ((SMOOTHED(-7, 10) < SMOOTHED(-11, 6)) << 4) + ((SMOOTHED(4, 3) < SMOOTHED(19, -7)) << 3) + ((SMOOTHED(-18, 5) < SMOOTHED(-4, 5)) << 2) + ((SMOOTHED(4, 0) < SMOOTHED(-20, 4)) << 1) + ((SMOOTHED(7, -11) < SMOOTHED(18, 12)) << 0));
|
||||
desc[10] = (uchar)(((SMOOTHED(-20, 17) < SMOOTHED(-18, 7)) << 7) + ((SMOOTHED(2, 15) < SMOOTHED(19, -11)) << 6) + ((SMOOTHED(-18, 6) < SMOOTHED(-7, 3)) << 5) + ((SMOOTHED(-4, 1) < SMOOTHED(-14, 13)) << 4) + ((SMOOTHED(17, 3) < SMOOTHED(2, -8)) << 3) + ((SMOOTHED(-7, 2) < SMOOTHED(1, 6)) << 2) + ((SMOOTHED(17, -9) < SMOOTHED(-2, 8)) << 1) + ((SMOOTHED(-8, -6) < SMOOTHED(-1, 12)) << 0));
|
||||
desc[11] = (uchar)(((SMOOTHED(-2, 4) < SMOOTHED(-1, 6)) << 7) + ((SMOOTHED(-2, 7) < SMOOTHED(6, 8)) << 6) + ((SMOOTHED(-8, -1) < SMOOTHED(-7, -9)) << 5) + ((SMOOTHED(8, -9) < SMOOTHED(15, 0)) << 4) + ((SMOOTHED(0, 22) < SMOOTHED(-4, -15)) << 3) + ((SMOOTHED(-14, -1) < SMOOTHED(3, -2)) << 2) + ((SMOOTHED(-7, -4) < SMOOTHED(17, -7)) << 1) + ((SMOOTHED(-8, -2) < SMOOTHED(9, -4)) << 0));
|
||||
desc[12] = (uchar)(((SMOOTHED(5, -7) < SMOOTHED(7, 7)) << 7) + ((SMOOTHED(-5, 13) < SMOOTHED(-8, 11)) << 6) + ((SMOOTHED(11, -4) < SMOOTHED(0, 8)) << 5) + ((SMOOTHED(5, -11) < SMOOTHED(-9, -6)) << 4) + ((SMOOTHED(2, -6) < SMOOTHED(3, -20)) << 3) + ((SMOOTHED(-6, 2) < SMOOTHED(6, 10)) << 2) + ((SMOOTHED(-6, -6) < SMOOTHED(-15, 7)) << 1) + ((SMOOTHED(-6, -3) < SMOOTHED(2, 1)) << 0));
|
||||
desc[13] = (uchar)(((SMOOTHED(11, 0) < SMOOTHED(-3, 2)) << 7) + ((SMOOTHED(7, -12) < SMOOTHED(14, 5)) << 6) + ((SMOOTHED(0, -7) < SMOOTHED(-1, -1)) << 5) + ((SMOOTHED(-16, 0) < SMOOTHED(6, 8)) << 4) + ((SMOOTHED(22, 11) < SMOOTHED(0, -3)) << 3) + ((SMOOTHED(19, 0) < SMOOTHED(5, -17)) << 2) + ((SMOOTHED(-23, -14) < SMOOTHED(-13, -19)) << 1) + ((SMOOTHED(-8, 10) < SMOOTHED(-11, -2)) << 0));
|
||||
desc[14] = (uchar)(((SMOOTHED(-11, 6) < SMOOTHED(-10, 13)) << 7) + ((SMOOTHED(1, -7) < SMOOTHED(14, 0)) << 6) + ((SMOOTHED(-12, 1) < SMOOTHED(-5, -5)) << 5) + ((SMOOTHED(4, 7) < SMOOTHED(8, -1)) << 4) + ((SMOOTHED(-1, -5) < SMOOTHED(15, 2)) << 3) + ((SMOOTHED(-3, -1) < SMOOTHED(7, -10)) << 2) + ((SMOOTHED(3, -6) < SMOOTHED(10, -18)) << 1) + ((SMOOTHED(-7, -13) < SMOOTHED(-13, 10)) << 0));
|
||||
desc[15] = (uchar)(((SMOOTHED(1, -1) < SMOOTHED(13, -10)) << 7) + ((SMOOTHED(-19, 14) < SMOOTHED(8, -14)) << 6) + ((SMOOTHED(-4, -13) < SMOOTHED(7, 1)) << 5) + ((SMOOTHED(1, -2) < SMOOTHED(12, -7)) << 4) + ((SMOOTHED(3, -5) < SMOOTHED(1, -5)) << 3) + ((SMOOTHED(-2, -2) < SMOOTHED(8, -10)) << 2) + ((SMOOTHED(2, 14) < SMOOTHED(8, 7)) << 1) + ((SMOOTHED(3, 9) < SMOOTHED(8, 2)) << 0));
|
||||
desc[16] = (uchar)(((SMOOTHED(-9, 1) < SMOOTHED(-18, 0)) << 7) + ((SMOOTHED(4, 0) < SMOOTHED(1, 12)) << 6) + ((SMOOTHED(0, 9) < SMOOTHED(-14, -10)) << 5) + ((SMOOTHED(-13, -9) < SMOOTHED(-2, 6)) << 4) + ((SMOOTHED(1, 5) < SMOOTHED(10, 10)) << 3) + ((SMOOTHED(-3, -6) < SMOOTHED(-16, -5)) << 2) + ((SMOOTHED(11, 6) < SMOOTHED(-5, 0)) << 1) + ((SMOOTHED(-23, 10) < SMOOTHED(1, 2)) << 0));
|
||||
desc[17] = (uchar)(((SMOOTHED(13, -5) < SMOOTHED(-3, 9)) << 7) + ((SMOOTHED(-4, -1) < SMOOTHED(-13, -5)) << 6) + ((SMOOTHED(10, 13) < SMOOTHED(-11, 8)) << 5) + ((SMOOTHED(19, 20) < SMOOTHED(-9, 2)) << 4) + ((SMOOTHED(4, -8) < SMOOTHED(0, -9)) << 3) + ((SMOOTHED(-14, 10) < SMOOTHED(15, 19)) << 2) + ((SMOOTHED(-14, -12) < SMOOTHED(-10, -3)) << 1) + ((SMOOTHED(-23, -3) < SMOOTHED(17, -2)) << 0));
|
||||
desc[18] = (uchar)(((SMOOTHED(-3, -11) < SMOOTHED(6, -14)) << 7) + ((SMOOTHED(19, -2) < SMOOTHED(-4, 2)) << 6) + ((SMOOTHED(-5, 5) < SMOOTHED(3, -13)) << 5) + ((SMOOTHED(2, -2) < SMOOTHED(-5, 4)) << 4) + ((SMOOTHED(17, 4) < SMOOTHED(17, -11)) << 3) + ((SMOOTHED(-7, -2) < SMOOTHED(1, 23)) << 2) + ((SMOOTHED(8, 13) < SMOOTHED(1, -16)) << 1) + ((SMOOTHED(-13, -5) < SMOOTHED(1, -17)) << 0));
|
||||
desc[19] = (uchar)(((SMOOTHED(4, 6) < SMOOTHED(-8, -3)) << 7) + ((SMOOTHED(-5, -9) < SMOOTHED(-2, -10)) << 6) + ((SMOOTHED(-9, 0) < SMOOTHED(-7, -2)) << 5) + ((SMOOTHED(5, 0) < SMOOTHED(5, 2)) << 4) + ((SMOOTHED(-4, -16) < SMOOTHED(6, 3)) << 3) + ((SMOOTHED(2, -15) < SMOOTHED(-2, 12)) << 2) + ((SMOOTHED(4, -1) < SMOOTHED(6, 2)) << 1) + ((SMOOTHED(1, 1) < SMOOTHED(-2, -8)) << 0));
|
||||
desc[20] = (uchar)(((SMOOTHED(-2, 12) < SMOOTHED(-5, -2)) << 7) + ((SMOOTHED(-8, 8) < SMOOTHED(-9, 9)) << 6) + ((SMOOTHED(2, -10) < SMOOTHED(3, 1)) << 5) + ((SMOOTHED(-4, 10) < SMOOTHED(-9, 4)) << 4) + ((SMOOTHED(6, 12) < SMOOTHED(2, 5)) << 3) + ((SMOOTHED(-3, -8) < SMOOTHED(0, 5)) << 2) + ((SMOOTHED(-13, 1) < SMOOTHED(-7, 2)) << 1) + ((SMOOTHED(-1, -10) < SMOOTHED(7, -18)) << 0));
|
||||
desc[21] = (uchar)(((SMOOTHED(-1, 8) < SMOOTHED(-9, -10)) << 7) + ((SMOOTHED(-23, -1) < SMOOTHED(6, 2)) << 6) + ((SMOOTHED(-5, -3) < SMOOTHED(3, 2)) << 5) + ((SMOOTHED(0, 11) < SMOOTHED(-4, -7)) << 4) + ((SMOOTHED(15, 2) < SMOOTHED(-10, -3)) << 3) + ((SMOOTHED(-20, -8) < SMOOTHED(-13, 3)) << 2) + ((SMOOTHED(-19, -12) < SMOOTHED(5, -11)) << 1) + ((SMOOTHED(-17, -13) < SMOOTHED(-3, 2)) << 0));
|
||||
desc[22] = (uchar)(((SMOOTHED(7, 4) < SMOOTHED(-12, 0)) << 7) + ((SMOOTHED(5, -1) < SMOOTHED(-14, -6)) << 6) + ((SMOOTHED(-4, 11) < SMOOTHED(0, -4)) << 5) + ((SMOOTHED(3, 10) < SMOOTHED(7, -3)) << 4) + ((SMOOTHED(13, 21) < SMOOTHED(-11, 6)) << 3) + ((SMOOTHED(-12, 24) < SMOOTHED(-7, -4)) << 2) + ((SMOOTHED(4, 16) < SMOOTHED(3, -14)) << 1) + ((SMOOTHED(-3, 5) < SMOOTHED(-7, -12)) << 0));
|
||||
desc[23] = (uchar)(((SMOOTHED(0, -4) < SMOOTHED(7, -5)) << 7) + ((SMOOTHED(-17, -9) < SMOOTHED(13, -7)) << 6) + ((SMOOTHED(22, -6) < SMOOTHED(-11, 5)) << 5) + ((SMOOTHED(2, -8) < SMOOTHED(23, -11)) << 4) + ((SMOOTHED(7, -10) < SMOOTHED(-1, 14)) << 3) + ((SMOOTHED(-3, -10) < SMOOTHED(8, 3)) << 2) + ((SMOOTHED(-13, 1) < SMOOTHED(-6, 0)) << 1) + ((SMOOTHED(-7, -21) < SMOOTHED(6, -14)) << 0));
|
||||
desc[24] = (uchar)(((SMOOTHED(18, 19) < SMOOTHED(-4, -6)) << 7) + ((SMOOTHED(10, 7) < SMOOTHED(-1, -4)) << 6) + ((SMOOTHED(-1, 21) < SMOOTHED(1, -5)) << 5) + ((SMOOTHED(-10, 6) < SMOOTHED(-11, -2)) << 4) + ((SMOOTHED(18, -3) < SMOOTHED(-1, 7)) << 3) + ((SMOOTHED(-3, -9) < SMOOTHED(-5, 10)) << 2) + ((SMOOTHED(-13, 14) < SMOOTHED(17, -3)) << 1) + ((SMOOTHED(11, -19) < SMOOTHED(-1, -18)) << 0));
|
||||
desc[25] = (uchar)(((SMOOTHED(8, -2) < SMOOTHED(-18, -23)) << 7) + ((SMOOTHED(0, -5) < SMOOTHED(-2, -9)) << 6) + ((SMOOTHED(-4, -11) < SMOOTHED(2, -8)) << 5) + ((SMOOTHED(14, 6) < SMOOTHED(-3, -6)) << 4) + ((SMOOTHED(-3, 0) < SMOOTHED(-15, 0)) << 3) + ((SMOOTHED(-9, 4) < SMOOTHED(-15, -9)) << 2) + ((SMOOTHED(-1, 11) < SMOOTHED(3, 11)) << 1) + ((SMOOTHED(-10, -16) < SMOOTHED(-7, 7)) << 0));
|
||||
desc[26] = (uchar)(((SMOOTHED(-2, -10) < SMOOTHED(-10, -2)) << 7) + ((SMOOTHED(-5, -3) < SMOOTHED(5, -23)) << 6) + ((SMOOTHED(13, -8) < SMOOTHED(-15, -11)) << 5) + ((SMOOTHED(-15, 11) < SMOOTHED(6, -6)) << 4) + ((SMOOTHED(-16, -3) < SMOOTHED(-2, 2)) << 3) + ((SMOOTHED(6, 12) < SMOOTHED(-16, 24)) << 2) + ((SMOOTHED(-10, 0) < SMOOTHED(8, 11)) << 1) + ((SMOOTHED(-7, 7) < SMOOTHED(-19, -7)) << 0));
|
||||
desc[27] = (uchar)(((SMOOTHED(5, 16) < SMOOTHED(9, -3)) << 7) + ((SMOOTHED(9, 7) < SMOOTHED(-7, -16)) << 6) + ((SMOOTHED(3, 2) < SMOOTHED(-10, 9)) << 5) + ((SMOOTHED(21, 1) < SMOOTHED(8, 7)) << 4) + ((SMOOTHED(7, 0) < SMOOTHED(1, 17)) << 3) + ((SMOOTHED(-8, 12) < SMOOTHED(9, 6)) << 2) + ((SMOOTHED(11, -7) < SMOOTHED(-8, -6)) << 1) + ((SMOOTHED(19, 0) < SMOOTHED(9, 3)) << 0));
|
||||
desc[28] = (uchar)(((SMOOTHED(1, -7) < SMOOTHED(-5, -11)) << 7) + ((SMOOTHED(0, 8) < SMOOTHED(-2, 14)) << 6) + ((SMOOTHED(12, -2) < SMOOTHED(-15, -6)) << 5) + ((SMOOTHED(4, 12) < SMOOTHED(0, -21)) << 4) + ((SMOOTHED(17, -4) < SMOOTHED(-6, -7)) << 3) + ((SMOOTHED(-10, -9) < SMOOTHED(-14, -7)) << 2) + ((SMOOTHED(-15, -10) < SMOOTHED(-15, -14)) << 1) + ((SMOOTHED(-7, -5) < SMOOTHED(5, -12)) << 0));
|
||||
desc[29] = (uchar)(((SMOOTHED(-4, 0) < SMOOTHED(15, -4)) << 7) + ((SMOOTHED(5, 2) < SMOOTHED(-6, -23)) << 6) + ((SMOOTHED(-4, -21) < SMOOTHED(-6, 4)) << 5) + ((SMOOTHED(-10, 5) < SMOOTHED(-15, 6)) << 4) + ((SMOOTHED(4, -3) < SMOOTHED(-1, 5)) << 3) + ((SMOOTHED(-4, 19) < SMOOTHED(-23, -4)) << 2) + ((SMOOTHED(-4, 17) < SMOOTHED(13, -11)) << 1) + ((SMOOTHED(1, 12) < SMOOTHED(4, -14)) << 0));
|
||||
desc[30] = (uchar)(((SMOOTHED(-11, -6) < SMOOTHED(-20, 10)) << 7) + ((SMOOTHED(4, 5) < SMOOTHED(3, 20)) << 6) + ((SMOOTHED(-8, -20) < SMOOTHED(3, 1)) << 5) + ((SMOOTHED(-19, 9) < SMOOTHED(9, -3)) << 4) + ((SMOOTHED(18, 15) < SMOOTHED(11, -4)) << 3) + ((SMOOTHED(12, 16) < SMOOTHED(8, 7)) << 2) + ((SMOOTHED(-14, -8) < SMOOTHED(-3, 9)) << 1) + ((SMOOTHED(-6, 0) < SMOOTHED(2, -4)) << 0));
|
||||
desc[31] = (uchar)(((SMOOTHED(1, -10) < SMOOTHED(-1, 2)) << 7) + ((SMOOTHED(8, -7) < SMOOTHED(-6, 18)) << 6) + ((SMOOTHED(9, 12) < SMOOTHED(-7, -23)) << 5) + ((SMOOTHED(8, -6) < SMOOTHED(5, 2)) << 4) + ((SMOOTHED(-9, 6) < SMOOTHED(-12, -7)) << 3) + ((SMOOTHED(-1, -2) < SMOOTHED(-7, 2)) << 2) + ((SMOOTHED(9, 9) < SMOOTHED(7, 15)) << 1) + ((SMOOTHED(6, 2) < SMOOTHED(-6, 6)) << 0));
|
||||
desc[32] = (uchar)(((SMOOTHED(16, 12) < SMOOTHED(0, 19)) << 7) + ((SMOOTHED(4, 3) < SMOOTHED(6, 0)) << 6) + ((SMOOTHED(-2, -1) < SMOOTHED(2, 17)) << 5) + ((SMOOTHED(8, 1) < SMOOTHED(3, 1)) << 4) + ((SMOOTHED(-12, -1) < SMOOTHED(-11, 0)) << 3) + ((SMOOTHED(-11, 2) < SMOOTHED(7, 9)) << 2) + ((SMOOTHED(-1, 3) < SMOOTHED(-19, 4)) << 1) + ((SMOOTHED(-1, -11) < SMOOTHED(-1, 3)) << 0));
|
||||
desc[33] = (uchar)(((SMOOTHED(1, -10) < SMOOTHED(-10, -4)) << 7) + ((SMOOTHED(-2, 3) < SMOOTHED(6, 11)) << 6) + ((SMOOTHED(3, 7) < SMOOTHED(-9, -8)) << 5) + ((SMOOTHED(24, -14) < SMOOTHED(-2, -10)) << 4) + ((SMOOTHED(-3, -3) < SMOOTHED(-18, -6)) << 3) + ((SMOOTHED(-13, -10) < SMOOTHED(-7, -1)) << 2) + ((SMOOTHED(2, -7) < SMOOTHED(9, -6)) << 1) + ((SMOOTHED(2, -4) < SMOOTHED(6, -13)) << 0));
|
||||
desc[34] = (uchar)(((SMOOTHED(4, -4) < SMOOTHED(-2, 3)) << 7) + ((SMOOTHED(-4, 2) < SMOOTHED(9, 13)) << 6) + ((SMOOTHED(-11, 5) < SMOOTHED(-6, -11)) << 5) + ((SMOOTHED(4, -2) < SMOOTHED(11, -9)) << 4) + ((SMOOTHED(-19, 0) < SMOOTHED(-23, -5)) << 3) + ((SMOOTHED(-5, -7) < SMOOTHED(-3, -6)) << 2) + ((SMOOTHED(-6, -4) < SMOOTHED(12, 14)) << 1) + ((SMOOTHED(12, -11) < SMOOTHED(-8, -16)) << 0));
|
||||
desc[35] = (uchar)(((SMOOTHED(-21, 15) < SMOOTHED(-12, 6)) << 7) + ((SMOOTHED(-2, -1) < SMOOTHED(-8, 16)) << 6) + ((SMOOTHED(6, -1) < SMOOTHED(-8, -2)) << 5) + ((SMOOTHED(1, -1) < SMOOTHED(-9, 8)) << 4) + ((SMOOTHED(3, -4) < SMOOTHED(-2, -2)) << 3) + ((SMOOTHED(-7, 0) < SMOOTHED(4, -8)) << 2) + ((SMOOTHED(11, -11) < SMOOTHED(-12, 2)) << 1) + ((SMOOTHED(2, 3) < SMOOTHED(11, 7)) << 0));
|
||||
desc[36] = (uchar)(((SMOOTHED(-7, -4) < SMOOTHED(-9, -6)) << 7) + ((SMOOTHED(3, -7) < SMOOTHED(-5, 0)) << 6) + ((SMOOTHED(3, -7) < SMOOTHED(-10, -5)) << 5) + ((SMOOTHED(-3, -1) < SMOOTHED(8, -10)) << 4) + ((SMOOTHED(0, 8) < SMOOTHED(5, 1)) << 3) + ((SMOOTHED(9, 0) < SMOOTHED(1, 16)) << 2) + ((SMOOTHED(8, 4) < SMOOTHED(-11, -3)) << 1) + ((SMOOTHED(-15, 9) < SMOOTHED(8, 17)) << 0));
|
||||
desc[37] = (uchar)(((SMOOTHED(0, 2) < SMOOTHED(-9, 17)) << 7) + ((SMOOTHED(-6, -11) < SMOOTHED(-10, -3)) << 6) + ((SMOOTHED(1, 1) < SMOOTHED(15, -8)) << 5) + ((SMOOTHED(-12, -13) < SMOOTHED(-2, 4)) << 4) + ((SMOOTHED(-6, 4) < SMOOTHED(-6, -10)) << 3) + ((SMOOTHED(5, -7) < SMOOTHED(7, -5)) << 2) + ((SMOOTHED(10, 6) < SMOOTHED(8, 9)) << 1) + ((SMOOTHED(-5, 7) < SMOOTHED(-18, -3)) << 0));
|
||||
desc[38] = (uchar)(((SMOOTHED(-6, 3) < SMOOTHED(5, 4)) << 7) + ((SMOOTHED(-10, -13) < SMOOTHED(-5, -3)) << 6) + ((SMOOTHED(-11, 2) < SMOOTHED(-16, 0)) << 5) + ((SMOOTHED(7, -21) < SMOOTHED(-5, -13)) << 4) + ((SMOOTHED(-14, -14) < SMOOTHED(-4, -4)) << 3) + ((SMOOTHED(4, 9) < SMOOTHED(7, -3)) << 2) + ((SMOOTHED(4, 11) < SMOOTHED(10, -4)) << 1) + ((SMOOTHED(6, 17) < SMOOTHED(9, 17)) << 0));
|
||||
desc[39] = (uchar)(((SMOOTHED(-10, 8) < SMOOTHED(0, -11)) << 7) + ((SMOOTHED(-6, -16) < SMOOTHED(-6, 8)) << 6) + ((SMOOTHED(-13, 5) < SMOOTHED(10, -5)) << 5) + ((SMOOTHED(3, 2) < SMOOTHED(12, 16)) << 4) + ((SMOOTHED(13, -8) < SMOOTHED(0, -6)) << 3) + ((SMOOTHED(10, 0) < SMOOTHED(4, -11)) << 2) + ((SMOOTHED(8, 5) < SMOOTHED(10, -2)) << 1) + ((SMOOTHED(11, -7) < SMOOTHED(-13, 3)) << 0));
|
||||
desc[40] = (uchar)(((SMOOTHED(2, 4) < SMOOTHED(-7, -3)) << 7) + ((SMOOTHED(-14, -2) < SMOOTHED(-11, 16)) << 6) + ((SMOOTHED(11, -6) < SMOOTHED(7, 6)) << 5) + ((SMOOTHED(-3, 15) < SMOOTHED(8, -10)) << 4) + ((SMOOTHED(-3, 8) < SMOOTHED(12, -12)) << 3) + ((SMOOTHED(-13, 6) < SMOOTHED(-14, 7)) << 2) + ((SMOOTHED(-11, -5) < SMOOTHED(-8, -6)) << 1) + ((SMOOTHED(7, -6) < SMOOTHED(6, 3)) << 0));
|
||||
desc[41] = (uchar)(((SMOOTHED(-4, 10) < SMOOTHED(5, 1)) << 7) + ((SMOOTHED(9, 16) < SMOOTHED(10, 13)) << 6) + ((SMOOTHED(-17, 10) < SMOOTHED(2, 8)) << 5) + ((SMOOTHED(-5, 1) < SMOOTHED(4, -4)) << 4) + ((SMOOTHED(-14, 8) < SMOOTHED(-5, 2)) << 3) + ((SMOOTHED(4, -9) < SMOOTHED(-6, -3)) << 2) + ((SMOOTHED(3, -7) < SMOOTHED(-10, 0)) << 1) + ((SMOOTHED(-2, -8) < SMOOTHED(-10, 4)) << 0));
|
||||
desc[42] = (uchar)(((SMOOTHED(-8, 5) < SMOOTHED(-9, 24)) << 7) + ((SMOOTHED(2, -8) < SMOOTHED(8, -9)) << 6) + ((SMOOTHED(-4, 17) < SMOOTHED(-5, 2)) << 5) + ((SMOOTHED(14, 0) < SMOOTHED(-9, 9)) << 4) + ((SMOOTHED(11, 15) < SMOOTHED(-6, 5)) << 3) + ((SMOOTHED(-8, 1) < SMOOTHED(-3, 4)) << 2) + ((SMOOTHED(9, -21) < SMOOTHED(10, 2)) << 1) + ((SMOOTHED(2, -1) < SMOOTHED(4, 11)) << 0));
|
||||
desc[43] = (uchar)(((SMOOTHED(24, 3) < SMOOTHED(2, -2)) << 7) + ((SMOOTHED(-8, 17) < SMOOTHED(-14, -10)) << 6) + ((SMOOTHED(6, 5) < SMOOTHED(-13, 7)) << 5) + ((SMOOTHED(11, 10) < SMOOTHED(0, -1)) << 4) + ((SMOOTHED(4, 6) < SMOOTHED(-10, 6)) << 3) + ((SMOOTHED(-12, -2) < SMOOTHED(5, 6)) << 2) + ((SMOOTHED(3, -1) < SMOOTHED(8, -15)) << 1) + ((SMOOTHED(1, -4) < SMOOTHED(-7, 11)) << 0));
|
||||
desc[44] = (uchar)(((SMOOTHED(1, 11) < SMOOTHED(5, 0)) << 7) + ((SMOOTHED(6, -12) < SMOOTHED(10, 1)) << 6) + ((SMOOTHED(-3, -2) < SMOOTHED(-1, 4)) << 5) + ((SMOOTHED(-2, -11) < SMOOTHED(-1, 12)) << 4) + ((SMOOTHED(7, -8) < SMOOTHED(-20, -18)) << 3) + ((SMOOTHED(2, 0) < SMOOTHED(-9, 2)) << 2) + ((SMOOTHED(-13, -1) < SMOOTHED(-16, 2)) << 1) + ((SMOOTHED(3, -1) < SMOOTHED(-5, -17)) << 0));
|
||||
desc[45] = (uchar)(((SMOOTHED(15, 8) < SMOOTHED(3, -14)) << 7) + ((SMOOTHED(-13, -12) < SMOOTHED(6, 15)) << 6) + ((SMOOTHED(2, -8) < SMOOTHED(2, 6)) << 5) + ((SMOOTHED(6, 22) < SMOOTHED(-3, -23)) << 4) + ((SMOOTHED(-2, -7) < SMOOTHED(-6, 0)) << 3) + ((SMOOTHED(13, -10) < SMOOTHED(-6, 6)) << 2) + ((SMOOTHED(6, 7) < SMOOTHED(-10, 12)) << 1) + ((SMOOTHED(-6, 7) < SMOOTHED(-2, 11)) << 0));
|
||||
desc[46] = (uchar)(((SMOOTHED(0, -22) < SMOOTHED(-2, -17)) << 7) + ((SMOOTHED(-4, -1) < SMOOTHED(-11, -14)) << 6) + ((SMOOTHED(-2, -8) < SMOOTHED(7, 12)) << 5) + ((SMOOTHED(12, -5) < SMOOTHED(7, -13)) << 4) + ((SMOOTHED(2, -2) < SMOOTHED(-7, 6)) << 3) + ((SMOOTHED(0, 8) < SMOOTHED(-3, 23)) << 2) + ((SMOOTHED(6, 12) < SMOOTHED(13, -11)) << 1) + ((SMOOTHED(-21, -10) < SMOOTHED(10, 8)) << 0));
|
||||
desc[47] = (uchar)(((SMOOTHED(-3, 0) < SMOOTHED(7, 15)) << 7) + ((SMOOTHED(7, -6) < SMOOTHED(-5, -12)) << 6) + ((SMOOTHED(-21, -10) < SMOOTHED(12, -11)) << 5) + ((SMOOTHED(-5, -11) < SMOOTHED(8, -11)) << 4) + ((SMOOTHED(5, 0) < SMOOTHED(-11, -1)) << 3) + ((SMOOTHED(8, -9) < SMOOTHED(7, -1)) << 2) + ((SMOOTHED(11, -23) < SMOOTHED(21, -5)) << 1) + ((SMOOTHED(0, -5) < SMOOTHED(-8, 6)) << 0));
|
||||
desc[48] = (uchar)(((SMOOTHED(-6, 8) < SMOOTHED(8, 12)) << 7) + ((SMOOTHED(-7, 5) < SMOOTHED(3, -2)) << 6) + ((SMOOTHED(-5, -20) < SMOOTHED(-12, 9)) << 5) + ((SMOOTHED(-6, 12) < SMOOTHED(-11, 3)) << 4) + ((SMOOTHED(4, 5) < SMOOTHED(13, 11)) << 3) + ((SMOOTHED(2, 12) < SMOOTHED(13, -12)) << 2) + ((SMOOTHED(-4, -13) < SMOOTHED(4, 7)) << 1) + ((SMOOTHED(0, 15) < SMOOTHED(-3, -16)) << 0));
|
||||
desc[49] = (uchar)(((SMOOTHED(-3, 2) < SMOOTHED(-2, 14)) << 7) + ((SMOOTHED(4, -14) < SMOOTHED(16, -11)) << 6) + ((SMOOTHED(-13, 3) < SMOOTHED(23, 10)) << 5) + ((SMOOTHED(9, -19) < SMOOTHED(2, 5)) << 4) + ((SMOOTHED(5, 3) < SMOOTHED(14, -7)) << 3) + ((SMOOTHED(19, -13) < SMOOTHED(-11, 15)) << 2) + ((SMOOTHED(14, 0) < SMOOTHED(-2, -5)) << 1) + ((SMOOTHED(11, -4) < SMOOTHED(0, -6)) << 0));
|
||||
desc[50] = (uchar)(((SMOOTHED(-2, 5) < SMOOTHED(-13, -8)) << 7) + ((SMOOTHED(-11, -15) < SMOOTHED(-7, -17)) << 6) + ((SMOOTHED(1, 3) < SMOOTHED(-10, -8)) << 5) + ((SMOOTHED(-13, -10) < SMOOTHED(7, -12)) << 4) + ((SMOOTHED(0, -13) < SMOOTHED(23, -6)) << 3) + ((SMOOTHED(2, -17) < SMOOTHED(-7, -3)) << 2) + ((SMOOTHED(1, 3) < SMOOTHED(4, -10)) << 1) + ((SMOOTHED(13, 4) < SMOOTHED(14, -6)) << 0));
|
||||
desc[51] = (uchar)(((SMOOTHED(-19, -2) < SMOOTHED(-1, 5)) << 7) + ((SMOOTHED(9, -8) < SMOOTHED(10, -5)) << 6) + ((SMOOTHED(7, -1) < SMOOTHED(5, 7)) << 5) + ((SMOOTHED(9, -10) < SMOOTHED(19, 0)) << 4) + ((SMOOTHED(7, 5) < SMOOTHED(-4, -7)) << 3) + ((SMOOTHED(-11, 1) < SMOOTHED(-1, -11)) << 2) + ((SMOOTHED(2, -1) < SMOOTHED(-4, 11)) << 1) + ((SMOOTHED(-1, 7) < SMOOTHED(2, -2)) << 0));
|
||||
desc[52] = (uchar)(((SMOOTHED(1, -20) < SMOOTHED(-9, -6)) << 7) + ((SMOOTHED(-4, -18) < SMOOTHED(8, -18)) << 6) + ((SMOOTHED(-16, -2) < SMOOTHED(7, -6)) << 5) + ((SMOOTHED(-3, -6) < SMOOTHED(-1, -4)) << 4) + ((SMOOTHED(0, -16) < SMOOTHED(24, -5)) << 3) + ((SMOOTHED(-4, -2) < SMOOTHED(-1, 9)) << 2) + ((SMOOTHED(-8, 2) < SMOOTHED(-6, 15)) << 1) + ((SMOOTHED(11, 4) < SMOOTHED(0, -3)) << 0));
|
||||
desc[53] = (uchar)(((SMOOTHED(7, 6) < SMOOTHED(2, -10)) << 7) + ((SMOOTHED(-7, -9) < SMOOTHED(12, -6)) << 6) + ((SMOOTHED(24, 15) < SMOOTHED(-8, -1)) << 5) + ((SMOOTHED(15, -9) < SMOOTHED(-3, -15)) << 4) + ((SMOOTHED(17, -5) < SMOOTHED(11, -10)) << 3) + ((SMOOTHED(-2, 13) < SMOOTHED(-15, 4)) << 2) + ((SMOOTHED(-2, -1) < SMOOTHED(4, -23)) << 1) + ((SMOOTHED(-16, 3) < SMOOTHED(-7, -14)) << 0));
|
||||
desc[54] = (uchar)(((SMOOTHED(-3, -5) < SMOOTHED(-10, -9)) << 7) + ((SMOOTHED(-5, 3) < SMOOTHED(-2, -1)) << 6) + ((SMOOTHED(-1, 4) < SMOOTHED(1, 8)) << 5) + ((SMOOTHED(12, 9) < SMOOTHED(9, -14)) << 4) + ((SMOOTHED(-9, 17) < SMOOTHED(-3, 0)) << 3) + ((SMOOTHED(5, 4) < SMOOTHED(13, -6)) << 2) + ((SMOOTHED(-1, -8) < SMOOTHED(19, 10)) << 1) + ((SMOOTHED(8, -5) < SMOOTHED(-15, 2)) << 0));
|
||||
desc[55] = (uchar)(((SMOOTHED(-12, -9) < SMOOTHED(-4, -5)) << 7) + ((SMOOTHED(12, 0) < SMOOTHED(24, 4)) << 6) + ((SMOOTHED(8, -2) < SMOOTHED(14, 4)) << 5) + ((SMOOTHED(8, -4) < SMOOTHED(-7, 16)) << 4) + ((SMOOTHED(5, -1) < SMOOTHED(-8, -4)) << 3) + ((SMOOTHED(-2, 18) < SMOOTHED(-5, 17)) << 2) + ((SMOOTHED(8, -2) < SMOOTHED(-9, -2)) << 1) + ((SMOOTHED(3, -7) < SMOOTHED(1, -6)) << 0));
|
||||
desc[56] = (uchar)(((SMOOTHED(-5, -22) < SMOOTHED(-5, -2)) << 7) + ((SMOOTHED(-8, -10) < SMOOTHED(14, 1)) << 6) + ((SMOOTHED(-3, -13) < SMOOTHED(3, 9)) << 5) + ((SMOOTHED(-4, -1) < SMOOTHED(-1, 0)) << 4) + ((SMOOTHED(-7, -21) < SMOOTHED(12, -19)) << 3) + ((SMOOTHED(-8, 8) < SMOOTHED(24, 8)) << 2) + ((SMOOTHED(12, -6) < SMOOTHED(-2, 3)) << 1) + ((SMOOTHED(-5, -11) < SMOOTHED(-22, -4)) << 0));
|
||||
desc[57] = (uchar)(((SMOOTHED(-3, 5) < SMOOTHED(-4, 4)) << 7) + ((SMOOTHED(-16, 24) < SMOOTHED(7, -9)) << 6) + ((SMOOTHED(-10, 23) < SMOOTHED(-9, 18)) << 5) + ((SMOOTHED(1, 12) < SMOOTHED(17, 21)) << 4) + ((SMOOTHED(24, -6) < SMOOTHED(-3, -11)) << 3) + ((SMOOTHED(-7, 17) < SMOOTHED(1, -6)) << 2) + ((SMOOTHED(4, 4) < SMOOTHED(2, -7)) << 1) + ((SMOOTHED(14, 6) < SMOOTHED(-12, 3)) << 0));
|
||||
desc[58] = (uchar)(((SMOOTHED(-6, 0) < SMOOTHED(-16, 13)) << 7) + ((SMOOTHED(-10, 5) < SMOOTHED(7, 12)) << 6) + ((SMOOTHED(5, 2) < SMOOTHED(6, -3)) << 5) + ((SMOOTHED(7, 0) < SMOOTHED(-23, 1)) << 4) + ((SMOOTHED(15, -5) < SMOOTHED(1, 14)) << 3) + ((SMOOTHED(-3, -1) < SMOOTHED(6, 6)) << 2) + ((SMOOTHED(6, -9) < SMOOTHED(-9, 12)) << 1) + ((SMOOTHED(4, -2) < SMOOTHED(-4, 7)) << 0));
|
||||
desc[59] = (uchar)(((SMOOTHED(-4, -5) < SMOOTHED(4, 4)) << 7) + ((SMOOTHED(-13, 0) < SMOOTHED(6, -10)) << 6) + ((SMOOTHED(2, -12) < SMOOTHED(-6, -3)) << 5) + ((SMOOTHED(16, 0) < SMOOTHED(-3, 3)) << 4) + ((SMOOTHED(5, -14) < SMOOTHED(6, 11)) << 3) + ((SMOOTHED(5, 11) < SMOOTHED(0, -13)) << 2) + ((SMOOTHED(7, 5) < SMOOTHED(-1, -5)) << 1) + ((SMOOTHED(12, 4) < SMOOTHED(6, 10)) << 0));
|
||||
desc[60] = (uchar)(((SMOOTHED(-10, 4) < SMOOTHED(-1, -11)) << 7) + ((SMOOTHED(4, 10) < SMOOTHED(-14, 5)) << 6) + ((SMOOTHED(11, -14) < SMOOTHED(-13, 0)) << 5) + ((SMOOTHED(2, 8) < SMOOTHED(12, 24)) << 4) + ((SMOOTHED(-1, 3) < SMOOTHED(-1, 2)) << 3) + ((SMOOTHED(9, -14) < SMOOTHED(-23, 3)) << 2) + ((SMOOTHED(-8, -6) < SMOOTHED(0, 9)) << 1) + ((SMOOTHED(-15, 14) < SMOOTHED(10, -10)) << 0));
|
||||
desc[61] = (uchar)(((SMOOTHED(-10, -6) < SMOOTHED(-7, -5)) << 7) + ((SMOOTHED(11, 5) < SMOOTHED(-3, -15)) << 6) + ((SMOOTHED(1, 0) < SMOOTHED(1, 8)) << 5) + ((SMOOTHED(-11, -6) < SMOOTHED(-4, -18)) << 4) + ((SMOOTHED(9, 0) < SMOOTHED(22, -4)) << 3) + ((SMOOTHED(-5, -1) < SMOOTHED(-9, 4)) << 2) + ((SMOOTHED(-20, 2) < SMOOTHED(1, 6)) << 1) + ((SMOOTHED(1, 2) < SMOOTHED(-9, -12)) << 0));
|
||||
desc[62] = (uchar)(((SMOOTHED(5, 15) < SMOOTHED(4, -6)) << 7) + ((SMOOTHED(19, 4) < SMOOTHED(4, 11)) << 6) + ((SMOOTHED(17, -4) < SMOOTHED(-8, -1)) << 5) + ((SMOOTHED(-8, -12) < SMOOTHED(7, -3)) << 4) + ((SMOOTHED(11, 9) < SMOOTHED(8, 1)) << 3) + ((SMOOTHED(9, 22) < SMOOTHED(-15, 15)) << 2) + ((SMOOTHED(-7, -7) < SMOOTHED(1, -23)) << 1) + ((SMOOTHED(-5, 13) < SMOOTHED(-8, 2)) << 0));
|
||||
desc[63] = (uchar)(((SMOOTHED(3, -5) < SMOOTHED(11, -11)) << 7) + ((SMOOTHED(3, -18) < SMOOTHED(14, -5)) << 6) + ((SMOOTHED(-20, 7) < SMOOTHED(-10, -23)) << 5) + ((SMOOTHED(-2, -5) < SMOOTHED(6, 0)) << 4) + ((SMOOTHED(-17, -13) < SMOOTHED(-3, 2)) << 3) + ((SMOOTHED(-6, -1) < SMOOTHED(14, -2)) << 2) + ((SMOOTHED(-12, -16) < SMOOTHED(15, 6)) << 1) + ((SMOOTHED(-12, -2) < SMOOTHED(3, -19)) << 0));
|
||||
#undef SMOOTHED
|
@@ -50,26 +50,7 @@
|
||||
namespace cv
|
||||
{
|
||||
|
||||
Mat windowedMatchingMask( const std::vector<KeyPoint>& keypoints1, const std::vector<KeyPoint>& keypoints2,
|
||||
float maxDeltaX, float maxDeltaY )
|
||||
{
|
||||
if( keypoints1.empty() || keypoints2.empty() )
|
||||
return Mat();
|
||||
|
||||
int n1 = (int)keypoints1.size(), n2 = (int)keypoints2.size();
|
||||
Mat mask( n1, n2, CV_8UC1 );
|
||||
for( int i = 0; i < n1; i++ )
|
||||
{
|
||||
for( int j = 0; j < n2; j++ )
|
||||
{
|
||||
Point2f diff = keypoints2[j].pt - keypoints1[i].pt;
|
||||
mask.at<uchar>(i, j) = std::abs(diff.x) < maxDeltaX && std::abs(diff.y) < maxDeltaY;
|
||||
}
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////ocl functions for BFMatcher ///////////////////////////////////////////////////////////////
|
||||
/////////////////////// ocl functions for BFMatcher ///////////////////////////
|
||||
|
||||
static void ensureSizeIsEnough(int rows, int cols, int type, UMat &m)
|
||||
{
|
||||
@@ -1507,382 +1488,4 @@ void FlannBasedMatcher::radiusMatchImpl( InputArray _queryDescriptors, std::vect
|
||||
convertToDMatches( mergedDescriptors, indices, dists, matches );
|
||||
}
|
||||
|
||||
/****************************************************************************************\
|
||||
* GenericDescriptorMatcher *
|
||||
\****************************************************************************************/
|
||||
/*
|
||||
* KeyPointCollection
|
||||
*/
|
||||
GenericDescriptorMatcher::KeyPointCollection::KeyPointCollection() : pointCount(0)
|
||||
{}
|
||||
|
||||
GenericDescriptorMatcher::KeyPointCollection::KeyPointCollection( const KeyPointCollection& collection )
|
||||
{
|
||||
pointCount = collection.pointCount;
|
||||
|
||||
std::transform( collection.images.begin(), collection.images.end(), images.begin(), clone_op );
|
||||
|
||||
keypoints.resize( collection.keypoints.size() );
|
||||
for( size_t i = 0; i < keypoints.size(); i++ )
|
||||
std::copy( collection.keypoints[i].begin(), collection.keypoints[i].end(), keypoints[i].begin() );
|
||||
|
||||
std::copy( collection.startIndices.begin(), collection.startIndices.end(), startIndices.begin() );
|
||||
}
|
||||
|
||||
void GenericDescriptorMatcher::KeyPointCollection::add( const std::vector<Mat>& _images,
|
||||
const std::vector<std::vector<KeyPoint> >& _points )
|
||||
{
|
||||
CV_Assert( !_images.empty() );
|
||||
CV_Assert( _images.size() == _points.size() );
|
||||
|
||||
images.insert( images.end(), _images.begin(), _images.end() );
|
||||
keypoints.insert( keypoints.end(), _points.begin(), _points.end() );
|
||||
for( size_t i = 0; i < _points.size(); i++ )
|
||||
pointCount += (int)_points[i].size();
|
||||
|
||||
size_t prevSize = startIndices.size(), addSize = _images.size();
|
||||
startIndices.resize( prevSize + addSize );
|
||||
|
||||
if( prevSize == 0 )
|
||||
startIndices[prevSize] = 0; //first
|
||||
else
|
||||
startIndices[prevSize] = (int)(startIndices[prevSize-1] + keypoints[prevSize-1].size());
|
||||
|
||||
for( size_t i = prevSize + 1; i < prevSize + addSize; i++ )
|
||||
{
|
||||
startIndices[i] = (int)(startIndices[i - 1] + keypoints[i - 1].size());
|
||||
}
|
||||
}
|
||||
|
||||
void GenericDescriptorMatcher::KeyPointCollection::clear()
|
||||
{
|
||||
pointCount = 0;
|
||||
|
||||
images.clear();
|
||||
keypoints.clear();
|
||||
startIndices.clear();
|
||||
}
|
||||
|
||||
size_t GenericDescriptorMatcher::KeyPointCollection::keypointCount() const
|
||||
{
|
||||
return pointCount;
|
||||
}
|
||||
|
||||
size_t GenericDescriptorMatcher::KeyPointCollection::imageCount() const
|
||||
{
|
||||
return images.size();
|
||||
}
|
||||
|
||||
const std::vector<std::vector<KeyPoint> >& GenericDescriptorMatcher::KeyPointCollection::getKeypoints() const
|
||||
{
|
||||
return keypoints;
|
||||
}
|
||||
|
||||
const std::vector<KeyPoint>& GenericDescriptorMatcher::KeyPointCollection::getKeypoints( int imgIdx ) const
|
||||
{
|
||||
CV_Assert( imgIdx < (int)imageCount() );
|
||||
return keypoints[imgIdx];
|
||||
}
|
||||
|
||||
const KeyPoint& GenericDescriptorMatcher::KeyPointCollection::getKeyPoint( int imgIdx, int localPointIdx ) const
|
||||
{
|
||||
CV_Assert( imgIdx < (int)images.size() );
|
||||
CV_Assert( localPointIdx < (int)keypoints[imgIdx].size() );
|
||||
return keypoints[imgIdx][localPointIdx];
|
||||
}
|
||||
|
||||
const KeyPoint& GenericDescriptorMatcher::KeyPointCollection::getKeyPoint( int globalPointIdx ) const
|
||||
{
|
||||
int imgIdx, localPointIdx;
|
||||
getLocalIdx( globalPointIdx, imgIdx, localPointIdx );
|
||||
return keypoints[imgIdx][localPointIdx];
|
||||
}
|
||||
|
||||
void GenericDescriptorMatcher::KeyPointCollection::getLocalIdx( int globalPointIdx, int& imgIdx, int& localPointIdx ) const
|
||||
{
|
||||
imgIdx = -1;
|
||||
CV_Assert( globalPointIdx < (int)keypointCount() );
|
||||
for( size_t i = 1; i < startIndices.size(); i++ )
|
||||
{
|
||||
if( globalPointIdx < startIndices[i] )
|
||||
{
|
||||
imgIdx = (int)(i - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
imgIdx = imgIdx == -1 ? (int)(startIndices.size() - 1) : imgIdx;
|
||||
localPointIdx = globalPointIdx - startIndices[imgIdx];
|
||||
}
|
||||
|
||||
const std::vector<Mat>& GenericDescriptorMatcher::KeyPointCollection::getImages() const
|
||||
{
|
||||
return images;
|
||||
}
|
||||
|
||||
const Mat& GenericDescriptorMatcher::KeyPointCollection::getImage( int imgIdx ) const
|
||||
{
|
||||
CV_Assert( imgIdx < (int)imageCount() );
|
||||
return images[imgIdx];
|
||||
}
|
||||
|
||||
/*
|
||||
* GenericDescriptorMatcher
|
||||
*/
|
||||
GenericDescriptorMatcher::GenericDescriptorMatcher()
|
||||
{}
|
||||
|
||||
GenericDescriptorMatcher::~GenericDescriptorMatcher()
|
||||
{}
|
||||
|
||||
void GenericDescriptorMatcher::add( InputArrayOfArrays _images,
|
||||
std::vector<std::vector<KeyPoint> >& keypoints )
|
||||
{
|
||||
std::vector<Mat> images;
|
||||
_images.getMatVector(images);
|
||||
CV_Assert( !images.empty() );
|
||||
CV_Assert( images.size() == keypoints.size() );
|
||||
|
||||
for( size_t i = 0; i < images.size(); i++ )
|
||||
{
|
||||
CV_Assert( !images[i].empty() );
|
||||
KeyPointsFilter::runByImageBorder( keypoints[i], images[i].size(), 0 );
|
||||
KeyPointsFilter::runByKeypointSize( keypoints[i], std::numeric_limits<float>::epsilon() );
|
||||
}
|
||||
|
||||
trainPointCollection.add( images, keypoints );
|
||||
}
|
||||
|
||||
const std::vector<Mat>& GenericDescriptorMatcher::getTrainImages() const
|
||||
{
|
||||
return trainPointCollection.getImages();
|
||||
}
|
||||
|
||||
const std::vector<std::vector<KeyPoint> >& GenericDescriptorMatcher::getTrainKeypoints() const
|
||||
{
|
||||
return trainPointCollection.getKeypoints();
|
||||
}
|
||||
|
||||
void GenericDescriptorMatcher::clear()
|
||||
{
|
||||
trainPointCollection.clear();
|
||||
}
|
||||
|
||||
void GenericDescriptorMatcher::train()
|
||||
{}
|
||||
|
||||
void GenericDescriptorMatcher::classify( InputArray queryImage, std::vector<KeyPoint>& queryKeypoints,
|
||||
InputArray trainImage, std::vector<KeyPoint>& trainKeypoints ) const
|
||||
{
|
||||
std::vector<DMatch> matches;
|
||||
match( queryImage, queryKeypoints, trainImage, trainKeypoints, matches );
|
||||
|
||||
// remap keypoint indices to descriptors
|
||||
for( size_t i = 0; i < matches.size(); i++ )
|
||||
queryKeypoints[matches[i].queryIdx].class_id = trainKeypoints[matches[i].trainIdx].class_id;
|
||||
}
|
||||
|
||||
void GenericDescriptorMatcher::classify( InputArray queryImage, std::vector<KeyPoint>& queryKeypoints )
|
||||
{
|
||||
std::vector<DMatch> matches;
|
||||
match( queryImage, queryKeypoints, matches );
|
||||
|
||||
// remap keypoint indices to descriptors
|
||||
for( size_t i = 0; i < matches.size(); i++ )
|
||||
queryKeypoints[matches[i].queryIdx].class_id = trainPointCollection.getKeyPoint( matches[i].trainIdx, matches[i].trainIdx ).class_id;
|
||||
}
|
||||
|
||||
void GenericDescriptorMatcher::match( InputArray queryImage, std::vector<KeyPoint>& queryKeypoints,
|
||||
InputArray _trainImage, std::vector<KeyPoint>& trainKeypoints,
|
||||
std::vector<DMatch>& matches, InputArray mask ) const
|
||||
{
|
||||
Mat trainImage = _trainImage.getMat();
|
||||
Ptr<GenericDescriptorMatcher> tempMatcher = clone( true );
|
||||
std::vector<std::vector<KeyPoint> > vecTrainPoints(1, trainKeypoints);
|
||||
tempMatcher->add( std::vector<Mat>(1, trainImage), vecTrainPoints );
|
||||
tempMatcher->match( queryImage, queryKeypoints, matches, std::vector<Mat>(1, mask.getMat()) );
|
||||
vecTrainPoints[0].swap( trainKeypoints );
|
||||
}
|
||||
|
||||
void GenericDescriptorMatcher::knnMatch( InputArray queryImage, std::vector<KeyPoint>& queryKeypoints,
|
||||
InputArray _trainImage, std::vector<KeyPoint>& trainKeypoints,
|
||||
std::vector<std::vector<DMatch> >& matches, int knn, InputArray mask, bool compactResult ) const
|
||||
{
|
||||
Mat trainImage = _trainImage.getMat();
|
||||
Ptr<GenericDescriptorMatcher> tempMatcher = clone( true );
|
||||
std::vector<std::vector<KeyPoint> > vecTrainPoints(1, trainKeypoints);
|
||||
tempMatcher->add( std::vector<Mat>(1, trainImage), vecTrainPoints );
|
||||
tempMatcher->knnMatch( queryImage, queryKeypoints, matches, knn, std::vector<Mat>(1, mask.getMat()), compactResult );
|
||||
vecTrainPoints[0].swap( trainKeypoints );
|
||||
}
|
||||
|
||||
void GenericDescriptorMatcher::radiusMatch( InputArray queryImage, std::vector<KeyPoint>& queryKeypoints,
|
||||
InputArray _trainImage, std::vector<KeyPoint>& trainKeypoints,
|
||||
std::vector<std::vector<DMatch> >& matches, float maxDistance,
|
||||
InputArray mask, bool compactResult ) const
|
||||
{
|
||||
Mat trainImage = _trainImage.getMat();
|
||||
Ptr<GenericDescriptorMatcher> tempMatcher = clone( true );
|
||||
std::vector<std::vector<KeyPoint> > vecTrainPoints(1, trainKeypoints);
|
||||
tempMatcher->add( std::vector<Mat>(1, trainImage), vecTrainPoints );
|
||||
tempMatcher->radiusMatch( queryImage, queryKeypoints, matches, maxDistance, std::vector<Mat>(1, mask.getMat()), compactResult );
|
||||
vecTrainPoints[0].swap( trainKeypoints );
|
||||
}
|
||||
|
||||
void GenericDescriptorMatcher::match( InputArray queryImage, std::vector<KeyPoint>& queryKeypoints,
|
||||
std::vector<DMatch>& matches, InputArrayOfArrays masks )
|
||||
{
|
||||
std::vector<std::vector<DMatch> > knnMatches;
|
||||
knnMatch( queryImage, queryKeypoints, knnMatches, 1, masks, false );
|
||||
convertMatches( knnMatches, matches );
|
||||
}
|
||||
|
||||
void GenericDescriptorMatcher::knnMatch( InputArray queryImage, std::vector<KeyPoint>& queryKeypoints,
|
||||
std::vector<std::vector<DMatch> >& matches, int knn,
|
||||
InputArrayOfArrays masks, bool compactResult )
|
||||
{
|
||||
matches.clear();
|
||||
|
||||
if( queryImage.empty() || queryKeypoints.empty() )
|
||||
return;
|
||||
|
||||
KeyPointsFilter::runByImageBorder( queryKeypoints, queryImage.size(), 0 );
|
||||
KeyPointsFilter::runByKeypointSize( queryKeypoints, std::numeric_limits<float>::epsilon() );
|
||||
|
||||
train();
|
||||
knnMatchImpl( queryImage, queryKeypoints, matches, knn, masks, compactResult );
|
||||
}
|
||||
|
||||
void GenericDescriptorMatcher::radiusMatch( InputArray queryImage, std::vector<KeyPoint>& queryKeypoints,
|
||||
std::vector<std::vector<DMatch> >& matches, float maxDistance,
|
||||
InputArrayOfArrays masks, bool compactResult )
|
||||
{
|
||||
matches.clear();
|
||||
|
||||
if( queryImage.empty() || queryKeypoints.empty() )
|
||||
return;
|
||||
|
||||
KeyPointsFilter::runByImageBorder( queryKeypoints, queryImage.size(), 0 );
|
||||
KeyPointsFilter::runByKeypointSize( queryKeypoints, std::numeric_limits<float>::epsilon() );
|
||||
|
||||
train();
|
||||
radiusMatchImpl( queryImage, queryKeypoints, matches, maxDistance, masks, compactResult );
|
||||
}
|
||||
|
||||
void GenericDescriptorMatcher::read( const FileNode& )
|
||||
{}
|
||||
|
||||
void GenericDescriptorMatcher::write( FileStorage& ) const
|
||||
{}
|
||||
|
||||
bool GenericDescriptorMatcher::empty() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Factory function for GenericDescriptorMatch creating
|
||||
*/
|
||||
Ptr<GenericDescriptorMatcher> GenericDescriptorMatcher::create( const String& genericDescritptorMatcherType,
|
||||
const String ¶msFilename )
|
||||
{
|
||||
Ptr<GenericDescriptorMatcher> descriptorMatcher =
|
||||
Algorithm::create<GenericDescriptorMatcher>("DescriptorMatcher." + genericDescritptorMatcherType);
|
||||
|
||||
if( !paramsFilename.empty() && descriptorMatcher )
|
||||
{
|
||||
FileStorage fs = FileStorage( paramsFilename, FileStorage::READ );
|
||||
if( fs.isOpened() )
|
||||
{
|
||||
descriptorMatcher->read( fs.root() );
|
||||
fs.release();
|
||||
}
|
||||
}
|
||||
return descriptorMatcher;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************\
|
||||
* VectorDescriptorMatcher *
|
||||
\****************************************************************************************/
|
||||
VectorDescriptorMatcher::VectorDescriptorMatcher( const Ptr<DescriptorExtractor>& _extractor,
|
||||
const Ptr<DescriptorMatcher>& _matcher )
|
||||
: extractor( _extractor ), matcher( _matcher )
|
||||
{
|
||||
CV_Assert( extractor && matcher );
|
||||
}
|
||||
|
||||
VectorDescriptorMatcher::~VectorDescriptorMatcher()
|
||||
{}
|
||||
|
||||
void VectorDescriptorMatcher::add( InputArrayOfArrays _imgCollection,
|
||||
std::vector<std::vector<KeyPoint> >& pointCollection )
|
||||
{
|
||||
std::vector<Mat> imgCollection, descriptors;
|
||||
_imgCollection.getMatVector(imgCollection);
|
||||
extractor->compute( imgCollection, pointCollection, descriptors );
|
||||
|
||||
matcher->add( descriptors );
|
||||
|
||||
trainPointCollection.add( imgCollection, pointCollection );
|
||||
}
|
||||
|
||||
void VectorDescriptorMatcher::clear()
|
||||
{
|
||||
//extractor->clear();
|
||||
matcher->clear();
|
||||
GenericDescriptorMatcher::clear();
|
||||
}
|
||||
|
||||
void VectorDescriptorMatcher::train()
|
||||
{
|
||||
matcher->train();
|
||||
}
|
||||
|
||||
bool VectorDescriptorMatcher::isMaskSupported()
|
||||
{
|
||||
return matcher->isMaskSupported();
|
||||
}
|
||||
|
||||
void VectorDescriptorMatcher::knnMatchImpl( InputArray queryImage, std::vector<KeyPoint>& queryKeypoints,
|
||||
std::vector<std::vector<DMatch> >& matches, int knn,
|
||||
InputArrayOfArrays masks, bool compactResult )
|
||||
{
|
||||
Mat queryDescriptors;
|
||||
extractor->compute( queryImage, queryKeypoints, queryDescriptors );
|
||||
matcher->knnMatch( queryDescriptors, matches, knn, masks, compactResult );
|
||||
}
|
||||
|
||||
void VectorDescriptorMatcher::radiusMatchImpl( InputArray queryImage, std::vector<KeyPoint>& queryKeypoints,
|
||||
std::vector<std::vector<DMatch> >& matches, float maxDistance,
|
||||
InputArrayOfArrays masks, bool compactResult )
|
||||
{
|
||||
Mat queryDescriptors;
|
||||
extractor->compute( queryImage, queryKeypoints, queryDescriptors );
|
||||
matcher->radiusMatch( queryDescriptors, matches, maxDistance, masks, compactResult );
|
||||
}
|
||||
|
||||
void VectorDescriptorMatcher::read( const FileNode& fn )
|
||||
{
|
||||
GenericDescriptorMatcher::read(fn);
|
||||
extractor->read(fn);
|
||||
}
|
||||
|
||||
void VectorDescriptorMatcher::write (FileStorage& fs) const
|
||||
{
|
||||
GenericDescriptorMatcher::write(fs);
|
||||
extractor->write (fs);
|
||||
}
|
||||
|
||||
bool VectorDescriptorMatcher::empty() const
|
||||
{
|
||||
return !extractor || extractor->empty() ||
|
||||
!matcher || matcher->empty();
|
||||
}
|
||||
|
||||
Ptr<GenericDescriptorMatcher> VectorDescriptorMatcher::clone( bool emptyTrainData ) const
|
||||
{
|
||||
// TODO clone extractor
|
||||
return makePtr<VectorDescriptorMatcher>( extractor, matcher->clone(emptyTrainData) );
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,472 +0,0 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2008-2012, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
template <typename inMatType, typename outMatType> static void
|
||||
computeIntegralImages( const Mat& matI, Mat& matS, Mat& matT, Mat& _FT,
|
||||
int iiType )
|
||||
{
|
||||
int x, y, rows = matI.rows, cols = matI.cols;
|
||||
|
||||
matS.create(rows + 1, cols + 1, iiType );
|
||||
matT.create(rows + 1, cols + 1, iiType );
|
||||
_FT.create(rows + 1, cols + 1, iiType );
|
||||
|
||||
const inMatType* I = matI.ptr<inMatType>();
|
||||
|
||||
outMatType *S = matS.ptr<outMatType>();
|
||||
outMatType *T = matT.ptr<outMatType>();
|
||||
outMatType *FT = _FT.ptr<outMatType>();
|
||||
|
||||
int istep = (int)(matI.step/matI.elemSize());
|
||||
int step = (int)(matS.step/matS.elemSize());
|
||||
|
||||
for( x = 0; x <= cols; x++ )
|
||||
S[x] = T[x] = FT[x] = 0;
|
||||
|
||||
S += step; T += step; FT += step;
|
||||
S[0] = T[0] = 0;
|
||||
FT[0] = I[0];
|
||||
for( x = 1; x < cols; x++ )
|
||||
{
|
||||
S[x] = S[x-1] + I[x-1];
|
||||
T[x] = I[x-1];
|
||||
FT[x] = I[x] + I[x-1];
|
||||
}
|
||||
S[cols] = S[cols-1] + I[cols-1];
|
||||
T[cols] = FT[cols] = I[cols-1];
|
||||
|
||||
for( y = 2; y <= rows; y++ )
|
||||
{
|
||||
I += istep, S += step, T += step, FT += step;
|
||||
|
||||
S[0] = S[-step]; S[1] = S[-step+1] + I[0];
|
||||
T[0] = T[-step + 1];
|
||||
T[1] = FT[0] = T[-step + 2] + I[-istep] + I[0];
|
||||
FT[1] = FT[-step + 2] + I[-istep] + I[1] + I[0];
|
||||
|
||||
for( x = 2; x < cols; x++ )
|
||||
{
|
||||
S[x] = S[x - 1] + S[-step + x] - S[-step + x - 1] + I[x - 1];
|
||||
T[x] = T[-step + x - 1] + T[-step + x + 1] - T[-step*2 + x] + I[-istep + x - 1] + I[x - 1];
|
||||
FT[x] = FT[-step + x - 1] + FT[-step + x + 1] - FT[-step*2 + x] + I[x] + I[x-1];
|
||||
}
|
||||
|
||||
S[cols] = S[cols - 1] + S[-step + cols] - S[-step + cols - 1] + I[cols - 1];
|
||||
T[cols] = FT[cols] = T[-step + cols - 1] + I[-istep + cols - 1] + I[cols - 1];
|
||||
}
|
||||
}
|
||||
|
||||
template <typename iiMatType> static int
|
||||
StarDetectorComputeResponses( const Mat& img, Mat& responses, Mat& sizes,
|
||||
int maxSize, int iiType )
|
||||
{
|
||||
const int MAX_PATTERN = 17;
|
||||
static const int sizes0[] = {1, 2, 3, 4, 6, 8, 11, 12, 16, 22, 23, 32, 45, 46, 64, 90, 128, -1};
|
||||
static const int pairs[][2] = {{1, 0}, {3, 1}, {4, 2}, {5, 3}, {7, 4}, {8, 5}, {9, 6},
|
||||
{11, 8}, {13, 10}, {14, 11}, {15, 12}, {16, 14}, {-1, -1}};
|
||||
float invSizes[MAX_PATTERN][2];
|
||||
int sizes1[MAX_PATTERN];
|
||||
|
||||
#if CV_SSE2
|
||||
__m128 invSizes4[MAX_PATTERN][2];
|
||||
__m128 sizes1_4[MAX_PATTERN];
|
||||
union { int i; float f; } absmask;
|
||||
absmask.i = 0x7fffffff;
|
||||
volatile bool useSIMD = cv::checkHardwareSupport(CV_CPU_SSE2) && iiType == CV_32S;
|
||||
#endif
|
||||
|
||||
struct StarFeature
|
||||
{
|
||||
int area;
|
||||
iiMatType* p[8];
|
||||
};
|
||||
|
||||
StarFeature f[MAX_PATTERN];
|
||||
|
||||
Mat sum, tilted, flatTilted;
|
||||
int y, rows = img.rows, cols = img.cols;
|
||||
int border, npatterns=0, maxIdx=0;
|
||||
|
||||
responses.create( img.size(), CV_32F );
|
||||
sizes.create( img.size(), CV_16S );
|
||||
|
||||
while( pairs[npatterns][0] >= 0 && !
|
||||
( sizes0[pairs[npatterns][0]] >= maxSize
|
||||
|| sizes0[pairs[npatterns+1][0]] + sizes0[pairs[npatterns+1][0]]/2 >= std::min(rows, cols) ) )
|
||||
{
|
||||
++npatterns;
|
||||
}
|
||||
|
||||
npatterns += (pairs[npatterns-1][0] >= 0);
|
||||
maxIdx = pairs[npatterns-1][0];
|
||||
|
||||
// Create the integral image appropriate for our type & usage
|
||||
if ( img.type() == CV_8U )
|
||||
computeIntegralImages<uchar, iiMatType>( img, sum, tilted, flatTilted, iiType );
|
||||
else if ( img.type() == CV_8S )
|
||||
computeIntegralImages<char, iiMatType>( img, sum, tilted, flatTilted, iiType );
|
||||
else if ( img.type() == CV_16U )
|
||||
computeIntegralImages<ushort, iiMatType>( img, sum, tilted, flatTilted, iiType );
|
||||
else if ( img.type() == CV_16S )
|
||||
computeIntegralImages<short, iiMatType>( img, sum, tilted, flatTilted, iiType );
|
||||
else
|
||||
CV_Error( Error::StsUnsupportedFormat, "" );
|
||||
|
||||
int step = (int)(sum.step/sum.elemSize());
|
||||
|
||||
for(int i = 0; i <= maxIdx; i++ )
|
||||
{
|
||||
int ur_size = sizes0[i], t_size = sizes0[i] + sizes0[i]/2;
|
||||
int ur_area = (2*ur_size + 1)*(2*ur_size + 1);
|
||||
int t_area = t_size*t_size + (t_size + 1)*(t_size + 1);
|
||||
|
||||
f[i].p[0] = sum.ptr<iiMatType>() + (ur_size + 1)*step + ur_size + 1;
|
||||
f[i].p[1] = sum.ptr<iiMatType>() - ur_size*step + ur_size + 1;
|
||||
f[i].p[2] = sum.ptr<iiMatType>() + (ur_size + 1)*step - ur_size;
|
||||
f[i].p[3] = sum.ptr<iiMatType>() - ur_size*step - ur_size;
|
||||
|
||||
f[i].p[4] = tilted.ptr<iiMatType>() + (t_size + 1)*step + 1;
|
||||
f[i].p[5] = flatTilted.ptr<iiMatType>() - t_size;
|
||||
f[i].p[6] = flatTilted.ptr<iiMatType>() + t_size + 1;
|
||||
f[i].p[7] = tilted.ptr<iiMatType>() - t_size*step + 1;
|
||||
|
||||
f[i].area = ur_area + t_area;
|
||||
sizes1[i] = sizes0[i];
|
||||
}
|
||||
// negate end points of the size range
|
||||
// for a faster rejection of very small or very large features in non-maxima suppression.
|
||||
sizes1[0] = -sizes1[0];
|
||||
sizes1[1] = -sizes1[1];
|
||||
sizes1[maxIdx] = -sizes1[maxIdx];
|
||||
border = sizes0[maxIdx] + sizes0[maxIdx]/2;
|
||||
|
||||
for(int i = 0; i < npatterns; i++ )
|
||||
{
|
||||
int innerArea = f[pairs[i][1]].area;
|
||||
int outerArea = f[pairs[i][0]].area - innerArea;
|
||||
invSizes[i][0] = 1.f/outerArea;
|
||||
invSizes[i][1] = 1.f/innerArea;
|
||||
}
|
||||
|
||||
#if CV_SSE2
|
||||
if( useSIMD )
|
||||
{
|
||||
for(int i = 0; i < npatterns; i++ )
|
||||
{
|
||||
_mm_store_ps((float*)&invSizes4[i][0], _mm_set1_ps(invSizes[i][0]));
|
||||
_mm_store_ps((float*)&invSizes4[i][1], _mm_set1_ps(invSizes[i][1]));
|
||||
}
|
||||
|
||||
for(int i = 0; i <= maxIdx; i++ )
|
||||
_mm_store_ps((float*)&sizes1_4[i], _mm_set1_ps((float)sizes1[i]));
|
||||
}
|
||||
#endif
|
||||
|
||||
for( y = 0; y < border; y++ )
|
||||
{
|
||||
float* r_ptr = responses.ptr<float>(y);
|
||||
float* r_ptr2 = responses.ptr<float>(rows - 1 - y);
|
||||
short* s_ptr = sizes.ptr<short>(y);
|
||||
short* s_ptr2 = sizes.ptr<short>(rows - 1 - y);
|
||||
|
||||
memset( r_ptr, 0, cols*sizeof(r_ptr[0]));
|
||||
memset( r_ptr2, 0, cols*sizeof(r_ptr2[0]));
|
||||
memset( s_ptr, 0, cols*sizeof(s_ptr[0]));
|
||||
memset( s_ptr2, 0, cols*sizeof(s_ptr2[0]));
|
||||
}
|
||||
|
||||
for( y = border; y < rows - border; y++ )
|
||||
{
|
||||
int x = border;
|
||||
float* r_ptr = responses.ptr<float>(y);
|
||||
short* s_ptr = sizes.ptr<short>(y);
|
||||
|
||||
memset( r_ptr, 0, border*sizeof(r_ptr[0]));
|
||||
memset( s_ptr, 0, border*sizeof(s_ptr[0]));
|
||||
memset( r_ptr + cols - border, 0, border*sizeof(r_ptr[0]));
|
||||
memset( s_ptr + cols - border, 0, border*sizeof(s_ptr[0]));
|
||||
|
||||
#if CV_SSE2
|
||||
if( useSIMD )
|
||||
{
|
||||
__m128 absmask4 = _mm_set1_ps(absmask.f);
|
||||
for( ; x <= cols - border - 4; x += 4 )
|
||||
{
|
||||
int ofs = y*step + x;
|
||||
__m128 vals[MAX_PATTERN];
|
||||
__m128 bestResponse = _mm_setzero_ps();
|
||||
__m128 bestSize = _mm_setzero_ps();
|
||||
|
||||
for(int i = 0; i <= maxIdx; i++ )
|
||||
{
|
||||
const iiMatType** p = (const iiMatType**)&f[i].p[0];
|
||||
__m128i r0 = _mm_sub_epi32(_mm_loadu_si128((const __m128i*)(p[0]+ofs)),
|
||||
_mm_loadu_si128((const __m128i*)(p[1]+ofs)));
|
||||
__m128i r1 = _mm_sub_epi32(_mm_loadu_si128((const __m128i*)(p[3]+ofs)),
|
||||
_mm_loadu_si128((const __m128i*)(p[2]+ofs)));
|
||||
__m128i r2 = _mm_sub_epi32(_mm_loadu_si128((const __m128i*)(p[4]+ofs)),
|
||||
_mm_loadu_si128((const __m128i*)(p[5]+ofs)));
|
||||
__m128i r3 = _mm_sub_epi32(_mm_loadu_si128((const __m128i*)(p[7]+ofs)),
|
||||
_mm_loadu_si128((const __m128i*)(p[6]+ofs)));
|
||||
r0 = _mm_add_epi32(_mm_add_epi32(r0,r1), _mm_add_epi32(r2,r3));
|
||||
_mm_store_ps((float*)&vals[i], _mm_cvtepi32_ps(r0));
|
||||
}
|
||||
|
||||
for(int i = 0; i < npatterns; i++ )
|
||||
{
|
||||
__m128 inner_sum = vals[pairs[i][1]];
|
||||
__m128 outer_sum = _mm_sub_ps(vals[pairs[i][0]], inner_sum);
|
||||
__m128 response = _mm_sub_ps(_mm_mul_ps(inner_sum, invSizes4[i][1]),
|
||||
_mm_mul_ps(outer_sum, invSizes4[i][0]));
|
||||
__m128 swapmask = _mm_cmpgt_ps(_mm_and_ps(response,absmask4),
|
||||
_mm_and_ps(bestResponse,absmask4));
|
||||
bestResponse = _mm_xor_ps(bestResponse,
|
||||
_mm_and_ps(_mm_xor_ps(response,bestResponse), swapmask));
|
||||
bestSize = _mm_xor_ps(bestSize,
|
||||
_mm_and_ps(_mm_xor_ps(sizes1_4[pairs[i][0]], bestSize), swapmask));
|
||||
}
|
||||
|
||||
_mm_storeu_ps(r_ptr + x, bestResponse);
|
||||
_mm_storel_epi64((__m128i*)(s_ptr + x),
|
||||
_mm_packs_epi32(_mm_cvtps_epi32(bestSize),_mm_setzero_si128()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for( ; x < cols - border; x++ )
|
||||
{
|
||||
int ofs = y*step + x;
|
||||
int vals[MAX_PATTERN];
|
||||
float bestResponse = 0;
|
||||
int bestSize = 0;
|
||||
|
||||
for(int i = 0; i <= maxIdx; i++ )
|
||||
{
|
||||
const iiMatType** p = (const iiMatType**)&f[i].p[0];
|
||||
vals[i] = (int)(p[0][ofs] - p[1][ofs] - p[2][ofs] + p[3][ofs] +
|
||||
p[4][ofs] - p[5][ofs] - p[6][ofs] + p[7][ofs]);
|
||||
}
|
||||
for(int i = 0; i < npatterns; i++ )
|
||||
{
|
||||
int inner_sum = vals[pairs[i][1]];
|
||||
int outer_sum = vals[pairs[i][0]] - inner_sum;
|
||||
float response = inner_sum*invSizes[i][1] - outer_sum*invSizes[i][0];
|
||||
if( fabs(response) > fabs(bestResponse) )
|
||||
{
|
||||
bestResponse = response;
|
||||
bestSize = sizes1[pairs[i][0]];
|
||||
}
|
||||
}
|
||||
|
||||
r_ptr[x] = bestResponse;
|
||||
s_ptr[x] = (short)bestSize;
|
||||
}
|
||||
}
|
||||
|
||||
return border;
|
||||
}
|
||||
|
||||
|
||||
static bool StarDetectorSuppressLines( const Mat& responses, const Mat& sizes, Point pt,
|
||||
int lineThresholdProjected, int lineThresholdBinarized )
|
||||
{
|
||||
const float* r_ptr = responses.ptr<float>();
|
||||
int rstep = (int)(responses.step/sizeof(r_ptr[0]));
|
||||
const short* s_ptr = sizes.ptr<short>();
|
||||
int sstep = (int)(sizes.step/sizeof(s_ptr[0]));
|
||||
int sz = s_ptr[pt.y*sstep + pt.x];
|
||||
int x, y, delta = sz/4, radius = delta*4;
|
||||
float Lxx = 0, Lyy = 0, Lxy = 0;
|
||||
int Lxxb = 0, Lyyb = 0, Lxyb = 0;
|
||||
|
||||
for( y = pt.y - radius; y <= pt.y + radius; y += delta )
|
||||
for( x = pt.x - radius; x <= pt.x + radius; x += delta )
|
||||
{
|
||||
float Lx = r_ptr[y*rstep + x + 1] - r_ptr[y*rstep + x - 1];
|
||||
float Ly = r_ptr[(y+1)*rstep + x] - r_ptr[(y-1)*rstep + x];
|
||||
Lxx += Lx*Lx; Lyy += Ly*Ly; Lxy += Lx*Ly;
|
||||
}
|
||||
|
||||
if( (Lxx + Lyy)*(Lxx + Lyy) >= lineThresholdProjected*(Lxx*Lyy - Lxy*Lxy) )
|
||||
return true;
|
||||
|
||||
for( y = pt.y - radius; y <= pt.y + radius; y += delta )
|
||||
for( x = pt.x - radius; x <= pt.x + radius; x += delta )
|
||||
{
|
||||
int Lxb = (s_ptr[y*sstep + x + 1] == sz) - (s_ptr[y*sstep + x - 1] == sz);
|
||||
int Lyb = (s_ptr[(y+1)*sstep + x] == sz) - (s_ptr[(y-1)*sstep + x] == sz);
|
||||
Lxxb += Lxb * Lxb; Lyyb += Lyb * Lyb; Lxyb += Lxb * Lyb;
|
||||
}
|
||||
|
||||
if( (Lxxb + Lyyb)*(Lxxb + Lyyb) >= lineThresholdBinarized*(Lxxb*Lyyb - Lxyb*Lxyb) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
StarDetectorSuppressNonmax( const Mat& responses, const Mat& sizes,
|
||||
std::vector<KeyPoint>& keypoints, int border,
|
||||
int responseThreshold,
|
||||
int lineThresholdProjected,
|
||||
int lineThresholdBinarized,
|
||||
int suppressNonmaxSize )
|
||||
{
|
||||
int x, y, x1, y1, delta = suppressNonmaxSize/2;
|
||||
int rows = responses.rows, cols = responses.cols;
|
||||
const float* r_ptr = responses.ptr<float>();
|
||||
int rstep = (int)(responses.step/sizeof(r_ptr[0]));
|
||||
const short* s_ptr = sizes.ptr<short>();
|
||||
int sstep = (int)(sizes.step/sizeof(s_ptr[0]));
|
||||
short featureSize = 0;
|
||||
|
||||
for( y = border; y < rows - border; y += delta+1 )
|
||||
for( x = border; x < cols - border; x += delta+1 )
|
||||
{
|
||||
float maxResponse = (float)responseThreshold;
|
||||
float minResponse = (float)-responseThreshold;
|
||||
Point maxPt(-1, -1), minPt(-1, -1);
|
||||
int tileEndY = MIN(y + delta, rows - border - 1);
|
||||
int tileEndX = MIN(x + delta, cols - border - 1);
|
||||
|
||||
for( y1 = y; y1 <= tileEndY; y1++ )
|
||||
for( x1 = x; x1 <= tileEndX; x1++ )
|
||||
{
|
||||
float val = r_ptr[y1*rstep + x1];
|
||||
if( maxResponse < val )
|
||||
{
|
||||
maxResponse = val;
|
||||
maxPt = Point(x1, y1);
|
||||
}
|
||||
else if( minResponse > val )
|
||||
{
|
||||
minResponse = val;
|
||||
minPt = Point(x1, y1);
|
||||
}
|
||||
}
|
||||
|
||||
if( maxPt.x >= 0 )
|
||||
{
|
||||
for( y1 = maxPt.y - delta; y1 <= maxPt.y + delta; y1++ )
|
||||
for( x1 = maxPt.x - delta; x1 <= maxPt.x + delta; x1++ )
|
||||
{
|
||||
float val = r_ptr[y1*rstep + x1];
|
||||
if( val >= maxResponse && (y1 != maxPt.y || x1 != maxPt.x))
|
||||
goto skip_max;
|
||||
}
|
||||
|
||||
if( (featureSize = s_ptr[maxPt.y*sstep + maxPt.x]) >= 4 &&
|
||||
!StarDetectorSuppressLines( responses, sizes, maxPt, lineThresholdProjected,
|
||||
lineThresholdBinarized ))
|
||||
{
|
||||
KeyPoint kpt((float)maxPt.x, (float)maxPt.y, featureSize, -1, maxResponse);
|
||||
keypoints.push_back(kpt);
|
||||
}
|
||||
}
|
||||
skip_max:
|
||||
if( minPt.x >= 0 )
|
||||
{
|
||||
for( y1 = minPt.y - delta; y1 <= minPt.y + delta; y1++ )
|
||||
for( x1 = minPt.x - delta; x1 <= minPt.x + delta; x1++ )
|
||||
{
|
||||
float val = r_ptr[y1*rstep + x1];
|
||||
if( val <= minResponse && (y1 != minPt.y || x1 != minPt.x))
|
||||
goto skip_min;
|
||||
}
|
||||
|
||||
if( (featureSize = s_ptr[minPt.y*sstep + minPt.x]) >= 4 &&
|
||||
!StarDetectorSuppressLines( responses, sizes, minPt,
|
||||
lineThresholdProjected, lineThresholdBinarized))
|
||||
{
|
||||
KeyPoint kpt((float)minPt.x, (float)minPt.y, featureSize, -1, maxResponse);
|
||||
keypoints.push_back(kpt);
|
||||
}
|
||||
}
|
||||
skip_min:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
StarDetector::StarDetector(int _maxSize, int _responseThreshold,
|
||||
int _lineThresholdProjected,
|
||||
int _lineThresholdBinarized,
|
||||
int _suppressNonmaxSize)
|
||||
: maxSize(_maxSize), responseThreshold(_responseThreshold),
|
||||
lineThresholdProjected(_lineThresholdProjected),
|
||||
lineThresholdBinarized(_lineThresholdBinarized),
|
||||
suppressNonmaxSize(_suppressNonmaxSize)
|
||||
{}
|
||||
|
||||
|
||||
void StarDetector::detectImpl( InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask ) const
|
||||
{
|
||||
Mat image = _image.getMat(), mask = _mask.getMat(), grayImage = image;
|
||||
if( image.channels() > 1 ) cvtColor( image, grayImage, COLOR_BGR2GRAY );
|
||||
|
||||
(*this)(grayImage, keypoints);
|
||||
KeyPointsFilter::runByPixelsMask( keypoints, mask );
|
||||
}
|
||||
|
||||
void StarDetector::operator()(const Mat& img, std::vector<KeyPoint>& keypoints) const
|
||||
{
|
||||
Mat responses, sizes;
|
||||
int border;
|
||||
|
||||
// Use 32-bit integers if we won't overflow in the integral image
|
||||
if ((img.depth() == CV_8U || img.depth() == CV_8S) &&
|
||||
(img.rows * img.cols) < 8388608 ) // 8388608 = 2 ^ (32 - 8(bit depth) - 1(sign bit))
|
||||
border = StarDetectorComputeResponses<int>( img, responses, sizes, maxSize, CV_32S );
|
||||
else
|
||||
border = StarDetectorComputeResponses<double>( img, responses, sizes, maxSize, CV_64F );
|
||||
|
||||
keypoints.clear();
|
||||
if( border >= 0 )
|
||||
StarDetectorSuppressNonmax( responses, sizes, keypoints, border,
|
||||
responseThreshold, lineThresholdProjected,
|
||||
lineThresholdBinarized, suppressNonmaxSize );
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user