Commit 957e80ab authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

lot's of changes; nonfree & photo modules added; SIFT & SURF -> nonfree module;…

lot's of changes; nonfree & photo modules added; SIFT & SURF -> nonfree module; Inpainting -> photo; refactored features2d (ORB is still failing tests), optimized brute-force matcher and made it non-template.
parent 6300215b
......@@ -48,6 +48,7 @@
#include "opencv2/flann/miniflann.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"
#include "opencv2/video/video.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/objdetect/objdetect.hpp"
......
***************************************
contrib. Contributed/Experimental Stuff
***************************************
The module contains some recently added functionality that has not been stabilized, or functionality that is considered optional.
......@@ -145,9 +145,8 @@ public:
class CV_EXPORTS CvFeatureTracker
{
private:
FeatureDetector* detector;
DescriptorExtractor* descriptor;
DescriptorMatcher* matcher;
Ptr<Feature2D> dd;
Ptr<DescriptorMatcher> matcher;
vector<DMatch> matches;
Mat prev_image;
......
......@@ -53,22 +53,24 @@ CvFeatureTracker::CvFeatureTracker(CvFeatureTrackerParams _params) :
switch (params.feature_type)
{
case CvFeatureTrackerParams::SIFT:
detector = new SiftFeatureDetector(
SIFT::DetectorParams::GET_DEFAULT_THRESHOLD(),
SIFT::DetectorParams::GET_DEFAULT_EDGE_THRESHOLD() + 0.7,
SIFT::CommonParams::DEFAULT_NOCTAVES + 4,
SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS + 2,
SIFT::CommonParams::DEFAULT_FIRST_OCTAVE,
SIFT::CommonParams::FIRST_ANGLE);
dd = Algorithm::create<Feature2D>("Feature2D.SIFT");
if( dd.empty() )
CV_Error(CV_StsNotImplemented, "OpenCV has been compiled without SIFT support");
dd->set("nOctaveLayers", 5);
dd->set("contrastThreshold", 0.04);
dd->set("edgeThreshold", 10.7);
case CvFeatureTrackerParams::SURF:
detector = new SurfFeatureDetector(400, 3, 4);
default:
detector = new GoodFeaturesToTrackDetector();
dd = Algorithm::create<Feature2D>("Feature2D.SURF");
if( dd.empty() )
CV_Error(CV_StsNotImplemented, "OpenCV has been compiled without SURF support");
dd->set("hessianThreshold", 400);
dd->set("nOctaves", 3);
dd->set("nOctaveLayers", 4);
default:
CV_Error(CV_StsBadArg, "Unknown feature type");
}
descriptor = new SurfDescriptorExtractor(3, 4, false);
matcher = new BruteForceMatcher<L2<float> > ();
matcher = new BFMatcher(NORM_L2);
}
CvFeatureTracker::~CvFeatureTracker()
......@@ -105,7 +107,7 @@ Rect CvFeatureTracker::updateTrackingWindowWithSIFT(Mat image)
rectangle(mask, Point(window.x, window.y), Point(window.x + window.width,
window.y + window.height), Scalar(255), CV_FILLED);
detector->detect(prev_image, prev_keypoints, mask);
dd->operator()(prev_image, mask, prev_keypoints, prev_desc);
window.x -= params.window_size;
window.y -= params.window_size;
......@@ -114,12 +116,12 @@ Rect CvFeatureTracker::updateTrackingWindowWithSIFT(Mat image)
rectangle(mask, Point(window.x, window.y), Point(window.x + window.width,
window.y + window.height), Scalar(255), CV_FILLED);
detector->detect(image, curr_keypoints, mask);
dd->operator()(image, mask, curr_keypoints, curr_desc);
if (prev_keypoints.size() > 4 && curr_keypoints.size() > 4)
{
descriptor->compute(prev_image, prev_keypoints, prev_desc);
descriptor->compute(image, curr_keypoints, curr_desc);
//descriptor->compute(prev_image, prev_keypoints, prev_desc);
//descriptor->compute(image, curr_keypoints, curr_desc);
matcher->match(prev_desc, curr_desc, matches);
......
#include "test_precomp.hpp"
CV_TEST_MAIN("cv")
#include "test_precomp.hpp"
#ifndef __OPENCV_TEST_PRECOMP_HPP__
#define __OPENCV_TEST_PRECOMP_HPP__
#include "opencv2/ts/ts.hpp"
#include "opencv2/contrib/contrib.hpp"
#include <iostream>
#endif
......@@ -118,7 +118,7 @@ CV_EXPORTS string tempfile( const char* suffix CV_DEFAULT(0));
// matrix decomposition types
enum { DECOMP_LU=0, DECOMP_SVD=1, DECOMP_EIG=2, DECOMP_CHOLESKY=3, DECOMP_QR=4, DECOMP_NORMAL=16 };
enum { NORM_INF=1, NORM_L1=2, NORM_L2=4, NORM_TYPE_MASK=7, NORM_RELATIVE=8, NORM_MINMAX=32};
enum { NORM_INF=1, NORM_L1=2, NORM_L2=4, NORM_L2SQR=5, NORM_HAMMING=6, NORM_HAMMING2=7, NORM_TYPE_MASK=7, NORM_RELATIVE=8, NORM_MINMAX=32 };
enum { CMP_EQ=0, CMP_GT=1, CMP_GE=2, CMP_LT=3, CMP_LE=4, CMP_NE=5 };
enum { GEMM_1_T=1, GEMM_2_T=2, GEMM_3_T=4 };
enum { DFT_INVERSE=1, DFT_SCALE=2, DFT_ROWS=4, DFT_COMPLEX_OUTPUT=16, DFT_REAL_OUTPUT=32,
......@@ -2057,6 +2057,14 @@ CV_EXPORTS_W double norm(InputArray src1, int normType=NORM_L2, InputArray mask=
//! computes norm of selected part of the difference between two arrays
CV_EXPORTS_W double norm(InputArray src1, InputArray src2,
int normType=NORM_L2, InputArray mask=noArray());
//! naive nearest neighbor finder
CV_EXPORTS_W void batchDistance(InputArray src1, InputArray src2,
OutputArray dist, int dtype, OutputArray nidx,
int normType=NORM_L2, int K=0,
InputArray mask=noArray(), int update=0,
bool crosscheck=false);
//! scales and shifts array elements so that either the specified norm (alpha) or the minimum (alpha) and maximum (beta) array values get the specified values
CV_EXPORTS_W void normalize( InputArray src, OutputArray dst, double alpha=1, double beta=0,
int norm_type=NORM_L2, int dtype=-1, InputArray mask=noArray());
......@@ -4244,10 +4252,20 @@ public:
template<typename _Tp> typename ParamType<_Tp>::member_type get(const string& name) const;
template<typename _Tp> typename ParamType<_Tp>::member_type get(const char* name) const;
template<typename _Tp> void set(const string& name,
typename ParamType<_Tp>::const_param_type value);
template<typename _Tp> void set(const char* name,
typename ParamType<_Tp>::const_param_type value);
void set(const string& name, int value);
void set(const string& name, double value);
void set(const string& name, bool value);
void set(const string& name, const string& value);
void set(const string& name, const Mat& value);
void set(const string& name, const Ptr<Algorithm>& value);
void set(const char* name, int value);
void set(const char* name, double value);
void set(const char* name, bool value);
void set(const char* name, const string& value);
void set(const char* name, const Mat& value);
void set(const char* name, const Ptr<Algorithm>& value);
string paramHelp(const string& name) const;
int paramType(const char* name) const;
int paramType(const string& name) const;
......@@ -4293,6 +4311,11 @@ public:
int (Algorithm::*getter)()=0,
void (Algorithm::*setter)(int)=0,
const string& help=string());
void addParam(const Algorithm* algo, const char* name,
const bool& value, bool readOnly=false,
int (Algorithm::*getter)()=0,
void (Algorithm::*setter)(int)=0,
const string& help=string());
void addParam(const Algorithm* algo, const char* name,
const double& value, bool readOnly=false,
double (Algorithm::*getter)()=0,
......
......@@ -3823,18 +3823,6 @@ template<typename _Tp> inline typename ParamType<_Tp>::member_type Algorithm::ge
return value;
}
template<typename _Tp> inline void Algorithm::set(const string& name,
typename ParamType<_Tp>::const_param_type value)
{
info()->set(this, name.c_str(), ParamType<_Tp>::type, &value);
}
template<typename _Tp> inline void Algorithm::set(const char* name,
typename ParamType<_Tp>::const_param_type value)
{
info()->set(this, name, ParamType<_Tp>::type, &value);
}
}
#endif // __cplusplus
......
......@@ -77,7 +77,7 @@ template<typename _KeyTp, typename _ValueTp> struct sorted_vector
b = c;
}
if( vec[a].first == key )
if( a < vec.size() && vec[a].first == key )
{
value = vec[a].second;
return true;
......@@ -176,6 +176,66 @@ string Algorithm::name() const
{
return info()->name();
}
void Algorithm::set(const string& name, int value)
{
info()->set(this, name.c_str(), ParamType<int>::type, &value);
}
void Algorithm::set(const string& name, double value)
{
info()->set(this, name.c_str(), ParamType<double>::type, &value);
}
void Algorithm::set(const string& name, bool value)
{
info()->set(this, name.c_str(), ParamType<bool>::type, &value);
}
void Algorithm::set(const string& name, const string& value)
{
info()->set(this, name.c_str(), ParamType<string>::type, &value);
}
void Algorithm::set(const string& name, const Mat& value)
{
info()->set(this, name.c_str(), ParamType<Mat>::type, &value);
}
void Algorithm::set(const string& name, const Ptr<Algorithm>& value)
{
info()->set(this, name.c_str(), ParamType<Algorithm>::type, &value);
}
void Algorithm::set(const char* name, int value)
{
info()->set(this, name, ParamType<int>::type, &value);
}
void Algorithm::set(const char* name, double value)
{
info()->set(this, name, ParamType<double>::type, &value);
}
void Algorithm::set(const char* name, bool value)
{
info()->set(this, name, ParamType<bool>::type, &value);
}
void Algorithm::set(const char* name, const string& value)
{
info()->set(this, name, ParamType<string>::type, &value);
}
void Algorithm::set(const char* name, const Mat& value)
{
info()->set(this, name, ParamType<Mat>::type, &value);
}
void Algorithm::set(const char* name, const Ptr<Algorithm>& value)
{
info()->set(this, name, ParamType<Algorithm>::type, &value);
}
string Algorithm::paramHelp(const string& name) const
{
......@@ -261,25 +321,25 @@ void AlgorithmInfo::read(Algorithm* algo, const FileNode& fn) const
if( n.empty() )
continue;
if( p.type == Param::INT )
algo->set<int>(pname, (int)n);
algo->set(pname, (int)n);
else if( p.type == Param::BOOLEAN )
algo->set<bool>(pname, (int)n != 0);
algo->set(pname, (int)n != 0);
else if( p.type == Param::REAL )
algo->set<double>(pname, (double)n);
algo->set(pname, (double)n);
else if( p.type == Param::STRING )
algo->set<string>(pname, (string)n);
algo->set(pname, (string)n);
else if( p.type == Param::MAT )
{
Mat m;
cv::read(fn, m);
algo->set<Mat>(pname, m);
algo->set(pname, m);
}
else if( p.type == Param::ALGORITHM )
{
Ptr<Algorithm> nestedAlgo = Algorithm::_create((string)n["name"]);
CV_Assert( !nestedAlgo.empty() );
nestedAlgo->read(n);
algo->set<Algorithm>(pname, nestedAlgo);
algo->set(pname, nestedAlgo);
}
else
CV_Error( CV_StsUnsupportedFormat, "unknown/unsupported parameter type");
......@@ -505,6 +565,16 @@ void AlgorithmInfo::addParam(const Algorithm* algo, const char* name,
(Algorithm::Getter)getter, (Algorithm::Setter)setter, help);
}
void AlgorithmInfo::addParam(const Algorithm* algo, const char* name,
const bool& value, bool readOnly,
int (Algorithm::*getter)(),
void (Algorithm::*setter)(int),
const string& help)
{
addParam_(algo, name, ParamType<bool>::type, &value, readOnly,
(Algorithm::Getter)getter, (Algorithm::Setter)setter, help);
}
void AlgorithmInfo::addParam(const Algorithm* algo, const char* name,
const double& value, bool readOnly,
double (Algorithm::*getter)(),
......
......@@ -113,11 +113,13 @@ namespace
const CvOpenGlFuncTab* g_glFuncTab = 0;
#ifdef HAVE_CUDA
const CvOpenGlFuncTab* glFuncTab()
{
static EmptyGlFuncTab empty;
return g_glFuncTab ? g_glFuncTab : &empty;
}
#endif
}
CvOpenGlFuncTab::~CvOpenGlFuncTab()
......
This diff is collapsed.
......@@ -92,177 +92,6 @@ Finds keypoints in an image
:param params: The algorithm parameters stored in ``CvStarDetectorParams`` (OpenCV 1.x API only)
SIFT
----
.. ocv:class:: SIFT
Class for extracting keypoints and computing descriptors using the Scale Invariant Feature Transform (SIFT) approach. ::
class CV_EXPORTS SIFT
{
public:
struct CommonParams
{
static const int DEFAULT_NOCTAVES = 4;
static const int DEFAULT_NOCTAVE_LAYERS = 3;
static const int DEFAULT_FIRST_OCTAVE = -1;
enum{ FIRST_ANGLE = 0, AVERAGE_ANGLE = 1 };
CommonParams();
CommonParams( int _nOctaves, int _nOctaveLayers, int _firstOctave,
int _angleMode );
int nOctaves, nOctaveLayers, firstOctave;
int angleMode;
};
struct DetectorParams
{
static double GET_DEFAULT_THRESHOLD()
{ return 0.04 / SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS / 2.0; }
static double GET_DEFAULT_EDGE_THRESHOLD() { return 10.0; }
DetectorParams();
DetectorParams( double _threshold, double _edgeThreshold );
double threshold, edgeThreshold;
};
struct DescriptorParams
{
static double GET_DEFAULT_MAGNIFICATION() { return 3.0; }
static const bool DEFAULT_IS_NORMALIZE = true;
static const int DESCRIPTOR_SIZE = 128;
DescriptorParams();
DescriptorParams( double _magnification, bool _isNormalize,
bool _recalculateAngles );
double magnification;
bool isNormalize;
bool recalculateAngles;
};
SIFT();
//! sift-detector constructor
SIFT( double _threshold, double _edgeThreshold,
int _nOctaves=CommonParams::DEFAULT_NOCTAVES,
int _nOctaveLayers=CommonParams::DEFAULT_NOCTAVE_LAYERS,
int _firstOctave=CommonParams::DEFAULT_FIRST_OCTAVE,
int _angleMode=CommonParams::FIRST_ANGLE );
//! sift-descriptor constructor
SIFT( double _magnification, bool _isNormalize=true,
bool _recalculateAngles = true,
int _nOctaves=CommonParams::DEFAULT_NOCTAVES,
int _nOctaveLayers=CommonParams::DEFAULT_NOCTAVE_LAYERS,
int _firstOctave=CommonParams::DEFAULT_FIRST_OCTAVE,
int _angleMode=CommonParams::FIRST_ANGLE );
SIFT( const CommonParams& _commParams,
const DetectorParams& _detectorParams = DetectorParams(),
const DescriptorParams& _descriptorParams = DescriptorParams() );
//! returns the descriptor size in floats (128)
int descriptorSize() const { return DescriptorParams::DESCRIPTOR_SIZE; }
//! finds the keypoints using the SIFT algorithm
void operator()(const Mat& img, const Mat& mask,
vector<KeyPoint>& keypoints) const;
//! finds the keypoints and computes descriptors for them using SIFT algorithm.
//! Optionally it can compute descriptors for the user-provided keypoints
void operator()(const Mat& img, const Mat& mask,
vector<KeyPoint>& keypoints,
Mat& descriptors,
bool useProvidedKeypoints=false) const;
CommonParams getCommonParams () const { return commParams; }
DetectorParams getDetectorParams () const { return detectorParams; }
DescriptorParams getDescriptorParams () const { return descriptorParams; }
protected:
...
};
SURF
----
.. ocv:class:: SURF
Class for extracting Speeded Up Robust Features from an image [Bay06]_. The class is derived from ``CvSURFParams`` structure, which specifies the algorithm parameters:
.. ocv:member:: int extended
* 0 means that the basic descriptors (64 elements each) shall be computed
* 1 means that the extended descriptors (128 elements each) shall be computed
.. ocv:member:: int upright
* 0 means that detector computes orientation of each feature.
* 1 means that the orientation is not computed (which is much, much faster). For example, if you match images from a stereo pair, or do image stitching, the matched features likely have very similar angles, and you can speed up feature extraction by setting ``upright=1``.
.. ocv:member:: double hessianThreshold
Threshold for the keypoint detector. Only features, whose hessian is larger than ``hessianThreshold`` are retained by the detector. Therefore, the larger the value, the less keypoints you will get. A good default value could be from 300 to 500, depending from the image contrast.
.. ocv:member:: int nOctaves
The number of a gaussian pyramid octaves that the detector uses. It is set to 4 by default. If you want to get very large features, use the larger value. If you want just small features, decrease it.
.. ocv:member:: int nOctaveLayers
The number of images within each octave of a gaussian pyramid. It is set to 2 by default.
.. [Bay06] Bay, H. and Tuytelaars, T. and Van Gool, L. "SURF: Speeded Up Robust Features", 9th European Conference on Computer Vision, 2006
SURF::SURF
----------
The SURF extractor constructors.
.. ocv:function:: SURF::SURF()
.. ocv:function:: SURF::SURF(double hessianThreshold, int nOctaves=4, int nOctaveLayers=2, bool extended=false, bool upright=false)
.. ocv:pyfunction:: cv2.SURF(_hessianThreshold[, _nOctaves[, _nOctaveLayers[, _extended[, _upright]]]]) -> <SURF object>
:param hessianThreshold: Threshold for hessian keypoint detector used in SURF.
:param nOctaves: Number of pyramid octaves the keypoint detector will use.
:param nOctaveLayers: Number of octave layers within each octave.
:param extended: Extended descriptor flag (true - use extended 128-element descriptors; false - use 64-element descriptors).
:param upright: Up-right or rotated features flag (true - do not compute orientation of features; false - compute orientation).
SURF::operator()
----------------
Detects keypoints and computes SURF descriptors for them.
.. ocv:function:: void SURF::operator()(const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints)
.. ocv:function:: void SURF::operator()(const Mat& image, const Mat& mask, vector<KeyPoint>& keypoints, vector<float>& descriptors, bool useProvidedKeypoints=false)
.. ocv:pyfunction:: cv2.SURF.detect(img, mask) -> keypoints
.. ocv:pyfunction:: cv2.SURF.detect(img, mask[, useProvidedKeypoints]) -> keypoints, descriptors
.. ocv:cfunction:: void cvExtractSURF( const CvArr* image, const CvArr* mask, CvSeq** keypoints, CvSeq** descriptors, CvMemStorage* storage, CvSURFParams params )
.. ocv:pyoldfunction:: cv.ExtractSURF(image, mask, storage, params)-> (keypoints, descriptors)
:param image: Input 8-bit grayscale image
:param mask: Optional input mask that marks the regions where we should detect features.
:param keypoints: The input/output vector of keypoints
:param descriptors: The output concatenated vectors of descriptors. Each descriptor is 64- or 128-element vector, as returned by ``SURF::descriptorSize()``. So the total size of ``descriptors`` will be ``keypoints.size()*descriptorSize()``.
:param useProvidedKeypoints: Boolean flag. If it is true, the keypoint detector is not run. Instead, the provided vector of keypoints is used and the algorithm just computes their descriptors.
:param storage: Memory storage for the output keypoints and descriptors in OpenCV 1.x API.
:param params: SURF algorithm parameters in OpenCV 1.x API.
ORB
----
.. ocv:class:: ORB
......
......@@ -22,7 +22,7 @@ PERF_TEST_P(orb, detect, testing::Values(ORB_IMAGES))
Mat mask;
declare.in(frame);
ORB detector(1500, ORB::CommonParams(1.3f, 5));
ORB detector(1500, 1.3f, 5);
vector<KeyPoint> points;
TEST_CYCLE() detector(frame, mask, points);
......@@ -39,7 +39,7 @@ PERF_TEST_P(orb, extract, testing::Values(ORB_IMAGES))
Mat mask;
declare.in(frame);
ORB detector(1500, ORB::CommonParams(1.3f, 5));
ORB detector(1500, 1.3f, 5);
vector<KeyPoint> points;
detector(frame, mask, points);
......@@ -58,7 +58,7 @@ PERF_TEST_P(orb, full, testing::Values(ORB_IMAGES))
Mat mask;
declare.in(frame);
ORB detector(1500, ORB::CommonParams(1.3f, 5));
ORB detector(1500, 1.3f, 5);
vector<KeyPoint> points;
Mat descriptors;
......
......@@ -77,11 +77,11 @@ void DescriptorExtractor::compute( const vector<Mat>& imageCollection, vector<ve
compute( imageCollection[i], pointCollection[i], descCollection[i] );
}
void DescriptorExtractor::read( const FileNode& )
/*void DescriptorExtractor::read( const FileNode& )
{}
void DescriptorExtractor::write( FileStorage& ) const
{}
{}*/
bool DescriptorExtractor::empty() const
{
......@@ -96,184 +96,16 @@ void DescriptorExtractor::removeBorderKeypoints( vector<KeyPoint>& keypoints,
Ptr<DescriptorExtractor> DescriptorExtractor::create(const string& descriptorExtractorType)
{
DescriptorExtractor* de = 0;
size_t pos = 0;
if (!descriptorExtractorType.compare("SIFT"))
if( descriptorExtractorType.find("Opponent") == 0)
{
de = new SiftDescriptorExtractor();
size_t pos = string("Opponent").size();
return DescriptorExtractor::create(descriptorExtractorType.substr(pos));
}
else if (!descriptorExtractorType.compare("SURF"))
{
de = new SurfDescriptorExtractor();
}
else if (!descriptorExtractorType.compare("ORB"))
{
de = new OrbDescriptorExtractor();
}
else if (!descriptorExtractorType.compare("BRIEF"))
{
de = new BriefDescriptorExtractor();
}
else if ( (pos=descriptorExtractorType.find("Opponent")) == 0)
{
pos += string("Opponent").size();
de = new OpponentColorDescriptorExtractor( DescriptorExtractor::create(descriptorExtractorType.substr(pos)) );
}
return de;
}
/****************************************************************************************\
* SiftDescriptorExtractor *
\****************************************************************************************/
SiftDescriptorExtractor::SiftDescriptorExtractor(const SIFT::DescriptorParams& descriptorParams,
const SIFT::CommonParams& commonParams)
: sift( descriptorParams.magnification, descriptorParams.isNormalize, descriptorParams.recalculateAngles,
commonParams.nOctaves, commonParams.nOctaveLayers, commonParams.firstOctave, commonParams.angleMode )
{}
SiftDescriptorExtractor::SiftDescriptorExtractor( double magnification, bool isNormalize, bool recalculateAngles,
int nOctaves, int nOctaveLayers, int firstOctave, int angleMode )
: sift( magnification, isNormalize, recalculateAngles, nOctaves, nOctaveLayers, firstOctave, angleMode )
{}
void SiftDescriptorExtractor::computeImpl( const Mat& image,
vector<KeyPoint>& keypoints,
Mat& descriptors) const
{
bool useProvidedKeypoints = true;
Mat grayImage = image;
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
sift(grayImage, Mat(), keypoints, descriptors, useProvidedKeypoints);
}
void SiftDescriptorExtractor::read (const FileNode &fn)
{
double magnification = fn["magnification"];
bool isNormalize = (int)fn["isNormalize"] != 0;
bool recalculateAngles = (int)fn["recalculateAngles"] != 0;
int nOctaves = fn["nOctaves"];
int nOctaveLayers = fn["nOctaveLayers"];
int firstOctave = fn["firstOctave"];
int angleMode = fn["angleMode"];
sift = SIFT( magnification, isNormalize, recalculateAngles, nOctaves, nOctaveLayers, firstOctave, angleMode );
}
void SiftDescriptorExtractor::write (FileStorage &fs) const
{
// fs << "algorithm" << getAlgorithmName ();
SIFT::CommonParams commParams = sift.getCommonParams ();
SIFT::DescriptorParams descriptorParams = sift.getDescriptorParams ();
fs << "magnification" << descriptorParams.magnification;
fs << "isNormalize" << descriptorParams.isNormalize;
fs << "recalculateAngles" << descriptorParams.recalculateAngles;
fs << "nOctaves" << commParams.nOctaves;
fs << "nOctaveLayers" << commParams.nOctaveLayers;
fs << "firstOctave" << commParams.firstOctave;
fs << "angleMode" << commParams.angleMode;
}
int SiftDescriptorExtractor::descriptorSize() const
{
return sift.descriptorSize();
}
int SiftDescriptorExtractor::descriptorType() const
{
return CV_32FC1;
}
/****************************************************************************************\
* SurfDescriptorExtractor *
\****************************************************************************************/
SurfDescriptorExtractor::SurfDescriptorExtractor( int nOctaves,
int nOctaveLayers, bool extended, bool upright )
: surf( 0.0, nOctaves, nOctaveLayers, extended, upright )
{}
void SurfDescriptorExtractor::computeImpl( const Mat& image,
vector<KeyPoint>& keypoints,
Mat& descriptors) const
{
// Compute descriptors for given keypoints
vector<float> _descriptors;
Mat mask;
bool useProvidedKeypoints = true;
Mat grayImage = image;
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
surf(grayImage, mask, keypoints, _descriptors, useProvidedKeypoints);
descriptors.create((int)keypoints.size(), (int)surf.descriptorSize(), CV_32FC1);
assert( (int)_descriptors.size() == descriptors.rows * descriptors.cols );
std::copy(_descriptors.begin(), _descriptors.end(), descriptors.begin<float>());
}
void SurfDescriptorExtractor::read( const FileNode &fn )
{
int nOctaves = fn["nOctaves"];
int nOctaveLayers = fn["nOctaveLayers"];
bool extended = (int)fn["extended"] != 0;
bool upright = (int)fn["upright"] != 0;
surf = SURF( 0.0, nOctaves, nOctaveLayers, extended, upright );
}
void SurfDescriptorExtractor::write( FileStorage &fs ) const
{
// fs << "algorithm" << getAlgorithmName ();
fs << "nOctaves" << surf.nOctaves;
fs << "nOctaveLayers" << surf.nOctaveLayers;
fs << "extended" << surf.extended;
fs << "upright" << surf.upright;
}
int SurfDescriptorExtractor::descriptorSize() const
{
return surf.descriptorSize();
}
int SurfDescriptorExtractor::descriptorType() const
{
return CV_32FC1;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/** Default constructor */
OrbDescriptorExtractor::OrbDescriptorExtractor(ORB::CommonParams params)
{
orb_ = ORB(0, params);
}
void OrbDescriptorExtractor::computeImpl(const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints,
cv::Mat& descriptors) const
{
cv::Mat empty_mask;
orb_(image, empty_mask, keypoints, descriptors, true);
}
void OrbDescriptorExtractor::read(const cv::FileNode& fn)
{
orb_.read(fn);
}
void OrbDescriptorExtractor::write(cv::FileStorage& fs) const
{
orb_.write(fs);
}
int OrbDescriptorExtractor::descriptorSize() const
{
return orb_.descriptorSize();
}
int OrbDescriptorExtractor::descriptorType() const
{
return CV_8UC1;
return Algorithm::create<DescriptorExtractor>("Feature2D." + descriptorExtractorType);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/****************************************************************************************\
* OpponentColorDescriptorExtractor *
......
This diff is collapsed.
......@@ -169,8 +169,9 @@ SurfAdjuster::SurfAdjuster( double initial_thresh, double min_thresh, double max
void SurfAdjuster::detectImpl(const Mat& image, vector<KeyPoint>& keypoints, const cv::Mat& mask) const
{
SurfFeatureDetector detector_tmp(thresh_);
detector_tmp.detect(image, keypoints, mask);
Ptr<FeatureDetector> surf = FeatureDetector::create("SURF");
surf->set("hessianThreshold", thresh_);
surf->detect(image, keypoints, mask);
}
void SurfAdjuster::tooFew(int, int)
......
......@@ -185,11 +185,10 @@ static int cornerScore(const uchar* ptr, const int pixel[], int threshold)
return threshold;
}
}
void cv::FAST(const Mat& img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression)
void FAST(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool nonmax_suppression)
{
Mat img = _img.getMat();
const int K = 8, N = 16 + K + 1;
int i, j, k, pixel[N];
makeOffsets(pixel, img.step);
......@@ -280,7 +279,7 @@ void cv::FAST(const Mat& img, std::vector<KeyPoint>& keypoints, int threshold, b
{
cornerpos[ncorners++] = j+k;
if(nonmax_suppression)
curr[j+k] = (uchar)cornerScore(ptr+k, pixel, threshold);
curr[j+k] = cornerScore(ptr+k, pixel, threshold);
}
}
#endif
......@@ -318,7 +317,7 @@ void cv::FAST(const Mat& img, std::vector<KeyPoint>& keypoints, int threshold, b
{
cornerpos[ncorners++] = j;
if(nonmax_suppression)
curr[j] = (uchar)cornerScore(ptr, pixel, threshold);
curr[j] = cornerScore(ptr, pixel, threshold);
break;
}
}
......@@ -340,7 +339,7 @@ void cv::FAST(const Mat& img, std::vector<KeyPoint>& keypoints, int threshold, b
{
cornerpos[ncorners++] = j;
if(nonmax_suppression)
curr[j] = (uchar)cornerScore(ptr, pixel, threshold);
curr[j] = cornerScore(ptr, pixel, threshold);
break;
}
}
......@@ -375,3 +374,38 @@ void cv::FAST(const Mat& img, std::vector<KeyPoint>& keypoints, int threshold, b
}
}
}
/*
* FastFeatureDetector
*/
FastFeatureDetector::FastFeatureDetector( int _threshold, bool _nonmaxSuppression )
: threshold(_threshold), nonmaxSuppression(_nonmaxSuppression)
{}
void FastFeatureDetector::detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask ) const
{
Mat grayImage = image;
if( image.type() != CV_8U ) cvtColor( image, grayImage, CV_BGR2GRAY );
FAST( grayImage, keypoints, threshold, nonmaxSuppression );
KeyPointsFilter::runByPixelsMask( keypoints, mask );
}
static Algorithm* createFAST() { return new FastFeatureDetector; }
static AlgorithmInfo fast_info("Feature2D.FAST", createFAST);
AlgorithmInfo* FastFeatureDetector::info() const
{
static volatile bool initialized = false;
if( !initialized )
{
fast_info.addParam(this, "threshold", threshold);
fast_info.addParam(this, "nonmaxSuppression", nonmaxSuppression);
initialized = true;
}
return &fast_info;
}
}
......@@ -165,6 +165,52 @@ float KeyPoint::overlap( const KeyPoint& kp1, const KeyPoint& kp2 )
return ovrl;
}
struct KeypointResponseGreaterThanThreshold
{
KeypointResponseGreaterThanThreshold(float _value) :
value(_value)
{
}
inline bool operator()(const KeyPoint& kpt) const
{
return kpt.response >= value;
}
float value;
};
struct KeypointResponseGreater
{
inline bool operator()(const KeyPoint& kp1, const KeyPoint& kp2) const
{
return kp1.response > kp2.response;
}
};
// takes keypoints and culls them by the response
void KeyPointsFilter::retainBest(vector<KeyPoint>& keypoints, int n_points)
{
//this is only necessary if the keypoints size is greater than the number of desired points.
if( n_points > 0 && keypoints.size() > (size_t)n_points )
{
if (n_points==0)
{
keypoints.clear();
return;
}
//first use nth element to partition the keypoints into the best and worst.
std::nth_element(keypoints.begin(), keypoints.begin() + n_points, keypoints.end(), KeypointResponseGreater());
//this is the boundary response, and in the case of FAST may be ambigous
float ambiguous_response = keypoints[n_points - 1].response;
//use std::partition to grab all of the keypoints with the boundary response.
vector<KeyPoint>::const_iterator new_end =
std::partition(keypoints.begin() + n_points, keypoints.end(),
KeypointResponseGreaterThanThreshold(ambiguous_response));
//resize the keypoints, given this new end point. nth_element and partition reordered the points inplace
keypoints.resize(new_end - keypoints.begin());
}
}
struct RoiPredicate
{
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -440,7 +440,7 @@ protected:
fs.open( string(ts->get_data_path()) + FEATURES2D_DIR + "/keypoints.xml.gz", FileStorage::WRITE );
if( fs.isOpened() )
{
SurfFeatureDetector fd;
ORB fd;
fd.detect(img, keypoints);
write( fs, "keypoints", keypoints );
}
......@@ -491,7 +491,7 @@ private:
CV_DescriptorExtractorTest& operator=(const CV_DescriptorExtractorTest&) { return *this; }
};
template<typename T, typename Distance>
/*template<typename T, typename Distance>
class CV_CalonderDescriptorExtractorTest : public CV_DescriptorExtractorTest<Distance>
{
public:
......@@ -506,7 +506,7 @@ protected:
new CalonderDescriptorExtractor<T>( string(CV_DescriptorExtractorTest<Distance>::ts->get_data_path()) +
FEATURES2D_DIR + "/calonder_classifier.rtc");
}
};
};*/
/****************************************************************************************\
* Algorithmic tests for descriptor matchers *
......@@ -991,24 +991,12 @@ TEST( Features2d_Detector_MSER, regression )
test.safe_run();
}
TEST( Features2d_Detector_SIFT, regression )
{
CV_FeatureDetectorTest test( "detector-sift", FeatureDetector::create("SIFT") );
test.safe_run();
}
TEST( Features2d_Detector_STAR, regression )
{
CV_FeatureDetectorTest test( "detector-star", FeatureDetector::create("STAR") );
test.safe_run();
}
TEST( Features2d_Detector_SURF, regression )
{
CV_FeatureDetectorTest test( "detector-surf", FeatureDetector::create("SURF") );
test.safe_run();
}
TEST( Features2d_Detector_ORB, regression )
{
CV_FeatureDetectorTest test( "detector-orb", FeatureDetector::create("ORB") );
......@@ -1027,23 +1015,6 @@ TEST( Features2d_Detector_PyramidFAST, regression )
test.safe_run();
}
/*
* Descriptors
*/
TEST( Features2d_DescriptorExtractor_SIFT, regression )
{
CV_DescriptorExtractorTest<L2<float> > test( "descriptor-sift", 0.03f,
DescriptorExtractor::create("SIFT"), 8.06652f );
test.safe_run();
}
TEST( Features2d_DescriptorExtractor_SURF, regression )
{
CV_DescriptorExtractorTest<L2<float> > test( "descriptor-surf", 0.035f,
DescriptorExtractor::create("SURF"), 0.147372f );
test.safe_run();
}
TEST( Features2d_DescriptorExtractor_ORB, regression )
{
// TODO adjust the parameters below
......@@ -1066,13 +1037,6 @@ TEST( Features2d_DescriptorExtractor_BRIEF, regression )
test.safe_run();
}*/
TEST( Features2d_DescriptorExtractor_OpponentSURF, regression )
{
CV_DescriptorExtractorTest<L2<float> > test( "descriptor-opponent-surf", 0.18f,
DescriptorExtractor::create("OpponentSURF"), 0.147372f );
test.safe_run();
}
#if CV_SSE2
TEST( Features2d_DescriptorExtractor_Calonder_uchar, regression )
{
......@@ -1096,7 +1060,7 @@ TEST( Features2d_DescriptorExtractor_Calonder_float, regression )
*/
TEST( Features2d_DescriptorMatcher_BruteForce, regression )
{
CV_DescriptorMatcherTest test( "descriptor-matcher-brute-force", new BruteForceMatcher<L2<float> >, 0.01f );
CV_DescriptorMatcherTest test( "descriptor-matcher-brute-force", new BFMatcher(NORM_L2), 0.01f );
test.safe_run();
}
......
......@@ -155,27 +155,24 @@ void CV_MserTest::run(int)
{
string image_path = string(ts->get_data_path()) + "mser/puzzle.png";
IplImage* img = cvLoadImage( image_path.c_str());
if (!img)
Mat img = imread( image_path );
if (img.empty())
{
ts->printf( cvtest::TS::LOG, "Unable to open image mser/puzzle.png\n");
ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA);
return;
}
CvSeq* contours;
CvMemStorage* storage= cvCreateMemStorage();
IplImage* hsv = cvCreateImage( cvGetSize( img ), IPL_DEPTH_8U, 3 );
cvCvtColor( img, hsv, CV_BGR2YCrCb );
CvMSERParams params = cvMSERParams();//cvMSERParams( 5, 60, cvRound(.2*img->width*img->height), .25, .2 );
cvExtractMSER( hsv, NULL, &contours, storage, params );
Mat yuv;
cvtColor(img, yuv, COLOR_BGR2YCrCb);
vector<vector<Point> > msers;
MSER()(yuv, msers);
vector<CvBox2D> boxes;
vector<CvBox2D> boxes_orig;
for ( int i = 0; i < contours->total; i++ )
for ( size_t i = 0; i < msers.size(); i++ )
{
CvContour* r = *(CvContour**)cvGetSeqElem( contours, i );
CvBox2D box = cvFitEllipse2( r );
RotatedRect box = fitEllipse(msers[i]);
box.angle=(float)CV_PI/2-box.angle;
boxes.push_back(box);
}
......@@ -203,10 +200,6 @@ void CV_MserTest::run(int)
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
ts->printf( cvtest::TS::LOG, "Incorrect correspondence in box %d\n",n_box);
}
cvReleaseMemStorage(&storage);
cvReleaseImage(&hsv);
cvReleaseImage(&img);
}
TEST(Features2d_MSER, regression) { CV_MserTest test; test.safe_run(); }
......
......@@ -1511,7 +1511,7 @@ private:
////////////////////////////////// SURF //////////////////////////////////////////
class CV_EXPORTS SURF_GPU : public CvSURFParams
class CV_EXPORTS SURF_GPU
{
public:
enum KeypointLayout
......@@ -1566,6 +1566,14 @@ public:
void releaseMemory();
// SURF parameters;
int extended;
int upright;
double hessianThreshold;
int nOctaves;
int nOctaveLayers;
//! max keypoints = min(keypointsRatio * img.size().area(), 65535)
float keypointsRatio;
......@@ -1656,7 +1664,7 @@ public:
//! Constructor
//! n_features - the number of desired features
//! detector_params - parameters to use
explicit ORB_GPU(size_t n_features = 500, const ORB::CommonParams& detector_params = ORB::CommonParams());
explicit ORB_GPU(size_t n_features = 500, float scaleFactor = 1.2f, int nlevels = 3);
//! Compute the ORB features on an image
//! image - the image to compute the features (supports only CV_8UC1 images)
......@@ -1682,7 +1690,7 @@ public:
//! returns the descriptor size in bytes
inline int descriptorSize() const { return kBytes; }
void setParams(size_t n_features, const ORB::CommonParams& detector_params);
void setParams(size_t n_features, float scaleFactor, int nlevels);
inline void setFastParams(int threshold, bool nonmaxSupression = true)
{
fastDetector_.threshold = threshold;
......@@ -1706,7 +1714,7 @@ private:
void mergeKeyPoints(GpuMat& keypoints);
ORB::CommonParams params_;
ORB params_;
// The number of desired features per scale
std::vector<size_t> n_features_per_level_;
......
This diff is collapsed.
......@@ -345,7 +345,7 @@ void prefix##remove_at_##type(_CVLIST* l, CVPOS pos)\
void prefix##set_##type(CVPOS pos, type* data)\
{\
ELEMENT_##type* element = ((ELEMENT_##type*)(pos.m_pos));\
memcpy(&(element->m_data), data, sizeof(data));\
memcpy(&(element->m_data), data, sizeof(*data));\
}\
type* prefix##get_##type(CVPOS pos)\
{\
......
This diff is collapsed.
This diff is collapsed.
#include "test_precomp.hpp"
CV_TEST_MAIN("cv")
#include "test_precomp.hpp"
This diff is collapsed.
set(the_description "Functionality with possible limitations on the use")
ocv_define_module(nonfree opencv_imgproc opencv_features2d)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#include "perf_precomp.hpp"
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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