Commit 2e9f5c43 authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

added improved ORB implementation, convex-convex polygon intersection, eigen2x2…

added improved ORB implementation, convex-convex polygon intersection, eigen2x2 low-level function ...
parent 5a702d7d
......@@ -260,7 +260,7 @@ public:
* @param sensitivity: strenght of the sigmoide
* @param maxOutputValue: the maximum output value
*/
inline void normalizeGrayOutputCentredSigmoide(const type meanValue=(type)0.0, const type sensitivity=(type)2.0, const type maxOutputValue=(type)255.0){normalizeGrayOutputCentredSigmoide(meanValue, sensitivity, 255.0, this->Buffer(), this->Buffer(), this->getNBpixels()), maxOutputValue;};
inline void normalizeGrayOutputCentredSigmoide(const type meanValue=(type)0.0, const type sensitivity=(type)2.0, const type maxOutputValue=(type)255.0){normalizeGrayOutputCentredSigmoide(meanValue, sensitivity, 255.0, this->Buffer(), this->Buffer(), this->getNBpixels());};
/**
* sigmoide image normalization function (saturates min and max values), in this function, the sigmoide is centered on low values (high saturation of the medium and high values
......
......@@ -729,6 +729,8 @@ public:
_Tp dot(const Point_& pt) const;
//! dot product computed in double-precision arithmetics
double ddot(const Point_& pt) const;
//! cross-product
double cross(const Point_& pt) const;
//! checks whether the point is inside the specified rectangle
bool inside(const Rect_<_Tp>& r) const;
......@@ -1274,6 +1276,7 @@ public:
_InputArray();
_InputArray(const Mat& m);
_InputArray(const MatExpr& expr);
template<typename _Tp> _InputArray(const _Tp* vec, int n);
template<typename _Tp> _InputArray(const vector<_Tp>& vec);
template<typename _Tp> _InputArray(const vector<vector<_Tp> >& vec);
_InputArray(const vector<Mat>& vec);
......@@ -1323,6 +1326,7 @@ public:
template<typename _Tp> _OutputArray(vector<vector<_Tp> >& vec);
_OutputArray(vector<Mat>& vec);
template<typename _Tp, int m, int n> _OutputArray(Matx<_Tp, m, n>& matx);
template<typename _Tp> _OutputArray(_Tp* vec, int n);
virtual bool fixedSize() const;
virtual bool fixedType() const;
virtual bool needed() const;
......
......@@ -1113,12 +1113,16 @@ template<typename _Tp> inline _InputArray::_InputArray(const vector<vector<_Tp>
template<typename _Tp, int m, int n> inline _InputArray::_InputArray(const Matx<_Tp, m, n>& mtx)
: flags(MATX + DataType<_Tp>::type), obj((void*)&mtx), sz(n, m) {}
template<typename _Tp> inline _InputArray::_InputArray(const _Tp* vec, int n)
: flags(MATX + DataType<_Tp>::type), obj((void*)vec), sz(n, 1) {}
inline _InputArray::_InputArray(const Scalar& s)
: flags(MATX + CV_64F), obj((void*)&s), sz(1, 4) {}
template<typename _Tp> inline _OutputArray::_OutputArray(vector<_Tp>& vec) : _InputArray(vec) {}
template<typename _Tp> inline _OutputArray::_OutputArray(vector<vector<_Tp> >& vec) : _InputArray(vec) {}
template<typename _Tp, int m, int n> inline _OutputArray::_OutputArray(Matx<_Tp, m, n>& mtx) : _InputArray(mtx) {}
template<typename _Tp> inline _OutputArray::_OutputArray(_Tp* vec, int n) : _InputArray(vec, n) {}
//////////////////////////////////// Matrix Expressions /////////////////////////////////////////
......
......@@ -1599,6 +1599,9 @@ template<typename _Tp> inline _Tp Point_<_Tp>::dot(const Point_& pt) const
template<typename _Tp> inline double Point_<_Tp>::ddot(const Point_& pt) const
{ return (double)x*pt.x + (double)y*pt.y; }
template<typename _Tp> inline double Point_<_Tp>::cross(const Point_& pt) const
{ return (double)x*pt.y - (double)y*pt.x; }
template<typename _Tp> static inline Point_<_Tp>&
operator += (Point_<_Tp>& a, const Point_<_Tp>& b)
{
......
......@@ -2050,7 +2050,9 @@ void cv::polylines(InputOutputArray _img, InputArrayOfArrays pts,
int thickness, int lineType, int shift )
{
Mat img = _img.getMat();
int i, ncontours = (int)pts.total();
bool manyContours = pts.kind() == _InputArray::STD_VECTOR_VECTOR ||
pts.kind() == _InputArray::STD_VECTOR_MAT;
int i, ncontours = manyContours ? (int)pts.total() : 1;
if( ncontours == 0 )
return;
AutoBuffer<Point*> _ptsptr(ncontours);
......@@ -2060,7 +2062,9 @@ void cv::polylines(InputOutputArray _img, InputArrayOfArrays pts,
for( i = 0; i < ncontours; i++ )
{
Mat p = pts.getMat(i);
Mat p = pts.getMat(manyContours ? i : -1);
if( p.total() == 0 )
continue;
CV_Assert(p.checkVector(2, CV_32S) >= 0);
ptsptr[i] = (Point*)p.data;
npts[i] = p.rows*p.cols*p.channels()/2;
......
......@@ -422,15 +422,14 @@ public:
struct CV_EXPORTS CommonParams
{
enum { DEFAULT_N_LEVELS = 3, DEFAULT_FIRST_LEVEL = 0};
enum { DEFAULT_N_LEVELS = 3, DEFAULT_FIRST_LEVEL = 0, HARRIS_SCORE=0, FAST_SCORE=1 };
/** default constructor */
CommonParams(float scale_factor = 1.2f, unsigned n_levels = DEFAULT_N_LEVELS, int edge_threshold = 31,
unsigned first_level = DEFAULT_FIRST_LEVEL) :
unsigned first_level = DEFAULT_FIRST_LEVEL, int WTA_K=2, int score_type=HARRIS_SCORE) :
scale_factor_(scale_factor), n_levels_(n_levels), first_level_(first_level >= n_levels ? 0 : first_level),
edge_threshold_(edge_threshold)
edge_threshold_(edge_threshold), WTA_K_(WTA_K), score_type_(score_type)
{
// No other patch size is supported right now
patch_size_ = 31;
}
void read(const FileNode& fn);
......@@ -444,12 +443,16 @@ public:
* if 1, that means we will also look at the image scale_factor_ times bigger
*/
unsigned first_level_;
/** How far from the boundary the points should be */
/** How far from the boundary the points should be. */
int edge_threshold_;
friend class ORB;
protected:
/** The size of the patch that will be used for orientation and comparisons */
/** How many random points are used to produce each cell of the descriptor (2, 3, 4 ...) */
int WTA_K_;
/** Type of the score to use (FAST, HARRIS, ...) */
int score_type_;
/** The size of the patch that will be used for orientation and comparisons (only 31 is supported)*/
int patch_size_;
};
......@@ -484,7 +487,11 @@ public:
operator()(const cv::Mat &image, const cv::Mat &mask, std::vector<cv::KeyPoint> & keypoints, cv::Mat & descriptors,
bool useProvidedKeypoints = false);
void read(const FileNode& fn);
void write(FileStorage& fs) const;
private:
/** The size of the patch used when comparing regions in the patterns */
static const int kKernelWidth = 5;
......@@ -539,28 +546,20 @@ private:
/** Parameters tuning ORB */
CommonParams params_;
/** size of the half patch used for orientation computation, see Rosin - 1999 - Measuring Corner Properties */
int half_patch_size_;
/** pre-computed offsets used for the Harris verification, one vector per scale */
std::vector<std::vector<int> > orientation_horizontal_offsets_;
std::vector<std::vector<int> > orientation_vertical_offsets_;
/** The steps of the integral images for each scale */
std::vector<size_t> integral_image_steps_;
vector<size_t> integral_image_steps_;
/** The number of desired features per scale */
std::vector<size_t> n_features_per_level_;
vector<size_t> n_features_per_level_;
/** The overall number of desired features */
size_t n_features_;
/** the end of a row in a circular patch */
std::vector<int> u_max_;
/** The circular region to compute a feature orientation */
vector<int> u_max_;
/** The patterns for each level (the patterns are the same, but not their offset */
class OrbPatterns;
std::vector<OrbPatterns*> patterns_;
/** Points to compute BRIEF descriptors from */
vector<Point> pattern;
};
/*!
......@@ -1551,10 +1550,6 @@ protected:
private:
/** the ORB object we use for the computations */
mutable ORB orb_;
/** The parameters used */
ORB::CommonParams params_;
/** the number of features that need to be retrieved */
unsigned n_features_;
};
class CV_EXPORTS SimpleBlobDetector : public cv::FeatureDetector
......@@ -1953,8 +1948,6 @@ protected:
private:
/** the ORB object we use for the computations */
mutable ORB orb_;
/** The parameters used */
ORB::CommonParams params_;
};
/*
......@@ -2157,6 +2150,17 @@ struct CV_EXPORTS Hamming
typedef Hamming HammingLUT;
template<int cellsize> struct CV_EXPORTS HammingMultilevel
{
typedef unsigned char ValueType;
typedef int ResultType;
ResultType operator()( const unsigned char* a, const unsigned char* b, int size ) const
{
return normHamming(a, b, size, cellsize);
}
};
/****************************************************************************************\
* DMatch *
\****************************************************************************************/
......
......@@ -63,7 +63,6 @@ void DescriptorExtractor::compute( const Mat& image, vector<KeyPoint>& keypoints
return;
}
KeyPointsFilter::runByImageBorder( keypoints, image.size(), 0 );
KeyPointsFilter::runByKeypointSize( keypoints, std::numeric_limits<float>::epsilon() );
......@@ -247,8 +246,7 @@ int SurfDescriptorExtractor::descriptorType() const
/** Default constructor */
OrbDescriptorExtractor::OrbDescriptorExtractor(ORB::CommonParams params) :
params_(params)
OrbDescriptorExtractor::OrbDescriptorExtractor(ORB::CommonParams params)
{
orb_ = ORB(0, params);
}
......@@ -260,16 +258,15 @@ void OrbDescriptorExtractor::computeImpl(const cv::Mat& image, std::vector<cv::K
}
void OrbDescriptorExtractor::read(const cv::FileNode& fn)
{
params_.read(fn);
orb_ = ORB(0, params_);
orb_.read(fn);
}
void OrbDescriptorExtractor::write(cv::FileStorage& fs) const
{
params_.write(fs);
orb_.write(fs);
}
int OrbDescriptorExtractor::descriptorSize() const
{
return ORB::kBytes;
return orb_.descriptorSize();
}
int OrbDescriptorExtractor::descriptorType() const
{
......
......@@ -449,43 +449,22 @@ void SurfFeatureDetector::detectImpl( const Mat& image, vector<KeyPoint>& keypoi
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ORB::CommonParams::read(const FileNode& fn)
{
scale_factor_ = fn["scaleFactor"];
n_levels_ = int(fn["nLevels"]);
first_level_ = int(fn["firstLevel"]);
edge_threshold_ = fn["edgeThreshold"];
patch_size_ = fn["patchSize"];
}
void ORB::CommonParams::write(FileStorage& fs) const
{
fs << "scaleFactor" << scale_factor_;
fs << "nLevels" << int(n_levels_);
fs << "firstLevel" << int(first_level_);
fs << "edgeThreshold" << int(edge_threshold_);
fs << "patchSize" << int(patch_size_);
}
/** Default constructor
* @param n_features the number of desired features
*/
OrbFeatureDetector::OrbFeatureDetector(size_t n_features, ORB::CommonParams params) :
params_(params)
OrbFeatureDetector::OrbFeatureDetector(size_t n_features, ORB::CommonParams params)
{
orb_ = ORB(n_features, params);
}
void OrbFeatureDetector::read(const FileNode& fn)
{
params_.read(fn);
n_features_ = int(fn["nFeatures"]);
orb_.read(fn);
}
void OrbFeatureDetector::write(FileStorage& fs) const
{
params_.write(fs);
fs << "nFeatures" << int(n_features_);
orb_.write(fs);
}
void OrbFeatureDetector::detectImpl(const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask) const
......
......@@ -138,6 +138,7 @@ static void _prepareImgAndDrawKeypoints( const Mat& img1, const vector<KeyPoint>
else
{
outImg.create( size, CV_MAKETYPE(img1.depth(), 3) );
outImg = Scalar::all(0);
outImg1 = outImg( Rect(0, 0, img1.cols, img1.rows) );
outImg2 = outImg( Rect(img1.cols, 0, img2.cols, img2.rows) );
......
......@@ -46,6 +46,39 @@
using namespace cv;
using namespace std;
template<typename _Tp> static int solveQuadratic(_Tp a, _Tp b, _Tp c, _Tp& x1, _Tp& x2)
{
if( a == 0 )
{
if( b == 0 )
{
x1 = x2 = 0;
return c == 0;
}
x1 = x2 = -c/b;
return 1;
}
_Tp d = b*b - 4*a*c;
if( d < 0 )
{
x1 = x2 = 0;
return 0;
}
if( d > 0 )
{
d = std::sqrt(d);
double s = 1/(2*a);
x1 = (-b - d)*s;
x2 = (-b + d)*s;
if( x1 > x2 )
std::swap(x1, x2);
return 2;
}
x1 = x2 = -b/(2*a);
return 1;
}
//for android ndk
#undef _S
static inline Point2f applyHomography( const Mat_<double>& H, const Point2f& pt )
......@@ -109,13 +142,13 @@ EllipticKeyPoint::EllipticKeyPoint( const Point2f& _center, const Scalar& _ellip
center = _center;
ellipse = _ellipse;
Mat_<double> M = getSecondMomentsMatrix(_ellipse), eval;
eigen( M, eval );
assert( eval.rows == 2 && eval.cols == 1 );
axes.width = 1.f / (float)sqrt(eval(0,0));
axes.height = 1.f / (float)sqrt(eval(1,0));
double a = ellipse[0], b = ellipse[1], c = ellipse[2];
double ac_b2 = a*c - b*b;
double x1, x2;
solveQuadratic(1., -(a+c), ac_b2, x1, x2);
axes.width = (float)(1/sqrt(x1));
axes.height = (float)(1/sqrt(x2));
double ac_b2 = ellipse[0]*ellipse[2] - ellipse[1]*ellipse[1];
boundingBox.width = (float)sqrt(ellipse[2]/ac_b2);
boundingBox.height = (float)sqrt(ellipse[0]/ac_b2);
}
......
......@@ -370,7 +370,7 @@ void cv::FAST(const Mat& img, std::vector<KeyPoint>& keypoints, int threshold, b
score > pprev[j-1] && score > pprev[j] && score > pprev[j+1] &&
score > curr[j-1] && score > curr[j] && score > curr[j+1]) )
{
keypoints.push_back(KeyPoint((float)j, (float)(i-1), 6.f, -1, (float)score));
keypoints.push_back(KeyPoint((float)j, (float)(i-1), 7.f, -1, (float)score));
}
}
}
......
......@@ -340,10 +340,20 @@ Ptr<DescriptorMatcher> DescriptorMatcher::create( const string& descriptorMatche
{
dm = new BruteForceMatcher<Hamming>();
}
else if( !descriptorMatcherType.compare( "BruteForce-HammingLUT") )
else if( !descriptorMatcherType.compare("BruteForce-HammingLUT") )
{
dm = new BruteForceMatcher<Hamming>();
}
else if( !descriptorMatcherType.compare("BruteForce-Hamming(2)") )
{
dm = new BruteForceMatcher<HammingMultilevel<2> >();
}
else if( !descriptorMatcherType.compare("BruteForce-Hamming(4)") )
{
dm = new BruteForceMatcher<HammingMultilevel<4> >();
}
else
CV_Error( CV_StsBadArg, "Unknown matcher name" );
return dm;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -445,6 +445,9 @@ CV_EXPORTS_W void cornerHarris( InputArray src, OutputArray dst, int blockSize,
int ksize, double k,
int borderType=BORDER_DEFAULT );
// low-level function for computing eigenvalues and eigenvectors of 2x2 matrices
CV_EXPORTS void eigen2x2( const float* a, float* e, int n );
//! computes both eigenvalues and the eigenvectors of 2x2 derivative covariation matrix at each pixel. The output is stored as 6-channel matrix.
CV_EXPORTS_W void cornerEigenValsAndVecs( InputArray src, OutputArray dst,
int blockSize, int ksize,
......@@ -1016,6 +1019,10 @@ CV_EXPORTS_W void convexHull( InputArray points, OutputArray hull,
//! returns true iff the contour is convex. Does not support contours with self-intersection
CV_EXPORTS_W bool isContourConvex( InputArray contour );
//! finds intersection of two convex polygons
CV_EXPORTS_W float intersectConvexConvex( InputArray _p1, InputArray _p2,
OutputArray _p12, bool handleNested=true );
//! fits ellipse to the set of 2D points
CV_EXPORTS_W RotatedRect fitEllipse( InputArray points );
......
......@@ -162,23 +162,9 @@ calcHarris( const Mat& _cov, Mat& _dst, double k )
}
static void
calcEigenValsVecs( const Mat& _cov, Mat& _dst )
void eigen2x2( const float* cov, float* dst, int n )
{
int i, j;
Size size = _cov.size();
if( _cov.isContinuous() && _dst.isContinuous() )
{
size.width *= size.height;
size.height = 1;
}
for( i = 0; i < size.height; i++ )
{
const float* cov = (const float*)(_cov.data + _cov.step*i);
float* dst = (float*)(_dst.data + _dst.step*i);
for( j = 0; j < size.width; j++ )
for( int j = 0; j < n; j++ )
{
double a = cov[j*3];
double b = cov[j*3+1];
......@@ -231,6 +217,24 @@ calcEigenValsVecs( const Mat& _cov, Mat& _dst )
dst[6*j + 4] = (float)(x*d);
dst[6*j + 5] = (float)(y*d);
}
}
static void
calcEigenValsVecs( const Mat& _cov, Mat& _dst )
{
Size size = _cov.size();
if( _cov.isContinuous() && _dst.isContinuous() )
{
size.width *= size.height;
size.height = 1;
}
for( int i = 0; i < size.height; i++ )
{
const float* cov = (const float*)(_cov.data + _cov.step*i);
float* dst = (float*)(_dst.data + _dst.step*i);
eigen2x2(cov, dst, size.width);
}
}
......
This diff is collapsed.
......@@ -206,6 +206,22 @@ void cv::copyMakeBorder( InputArray _src, OutputArray _dst, int top, int bottom,
_dst.create( src.rows + top + bottom, src.cols + left + right, src.type() );
Mat dst = _dst.getMat();
if( src.isSubmatrix() && (borderType & BORDER_ISOLATED) == 0 )
{
Size wholeSize;
Point ofs;
src.locateROI(wholeSize, ofs);
int dtop = std::min(ofs.y, top);
int dbottom = std::min(wholeSize.height - src.rows - ofs.y, bottom);
int dleft = std::min(ofs.x, left);
int dright = std::min(wholeSize.width - src.cols - ofs.x, right);
src.adjustROI(dtop, dbottom, dleft, dright);
top -= dtop;
left -= dleft;
}
borderType &= ~BORDER_ISOLATED;
if( borderType != BORDER_CONSTANT )
copyMakeBorder_8u( src.data, src.step, src.size(),
dst.data, dst.step, dst.size(),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment