Merge pull request #3339 from vpisarev:refactor_features2d_take4
This commit is contained in:
commit
22ff1e8826
@ -16,25 +16,16 @@ The goal of this tutorial is to learn how to use *features2d* and *calib3d* modu
|
|||||||
Mat img2 = imread(argv[2], IMREAD_GRAYSCALE);
|
Mat img2 = imread(argv[2], IMREAD_GRAYSCALE);
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Detect keypoints in both images. ::
|
Detect keypoints in both images and compute descriptors for each of the keypoints. ::
|
||||||
|
|
||||||
// detecting keypoints
|
// detecting keypoints
|
||||||
FastFeatureDetector detector(15);
|
Ptr<Feature2D> surf = SURF::create();
|
||||||
vector<KeyPoint> keypoints1;
|
vector<KeyPoint> keypoints1;
|
||||||
detector.detect(img1, keypoints1);
|
Mat descriptors1;
|
||||||
|
surf->detectAndCompute(img1, Mat(), keypoints1, descriptors1);
|
||||||
|
|
||||||
... // do the same for the second image
|
... // do the same for the second image
|
||||||
|
|
||||||
#.
|
|
||||||
Compute descriptors for each of the keypoints. ::
|
|
||||||
|
|
||||||
// computing descriptors
|
|
||||||
SurfDescriptorExtractor extractor;
|
|
||||||
Mat descriptors1;
|
|
||||||
extractor.compute(img1, keypoints1, descriptors1);
|
|
||||||
|
|
||||||
... // process keypoints from the second image as well
|
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Now, find the closest matches between descriptors from the first image to the second: ::
|
Now, find the closest matches between descriptors from the first image to the second: ::
|
||||||
|
|
||||||
|
@ -65,18 +65,18 @@ Let us break the code down. ::
|
|||||||
We load two images and check if they are loaded correctly.::
|
We load two images and check if they are loaded correctly.::
|
||||||
|
|
||||||
// detecting keypoints
|
// detecting keypoints
|
||||||
FastFeatureDetector detector(15);
|
Ptr<FeatureDetector> detector = FastFeatureDetector::create(15);
|
||||||
vector<KeyPoint> keypoints1, keypoints2;
|
vector<KeyPoint> keypoints1, keypoints2;
|
||||||
detector.detect(img1, keypoints1);
|
detector->detect(img1, keypoints1);
|
||||||
detector.detect(img2, keypoints2);
|
detector->detect(img2, keypoints2);
|
||||||
|
|
||||||
First, we create an instance of a keypoint detector. All detectors inherit the abstract ``FeatureDetector`` interface, but the constructors are algorithm-dependent. The first argument to each detector usually controls the balance between the amount of keypoints and their stability. The range of values is different for different detectors (For instance, *FAST* threshold has the meaning of pixel intensity difference and usually varies in the region *[0,40]*. *SURF* threshold is applied to a Hessian of an image and usually takes on values larger than *100*), so use defaults in case of doubt. ::
|
First, we create an instance of a keypoint detector. All detectors inherit the abstract ``FeatureDetector`` interface, but the constructors are algorithm-dependent. The first argument to each detector usually controls the balance between the amount of keypoints and their stability. The range of values is different for different detectors (For instance, *FAST* threshold has the meaning of pixel intensity difference and usually varies in the region *[0,40]*. *SURF* threshold is applied to a Hessian of an image and usually takes on values larger than *100*), so use defaults in case of doubt. ::
|
||||||
|
|
||||||
// computing descriptors
|
// computing descriptors
|
||||||
SurfDescriptorExtractor extractor;
|
Ptr<SURF> extractor = SURF::create();
|
||||||
Mat descriptors1, descriptors2;
|
Mat descriptors1, descriptors2;
|
||||||
extractor.compute(img1, keypoints1, descriptors1);
|
extractor->compute(img1, keypoints1, descriptors1);
|
||||||
extractor.compute(img2, keypoints2, descriptors2);
|
extractor->compute(img2, keypoints2, descriptors2);
|
||||||
|
|
||||||
We create an instance of descriptor extractor. The most of OpenCV descriptors inherit ``DescriptorExtractor`` abstract interface. Then we compute descriptors for each of the keypoints. The output ``Mat`` of the ``DescriptorExtractor::compute`` method contains a descriptor in a row *i* for each *i*-th keypoint. Note that the method can modify the keypoints vector by removing the keypoints such that a descriptor for them is not defined (usually these are the keypoints near image border). The method makes sure that the ouptut keypoints and descriptors are consistent with each other (so that the number of keypoints is equal to the descriptors row count). ::
|
We create an instance of descriptor extractor. The most of OpenCV descriptors inherit ``DescriptorExtractor`` abstract interface. Then we compute descriptors for each of the keypoints. The output ``Mat`` of the ``DescriptorExtractor::compute`` method contains a descriptor in a row *i* for each *i*-th keypoint. Note that the method can modify the keypoints vector by removing the keypoints such that a descriptor for them is not defined (usually these are the keypoints near image border). The method makes sure that the ouptut keypoints and descriptors are consistent with each other (so that the number of keypoints is equal to the descriptors row count). ::
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ CV_EXPORTS_W void drawChessboardCorners( InputOutputArray image, Size patternSiz
|
|||||||
//! finds circles' grid pattern of the specified size in the image
|
//! finds circles' grid pattern of the specified size in the image
|
||||||
CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize,
|
CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize,
|
||||||
OutputArray centers, int flags = CALIB_CB_SYMMETRIC_GRID,
|
OutputArray centers, int flags = CALIB_CB_SYMMETRIC_GRID,
|
||||||
const Ptr<FeatureDetector> &blobDetector = makePtr<SimpleBlobDetector>());
|
const Ptr<FeatureDetector> &blobDetector = SimpleBlobDetector::create());
|
||||||
|
|
||||||
//! finds intrinsic and extrinsic camera parameters from several fews of a known calibration pattern.
|
//! finds intrinsic and extrinsic camera parameters from several fews of a known calibration pattern.
|
||||||
CV_EXPORTS_W double calibrateCamera( InputArrayOfArrays objectPoints,
|
CV_EXPORTS_W double calibrateCamera( InputArrayOfArrays objectPoints,
|
||||||
|
@ -115,6 +115,9 @@ bool cv::solvePnP( InputArray _opoints, InputArray _ipoints,
|
|||||||
cv::Mat R, rvec = _rvec.getMat(), tvec = _tvec.getMat();
|
cv::Mat R, rvec = _rvec.getMat(), tvec = _tvec.getMat();
|
||||||
double f = PnP.compute_pose(R, tvec);
|
double f = PnP.compute_pose(R, tvec);
|
||||||
cv::Rodrigues(R, rvec);
|
cv::Rodrigues(R, rvec);
|
||||||
|
if(cameraMatrix.type() == CV_32F)
|
||||||
|
cameraMatrix.at<float>(0,0) = cameraMatrix.at<float>(1,1) = (float)f;
|
||||||
|
else
|
||||||
cameraMatrix.at<double>(0,0) = cameraMatrix.at<double>(1,1) = f;
|
cameraMatrix.at<double>(0,0) = cameraMatrix.at<double>(1,1) = f;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -73,12 +73,12 @@ private:
|
|||||||
{
|
{
|
||||||
for(int i = 0; i < number_of_correspondences; i++)
|
for(int i = 0; i < number_of_correspondences; i++)
|
||||||
{
|
{
|
||||||
pws[3 * i ] = opoints.at<OpointType>(0,i).x;
|
pws[3 * i ] = opoints.at<OpointType>(i).x;
|
||||||
pws[3 * i + 1] = opoints.at<OpointType>(0,i).y;
|
pws[3 * i + 1] = opoints.at<OpointType>(i).y;
|
||||||
pws[3 * i + 2] = opoints.at<OpointType>(0,i).z;
|
pws[3 * i + 2] = opoints.at<OpointType>(i).z;
|
||||||
|
|
||||||
us[2 * i ] = ipoints.at<IpointType>(0,i).x;
|
us[2 * i ] = ipoints.at<IpointType>(i).x;
|
||||||
us[2 * i + 1] = ipoints.at<IpointType>(0,i).y;
|
us[2 * i + 1] = ipoints.at<IpointType>(i).y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -874,6 +874,9 @@ public:
|
|||||||
virtual ~Algorithm();
|
virtual ~Algorithm();
|
||||||
String name() const;
|
String name() const;
|
||||||
|
|
||||||
|
virtual void set(int, double);
|
||||||
|
virtual double get(int) const;
|
||||||
|
|
||||||
template<typename _Tp> typename ParamType<_Tp>::member_type get(const String& name) const;
|
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> typename ParamType<_Tp>::member_type get(const char* name) const;
|
||||||
|
|
||||||
|
@ -179,6 +179,9 @@ String Algorithm::name() const
|
|||||||
return info()->name();
|
return info()->name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Algorithm::set(int, double) {}
|
||||||
|
double Algorithm::get(int) const { return 0.; }
|
||||||
|
|
||||||
void Algorithm::set(const String& parameter, int value)
|
void Algorithm::set(const String& parameter, int value)
|
||||||
{
|
{
|
||||||
info()->set(this, parameter.c_str(), ParamType<int>::type, &value);
|
info()->set(this, parameter.c_str(), ParamType<int>::type, &value);
|
||||||
|
@ -59,100 +59,60 @@ Detects keypoints in an image (first variant) or image set (second variant).
|
|||||||
|
|
||||||
:param masks: Masks for each input image specifying where to look for keypoints (optional). ``masks[i]`` is a mask for ``images[i]``.
|
:param masks: Masks for each input image specifying where to look for keypoints (optional). ``masks[i]`` is a mask for ``images[i]``.
|
||||||
|
|
||||||
FeatureDetector::create
|
|
||||||
-----------------------
|
|
||||||
Creates a feature detector by its name.
|
|
||||||
|
|
||||||
.. ocv:function:: Ptr<FeatureDetector> FeatureDetector::create( const String& detectorType )
|
|
||||||
|
|
||||||
.. ocv:pyfunction:: cv2.FeatureDetector_create(detectorType) -> retval
|
|
||||||
|
|
||||||
:param detectorType: Feature detector type.
|
|
||||||
|
|
||||||
The following detector types are supported:
|
|
||||||
|
|
||||||
* ``"FAST"`` -- :ocv:class:`FastFeatureDetector`
|
|
||||||
* ``"ORB"`` -- :ocv:class:`ORB`
|
|
||||||
* ``"BRISK"`` -- :ocv:class:`BRISK`
|
|
||||||
* ``"MSER"`` -- :ocv:class:`MSER`
|
|
||||||
* ``"GFTT"`` -- :ocv:class:`GoodFeaturesToTrackDetector`
|
|
||||||
* ``"HARRIS"`` -- :ocv:class:`GoodFeaturesToTrackDetector` with Harris detector enabled
|
|
||||||
* ``"SimpleBlob"`` -- :ocv:class:`SimpleBlobDetector`
|
|
||||||
|
|
||||||
FastFeatureDetector
|
FastFeatureDetector
|
||||||
-------------------
|
-------------------
|
||||||
.. ocv:class:: FastFeatureDetector : public FeatureDetector
|
.. ocv:class:: FastFeatureDetector : public Feature2D
|
||||||
|
|
||||||
Wrapping class for feature detection using the
|
Wrapping class for feature detection using the
|
||||||
:ocv:func:`FAST` method. ::
|
:ocv:func:`FAST` method. ::
|
||||||
|
|
||||||
class FastFeatureDetector : public FeatureDetector
|
class FastFeatureDetector : public Feature2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FastFeatureDetector( int threshold=1, bool nonmaxSuppression=true, type=FastFeatureDetector::TYPE_9_16 );
|
static Ptr<FastFeatureDetector> create( int threshold=1, bool nonmaxSuppression=true, type=FastFeatureDetector::TYPE_9_16 );
|
||||||
virtual void read( const FileNode& fn );
|
|
||||||
virtual void write( FileStorage& fs ) const;
|
|
||||||
protected:
|
|
||||||
...
|
|
||||||
};
|
};
|
||||||
|
|
||||||
GoodFeaturesToTrackDetector
|
GFTTDetector
|
||||||
---------------------------
|
---------------------------
|
||||||
.. ocv:class:: GoodFeaturesToTrackDetector : public FeatureDetector
|
.. ocv:class:: GFTTDetector : public FeatureDetector
|
||||||
|
|
||||||
Wrapping class for feature detection using the
|
Wrapping class for feature detection using the
|
||||||
:ocv:func:`goodFeaturesToTrack` function. ::
|
:ocv:func:`goodFeaturesToTrack` function. ::
|
||||||
|
|
||||||
class GoodFeaturesToTrackDetector : public FeatureDetector
|
class GFTTDetector : public Feature2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
class Params
|
enum { USE_HARRIS_DETECTOR=10000 };
|
||||||
{
|
static Ptr<GFTTDetector> create( int maxCorners=1000, double qualityLevel=0.01,
|
||||||
public:
|
double minDistance=1, int blockSize=3,
|
||||||
Params( int maxCorners=1000, double qualityLevel=0.01,
|
|
||||||
double minDistance=1., int blockSize=3,
|
|
||||||
bool useHarrisDetector=false, double k=0.04 );
|
bool useHarrisDetector=false, double k=0.04 );
|
||||||
void read( const FileNode& fn );
|
|
||||||
void write( FileStorage& fs ) const;
|
|
||||||
|
|
||||||
int maxCorners;
|
|
||||||
double qualityLevel;
|
|
||||||
double minDistance;
|
|
||||||
int blockSize;
|
|
||||||
bool useHarrisDetector;
|
|
||||||
double k;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
GoodFeaturesToTrackDetector( const GoodFeaturesToTrackDetector::Params& params=
|
MSER
|
||||||
GoodFeaturesToTrackDetector::Params() );
|
|
||||||
GoodFeaturesToTrackDetector( int maxCorners, double qualityLevel,
|
|
||||||
double minDistance, int blockSize=3,
|
|
||||||
bool useHarrisDetector=false, double k=0.04 );
|
|
||||||
virtual void read( const FileNode& fn );
|
|
||||||
virtual void write( FileStorage& fs ) const;
|
|
||||||
protected:
|
|
||||||
...
|
|
||||||
};
|
|
||||||
|
|
||||||
MserFeatureDetector
|
|
||||||
-------------------
|
-------------------
|
||||||
.. ocv:class:: MserFeatureDetector : public FeatureDetector
|
.. ocv:class:: MSER : public Feature2D
|
||||||
|
|
||||||
Wrapping class for feature detection using the
|
Maximally stable region detector ::
|
||||||
:ocv:class:`MSER` class. ::
|
|
||||||
|
|
||||||
class MserFeatureDetector : public FeatureDetector
|
class MSER : public Feature2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MserFeatureDetector( CvMSERParams params=cvMSERParams() );
|
enum
|
||||||
MserFeatureDetector( int delta, int minArea, int maxArea,
|
{
|
||||||
double maxVariation, double minDiversity,
|
DELTA=10000, MIN_AREA=10001, MAX_AREA=10002, PASS2_ONLY=10003,
|
||||||
int maxEvolution, double areaThreshold,
|
MAX_EVOLUTION=10004, AREA_THRESHOLD=10005,
|
||||||
double minMargin, int edgeBlurSize );
|
MIN_MARGIN=10006, EDGE_BLUR_SIZE=10007
|
||||||
virtual void read( const FileNode& fn );
|
};
|
||||||
virtual void write( FileStorage& fs ) const;
|
|
||||||
protected:
|
//! the full constructor
|
||||||
...
|
static Ptr<MSER> create( int _delta=5, int _min_area=60, int _max_area=14400,
|
||||||
|
double _max_variation=0.25, double _min_diversity=.2,
|
||||||
|
int _max_evolution=200, double _area_threshold=1.01,
|
||||||
|
double _min_margin=0.003, int _edge_blur_size=5 );
|
||||||
|
|
||||||
|
virtual void detectRegions( InputArray image,
|
||||||
|
std::vector<std::vector<Point> >& msers,
|
||||||
|
std::vector<Rect>& bboxes ) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
SimpleBlobDetector
|
SimpleBlobDetector
|
||||||
@ -189,10 +149,8 @@ Class for extracting blobs from an image. ::
|
|||||||
float minConvexity, maxConvexity;
|
float minConvexity, maxConvexity;
|
||||||
};
|
};
|
||||||
|
|
||||||
SimpleBlobDetector(const SimpleBlobDetector::Params ¶meters = SimpleBlobDetector::Params());
|
static Ptr<SimpleBlobDetector> create(const SimpleBlobDetector::Params
|
||||||
|
¶meters = SimpleBlobDetector::Params());
|
||||||
protected:
|
|
||||||
...
|
|
||||||
};
|
};
|
||||||
|
|
||||||
The class implements a simple algorithm for extracting blobs from an image:
|
The class implements a simple algorithm for extracting blobs from an image:
|
||||||
|
@ -14,11 +14,6 @@ Detects corners using the FAST algorithm
|
|||||||
.. ocv:function:: void FAST( InputArray image, vector<KeyPoint>& keypoints, int threshold, bool nonmaxSuppression=true )
|
.. ocv:function:: void FAST( InputArray image, vector<KeyPoint>& keypoints, int threshold, bool nonmaxSuppression=true )
|
||||||
.. ocv:function:: void FAST( InputArray image, vector<KeyPoint>& keypoints, int threshold, bool nonmaxSuppression, int type )
|
.. ocv:function:: void FAST( InputArray image, vector<KeyPoint>& keypoints, int threshold, bool nonmaxSuppression, int type )
|
||||||
|
|
||||||
.. ocv:pyfunction:: cv2.FastFeatureDetector([, threshold[, nonmaxSuppression]]) -> <FastFeatureDetector object>
|
|
||||||
.. ocv:pyfunction:: cv2.FastFeatureDetector(threshold, nonmaxSuppression, type) -> <FastFeatureDetector object>
|
|
||||||
.. ocv:pyfunction:: cv2.FastFeatureDetector.detect(image[, mask]) -> keypoints
|
|
||||||
|
|
||||||
|
|
||||||
:param image: grayscale image where keypoints (corners) are detected.
|
:param image: grayscale image where keypoints (corners) are detected.
|
||||||
|
|
||||||
:param keypoints: keypoints detected on the image.
|
:param keypoints: keypoints detected on the image.
|
||||||
@ -55,7 +50,7 @@ Maximally stable extremal region extractor. ::
|
|||||||
// runs the extractor on the specified image; returns the MSERs,
|
// runs the extractor on the specified image; returns the MSERs,
|
||||||
// each encoded as a contour (vector<Point>, see findContours)
|
// each encoded as a contour (vector<Point>, see findContours)
|
||||||
// the optional mask marks the area where MSERs are searched for
|
// the optional mask marks the area where MSERs are searched for
|
||||||
void operator()( const Mat& image, vector<vector<Point> >& msers, const Mat& mask ) const;
|
void detectRegions( InputArray image, vector<vector<Point> >& msers, vector<Rect>& bboxes ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
The class encapsulates all the parameters of the MSER extraction algorithm (see
|
The class encapsulates all the parameters of the MSER extraction algorithm (see
|
||||||
|
@ -49,8 +49,6 @@
|
|||||||
namespace cv
|
namespace cv
|
||||||
{
|
{
|
||||||
|
|
||||||
CV_EXPORTS bool initModule_features2d(void);
|
|
||||||
|
|
||||||
// //! writes vector of keypoints to the file storage
|
// //! writes vector of keypoints to the file storage
|
||||||
// CV_EXPORTS void write(FileStorage& fs, const String& name, const std::vector<KeyPoint>& keypoints);
|
// CV_EXPORTS void write(FileStorage& fs, const String& name, const std::vector<KeyPoint>& keypoints);
|
||||||
// //! reads vector of keypoints from the specified file storage node
|
// //! reads vector of keypoints from the specified file storage node
|
||||||
@ -94,12 +92,12 @@ public:
|
|||||||
/************************************ Base Classes ************************************/
|
/************************************ Base Classes ************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Abstract base class for 2D image feature detectors.
|
* Abstract base class for 2D image feature detectors and descriptor extractors
|
||||||
*/
|
*/
|
||||||
class CV_EXPORTS_W FeatureDetector : public virtual Algorithm
|
class CV_EXPORTS_W Feature2D : public virtual Algorithm
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~FeatureDetector();
|
virtual ~Feature2D();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Detect keypoints in an image.
|
* Detect keypoints in an image.
|
||||||
@ -108,47 +106,13 @@ public:
|
|||||||
* mask Mask specifying where to look for keypoints (optional). Must be a char
|
* mask Mask specifying where to look for keypoints (optional). Must be a char
|
||||||
* matrix with non-zero values in the region of interest.
|
* matrix with non-zero values in the region of interest.
|
||||||
*/
|
*/
|
||||||
CV_WRAP void detect( InputArray image, CV_OUT std::vector<KeyPoint>& keypoints, InputArray mask=noArray() ) const;
|
CV_WRAP virtual void detect( InputArray image,
|
||||||
|
CV_OUT std::vector<KeyPoint>& keypoints,
|
||||||
|
InputArray mask=noArray() );
|
||||||
|
|
||||||
/*
|
virtual void detect( InputArrayOfArrays images,
|
||||||
* Detect keypoints in an image set.
|
std::vector<std::vector<KeyPoint> >& keypoints,
|
||||||
* images Image collection.
|
InputArrayOfArrays masks=noArray() );
|
||||||
* keypoints Collection of keypoints detected in an input images. keypoints[i] is a set of keypoints detected in an images[i].
|
|
||||||
* masks Masks for image set. masks[i] is a mask for images[i].
|
|
||||||
*/
|
|
||||||
void detect( InputArrayOfArrays images, std::vector<std::vector<KeyPoint> >& keypoints, InputArrayOfArrays masks=noArray() ) const;
|
|
||||||
|
|
||||||
// Return true if detector object is empty
|
|
||||||
CV_WRAP virtual bool empty() const;
|
|
||||||
|
|
||||||
// Create feature detector by detector name.
|
|
||||||
CV_WRAP static Ptr<FeatureDetector> create( const String& detectorType );
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void detectImpl( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask=noArray() ) const = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove keypoints that are not in the mask.
|
|
||||||
* Helper function, useful when wrapping a library call for keypoint detection that
|
|
||||||
* does not support a mask argument.
|
|
||||||
*/
|
|
||||||
static void removeInvalidPoints( const Mat & mask, std::vector<KeyPoint>& keypoints );
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Abstract base class for computing descriptors for image keypoints.
|
|
||||||
*
|
|
||||||
* In this interface we assume a keypoint descriptor can be represented as a
|
|
||||||
* dense, fixed-dimensional vector of some basic type. Most descriptors used
|
|
||||||
* in practice follow this pattern, as it makes it very easy to compute
|
|
||||||
* distances between descriptors. Therefore we represent a collection of
|
|
||||||
* descriptors as a Mat, where each row is one keypoint descriptor.
|
|
||||||
*/
|
|
||||||
class CV_EXPORTS_W DescriptorExtractor : public virtual Algorithm
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~DescriptorExtractor();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute the descriptors for a set of keypoints in an image.
|
* Compute the descriptors for a set of keypoints in an image.
|
||||||
@ -156,157 +120,43 @@ public:
|
|||||||
* keypoints The input keypoints. Keypoints for which a descriptor cannot be computed are removed.
|
* keypoints The input keypoints. Keypoints for which a descriptor cannot be computed are removed.
|
||||||
* descriptors Copmputed descriptors. Row i is the descriptor for keypoint i.
|
* descriptors Copmputed descriptors. Row i is the descriptor for keypoint i.
|
||||||
*/
|
*/
|
||||||
CV_WRAP void compute( InputArray image, CV_OUT CV_IN_OUT std::vector<KeyPoint>& keypoints, OutputArray descriptors ) const;
|
CV_WRAP virtual void compute( InputArray image,
|
||||||
|
CV_OUT CV_IN_OUT std::vector<KeyPoint>& keypoints,
|
||||||
|
OutputArray descriptors );
|
||||||
|
|
||||||
/*
|
virtual void compute( InputArrayOfArrays images,
|
||||||
* Compute the descriptors for a keypoints collection detected in image collection.
|
std::vector<std::vector<KeyPoint> >& keypoints,
|
||||||
* images Image collection.
|
OutputArrayOfArrays descriptors );
|
||||||
* keypoints Input keypoints collection. keypoints[i] is keypoints detected in images[i].
|
|
||||||
* Keypoints for which a descriptor cannot be computed are removed.
|
|
||||||
* descriptors Descriptor collection. descriptors[i] are descriptors computed for set keypoints[i].
|
|
||||||
*/
|
|
||||||
void compute( InputArrayOfArrays images, std::vector<std::vector<KeyPoint> >& keypoints, OutputArrayOfArrays descriptors ) const;
|
|
||||||
|
|
||||||
CV_WRAP virtual int descriptorSize() const = 0;
|
/* Detects keypoints and computes the descriptors */
|
||||||
CV_WRAP virtual int descriptorType() const = 0;
|
CV_WRAP virtual void detectAndCompute( InputArray image, InputArray mask,
|
||||||
CV_WRAP virtual int defaultNorm() const = 0;
|
|
||||||
|
|
||||||
CV_WRAP virtual bool empty() const;
|
|
||||||
|
|
||||||
CV_WRAP static Ptr<DescriptorExtractor> create( const String& descriptorExtractorType );
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void computeImpl( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors ) const = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove keypoints within borderPixels of an image edge.
|
|
||||||
*/
|
|
||||||
static void removeBorderKeypoints( std::vector<KeyPoint>& keypoints,
|
|
||||||
Size imageSize, int borderSize );
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Abstract base class for simultaneous 2D feature detection descriptor extraction.
|
|
||||||
*/
|
|
||||||
class CV_EXPORTS_W Feature2D : public FeatureDetector, public DescriptorExtractor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/*
|
|
||||||
* Detect keypoints in an image.
|
|
||||||
* image The image.
|
|
||||||
* keypoints The detected keypoints.
|
|
||||||
* mask Mask specifying where to look for keypoints (optional). Must be a char
|
|
||||||
* matrix with non-zero values in the region of interest.
|
|
||||||
* useProvidedKeypoints If true, the method will skip the detection phase and will compute
|
|
||||||
* descriptors for the provided keypoints
|
|
||||||
*/
|
|
||||||
CV_WRAP_AS(detectAndCompute) virtual void operator()( InputArray image, InputArray mask,
|
|
||||||
CV_OUT std::vector<KeyPoint>& keypoints,
|
CV_OUT std::vector<KeyPoint>& keypoints,
|
||||||
OutputArray descriptors,
|
OutputArray descriptors,
|
||||||
bool useProvidedKeypoints=false ) const = 0;
|
bool useProvidedKeypoints=false );
|
||||||
|
|
||||||
CV_WRAP void compute( InputArray image, CV_OUT CV_IN_OUT std::vector<KeyPoint>& keypoints, OutputArray descriptors ) const;
|
CV_WRAP virtual int descriptorSize() const;
|
||||||
|
CV_WRAP virtual int descriptorType() const;
|
||||||
|
CV_WRAP virtual int defaultNorm() const;
|
||||||
|
|
||||||
// Create feature detector and descriptor extractor by name.
|
// Return true if detector object is empty
|
||||||
CV_WRAP static Ptr<Feature2D> create( const String& name );
|
CV_WRAP virtual bool empty() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef Feature2D FeatureDetector;
|
||||||
|
typedef Feature2D DescriptorExtractor;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
BRISK implementation
|
BRISK implementation
|
||||||
*/
|
*/
|
||||||
class CV_EXPORTS_W BRISK : public Feature2D
|
class CV_EXPORTS_W BRISK : public Feature2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CV_WRAP explicit BRISK(int thresh=30, int octaves=3, float patternScale=1.0f);
|
CV_WRAP static Ptr<BRISK> create(int thresh=30, int octaves=3, float patternScale=1.0f);
|
||||||
|
|
||||||
virtual ~BRISK();
|
|
||||||
|
|
||||||
// returns the descriptor size in bytes
|
|
||||||
int descriptorSize() const;
|
|
||||||
// returns the descriptor type
|
|
||||||
int descriptorType() const;
|
|
||||||
// returns the default norm type
|
|
||||||
int defaultNorm() const;
|
|
||||||
|
|
||||||
// Compute the BRISK features on an image
|
|
||||||
void operator()(InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints) const;
|
|
||||||
|
|
||||||
// Compute the BRISK features and descriptors on an image
|
|
||||||
void operator()( InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints,
|
|
||||||
OutputArray descriptors, bool useProvidedKeypoints=false ) const;
|
|
||||||
|
|
||||||
AlgorithmInfo* info() const;
|
|
||||||
|
|
||||||
// custom setup
|
// custom setup
|
||||||
CV_WRAP explicit BRISK(std::vector<float> &radiusList, std::vector<int> &numberList,
|
CV_WRAP static Ptr<BRISK> create(const std::vector<float> &radiusList, const std::vector<int> &numberList,
|
||||||
float dMax=5.85f, float dMin=8.2f, std::vector<int> indexChange=std::vector<int>());
|
float dMax=5.85f, float dMin=8.2f, const std::vector<int>& indexChange=std::vector<int>());
|
||||||
|
|
||||||
// call this to generate the kernel:
|
|
||||||
// circle of radius r (pixels), with n points;
|
|
||||||
// short pairings with dMax, long pairings with dMin
|
|
||||||
CV_WRAP void generateKernel(std::vector<float> &radiusList,
|
|
||||||
std::vector<int> &numberList, float dMax=5.85f, float dMin=8.2f,
|
|
||||||
std::vector<int> indexChange=std::vector<int>());
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void computeImpl( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors ) const;
|
|
||||||
void detectImpl( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask=noArray() ) const;
|
|
||||||
|
|
||||||
void computeKeypointsNoOrientation(InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints) const;
|
|
||||||
void computeDescriptorsAndOrOrientation(InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints,
|
|
||||||
OutputArray descriptors, bool doDescriptors, bool doOrientation,
|
|
||||||
bool useProvidedKeypoints) const;
|
|
||||||
|
|
||||||
// Feature parameters
|
|
||||||
CV_PROP_RW int threshold;
|
|
||||||
CV_PROP_RW int octaves;
|
|
||||||
|
|
||||||
// some helper structures for the Brisk pattern representation
|
|
||||||
struct BriskPatternPoint{
|
|
||||||
float x; // x coordinate relative to center
|
|
||||||
float y; // x coordinate relative to center
|
|
||||||
float sigma; // Gaussian smoothing sigma
|
|
||||||
};
|
|
||||||
struct BriskShortPair{
|
|
||||||
unsigned int i; // index of the first pattern point
|
|
||||||
unsigned int j; // index of other pattern point
|
|
||||||
};
|
|
||||||
struct BriskLongPair{
|
|
||||||
unsigned int i; // index of the first pattern point
|
|
||||||
unsigned int j; // index of other pattern point
|
|
||||||
int weighted_dx; // 1024.0/dx
|
|
||||||
int weighted_dy; // 1024.0/dy
|
|
||||||
};
|
|
||||||
inline int smoothedIntensity(const cv::Mat& image,
|
|
||||||
const cv::Mat& integral,const float key_x,
|
|
||||||
const float key_y, const unsigned int scale,
|
|
||||||
const unsigned int rot, const unsigned int point) const;
|
|
||||||
// pattern properties
|
|
||||||
BriskPatternPoint* patternPoints_; //[i][rotation][scale]
|
|
||||||
unsigned int points_; // total number of collocation points
|
|
||||||
float* scaleList_; // lists the scaling per scale index [scale]
|
|
||||||
unsigned int* sizeList_; // lists the total pattern size per scale index [scale]
|
|
||||||
static const unsigned int scales_; // scales discretization
|
|
||||||
static const float scalerange_; // span of sizes 40->4 Octaves - else, this needs to be adjusted...
|
|
||||||
static const unsigned int n_rot_; // discretization of the rotation look-up
|
|
||||||
|
|
||||||
// pairs
|
|
||||||
int strings_; // number of uchars the descriptor consists of
|
|
||||||
float dMax_; // short pair maximum distance
|
|
||||||
float dMin_; // long pair maximum distance
|
|
||||||
BriskShortPair* shortPairs_; // d<_dMax
|
|
||||||
BriskLongPair* longPairs_; // d>_dMin
|
|
||||||
unsigned int noShortPairs_; // number of shortParis
|
|
||||||
unsigned int noLongPairs_; // number of longParis
|
|
||||||
|
|
||||||
// general
|
|
||||||
static const float basicSize_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
ORB implementation.
|
ORB implementation.
|
||||||
*/
|
*/
|
||||||
@ -314,46 +164,18 @@ class CV_EXPORTS_W ORB : public Feature2D
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// the size of the signature in bytes
|
// the size of the signature in bytes
|
||||||
enum { kBytes = 32, HARRIS_SCORE=0, FAST_SCORE=1 };
|
enum
|
||||||
|
{
|
||||||
|
kBytes = 32, HARRIS_SCORE=0, FAST_SCORE=1,
|
||||||
|
NFEATURES=10000, SCALE_FACTOR=10001, NLEVELS=10002,
|
||||||
|
EDGE_THRESHOLD=10003, FIRST_LEVEL=10004, WTA_K=10005,
|
||||||
|
SCORE_TYPE=10006, PATCH_SIZE=10007, FAST_THRESHOLD=10008
|
||||||
|
};
|
||||||
|
|
||||||
CV_WRAP explicit ORB(int nfeatures = 500, float scaleFactor = 1.2f, int nlevels = 8, int edgeThreshold = 31,
|
CV_WRAP static Ptr<ORB> create(int nfeatures = 500, float scaleFactor = 1.2f, int nlevels = 8, int edgeThreshold = 31,
|
||||||
int firstLevel = 0, int WTA_K=2, int scoreType=ORB::HARRIS_SCORE, int patchSize=31, int fastThreshold = 20);
|
int firstLevel = 0, int WTA_K=2, int scoreType=ORB::HARRIS_SCORE, int patchSize=31, int fastThreshold = 20);
|
||||||
|
|
||||||
// returns the descriptor size in bytes
|
|
||||||
int descriptorSize() const;
|
|
||||||
// returns the descriptor type
|
|
||||||
int descriptorType() const;
|
|
||||||
// returns the default norm type
|
|
||||||
int defaultNorm() const;
|
|
||||||
|
|
||||||
// Compute the ORB features and descriptors on an image
|
|
||||||
void operator()(InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints) const;
|
|
||||||
|
|
||||||
// Compute the ORB features and descriptors on an image
|
|
||||||
void operator()( InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints,
|
|
||||||
OutputArray descriptors, bool useProvidedKeypoints=false ) const;
|
|
||||||
|
|
||||||
AlgorithmInfo* info() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void computeImpl( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors ) const;
|
|
||||||
void detectImpl( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask=noArray() ) const;
|
|
||||||
|
|
||||||
CV_PROP_RW int nfeatures;
|
|
||||||
CV_PROP_RW double scaleFactor;
|
|
||||||
CV_PROP_RW int nlevels;
|
|
||||||
CV_PROP_RW int edgeThreshold;
|
|
||||||
CV_PROP_RW int firstLevel;
|
|
||||||
CV_PROP_RW int WTA_K;
|
|
||||||
CV_PROP_RW int scoreType;
|
|
||||||
CV_PROP_RW int patchSize;
|
|
||||||
CV_PROP_RW int fastThreshold;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef ORB OrbFeatureDetector;
|
|
||||||
typedef ORB OrbDescriptorExtractor;
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Maximal Stable Extremal Regions class.
|
Maximal Stable Extremal Regions class.
|
||||||
|
|
||||||
@ -363,36 +185,27 @@ typedef ORB OrbDescriptorExtractor;
|
|||||||
|
|
||||||
It returns the regions, each of those is encoded as a contour.
|
It returns the regions, each of those is encoded as a contour.
|
||||||
*/
|
*/
|
||||||
class CV_EXPORTS_W MSER : public FeatureDetector
|
class CV_EXPORTS_W MSER : public Feature2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DELTA=10000, MIN_AREA=10001, MAX_AREA=10002, PASS2_ONLY=10003,
|
||||||
|
MAX_EVOLUTION=10004, AREA_THRESHOLD=10005,
|
||||||
|
MIN_MARGIN=10006, EDGE_BLUR_SIZE=10007
|
||||||
|
};
|
||||||
|
|
||||||
//! the full constructor
|
//! the full constructor
|
||||||
CV_WRAP explicit MSER( int _delta=5, int _min_area=60, int _max_area=14400,
|
CV_WRAP static Ptr<MSER> create( int _delta=5, int _min_area=60, int _max_area=14400,
|
||||||
double _max_variation=0.25, double _min_diversity=.2,
|
double _max_variation=0.25, double _min_diversity=.2,
|
||||||
int _max_evolution=200, double _area_threshold=1.01,
|
int _max_evolution=200, double _area_threshold=1.01,
|
||||||
double _min_margin=0.003, int _edge_blur_size=5 );
|
double _min_margin=0.003, int _edge_blur_size=5 );
|
||||||
|
|
||||||
//! the operator that extracts the MSERs from the image or the specific part of it
|
CV_WRAP virtual void detectRegions( InputArray image,
|
||||||
CV_WRAP_AS(detect) void operator()( InputArray image, CV_OUT std::vector<std::vector<Point> >& msers,
|
std::vector<std::vector<Point> >& msers,
|
||||||
InputArray mask=noArray() ) const;
|
std::vector<Rect>& bboxes ) = 0;
|
||||||
AlgorithmInfo* info() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void detectImpl( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask=noArray() ) const;
|
|
||||||
|
|
||||||
int delta;
|
|
||||||
int minArea;
|
|
||||||
int maxArea;
|
|
||||||
double maxVariation;
|
|
||||||
double minDiversity;
|
|
||||||
int maxEvolution;
|
|
||||||
double areaThreshold;
|
|
||||||
double minMargin;
|
|
||||||
int edgeBlurSize;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef MSER MserFeatureDetector;
|
|
||||||
|
|
||||||
//! detects corners using FAST algorithm by E. Rosten
|
//! detects corners using FAST algorithm by E. Rosten
|
||||||
CV_EXPORTS void FAST( InputArray image, CV_OUT std::vector<KeyPoint>& keypoints,
|
CV_EXPORTS void FAST( InputArray image, CV_OUT std::vector<KeyPoint>& keypoints,
|
||||||
int threshold, bool nonmaxSuppression=true );
|
int threshold, bool nonmaxSuppression=true );
|
||||||
@ -400,48 +213,31 @@ CV_EXPORTS void FAST( InputArray image, CV_OUT std::vector<KeyPoint>& keypoints,
|
|||||||
CV_EXPORTS void FAST( InputArray image, CV_OUT std::vector<KeyPoint>& keypoints,
|
CV_EXPORTS void FAST( InputArray image, CV_OUT std::vector<KeyPoint>& keypoints,
|
||||||
int threshold, bool nonmaxSuppression, int type );
|
int threshold, bool nonmaxSuppression, int type );
|
||||||
|
|
||||||
class CV_EXPORTS_W FastFeatureDetector : public FeatureDetector
|
class CV_EXPORTS_W FastFeatureDetector : public Feature2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Type
|
enum
|
||||||
{
|
{
|
||||||
TYPE_5_8 = 0, TYPE_7_12 = 1, TYPE_9_16 = 2
|
TYPE_5_8 = 0, TYPE_7_12 = 1, TYPE_9_16 = 2,
|
||||||
|
THRESHOLD = 10000, NONMAX_SUPPRESSION=10001, FAST_N=10002,
|
||||||
};
|
};
|
||||||
|
|
||||||
CV_WRAP FastFeatureDetector( int threshold=10, bool nonmaxSuppression=true);
|
CV_WRAP static Ptr<FastFeatureDetector> create( int threshold=10,
|
||||||
CV_WRAP FastFeatureDetector( int threshold, bool nonmaxSuppression, int type);
|
bool nonmaxSuppression=true,
|
||||||
AlgorithmInfo* info() const;
|
int type=FastFeatureDetector::TYPE_9_16 );
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void detectImpl( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask=noArray() ) const;
|
|
||||||
|
|
||||||
int threshold;
|
|
||||||
bool nonmaxSuppression;
|
|
||||||
int type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class CV_EXPORTS_W GFTTDetector : public FeatureDetector
|
class CV_EXPORTS_W GFTTDetector : public Feature2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CV_WRAP GFTTDetector( int maxCorners=1000, double qualityLevel=0.01, double minDistance=1,
|
enum { USE_HARRIS_DETECTOR=10000 };
|
||||||
|
CV_WRAP static Ptr<GFTTDetector> create( int maxCorners=1000, double qualityLevel=0.01, double minDistance=1,
|
||||||
int blockSize=3, bool useHarrisDetector=false, double k=0.04 );
|
int blockSize=3, bool useHarrisDetector=false, double k=0.04 );
|
||||||
AlgorithmInfo* info() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void detectImpl( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask=noArray() ) const;
|
|
||||||
|
|
||||||
int nfeatures;
|
|
||||||
double qualityLevel;
|
|
||||||
double minDistance;
|
|
||||||
int blockSize;
|
|
||||||
bool useHarrisDetector;
|
|
||||||
double k;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef GFTTDetector GoodFeaturesToTrackDetector;
|
|
||||||
|
|
||||||
class CV_EXPORTS_W SimpleBlobDetector : public FeatureDetector
|
class CV_EXPORTS_W SimpleBlobDetector : public Feature2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct CV_EXPORTS_W_SIMPLE Params
|
struct CV_EXPORTS_W_SIMPLE Params
|
||||||
@ -472,81 +268,29 @@ public:
|
|||||||
void write( FileStorage& fs ) const;
|
void write( FileStorage& fs ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
CV_WRAP SimpleBlobDetector(const SimpleBlobDetector::Params ¶meters = SimpleBlobDetector::Params());
|
CV_WRAP static Ptr<SimpleBlobDetector>
|
||||||
|
create(const SimpleBlobDetector::Params ¶meters = SimpleBlobDetector::Params());
|
||||||
virtual void read( const FileNode& fn );
|
|
||||||
virtual void write( FileStorage& fs ) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
struct CV_EXPORTS Center
|
|
||||||
{
|
|
||||||
Point2d location;
|
|
||||||
double radius;
|
|
||||||
double confidence;
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual void detectImpl( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask=noArray() ) const;
|
|
||||||
virtual void findBlobs(InputArray image, InputArray binaryImage, std::vector<Center> ¢ers) const;
|
|
||||||
|
|
||||||
Params params;
|
|
||||||
AlgorithmInfo* info() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// KAZE/AKAZE diffusivity
|
|
||||||
enum {
|
|
||||||
DIFF_PM_G1 = 0,
|
|
||||||
DIFF_PM_G2 = 1,
|
|
||||||
DIFF_WEICKERT = 2,
|
|
||||||
DIFF_CHARBONNIER = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
// AKAZE descriptor type
|
|
||||||
enum {
|
|
||||||
DESCRIPTOR_KAZE_UPRIGHT = 2, ///< Upright descriptors, not invariant to rotation
|
|
||||||
DESCRIPTOR_KAZE = 3,
|
|
||||||
DESCRIPTOR_MLDB_UPRIGHT = 4, ///< Upright descriptors, not invariant to rotation
|
|
||||||
DESCRIPTOR_MLDB = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
KAZE implementation
|
KAZE implementation
|
||||||
*/
|
*/
|
||||||
class CV_EXPORTS_W KAZE : public Feature2D
|
class CV_EXPORTS_W KAZE : public Feature2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CV_WRAP KAZE();
|
enum
|
||||||
CV_WRAP explicit KAZE(bool extended, bool upright, float threshold = 0.001f,
|
{
|
||||||
int octaves = 4, int sublevels = 4, int diffusivity = DIFF_PM_G2);
|
DIFF_PM_G1 = 0,
|
||||||
|
DIFF_PM_G2 = 1,
|
||||||
|
DIFF_WEICKERT = 2,
|
||||||
|
DIFF_CHARBONNIER = 3
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~KAZE();
|
CV_WRAP static Ptr<KAZE> create(bool extended=false, bool upright=false,
|
||||||
|
float threshold = 0.001f,
|
||||||
// returns the descriptor size in bytes
|
int octaves = 4, int sublevels = 4,
|
||||||
int descriptorSize() const;
|
int diffusivity = KAZE::DIFF_PM_G2);
|
||||||
// returns the descriptor type
|
|
||||||
int descriptorType() const;
|
|
||||||
// returns the default norm type
|
|
||||||
int defaultNorm() const;
|
|
||||||
|
|
||||||
AlgorithmInfo* info() const;
|
|
||||||
|
|
||||||
// Compute the KAZE features on an image
|
|
||||||
void operator()(InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints) const;
|
|
||||||
|
|
||||||
// Compute the KAZE features and descriptors on an image
|
|
||||||
void operator()(InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints,
|
|
||||||
OutputArray descriptors, bool useProvidedKeypoints = false) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void detectImpl(InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask) const;
|
|
||||||
void computeImpl(InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors) const;
|
|
||||||
|
|
||||||
CV_PROP bool extended;
|
|
||||||
CV_PROP bool upright;
|
|
||||||
CV_PROP float threshold;
|
|
||||||
CV_PROP int octaves;
|
|
||||||
CV_PROP int sublevels;
|
|
||||||
CV_PROP int diffusivity;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -555,41 +299,21 @@ AKAZE implementation
|
|||||||
class CV_EXPORTS_W AKAZE : public Feature2D
|
class CV_EXPORTS_W AKAZE : public Feature2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CV_WRAP AKAZE();
|
// AKAZE descriptor type
|
||||||
CV_WRAP explicit AKAZE(int descriptor_type, int descriptor_size = 0, int descriptor_channels = 3,
|
enum
|
||||||
float threshold = 0.001f, int octaves = 4, int sublevels = 4, int diffusivity = DIFF_PM_G2);
|
{
|
||||||
|
DESCRIPTOR_KAZE_UPRIGHT = 2, ///< Upright descriptors, not invariant to rotation
|
||||||
|
DESCRIPTOR_KAZE = 3,
|
||||||
|
DESCRIPTOR_MLDB_UPRIGHT = 4, ///< Upright descriptors, not invariant to rotation
|
||||||
|
DESCRIPTOR_MLDB = 5
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~AKAZE();
|
CV_WRAP static Ptr<AKAZE> create(int descriptor_type=AKAZE::DESCRIPTOR_MLDB,
|
||||||
|
int descriptor_size = 0, int descriptor_channels = 3,
|
||||||
// returns the descriptor size in bytes
|
float threshold = 0.001f, int octaves = 4,
|
||||||
int descriptorSize() const;
|
int sublevels = 4, int diffusivity = KAZE::DIFF_PM_G2);
|
||||||
// returns the descriptor type
|
|
||||||
int descriptorType() const;
|
|
||||||
// returns the default norm type
|
|
||||||
int defaultNorm() const;
|
|
||||||
|
|
||||||
// Compute the AKAZE features on an image
|
|
||||||
void operator()(InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints) const;
|
|
||||||
|
|
||||||
// Compute the AKAZE features and descriptors on an image
|
|
||||||
void operator()(InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints,
|
|
||||||
OutputArray descriptors, bool useProvidedKeypoints = false) const;
|
|
||||||
|
|
||||||
AlgorithmInfo* info() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void computeImpl(InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors) const;
|
|
||||||
void detectImpl(InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask = noArray()) const;
|
|
||||||
|
|
||||||
CV_PROP int descriptor;
|
|
||||||
CV_PROP int descriptor_channels;
|
|
||||||
CV_PROP int descriptor_size;
|
|
||||||
CV_PROP float threshold;
|
|
||||||
CV_PROP int octaves;
|
|
||||||
CV_PROP int sublevels;
|
|
||||||
CV_PROP int diffusivity;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************************\
|
/****************************************************************************************\
|
||||||
* Distance *
|
* Distance *
|
||||||
\****************************************************************************************/
|
\****************************************************************************************/
|
||||||
@ -837,8 +561,6 @@ public:
|
|||||||
virtual bool isMaskSupported() const { return true; }
|
virtual bool isMaskSupported() const { return true; }
|
||||||
|
|
||||||
virtual Ptr<DescriptorMatcher> clone( bool emptyTrainData=false ) const;
|
virtual Ptr<DescriptorMatcher> clone( bool emptyTrainData=false ) const;
|
||||||
|
|
||||||
AlgorithmInfo* info() const;
|
|
||||||
protected:
|
protected:
|
||||||
virtual void knnMatchImpl( InputArray queryDescriptors, std::vector<std::vector<DMatch> >& matches, int k,
|
virtual void knnMatchImpl( InputArray queryDescriptors, std::vector<std::vector<DMatch> >& matches, int k,
|
||||||
InputArrayOfArrays masks=noArray(), bool compactResult=false );
|
InputArrayOfArrays masks=noArray(), bool compactResult=false );
|
||||||
@ -871,8 +593,6 @@ public:
|
|||||||
virtual bool isMaskSupported() const;
|
virtual bool isMaskSupported() const;
|
||||||
|
|
||||||
virtual Ptr<DescriptorMatcher> clone( bool emptyTrainData=false ) const;
|
virtual Ptr<DescriptorMatcher> clone( bool emptyTrainData=false ) const;
|
||||||
|
|
||||||
AlgorithmInfo* info() const;
|
|
||||||
protected:
|
protected:
|
||||||
static void convertToDMatches( const DescriptorCollection& descriptors,
|
static void convertToDMatches( const DescriptorCollection& descriptors,
|
||||||
const Mat& indices, const Mat& distances,
|
const Mat& indices, const Mat& distances,
|
||||||
|
@ -32,11 +32,8 @@ OCL_PERF_TEST_P(FASTFixture, FastDetect, testing::Combine(
|
|||||||
mframe.copyTo(frame);
|
mframe.copyTo(frame);
|
||||||
declare.in(frame);
|
declare.in(frame);
|
||||||
|
|
||||||
Ptr<FeatureDetector> fd = Algorithm::create<FeatureDetector>("Feature2D.FAST");
|
Ptr<FeatureDetector> fd = FastFeatureDetector::create(20, true, type);
|
||||||
ASSERT_FALSE( fd.empty() );
|
ASSERT_FALSE( fd.empty() );
|
||||||
fd->set("threshold", 20);
|
|
||||||
fd->set("nonmaxSuppression", true);
|
|
||||||
fd->set("type", type);
|
|
||||||
vector<KeyPoint> points;
|
vector<KeyPoint> points;
|
||||||
|
|
||||||
OCL_TEST_CYCLE() fd->detect(frame, points);
|
OCL_TEST_CYCLE() fd->detect(frame, points);
|
||||||
|
@ -22,10 +22,10 @@ OCL_PERF_TEST_P(ORBFixture, ORB_Detect, ORB_IMAGES)
|
|||||||
mframe.copyTo(frame);
|
mframe.copyTo(frame);
|
||||||
|
|
||||||
declare.in(frame);
|
declare.in(frame);
|
||||||
ORB detector(1500, 1.3f, 1);
|
Ptr<ORB> detector = ORB::create(1500, 1.3f, 1);
|
||||||
vector<KeyPoint> points;
|
vector<KeyPoint> points;
|
||||||
|
|
||||||
OCL_TEST_CYCLE() detector(frame, mask, points);
|
OCL_TEST_CYCLE() detector->detect(frame, points, mask);
|
||||||
|
|
||||||
std::sort(points.begin(), points.end(), comparators::KeypointGreater());
|
std::sort(points.begin(), points.end(), comparators::KeypointGreater());
|
||||||
SANITY_CHECK_KEYPOINTS(points, 1e-5);
|
SANITY_CHECK_KEYPOINTS(points, 1e-5);
|
||||||
@ -44,14 +44,14 @@ OCL_PERF_TEST_P(ORBFixture, ORB_Extract, ORB_IMAGES)
|
|||||||
|
|
||||||
declare.in(frame);
|
declare.in(frame);
|
||||||
|
|
||||||
ORB detector(1500, 1.3f, 1);
|
Ptr<ORB> detector = ORB::create(1500, 1.3f, 1);
|
||||||
vector<KeyPoint> points;
|
vector<KeyPoint> points;
|
||||||
detector(frame, mask, points);
|
detector->detect(frame, points, mask);
|
||||||
std::sort(points.begin(), points.end(), comparators::KeypointGreater());
|
std::sort(points.begin(), points.end(), comparators::KeypointGreater());
|
||||||
|
|
||||||
UMat descriptors;
|
UMat descriptors;
|
||||||
|
|
||||||
OCL_TEST_CYCLE() detector(frame, mask, points, descriptors, true);
|
OCL_TEST_CYCLE() detector->compute(frame, points, descriptors);
|
||||||
|
|
||||||
SANITY_CHECK(descriptors);
|
SANITY_CHECK(descriptors);
|
||||||
}
|
}
|
||||||
@ -68,12 +68,12 @@ OCL_PERF_TEST_P(ORBFixture, ORB_Full, ORB_IMAGES)
|
|||||||
mframe.copyTo(frame);
|
mframe.copyTo(frame);
|
||||||
|
|
||||||
declare.in(frame);
|
declare.in(frame);
|
||||||
ORB detector(1500, 1.3f, 1);
|
Ptr<ORB> detector = ORB::create(1500, 1.3f, 1);
|
||||||
|
|
||||||
vector<KeyPoint> points;
|
vector<KeyPoint> points;
|
||||||
UMat descriptors;
|
UMat descriptors;
|
||||||
|
|
||||||
OCL_TEST_CYCLE() detector(frame, mask, points, descriptors, false);
|
OCL_TEST_CYCLE() detector->detectAndCompute(frame, mask, points, descriptors, false);
|
||||||
|
|
||||||
::perf::sort(points, descriptors);
|
::perf::sort(points, descriptors);
|
||||||
SANITY_CHECK_KEYPOINTS(points, 1e-5);
|
SANITY_CHECK_KEYPOINTS(points, 1e-5);
|
||||||
|
@ -30,11 +30,8 @@ PERF_TEST_P(fast, detect, testing::Combine(
|
|||||||
|
|
||||||
declare.in(frame);
|
declare.in(frame);
|
||||||
|
|
||||||
Ptr<FeatureDetector> fd = Algorithm::create<FeatureDetector>("Feature2D.FAST");
|
Ptr<FeatureDetector> fd = FastFeatureDetector::create(20, true, type);
|
||||||
ASSERT_FALSE( fd.empty() );
|
ASSERT_FALSE( fd.empty() );
|
||||||
fd->set("threshold", 20);
|
|
||||||
fd->set("nonmaxSuppression", true);
|
|
||||||
fd->set("type", type);
|
|
||||||
vector<KeyPoint> points;
|
vector<KeyPoint> points;
|
||||||
|
|
||||||
TEST_CYCLE() fd->detect(frame, points);
|
TEST_CYCLE() fd->detect(frame, points);
|
||||||
|
@ -22,10 +22,10 @@ PERF_TEST_P(orb, detect, testing::Values(ORB_IMAGES))
|
|||||||
|
|
||||||
Mat mask;
|
Mat mask;
|
||||||
declare.in(frame);
|
declare.in(frame);
|
||||||
ORB detector(1500, 1.3f, 1);
|
Ptr<ORB> detector = ORB::create(1500, 1.3f, 1);
|
||||||
vector<KeyPoint> points;
|
vector<KeyPoint> points;
|
||||||
|
|
||||||
TEST_CYCLE() detector(frame, mask, points);
|
TEST_CYCLE() detector->detect(frame, points, mask);
|
||||||
|
|
||||||
sort(points.begin(), points.end(), comparators::KeypointGreater());
|
sort(points.begin(), points.end(), comparators::KeypointGreater());
|
||||||
SANITY_CHECK_KEYPOINTS(points, 1e-5);
|
SANITY_CHECK_KEYPOINTS(points, 1e-5);
|
||||||
@ -42,14 +42,14 @@ PERF_TEST_P(orb, extract, testing::Values(ORB_IMAGES))
|
|||||||
Mat mask;
|
Mat mask;
|
||||||
declare.in(frame);
|
declare.in(frame);
|
||||||
|
|
||||||
ORB detector(1500, 1.3f, 1);
|
Ptr<ORB> detector = ORB::create(1500, 1.3f, 1);
|
||||||
vector<KeyPoint> points;
|
vector<KeyPoint> points;
|
||||||
detector(frame, mask, points);
|
detector->detect(frame, points, mask);
|
||||||
sort(points.begin(), points.end(), comparators::KeypointGreater());
|
sort(points.begin(), points.end(), comparators::KeypointGreater());
|
||||||
|
|
||||||
Mat descriptors;
|
Mat descriptors;
|
||||||
|
|
||||||
TEST_CYCLE() detector(frame, mask, points, descriptors, true);
|
TEST_CYCLE() detector->compute(frame, points, descriptors);
|
||||||
|
|
||||||
SANITY_CHECK(descriptors);
|
SANITY_CHECK(descriptors);
|
||||||
}
|
}
|
||||||
@ -64,12 +64,12 @@ PERF_TEST_P(orb, full, testing::Values(ORB_IMAGES))
|
|||||||
|
|
||||||
Mat mask;
|
Mat mask;
|
||||||
declare.in(frame);
|
declare.in(frame);
|
||||||
ORB detector(1500, 1.3f, 1);
|
Ptr<ORB> detector = ORB::create(1500, 1.3f, 1);
|
||||||
|
|
||||||
vector<KeyPoint> points;
|
vector<KeyPoint> points;
|
||||||
Mat descriptors;
|
Mat descriptors;
|
||||||
|
|
||||||
TEST_CYCLE() detector(frame, mask, points, descriptors, false);
|
TEST_CYCLE() detector->detectAndCompute(frame, mask, points, descriptors, false);
|
||||||
|
|
||||||
perf::sort(points, descriptors);
|
perf::sort(points, descriptors);
|
||||||
SANITY_CHECK_KEYPOINTS(points, 1e-5);
|
SANITY_CHECK_KEYPOINTS(points, 1e-5);
|
||||||
|
@ -52,22 +52,15 @@ http://www.robesafe.com/personal/pablo.alcantarilla/papers/Alcantarilla13bmvc.pd
|
|||||||
#include "kaze/AKAZEFeatures.h"
|
#include "kaze/AKAZEFeatures.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace cv
|
namespace cv
|
||||||
{
|
{
|
||||||
AKAZE::AKAZE()
|
using namespace std;
|
||||||
: descriptor(DESCRIPTOR_MLDB)
|
|
||||||
, descriptor_channels(3)
|
|
||||||
, descriptor_size(0)
|
|
||||||
, threshold(0.001f)
|
|
||||||
, octaves(4)
|
|
||||||
, sublevels(4)
|
|
||||||
, diffusivity(DIFF_PM_G2)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
AKAZE::AKAZE(int _descriptor_type, int _descriptor_size, int _descriptor_channels,
|
class AKAZE_Impl : public AKAZE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AKAZE_Impl(int _descriptor_type, int _descriptor_size, int _descriptor_channels,
|
||||||
float _threshold, int _octaves, int _sublevels, int _diffusivity)
|
float _threshold, int _octaves, int _sublevels, int _diffusivity)
|
||||||
: descriptor(_descriptor_type)
|
: descriptor(_descriptor_type)
|
||||||
, descriptor_channels(_descriptor_channels)
|
, descriptor_channels(_descriptor_channels)
|
||||||
@ -77,25 +70,24 @@ namespace cv
|
|||||||
, sublevels(_sublevels)
|
, sublevels(_sublevels)
|
||||||
, diffusivity(_diffusivity)
|
, diffusivity(_diffusivity)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AKAZE::~AKAZE()
|
virtual ~AKAZE_Impl()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the descriptor size in bytes
|
// returns the descriptor size in bytes
|
||||||
int AKAZE::descriptorSize() const
|
int descriptorSize() const
|
||||||
{
|
{
|
||||||
switch (descriptor)
|
switch (descriptor)
|
||||||
{
|
{
|
||||||
case cv::DESCRIPTOR_KAZE:
|
case DESCRIPTOR_KAZE:
|
||||||
case cv::DESCRIPTOR_KAZE_UPRIGHT:
|
case DESCRIPTOR_KAZE_UPRIGHT:
|
||||||
return 64;
|
return 64;
|
||||||
|
|
||||||
case cv::DESCRIPTOR_MLDB:
|
case DESCRIPTOR_MLDB:
|
||||||
case cv::DESCRIPTOR_MLDB_UPRIGHT:
|
case DESCRIPTOR_MLDB_UPRIGHT:
|
||||||
// We use the full length binary descriptor -> 486 bits
|
// We use the full length binary descriptor -> 486 bits
|
||||||
if (descriptor_size == 0)
|
if (descriptor_size == 0)
|
||||||
{
|
{
|
||||||
@ -114,16 +106,16 @@ namespace cv
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns the descriptor type
|
// returns the descriptor type
|
||||||
int AKAZE::descriptorType() const
|
int descriptorType() const
|
||||||
{
|
{
|
||||||
switch (descriptor)
|
switch (descriptor)
|
||||||
{
|
{
|
||||||
case cv::DESCRIPTOR_KAZE:
|
case DESCRIPTOR_KAZE:
|
||||||
case cv::DESCRIPTOR_KAZE_UPRIGHT:
|
case DESCRIPTOR_KAZE_UPRIGHT:
|
||||||
return CV_32F;
|
return CV_32F;
|
||||||
|
|
||||||
case cv::DESCRIPTOR_MLDB:
|
case DESCRIPTOR_MLDB:
|
||||||
case cv::DESCRIPTOR_MLDB_UPRIGHT:
|
case DESCRIPTOR_MLDB_UPRIGHT:
|
||||||
return CV_8U;
|
return CV_8U;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -132,38 +124,35 @@ namespace cv
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns the default norm type
|
// returns the default norm type
|
||||||
int AKAZE::defaultNorm() const
|
int defaultNorm() const
|
||||||
{
|
{
|
||||||
switch (descriptor)
|
switch (descriptor)
|
||||||
{
|
{
|
||||||
case cv::DESCRIPTOR_KAZE:
|
case DESCRIPTOR_KAZE:
|
||||||
case cv::DESCRIPTOR_KAZE_UPRIGHT:
|
case DESCRIPTOR_KAZE_UPRIGHT:
|
||||||
return cv::NORM_L2;
|
return NORM_L2;
|
||||||
|
|
||||||
case cv::DESCRIPTOR_MLDB:
|
case DESCRIPTOR_MLDB:
|
||||||
case cv::DESCRIPTOR_MLDB_UPRIGHT:
|
case DESCRIPTOR_MLDB_UPRIGHT:
|
||||||
return cv::NORM_HAMMING;
|
return NORM_HAMMING;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void detectAndCompute(InputArray image, InputArray mask,
|
||||||
void AKAZE::operator()(InputArray image, InputArray mask,
|
|
||||||
std::vector<KeyPoint>& keypoints,
|
std::vector<KeyPoint>& keypoints,
|
||||||
OutputArray descriptors,
|
OutputArray descriptors,
|
||||||
bool useProvidedKeypoints) const
|
bool useProvidedKeypoints)
|
||||||
{
|
{
|
||||||
cv::Mat img = image.getMat();
|
Mat img = image.getMat();
|
||||||
if (img.type() != CV_8UC1)
|
if (img.type() != CV_8UC1)
|
||||||
cvtColor(image, img, COLOR_BGR2GRAY);
|
cvtColor(image, img, COLOR_BGR2GRAY);
|
||||||
|
|
||||||
Mat img1_32;
|
Mat img1_32;
|
||||||
img.convertTo(img1_32, CV_32F, 1.0 / 255.0, 0);
|
img.convertTo(img1_32, CV_32F, 1.0 / 255.0, 0);
|
||||||
|
|
||||||
cv::Mat& desc = descriptors.getMatRef();
|
|
||||||
|
|
||||||
AKAZEOptions options;
|
AKAZEOptions options;
|
||||||
options.descriptor = descriptor;
|
options.descriptor = descriptor;
|
||||||
options.descriptor_channels = descriptor_channels;
|
options.descriptor_channels = descriptor_channels;
|
||||||
@ -185,72 +174,56 @@ namespace cv
|
|||||||
|
|
||||||
if (!mask.empty())
|
if (!mask.empty())
|
||||||
{
|
{
|
||||||
cv::KeyPointsFilter::runByPixelsMask(keypoints, mask.getMat());
|
KeyPointsFilter::runByPixelsMask(keypoints, mask.getMat());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( descriptors.needed() )
|
||||||
|
{
|
||||||
|
Mat& desc = descriptors.getMatRef();
|
||||||
impl.Compute_Descriptors(keypoints, desc);
|
impl.Compute_Descriptors(keypoints, desc);
|
||||||
|
|
||||||
CV_Assert((!desc.rows || desc.cols == descriptorSize()));
|
CV_Assert((!desc.rows || desc.cols == descriptorSize()));
|
||||||
CV_Assert((!desc.rows || (desc.type() == descriptorType())));
|
CV_Assert((!desc.rows || (desc.type() == descriptorType())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AKAZE::detectImpl(InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask) const
|
|
||||||
{
|
|
||||||
cv::Mat img = image.getMat();
|
|
||||||
if (img.type() != CV_8UC1)
|
|
||||||
cvtColor(image, img, COLOR_BGR2GRAY);
|
|
||||||
|
|
||||||
Mat img1_32;
|
|
||||||
img.convertTo(img1_32, CV_32F, 1.0 / 255.0, 0);
|
|
||||||
|
|
||||||
AKAZEOptions options;
|
|
||||||
options.descriptor = descriptor;
|
|
||||||
options.descriptor_channels = descriptor_channels;
|
|
||||||
options.descriptor_size = descriptor_size;
|
|
||||||
options.img_width = img.cols;
|
|
||||||
options.img_height = img.rows;
|
|
||||||
options.dthreshold = threshold;
|
|
||||||
options.omax = octaves;
|
|
||||||
options.nsublevels = sublevels;
|
|
||||||
options.diffusivity = diffusivity;
|
|
||||||
|
|
||||||
AKAZEFeatures impl(options);
|
|
||||||
impl.Create_Nonlinear_Scale_Space(img1_32);
|
|
||||||
impl.Feature_Detection(keypoints);
|
|
||||||
|
|
||||||
if (!mask.empty())
|
|
||||||
{
|
|
||||||
cv::KeyPointsFilter::runByPixelsMask(keypoints, mask.getMat());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AKAZE::computeImpl(InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors) const
|
void write(FileStorage& fs) const
|
||||||
{
|
{
|
||||||
cv::Mat img = image.getMat();
|
fs << "descriptor" << descriptor;
|
||||||
if (img.type() != CV_8UC1)
|
fs << "descriptor_channels" << descriptor_channels;
|
||||||
cvtColor(image, img, COLOR_BGR2GRAY);
|
fs << "descriptor_size" << descriptor_size;
|
||||||
|
fs << "threshold" << threshold;
|
||||||
|
fs << "octaves" << octaves;
|
||||||
|
fs << "sublevels" << sublevels;
|
||||||
|
fs << "diffusivity" << diffusivity;
|
||||||
|
}
|
||||||
|
|
||||||
Mat img1_32;
|
void read(const FileNode& fn)
|
||||||
img.convertTo(img1_32, CV_32F, 1.0 / 255.0, 0);
|
{
|
||||||
|
descriptor = (int)fn["descriptor"];
|
||||||
|
descriptor_channels = (int)fn["descriptor_channels"];
|
||||||
|
descriptor_size = (int)fn["descriptor_size"];
|
||||||
|
threshold = (float)fn["threshold"];
|
||||||
|
octaves = (int)fn["octaves"];
|
||||||
|
sublevels = (int)fn["sublevels"];
|
||||||
|
diffusivity = (int)fn["diffusivity"];
|
||||||
|
}
|
||||||
|
|
||||||
cv::Mat& desc = descriptors.getMatRef();
|
int descriptor;
|
||||||
|
int descriptor_channels;
|
||||||
|
int descriptor_size;
|
||||||
|
float threshold;
|
||||||
|
int octaves;
|
||||||
|
int sublevels;
|
||||||
|
int diffusivity;
|
||||||
|
};
|
||||||
|
|
||||||
AKAZEOptions options;
|
Ptr<AKAZE> AKAZE::create(int descriptor_type,
|
||||||
options.descriptor = descriptor;
|
int descriptor_size, int descriptor_channels,
|
||||||
options.descriptor_channels = descriptor_channels;
|
float threshold, int octaves,
|
||||||
options.descriptor_size = descriptor_size;
|
int sublevels, int diffusivity)
|
||||||
options.img_width = img.cols;
|
{
|
||||||
options.img_height = img.rows;
|
return makePtr<AKAZE_Impl>(descriptor_type, descriptor_size, descriptor_channels,
|
||||||
options.dthreshold = threshold;
|
threshold, octaves, sublevels, diffusivity);
|
||||||
options.omax = octaves;
|
|
||||||
options.nsublevels = sublevels;
|
|
||||||
options.diffusivity = diffusivity;
|
|
||||||
|
|
||||||
AKAZEFeatures impl(options);
|
|
||||||
impl.Create_Nonlinear_Scale_Space(img1_32);
|
|
||||||
impl.Compute_Descriptors(keypoints, desc);
|
|
||||||
|
|
||||||
CV_Assert((!desc.rows || desc.cols == descriptorSize()));
|
|
||||||
CV_Assert((!desc.rows || (desc.type() == descriptorType())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,31 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace cv;
|
namespace cv
|
||||||
|
{
|
||||||
|
|
||||||
|
class CV_EXPORTS_W SimpleBlobDetectorImpl : public SimpleBlobDetector
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit SimpleBlobDetectorImpl(const SimpleBlobDetector::Params ¶meters = SimpleBlobDetector::Params());
|
||||||
|
|
||||||
|
virtual void read( const FileNode& fn );
|
||||||
|
virtual void write( FileStorage& fs ) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
struct CV_EXPORTS Center
|
||||||
|
{
|
||||||
|
Point2d location;
|
||||||
|
double radius;
|
||||||
|
double confidence;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void detect( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask=noArray() );
|
||||||
|
virtual void findBlobs(InputArray image, InputArray binaryImage, std::vector<Center> ¢ers) const;
|
||||||
|
|
||||||
|
Params params;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SimpleBlobDetector
|
* SimpleBlobDetector
|
||||||
@ -148,22 +172,22 @@ void SimpleBlobDetector::Params::write(cv::FileStorage& fs) const
|
|||||||
fs << "maxConvexity" << maxConvexity;
|
fs << "maxConvexity" << maxConvexity;
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleBlobDetector::SimpleBlobDetector(const SimpleBlobDetector::Params ¶meters) :
|
SimpleBlobDetectorImpl::SimpleBlobDetectorImpl(const SimpleBlobDetector::Params ¶meters) :
|
||||||
params(parameters)
|
params(parameters)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleBlobDetector::read( const cv::FileNode& fn )
|
void SimpleBlobDetectorImpl::read( const cv::FileNode& fn )
|
||||||
{
|
{
|
||||||
params.read(fn);
|
params.read(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleBlobDetector::write( cv::FileStorage& fs ) const
|
void SimpleBlobDetectorImpl::write( cv::FileStorage& fs ) const
|
||||||
{
|
{
|
||||||
params.write(fs);
|
params.write(fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleBlobDetector::findBlobs(InputArray _image, InputArray _binaryImage, std::vector<Center> ¢ers) const
|
void SimpleBlobDetectorImpl::findBlobs(InputArray _image, InputArray _binaryImage, std::vector<Center> ¢ers) const
|
||||||
{
|
{
|
||||||
Mat image = _image.getMat(), binaryImage = _binaryImage.getMat();
|
Mat image = _image.getMat(), binaryImage = _binaryImage.getMat();
|
||||||
(void)image;
|
(void)image;
|
||||||
@ -277,7 +301,7 @@ void SimpleBlobDetector::findBlobs(InputArray _image, InputArray _binaryImage, s
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleBlobDetector::detectImpl(InputArray image, std::vector<cv::KeyPoint>& keypoints, InputArray) const
|
void SimpleBlobDetectorImpl::detect(InputArray image, std::vector<cv::KeyPoint>& keypoints, InputArray)
|
||||||
{
|
{
|
||||||
//TODO: support mask
|
//TODO: support mask
|
||||||
keypoints.clear();
|
keypoints.clear();
|
||||||
@ -340,3 +364,10 @@ void SimpleBlobDetector::detectImpl(InputArray image, std::vector<cv::KeyPoint>&
|
|||||||
keypoints.push_back(kpt);
|
keypoints.push_back(kpt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ptr<SimpleBlobDetector> SimpleBlobDetector::create(const SimpleBlobDetector::Params& params)
|
||||||
|
{
|
||||||
|
return makePtr<SimpleBlobDetectorImpl>(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -42,9 +42,7 @@
|
|||||||
the IEEE International Conference on Computer Vision (ICCV2011).
|
the IEEE International Conference on Computer Vision (ICCV2011).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <opencv2/features2d.hpp>
|
#include "precomp.hpp"
|
||||||
#include <opencv2/core.hpp>
|
|
||||||
#include <opencv2/imgproc.hpp>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@ -53,6 +51,97 @@
|
|||||||
namespace cv
|
namespace cv
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class BRISK_Impl : public BRISK
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit BRISK_Impl(int thresh=30, int octaves=3, float patternScale=1.0f);
|
||||||
|
// custom setup
|
||||||
|
explicit BRISK_Impl(const std::vector<float> &radiusList, const std::vector<int> &numberList,
|
||||||
|
float dMax=5.85f, float dMin=8.2f, const std::vector<int> indexChange=std::vector<int>());
|
||||||
|
|
||||||
|
virtual ~BRISK_Impl();
|
||||||
|
|
||||||
|
int descriptorSize() const
|
||||||
|
{
|
||||||
|
return strings_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int descriptorType() const
|
||||||
|
{
|
||||||
|
return CV_8U;
|
||||||
|
}
|
||||||
|
|
||||||
|
int defaultNorm() const
|
||||||
|
{
|
||||||
|
return NORM_HAMMING;
|
||||||
|
}
|
||||||
|
|
||||||
|
// call this to generate the kernel:
|
||||||
|
// circle of radius r (pixels), with n points;
|
||||||
|
// short pairings with dMax, long pairings with dMin
|
||||||
|
void generateKernel(const std::vector<float> &radiusList,
|
||||||
|
const std::vector<int> &numberList, float dMax=5.85f, float dMin=8.2f,
|
||||||
|
const std::vector<int> &indexChange=std::vector<int>());
|
||||||
|
|
||||||
|
void detectAndCompute( InputArray image, InputArray mask,
|
||||||
|
CV_OUT std::vector<KeyPoint>& keypoints,
|
||||||
|
OutputArray descriptors,
|
||||||
|
bool useProvidedKeypoints );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void computeKeypointsNoOrientation(InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints) const;
|
||||||
|
void computeDescriptorsAndOrOrientation(InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints,
|
||||||
|
OutputArray descriptors, bool doDescriptors, bool doOrientation,
|
||||||
|
bool useProvidedKeypoints) const;
|
||||||
|
|
||||||
|
// Feature parameters
|
||||||
|
CV_PROP_RW int threshold;
|
||||||
|
CV_PROP_RW int octaves;
|
||||||
|
|
||||||
|
// some helper structures for the Brisk pattern representation
|
||||||
|
struct BriskPatternPoint{
|
||||||
|
float x; // x coordinate relative to center
|
||||||
|
float y; // x coordinate relative to center
|
||||||
|
float sigma; // Gaussian smoothing sigma
|
||||||
|
};
|
||||||
|
struct BriskShortPair{
|
||||||
|
unsigned int i; // index of the first pattern point
|
||||||
|
unsigned int j; // index of other pattern point
|
||||||
|
};
|
||||||
|
struct BriskLongPair{
|
||||||
|
unsigned int i; // index of the first pattern point
|
||||||
|
unsigned int j; // index of other pattern point
|
||||||
|
int weighted_dx; // 1024.0/dx
|
||||||
|
int weighted_dy; // 1024.0/dy
|
||||||
|
};
|
||||||
|
inline int smoothedIntensity(const cv::Mat& image,
|
||||||
|
const cv::Mat& integral,const float key_x,
|
||||||
|
const float key_y, const unsigned int scale,
|
||||||
|
const unsigned int rot, const unsigned int point) const;
|
||||||
|
// pattern properties
|
||||||
|
BriskPatternPoint* patternPoints_; //[i][rotation][scale]
|
||||||
|
unsigned int points_; // total number of collocation points
|
||||||
|
float* scaleList_; // lists the scaling per scale index [scale]
|
||||||
|
unsigned int* sizeList_; // lists the total pattern size per scale index [scale]
|
||||||
|
static const unsigned int scales_; // scales discretization
|
||||||
|
static const float scalerange_; // span of sizes 40->4 Octaves - else, this needs to be adjusted...
|
||||||
|
static const unsigned int n_rot_; // discretization of the rotation look-up
|
||||||
|
|
||||||
|
// pairs
|
||||||
|
int strings_; // number of uchars the descriptor consists of
|
||||||
|
float dMax_; // short pair maximum distance
|
||||||
|
float dMin_; // long pair maximum distance
|
||||||
|
BriskShortPair* shortPairs_; // d<_dMax
|
||||||
|
BriskLongPair* longPairs_; // d>_dMin
|
||||||
|
unsigned int noShortPairs_; // number of shortParis
|
||||||
|
unsigned int noLongPairs_; // number of longParis
|
||||||
|
|
||||||
|
// general
|
||||||
|
static const float basicSize_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// a layer in the Brisk detector pyramid
|
// a layer in the Brisk detector pyramid
|
||||||
class CV_EXPORTS BriskLayer
|
class CV_EXPORTS BriskLayer
|
||||||
{
|
{
|
||||||
@ -183,16 +272,16 @@ protected:
|
|||||||
static const float basicSize_;
|
static const float basicSize_;
|
||||||
};
|
};
|
||||||
|
|
||||||
const float BRISK::basicSize_ = 12.0f;
|
const float BRISK_Impl::basicSize_ = 12.0f;
|
||||||
const unsigned int BRISK::scales_ = 64;
|
const unsigned int BRISK_Impl::scales_ = 64;
|
||||||
const float BRISK::scalerange_ = 30.f; // 40->4 Octaves - else, this needs to be adjusted...
|
const float BRISK_Impl::scalerange_ = 30.f; // 40->4 Octaves - else, this needs to be adjusted...
|
||||||
const unsigned int BRISK::n_rot_ = 1024; // discretization of the rotation look-up
|
const unsigned int BRISK_Impl::n_rot_ = 1024; // discretization of the rotation look-up
|
||||||
|
|
||||||
const float BriskScaleSpace::safetyFactor_ = 1.0f;
|
const float BriskScaleSpace::safetyFactor_ = 1.0f;
|
||||||
const float BriskScaleSpace::basicSize_ = 12.0f;
|
const float BriskScaleSpace::basicSize_ = 12.0f;
|
||||||
|
|
||||||
// constructors
|
// constructors
|
||||||
BRISK::BRISK(int thresh, int octaves_in, float patternScale)
|
BRISK_Impl::BRISK_Impl(int thresh, int octaves_in, float patternScale)
|
||||||
{
|
{
|
||||||
threshold = thresh;
|
threshold = thresh;
|
||||||
octaves = octaves_in;
|
octaves = octaves_in;
|
||||||
@ -218,10 +307,12 @@ BRISK::BRISK(int thresh, int octaves_in, float patternScale)
|
|||||||
nList[4] = 20;
|
nList[4] = 20;
|
||||||
|
|
||||||
generateKernel(rList, nList, (float)(5.85 * patternScale), (float)(8.2 * patternScale));
|
generateKernel(rList, nList, (float)(5.85 * patternScale), (float)(8.2 * patternScale));
|
||||||
|
|
||||||
}
|
}
|
||||||
BRISK::BRISK(std::vector<float> &radiusList, std::vector<int> &numberList, float dMax, float dMin,
|
|
||||||
std::vector<int> indexChange)
|
BRISK_Impl::BRISK_Impl(const std::vector<float> &radiusList,
|
||||||
|
const std::vector<int> &numberList,
|
||||||
|
float dMax, float dMin,
|
||||||
|
const std::vector<int> indexChange)
|
||||||
{
|
{
|
||||||
generateKernel(radiusList, numberList, dMax, dMin, indexChange);
|
generateKernel(radiusList, numberList, dMax, dMin, indexChange);
|
||||||
threshold = 20;
|
threshold = 20;
|
||||||
@ -229,10 +320,12 @@ BRISK::BRISK(std::vector<float> &radiusList, std::vector<int> &numberList, float
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BRISK::generateKernel(std::vector<float> &radiusList, std::vector<int> &numberList, float dMax,
|
BRISK_Impl::generateKernel(const std::vector<float> &radiusList,
|
||||||
float dMin, std::vector<int> indexChange)
|
const std::vector<int> &numberList,
|
||||||
|
float dMax, float dMin,
|
||||||
|
const std::vector<int>& _indexChange)
|
||||||
{
|
{
|
||||||
|
std::vector<int> indexChange = _indexChange;
|
||||||
dMax_ = dMax;
|
dMax_ = dMax;
|
||||||
dMin_ = dMin;
|
dMin_ = dMin;
|
||||||
|
|
||||||
@ -354,7 +447,7 @@ BRISK::generateKernel(std::vector<float> &radiusList, std::vector<int> &numberLi
|
|||||||
|
|
||||||
// simple alternative:
|
// simple alternative:
|
||||||
inline int
|
inline int
|
||||||
BRISK::smoothedIntensity(const cv::Mat& image, const cv::Mat& integral, const float key_x,
|
BRISK_Impl::smoothedIntensity(const cv::Mat& image, const cv::Mat& integral, const float key_x,
|
||||||
const float key_y, const unsigned int scale, const unsigned int rot,
|
const float key_y, const unsigned int scale, const unsigned int rot,
|
||||||
const unsigned int point) const
|
const unsigned int point) const
|
||||||
{
|
{
|
||||||
@ -521,8 +614,8 @@ RoiPredicate(const float minX, const float minY, const float maxX, const float m
|
|||||||
|
|
||||||
// computes the descriptor
|
// computes the descriptor
|
||||||
void
|
void
|
||||||
BRISK::operator()( InputArray _image, InputArray _mask, std::vector<KeyPoint>& keypoints,
|
BRISK_Impl::detectAndCompute( InputArray _image, InputArray _mask, std::vector<KeyPoint>& keypoints,
|
||||||
OutputArray _descriptors, bool useProvidedKeypoints) const
|
OutputArray _descriptors, bool useProvidedKeypoints)
|
||||||
{
|
{
|
||||||
bool doOrientation=true;
|
bool doOrientation=true;
|
||||||
if (useProvidedKeypoints)
|
if (useProvidedKeypoints)
|
||||||
@ -536,7 +629,7 @@ BRISK::operator()( InputArray _image, InputArray _mask, std::vector<KeyPoint>& k
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BRISK::computeDescriptorsAndOrOrientation(InputArray _image, InputArray _mask, std::vector<KeyPoint>& keypoints,
|
BRISK_Impl::computeDescriptorsAndOrOrientation(InputArray _image, InputArray _mask, std::vector<KeyPoint>& keypoints,
|
||||||
OutputArray _descriptors, bool doDescriptors, bool doOrientation,
|
OutputArray _descriptors, bool doDescriptors, bool doOrientation,
|
||||||
bool useProvidedKeypoints) const
|
bool useProvidedKeypoints) const
|
||||||
{
|
{
|
||||||
@ -702,25 +795,8 @@ BRISK::computeDescriptorsAndOrOrientation(InputArray _image, InputArray _mask, s
|
|||||||
delete[] _values;
|
delete[] _values;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
BRISK::descriptorSize() const
|
|
||||||
{
|
|
||||||
return strings_;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
BRISK_Impl::~BRISK_Impl()
|
||||||
BRISK::descriptorType() const
|
|
||||||
{
|
|
||||||
return CV_8U;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
BRISK::defaultNorm() const
|
|
||||||
{
|
|
||||||
return NORM_HAMMING;
|
|
||||||
}
|
|
||||||
|
|
||||||
BRISK::~BRISK()
|
|
||||||
{
|
{
|
||||||
delete[] patternPoints_;
|
delete[] patternPoints_;
|
||||||
delete[] shortPairs_;
|
delete[] shortPairs_;
|
||||||
@ -730,14 +806,7 @@ BRISK::~BRISK()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BRISK::operator()(InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints) const
|
BRISK_Impl::computeKeypointsNoOrientation(InputArray _image, InputArray _mask, std::vector<KeyPoint>& keypoints) const
|
||||||
{
|
|
||||||
computeKeypointsNoOrientation(image, mask, keypoints);
|
|
||||||
computeDescriptorsAndOrOrientation(image, mask, keypoints, cv::noArray(), false, true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
BRISK::computeKeypointsNoOrientation(InputArray _image, InputArray _mask, std::vector<KeyPoint>& keypoints) const
|
|
||||||
{
|
{
|
||||||
Mat image = _image.getMat(), mask = _mask.getMat();
|
Mat image = _image.getMat(), mask = _mask.getMat();
|
||||||
if( image.type() != CV_8UC1 )
|
if( image.type() != CV_8UC1 )
|
||||||
@ -748,20 +817,7 @@ BRISK::computeKeypointsNoOrientation(InputArray _image, InputArray _mask, std::v
|
|||||||
briskScaleSpace.getKeypoints(threshold, keypoints);
|
briskScaleSpace.getKeypoints(threshold, keypoints);
|
||||||
|
|
||||||
// remove invalid points
|
// remove invalid points
|
||||||
removeInvalidPoints(mask, keypoints);
|
KeyPointsFilter::runByPixelsMask(keypoints, mask);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
BRISK::detectImpl( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask) const
|
|
||||||
{
|
|
||||||
(*this)(image.getMat(), mask.getMat(), keypoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
BRISK::computeImpl( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors) const
|
|
||||||
{
|
|
||||||
(*this)(image, Mat(), keypoints, descriptors, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// construct telling the octaves number:
|
// construct telling the octaves number:
|
||||||
@ -2011,7 +2067,7 @@ BriskLayer::BriskLayer(const cv::Mat& img_in, float scale_in, float offset_in)
|
|||||||
scale_ = scale_in;
|
scale_ = scale_in;
|
||||||
offset_ = offset_in;
|
offset_ = offset_in;
|
||||||
// create an agast detector
|
// create an agast detector
|
||||||
fast_9_16_ = makePtr<FastFeatureDetector>(1, true, FastFeatureDetector::TYPE_9_16);
|
fast_9_16_ = FastFeatureDetector::create(1, true, FastFeatureDetector::TYPE_9_16);
|
||||||
makeOffsets(pixel_5_8_, (int)img_.step, 8);
|
makeOffsets(pixel_5_8_, (int)img_.step, 8);
|
||||||
makeOffsets(pixel_9_16_, (int)img_.step, 16);
|
makeOffsets(pixel_9_16_, (int)img_.step, 16);
|
||||||
}
|
}
|
||||||
@ -2033,7 +2089,7 @@ BriskLayer::BriskLayer(const BriskLayer& layer, int mode)
|
|||||||
offset_ = 0.5f * scale_ - 0.5f;
|
offset_ = 0.5f * scale_ - 0.5f;
|
||||||
}
|
}
|
||||||
scores_ = cv::Mat::zeros(img_.rows, img_.cols, CV_8U);
|
scores_ = cv::Mat::zeros(img_.rows, img_.cols, CV_8U);
|
||||||
fast_9_16_ = makePtr<FastFeatureDetector>(1, false, FastFeatureDetector::TYPE_9_16);
|
fast_9_16_ = FastFeatureDetector::create(1, false, FastFeatureDetector::TYPE_9_16);
|
||||||
makeOffsets(pixel_5_8_, (int)img_.step, 8);
|
makeOffsets(pixel_5_8_, (int)img_.step, 8);
|
||||||
makeOffsets(pixel_9_16_, (int)img_.step, 16);
|
makeOffsets(pixel_9_16_, (int)img_.step, 16);
|
||||||
}
|
}
|
||||||
@ -2043,7 +2099,7 @@ BriskLayer::BriskLayer(const BriskLayer& layer, int mode)
|
|||||||
void
|
void
|
||||||
BriskLayer::getAgastPoints(int threshold, std::vector<KeyPoint>& keypoints)
|
BriskLayer::getAgastPoints(int threshold, std::vector<KeyPoint>& keypoints)
|
||||||
{
|
{
|
||||||
fast_9_16_->set("threshold", threshold);
|
fast_9_16_->set(FastFeatureDetector::THRESHOLD, threshold);
|
||||||
fast_9_16_->detect(img_, keypoints);
|
fast_9_16_->detect(img_, keypoints);
|
||||||
|
|
||||||
// also write scores
|
// also write scores
|
||||||
@ -2245,4 +2301,16 @@ BriskLayer::twothirdsample(const cv::Mat& srcimg, cv::Mat& dstimg)
|
|||||||
resize(srcimg, dstimg, dstimg.size(), 0, 0, INTER_AREA);
|
resize(srcimg, dstimg, dstimg.size(), 0, 0, INTER_AREA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ptr<BRISK> BRISK::create(int thresh, int octaves, float patternScale)
|
||||||
|
{
|
||||||
|
return makePtr<BRISK_Impl>(thresh, octaves, patternScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
// custom setup
|
||||||
|
Ptr<BRISK> BRISK::create(const std::vector<float> &radiusList, const std::vector<int> &numberList,
|
||||||
|
float dMax, float dMin, const std::vector<int>& indexChange)
|
||||||
|
{
|
||||||
|
return makePtr<BRISK_Impl>(radiusList, numberList, dMax, dMin, indexChange);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,110 +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.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Intel License Agreement
|
|
||||||
// For Open Source Computer Vision Library
|
|
||||||
//
|
|
||||||
// Copyright (C) 2000, Intel Corporation, 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"
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
namespace cv
|
|
||||||
{
|
|
||||||
|
|
||||||
/****************************************************************************************\
|
|
||||||
* DescriptorExtractor *
|
|
||||||
\****************************************************************************************/
|
|
||||||
/*
|
|
||||||
* DescriptorExtractor
|
|
||||||
*/
|
|
||||||
DescriptorExtractor::~DescriptorExtractor()
|
|
||||||
{}
|
|
||||||
|
|
||||||
void DescriptorExtractor::compute( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors ) const
|
|
||||||
{
|
|
||||||
if( image.empty() || keypoints.empty() )
|
|
||||||
{
|
|
||||||
descriptors.release();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyPointsFilter::runByImageBorder( keypoints, image.size(), 0 );
|
|
||||||
KeyPointsFilter::runByKeypointSize( keypoints, std::numeric_limits<float>::epsilon() );
|
|
||||||
|
|
||||||
computeImpl( image, keypoints, descriptors );
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptorExtractor::compute( InputArrayOfArrays _imageCollection, std::vector<std::vector<KeyPoint> >& pointCollection, OutputArrayOfArrays _descCollection ) const
|
|
||||||
{
|
|
||||||
std::vector<Mat> imageCollection, descCollection;
|
|
||||||
_imageCollection.getMatVector(imageCollection);
|
|
||||||
_descCollection.getMatVector(descCollection);
|
|
||||||
CV_Assert( imageCollection.size() == pointCollection.size() );
|
|
||||||
descCollection.resize( imageCollection.size() );
|
|
||||||
for( size_t i = 0; i < imageCollection.size(); i++ )
|
|
||||||
compute( imageCollection[i], pointCollection[i], descCollection[i] );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*void DescriptorExtractor::read( const FileNode& )
|
|
||||||
{}
|
|
||||||
|
|
||||||
void DescriptorExtractor::write( FileStorage& ) const
|
|
||||||
{}*/
|
|
||||||
|
|
||||||
bool DescriptorExtractor::empty() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptorExtractor::removeBorderKeypoints( std::vector<KeyPoint>& keypoints,
|
|
||||||
Size imageSize, int borderSize )
|
|
||||||
{
|
|
||||||
KeyPointsFilter::runByImageBorder( keypoints, imageSize, borderSize );
|
|
||||||
}
|
|
||||||
|
|
||||||
Ptr<DescriptorExtractor> DescriptorExtractor::create(const String& descriptorExtractorType)
|
|
||||||
{
|
|
||||||
return Algorithm::create<DescriptorExtractor>("Feature2D." + descriptorExtractorType);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CV_WRAP void Feature2D::compute( InputArray image, CV_OUT CV_IN_OUT std::vector<KeyPoint>& keypoints, OutputArray descriptors ) const
|
|
||||||
{
|
|
||||||
DescriptorExtractor::compute(image, keypoints, descriptors);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,161 +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.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Intel License Agreement
|
|
||||||
// For Open Source Computer Vision Library
|
|
||||||
//
|
|
||||||
// Copyright (C) 2000, Intel Corporation, 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
|
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FeatureDetector
|
|
||||||
*/
|
|
||||||
|
|
||||||
FeatureDetector::~FeatureDetector()
|
|
||||||
{}
|
|
||||||
|
|
||||||
void FeatureDetector::detect( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask ) const
|
|
||||||
{
|
|
||||||
keypoints.clear();
|
|
||||||
|
|
||||||
if( image.empty() )
|
|
||||||
return;
|
|
||||||
|
|
||||||
CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()) );
|
|
||||||
|
|
||||||
detectImpl( image, keypoints, mask );
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeatureDetector::detect(InputArrayOfArrays _imageCollection, std::vector<std::vector<KeyPoint> >& pointCollection,
|
|
||||||
InputArrayOfArrays _masks ) const
|
|
||||||
{
|
|
||||||
if (_imageCollection.isUMatVector())
|
|
||||||
{
|
|
||||||
std::vector<UMat> uimageCollection, umasks;
|
|
||||||
_imageCollection.getUMatVector(uimageCollection);
|
|
||||||
_masks.getUMatVector(umasks);
|
|
||||||
|
|
||||||
pointCollection.resize( uimageCollection.size() );
|
|
||||||
for( size_t i = 0; i < uimageCollection.size(); i++ )
|
|
||||||
detect( uimageCollection[i], pointCollection[i], umasks.empty() ? noArray() : umasks[i] );
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Mat> imageCollection, masks;
|
|
||||||
_imageCollection.getMatVector(imageCollection);
|
|
||||||
_masks.getMatVector(masks);
|
|
||||||
|
|
||||||
pointCollection.resize( imageCollection.size() );
|
|
||||||
for( size_t i = 0; i < imageCollection.size(); i++ )
|
|
||||||
detect( imageCollection[i], pointCollection[i], masks.empty() ? noArray() : masks[i] );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*void FeatureDetector::read( const FileNode& )
|
|
||||||
{}
|
|
||||||
|
|
||||||
void FeatureDetector::write( FileStorage& ) const
|
|
||||||
{}*/
|
|
||||||
|
|
||||||
bool FeatureDetector::empty() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeatureDetector::removeInvalidPoints( const Mat& mask, std::vector<KeyPoint>& keypoints )
|
|
||||||
{
|
|
||||||
KeyPointsFilter::runByPixelsMask( keypoints, mask );
|
|
||||||
}
|
|
||||||
|
|
||||||
Ptr<FeatureDetector> FeatureDetector::create( const String& detectorType )
|
|
||||||
{
|
|
||||||
if( detectorType.compare( "HARRIS" ) == 0 )
|
|
||||||
{
|
|
||||||
Ptr<FeatureDetector> fd = FeatureDetector::create("GFTT");
|
|
||||||
fd->set("useHarrisDetector", true);
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Algorithm::create<FeatureDetector>("Feature2D." + detectorType);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
GFTTDetector::GFTTDetector( int _nfeatures, double _qualityLevel,
|
|
||||||
double _minDistance, int _blockSize,
|
|
||||||
bool _useHarrisDetector, double _k )
|
|
||||||
: nfeatures(_nfeatures), qualityLevel(_qualityLevel), minDistance(_minDistance),
|
|
||||||
blockSize(_blockSize), useHarrisDetector(_useHarrisDetector), k(_k)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void GFTTDetector::detectImpl( InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask) const
|
|
||||||
{
|
|
||||||
std::vector<Point2f> corners;
|
|
||||||
|
|
||||||
if (_image.isUMat())
|
|
||||||
{
|
|
||||||
UMat ugrayImage;
|
|
||||||
if( _image.type() != CV_8U )
|
|
||||||
cvtColor( _image, ugrayImage, COLOR_BGR2GRAY );
|
|
||||||
else
|
|
||||||
ugrayImage = _image.getUMat();
|
|
||||||
|
|
||||||
goodFeaturesToTrack( ugrayImage, corners, nfeatures, qualityLevel, minDistance, _mask,
|
|
||||||
blockSize, useHarrisDetector, k );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Mat image = _image.getMat(), grayImage = image;
|
|
||||||
if( image.type() != CV_8U )
|
|
||||||
cvtColor( image, grayImage, COLOR_BGR2GRAY );
|
|
||||||
|
|
||||||
goodFeaturesToTrack( grayImage, corners, nfeatures, qualityLevel, minDistance, _mask,
|
|
||||||
blockSize, useHarrisDetector, k );
|
|
||||||
}
|
|
||||||
|
|
||||||
keypoints.resize(corners.size());
|
|
||||||
std::vector<Point2f>::const_iterator corner_it = corners.begin();
|
|
||||||
std::vector<KeyPoint>::iterator keypoint_it = keypoints.begin();
|
|
||||||
for( ; corner_it != corners.end(); ++corner_it, ++keypoint_it )
|
|
||||||
*keypoint_it = KeyPoint( *corner_it, (float)blockSize );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -359,19 +359,17 @@ void FAST(InputArray _img, std::vector<KeyPoint>& keypoints, int threshold, bool
|
|||||||
{
|
{
|
||||||
FAST(_img, keypoints, threshold, nonmax_suppression, FastFeatureDetector::TYPE_9_16);
|
FAST(_img, keypoints, threshold, nonmax_suppression, FastFeatureDetector::TYPE_9_16);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* FastFeatureDetector
|
|
||||||
*/
|
|
||||||
FastFeatureDetector::FastFeatureDetector( int _threshold, bool _nonmaxSuppression )
|
|
||||||
: threshold(_threshold), nonmaxSuppression(_nonmaxSuppression), type(FastFeatureDetector::TYPE_9_16)
|
|
||||||
{}
|
|
||||||
|
|
||||||
FastFeatureDetector::FastFeatureDetector( int _threshold, bool _nonmaxSuppression, int _type )
|
|
||||||
: threshold(_threshold), nonmaxSuppression(_nonmaxSuppression), type((short)_type)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void FastFeatureDetector::detectImpl( InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask ) const
|
class FastFeatureDetector_Impl : public FastFeatureDetector
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
FastFeatureDetector_Impl( int _threshold, bool _nonmaxSuppression, int _type )
|
||||||
|
: threshold(_threshold), nonmaxSuppression(_nonmaxSuppression), type((short)_type)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void detect( InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask )
|
||||||
|
{
|
||||||
Mat mask = _mask.getMat(), grayImage;
|
Mat mask = _mask.getMat(), grayImage;
|
||||||
UMat ugrayImage;
|
UMat ugrayImage;
|
||||||
_InputArray gray = _image;
|
_InputArray gray = _image;
|
||||||
@ -383,6 +381,41 @@ void FastFeatureDetector::detectImpl( InputArray _image, std::vector<KeyPoint>&
|
|||||||
}
|
}
|
||||||
FAST( gray, keypoints, threshold, nonmaxSuppression, type );
|
FAST( gray, keypoints, threshold, nonmaxSuppression, type );
|
||||||
KeyPointsFilter::runByPixelsMask( keypoints, mask );
|
KeyPointsFilter::runByPixelsMask( keypoints, mask );
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(int prop, double value)
|
||||||
|
{
|
||||||
|
if(prop == THRESHOLD)
|
||||||
|
threshold = cvRound(value);
|
||||||
|
else if(prop == NONMAX_SUPPRESSION)
|
||||||
|
nonmaxSuppression = value != 0;
|
||||||
|
else if(prop == FAST_N)
|
||||||
|
type = cvRound(value);
|
||||||
|
else
|
||||||
|
CV_Error(Error::StsBadArg, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
double get(int prop) const
|
||||||
|
{
|
||||||
|
if(prop == THRESHOLD)
|
||||||
|
return threshold;
|
||||||
|
if(prop == NONMAX_SUPPRESSION)
|
||||||
|
return nonmaxSuppression;
|
||||||
|
if(prop == FAST_N)
|
||||||
|
return type;
|
||||||
|
CV_Error(Error::StsBadArg, "");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int threshold;
|
||||||
|
bool nonmaxSuppression;
|
||||||
|
int type;
|
||||||
|
};
|
||||||
|
|
||||||
|
Ptr<FastFeatureDetector> FastFeatureDetector::create( int threshold, bool nonmaxSuppression, int type )
|
||||||
|
{
|
||||||
|
return makePtr<FastFeatureDetector_Impl>(threshold, nonmaxSuppression, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
169
modules/features2d/src/feature2d.cpp
Normal file
169
modules/features2d/src/feature2d.cpp
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/*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, 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"
|
||||||
|
|
||||||
|
namespace cv
|
||||||
|
{
|
||||||
|
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
Feature2D::~Feature2D() {}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Detect keypoints in an image.
|
||||||
|
* image The image.
|
||||||
|
* keypoints The detected keypoints.
|
||||||
|
* mask Mask specifying where to look for keypoints (optional). Must be a char
|
||||||
|
* matrix with non-zero values in the region of interest.
|
||||||
|
*/
|
||||||
|
void Feature2D::detect( InputArray image,
|
||||||
|
std::vector<KeyPoint>& keypoints,
|
||||||
|
InputArray mask )
|
||||||
|
{
|
||||||
|
if( image.empty() )
|
||||||
|
{
|
||||||
|
keypoints.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
detectAndCompute(image, mask, keypoints, noArray(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Feature2D::detect( InputArrayOfArrays _images,
|
||||||
|
std::vector<std::vector<KeyPoint> >& keypoints,
|
||||||
|
InputArrayOfArrays _masks )
|
||||||
|
{
|
||||||
|
vector<Mat> images, masks;
|
||||||
|
|
||||||
|
_images.getMatVector(images);
|
||||||
|
size_t i, nimages = images.size();
|
||||||
|
|
||||||
|
if( !_masks.empty() )
|
||||||
|
{
|
||||||
|
_masks.getMatVector(masks);
|
||||||
|
CV_Assert(masks.size() == nimages);
|
||||||
|
}
|
||||||
|
|
||||||
|
keypoints.resize(nimages);
|
||||||
|
|
||||||
|
for( i = 0; i < nimages; i++ )
|
||||||
|
{
|
||||||
|
detect(images[i], keypoints[i], masks.empty() ? Mat() : masks[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute the descriptors for a set of keypoints in an image.
|
||||||
|
* image The image.
|
||||||
|
* keypoints The input keypoints. Keypoints for which a descriptor cannot be computed are removed.
|
||||||
|
* descriptors Copmputed descriptors. Row i is the descriptor for keypoint i.
|
||||||
|
*/
|
||||||
|
void Feature2D::compute( InputArray image,
|
||||||
|
std::vector<KeyPoint>& keypoints,
|
||||||
|
OutputArray descriptors )
|
||||||
|
{
|
||||||
|
if( image.empty() )
|
||||||
|
{
|
||||||
|
descriptors.release();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
detectAndCompute(image, noArray(), keypoints, descriptors, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Feature2D::compute( InputArrayOfArrays _images,
|
||||||
|
std::vector<std::vector<KeyPoint> >& keypoints,
|
||||||
|
OutputArrayOfArrays _descriptors )
|
||||||
|
{
|
||||||
|
if( !_descriptors.needed() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
vector<Mat> images;
|
||||||
|
|
||||||
|
_images.getMatVector(images);
|
||||||
|
size_t i, nimages = images.size();
|
||||||
|
|
||||||
|
CV_Assert( keypoints.size() == nimages );
|
||||||
|
CV_Assert( _descriptors.kind() == _InputArray::STD_VECTOR_MAT );
|
||||||
|
|
||||||
|
vector<Mat>& descriptors = *(vector<Mat>*)_descriptors.getObj();
|
||||||
|
descriptors.resize(nimages);
|
||||||
|
|
||||||
|
for( i = 0; i < nimages; i++ )
|
||||||
|
{
|
||||||
|
compute(images[i], keypoints[i], descriptors[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Detects keypoints and computes the descriptors */
|
||||||
|
void Feature2D::detectAndCompute( InputArray, InputArray,
|
||||||
|
std::vector<KeyPoint>&,
|
||||||
|
OutputArray,
|
||||||
|
bool )
|
||||||
|
{
|
||||||
|
CV_Error(Error::StsNotImplemented, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
int Feature2D::descriptorSize() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Feature2D::descriptorType() const
|
||||||
|
{
|
||||||
|
return CV_32F;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Feature2D::defaultNorm() const
|
||||||
|
{
|
||||||
|
int tp = descriptorType();
|
||||||
|
return tp == CV_8U ? NORM_HAMMING : NORM_L2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if detector object is empty
|
||||||
|
bool Feature2D::empty() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,195 +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, 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"
|
|
||||||
|
|
||||||
using namespace cv;
|
|
||||||
|
|
||||||
Ptr<Feature2D> Feature2D::create( const String& feature2DType )
|
|
||||||
{
|
|
||||||
return Algorithm::create<Feature2D>("Feature2D." + feature2DType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////// AlgorithmInfo for various detector & descriptors ////////////////////////////
|
|
||||||
|
|
||||||
/* NOTE!!!
|
|
||||||
All the AlgorithmInfo-related stuff should be in the same file as initModule_features2d().
|
|
||||||
Otherwise, linker may throw away some seemingly unused stuff.
|
|
||||||
*/
|
|
||||||
|
|
||||||
CV_INIT_ALGORITHM(BRISK, "Feature2D.BRISK",
|
|
||||||
obj.info()->addParam(obj, "thres", obj.threshold);
|
|
||||||
obj.info()->addParam(obj, "octaves", obj.octaves))
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
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(MSER, "Feature2D.MSER",
|
|
||||||
obj.info()->addParam(obj, "delta", obj.delta);
|
|
||||||
obj.info()->addParam(obj, "minArea", obj.minArea);
|
|
||||||
obj.info()->addParam(obj, "maxArea", obj.maxArea);
|
|
||||||
obj.info()->addParam(obj, "maxVariation", obj.maxVariation);
|
|
||||||
obj.info()->addParam(obj, "minDiversity", obj.minDiversity);
|
|
||||||
obj.info()->addParam(obj, "maxEvolution", obj.maxEvolution);
|
|
||||||
obj.info()->addParam(obj, "areaThreshold", obj.areaThreshold);
|
|
||||||
obj.info()->addParam(obj, "minMargin", obj.minMargin);
|
|
||||||
obj.info()->addParam(obj, "edgeBlurSize", obj.edgeBlurSize))
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
CV_INIT_ALGORITHM(ORB, "Feature2D.ORB",
|
|
||||||
obj.info()->addParam(obj, "nFeatures", obj.nfeatures);
|
|
||||||
obj.info()->addParam(obj, "scaleFactor", obj.scaleFactor);
|
|
||||||
obj.info()->addParam(obj, "nLevels", obj.nlevels);
|
|
||||||
obj.info()->addParam(obj, "firstLevel", obj.firstLevel);
|
|
||||||
obj.info()->addParam(obj, "edgeThreshold", obj.edgeThreshold);
|
|
||||||
obj.info()->addParam(obj, "patchSize", obj.patchSize);
|
|
||||||
obj.info()->addParam(obj, "WTA_K", obj.WTA_K);
|
|
||||||
obj.info()->addParam(obj, "scoreType", obj.scoreType);
|
|
||||||
obj.info()->addParam(obj, "fastThreshold", obj.fastThreshold))
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
CV_INIT_ALGORITHM(GFTTDetector, "Feature2D.GFTT",
|
|
||||||
obj.info()->addParam(obj, "nfeatures", obj.nfeatures);
|
|
||||||
obj.info()->addParam(obj, "qualityLevel", obj.qualityLevel);
|
|
||||||
obj.info()->addParam(obj, "minDistance", obj.minDistance);
|
|
||||||
obj.info()->addParam(obj, "useHarrisDetector", obj.useHarrisDetector);
|
|
||||||
obj.info()->addParam(obj, "k", obj.k))
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
CV_INIT_ALGORITHM(KAZE, "Feature2D.KAZE",
|
|
||||||
obj.info()->addParam(obj, "upright", obj.upright);
|
|
||||||
obj.info()->addParam(obj, "extended", obj.extended);
|
|
||||||
obj.info()->addParam(obj, "threshold", obj.threshold);
|
|
||||||
obj.info()->addParam(obj, "octaves", obj.octaves);
|
|
||||||
obj.info()->addParam(obj, "sublevels", obj.sublevels);
|
|
||||||
obj.info()->addParam(obj, "diffusivity", obj.diffusivity))
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
CV_INIT_ALGORITHM(AKAZE, "Feature2D.AKAZE",
|
|
||||||
obj.info()->addParam(obj, "descriptor", obj.descriptor);
|
|
||||||
obj.info()->addParam(obj, "descriptor_channels", obj.descriptor_channels);
|
|
||||||
obj.info()->addParam(obj, "descriptor_size", obj.descriptor_size);
|
|
||||||
obj.info()->addParam(obj, "threshold", obj.threshold);
|
|
||||||
obj.info()->addParam(obj, "octaves", obj.octaves);
|
|
||||||
obj.info()->addParam(obj, "sublevels", obj.sublevels);
|
|
||||||
obj.info()->addParam(obj, "diffusivity", obj.diffusivity))
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CV_INIT_ALGORITHM(SimpleBlobDetector, "Feature2D.SimpleBlob",
|
|
||||||
obj.info()->addParam(obj, "thresholdStep", obj.params.thresholdStep);
|
|
||||||
obj.info()->addParam(obj, "minThreshold", obj.params.minThreshold);
|
|
||||||
obj.info()->addParam(obj, "maxThreshold", obj.params.maxThreshold);
|
|
||||||
obj.info()->addParam_(obj, "minRepeatability", (sizeof(size_t) == sizeof(uint64))?Param::UINT64 : Param::UNSIGNED_INT, &obj.params.minRepeatability, false, 0, 0);
|
|
||||||
obj.info()->addParam(obj, "minDistBetweenBlobs", obj.params.minDistBetweenBlobs);
|
|
||||||
obj.info()->addParam(obj, "filterByColor", obj.params.filterByColor);
|
|
||||||
obj.info()->addParam(obj, "blobColor", obj.params.blobColor);
|
|
||||||
obj.info()->addParam(obj, "filterByArea", obj.params.filterByArea);
|
|
||||||
obj.info()->addParam(obj, "maxArea", obj.params.maxArea);
|
|
||||||
obj.info()->addParam(obj, "filterByCircularity", obj.params.filterByCircularity);
|
|
||||||
obj.info()->addParam(obj, "maxCircularity", obj.params.maxCircularity);
|
|
||||||
obj.info()->addParam(obj, "filterByInertia", obj.params.filterByInertia);
|
|
||||||
obj.info()->addParam(obj, "maxInertiaRatio", obj.params.maxInertiaRatio);
|
|
||||||
obj.info()->addParam(obj, "filterByConvexity", obj.params.filterByConvexity);
|
|
||||||
obj.info()->addParam(obj, "maxConvexity", obj.params.maxConvexity);
|
|
||||||
)
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
class CV_EXPORTS HarrisDetector : public GFTTDetector
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HarrisDetector( int maxCorners=1000, double qualityLevel=0.01, double minDistance=1,
|
|
||||||
int blockSize=3, bool useHarrisDetector=true, double k=0.04 );
|
|
||||||
AlgorithmInfo* info() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline HarrisDetector::HarrisDetector( int _maxCorners, double _qualityLevel, double _minDistance,
|
|
||||||
int _blockSize, bool _useHarrisDetector, double _k )
|
|
||||||
: GFTTDetector( _maxCorners, _qualityLevel, _minDistance, _blockSize, _useHarrisDetector, _k ) {}
|
|
||||||
|
|
||||||
CV_INIT_ALGORITHM(HarrisDetector, "Feature2D.HARRIS",
|
|
||||||
obj.info()->addParam(obj, "nfeatures", obj.nfeatures);
|
|
||||||
obj.info()->addParam(obj, "qualityLevel", obj.qualityLevel);
|
|
||||||
obj.info()->addParam(obj, "minDistance", obj.minDistance);
|
|
||||||
obj.info()->addParam(obj, "useHarrisDetector", obj.useHarrisDetector);
|
|
||||||
obj.info()->addParam(obj, "k", obj.k))
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
CV_INIT_ALGORITHM(BFMatcher, "DescriptorMatcher.BFMatcher",
|
|
||||||
obj.info()->addParam(obj, "normType", obj.normType);
|
|
||||||
obj.info()->addParam(obj, "crossCheck", obj.crossCheck))
|
|
||||||
|
|
||||||
CV_INIT_ALGORITHM(FlannBasedMatcher, "DescriptorMatcher.FlannBasedMatcher",)
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
bool cv::initModule_features2d(void)
|
|
||||||
{
|
|
||||||
bool all = true;
|
|
||||||
all &= !BRISK_info_auto.name().empty();
|
|
||||||
all &= !FastFeatureDetector_info_auto.name().empty();
|
|
||||||
all &= !MSER_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 &= !BFMatcher_info_auto.name().empty();
|
|
||||||
all &= !FlannBasedMatcher_info_auto.name().empty();
|
|
||||||
|
|
||||||
return all;
|
|
||||||
}
|
|
126
modules/features2d/src/gftt.cpp
Normal file
126
modules/features2d/src/gftt.cpp
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*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.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Intel License Agreement
|
||||||
|
// For Open Source Computer Vision Library
|
||||||
|
//
|
||||||
|
// Copyright (C) 2000, Intel Corporation, 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
|
||||||
|
{
|
||||||
|
|
||||||
|
class GFTTDetector_Impl : public GFTTDetector
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GFTTDetector_Impl( int _nfeatures, double _qualityLevel,
|
||||||
|
double _minDistance, int _blockSize,
|
||||||
|
bool _useHarrisDetector, double _k )
|
||||||
|
: nfeatures(_nfeatures), qualityLevel(_qualityLevel), minDistance(_minDistance),
|
||||||
|
blockSize(_blockSize), useHarrisDetector(_useHarrisDetector), k(_k)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(int prop, double value)
|
||||||
|
{
|
||||||
|
if( prop == USE_HARRIS_DETECTOR )
|
||||||
|
useHarrisDetector = value != 0;
|
||||||
|
else
|
||||||
|
CV_Error(Error::StsBadArg, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
double get(int prop) const
|
||||||
|
{
|
||||||
|
double value = 0;
|
||||||
|
if( prop == USE_HARRIS_DETECTOR )
|
||||||
|
value = useHarrisDetector;
|
||||||
|
else
|
||||||
|
CV_Error(Error::StsBadArg, "");
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void detect( InputArray _image, std::vector<KeyPoint>& keypoints, InputArray _mask )
|
||||||
|
{
|
||||||
|
std::vector<Point2f> corners;
|
||||||
|
|
||||||
|
if (_image.isUMat())
|
||||||
|
{
|
||||||
|
UMat ugrayImage;
|
||||||
|
if( _image.type() != CV_8U )
|
||||||
|
cvtColor( _image, ugrayImage, COLOR_BGR2GRAY );
|
||||||
|
else
|
||||||
|
ugrayImage = _image.getUMat();
|
||||||
|
|
||||||
|
goodFeaturesToTrack( ugrayImage, corners, nfeatures, qualityLevel, minDistance, _mask,
|
||||||
|
blockSize, useHarrisDetector, k );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Mat image = _image.getMat(), grayImage = image;
|
||||||
|
if( image.type() != CV_8U )
|
||||||
|
cvtColor( image, grayImage, COLOR_BGR2GRAY );
|
||||||
|
|
||||||
|
goodFeaturesToTrack( grayImage, corners, nfeatures, qualityLevel, minDistance, _mask,
|
||||||
|
blockSize, useHarrisDetector, k );
|
||||||
|
}
|
||||||
|
|
||||||
|
keypoints.resize(corners.size());
|
||||||
|
std::vector<Point2f>::const_iterator corner_it = corners.begin();
|
||||||
|
std::vector<KeyPoint>::iterator keypoint_it = keypoints.begin();
|
||||||
|
for( ; corner_it != corners.end(); ++corner_it, ++keypoint_it )
|
||||||
|
*keypoint_it = KeyPoint( *corner_it, (float)blockSize );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int nfeatures;
|
||||||
|
double qualityLevel;
|
||||||
|
double minDistance;
|
||||||
|
int blockSize;
|
||||||
|
bool useHarrisDetector;
|
||||||
|
double k;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Ptr<GFTTDetector> GFTTDetector::create( int _nfeatures, double _qualityLevel,
|
||||||
|
double _minDistance, int _blockSize,
|
||||||
|
bool _useHarrisDetector, double _k )
|
||||||
|
{
|
||||||
|
return makePtr<GFTTDetector_Impl>(_nfeatures, _qualityLevel,
|
||||||
|
_minDistance, _blockSize, _useHarrisDetector, _k);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -52,17 +52,11 @@ http://www.robesafe.com/personal/pablo.alcantarilla/papers/Alcantarilla12eccv.pd
|
|||||||
|
|
||||||
namespace cv
|
namespace cv
|
||||||
{
|
{
|
||||||
KAZE::KAZE()
|
|
||||||
: extended(false)
|
|
||||||
, upright(false)
|
|
||||||
, threshold(0.001f)
|
|
||||||
, octaves(4)
|
|
||||||
, sublevels(4)
|
|
||||||
, diffusivity(DIFF_PM_G2)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
KAZE::KAZE(bool _extended, bool _upright, float _threshold, int _octaves,
|
class KAZE_Impl : public KAZE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KAZE_Impl(bool _extended, bool _upright, float _threshold, int _octaves,
|
||||||
int _sublevels, int _diffusivity)
|
int _sublevels, int _diffusivity)
|
||||||
: extended(_extended)
|
: extended(_extended)
|
||||||
, upright(_upright)
|
, upright(_upright)
|
||||||
@ -71,40 +65,32 @@ namespace cv
|
|||||||
, sublevels(_sublevels)
|
, sublevels(_sublevels)
|
||||||
, diffusivity(_diffusivity)
|
, diffusivity(_diffusivity)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
KAZE::~KAZE()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
virtual ~KAZE_Impl() {}
|
||||||
|
|
||||||
// returns the descriptor size in bytes
|
// returns the descriptor size in bytes
|
||||||
int KAZE::descriptorSize() const
|
int descriptorSize() const
|
||||||
{
|
{
|
||||||
return extended ? 128 : 64;
|
return extended ? 128 : 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the descriptor type
|
// returns the descriptor type
|
||||||
int KAZE::descriptorType() const
|
int descriptorType() const
|
||||||
{
|
{
|
||||||
return CV_32F;
|
return CV_32F;
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the default norm type
|
// returns the default norm type
|
||||||
int KAZE::defaultNorm() const
|
int defaultNorm() const
|
||||||
{
|
{
|
||||||
return NORM_L2;
|
return NORM_L2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KAZE::operator()(InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints) const
|
void detectAndCompute(InputArray image, InputArray mask,
|
||||||
{
|
|
||||||
detectImpl(image, keypoints, mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KAZE::operator()(InputArray image, InputArray mask,
|
|
||||||
std::vector<KeyPoint>& keypoints,
|
std::vector<KeyPoint>& keypoints,
|
||||||
OutputArray descriptors,
|
OutputArray descriptors,
|
||||||
bool useProvidedKeypoints) const
|
bool useProvidedKeypoints)
|
||||||
{
|
{
|
||||||
cv::Mat img = image.getMat();
|
cv::Mat img = image.getMat();
|
||||||
if (img.type() != CV_8UC1)
|
if (img.type() != CV_8UC1)
|
||||||
@ -113,8 +99,6 @@ namespace cv
|
|||||||
Mat img1_32;
|
Mat img1_32;
|
||||||
img.convertTo(img1_32, CV_32F, 1.0 / 255.0, 0);
|
img.convertTo(img1_32, CV_32F, 1.0 / 255.0, 0);
|
||||||
|
|
||||||
cv::Mat& desc = descriptors.getMatRef();
|
|
||||||
|
|
||||||
KAZEOptions options;
|
KAZEOptions options;
|
||||||
options.img_width = img.cols;
|
options.img_width = img.cols;
|
||||||
options.img_height = img.rows;
|
options.img_height = img.rows;
|
||||||
@ -138,67 +122,49 @@ namespace cv
|
|||||||
cv::KeyPointsFilter::runByPixelsMask(keypoints, mask.getMat());
|
cv::KeyPointsFilter::runByPixelsMask(keypoints, mask.getMat());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( descriptors.needed() )
|
||||||
|
{
|
||||||
|
Mat& desc = descriptors.getMatRef();
|
||||||
impl.Feature_Description(keypoints, desc);
|
impl.Feature_Description(keypoints, desc);
|
||||||
|
|
||||||
CV_Assert((!desc.rows || desc.cols == descriptorSize()));
|
CV_Assert((!desc.rows || desc.cols == descriptorSize()));
|
||||||
CV_Assert((!desc.rows || (desc.type() == descriptorType())));
|
CV_Assert((!desc.rows || (desc.type() == descriptorType())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void KAZE::detectImpl(InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask) const
|
|
||||||
{
|
|
||||||
Mat img = image.getMat();
|
|
||||||
if (img.type() != CV_8UC1)
|
|
||||||
cvtColor(image, img, COLOR_BGR2GRAY);
|
|
||||||
|
|
||||||
Mat img1_32;
|
|
||||||
img.convertTo(img1_32, CV_32F, 1.0 / 255.0, 0);
|
|
||||||
|
|
||||||
KAZEOptions options;
|
|
||||||
options.img_width = img.cols;
|
|
||||||
options.img_height = img.rows;
|
|
||||||
options.extended = extended;
|
|
||||||
options.upright = upright;
|
|
||||||
options.dthreshold = threshold;
|
|
||||||
options.omax = octaves;
|
|
||||||
options.nsublevels = sublevels;
|
|
||||||
options.diffusivity = diffusivity;
|
|
||||||
|
|
||||||
KAZEFeatures impl(options);
|
|
||||||
impl.Create_Nonlinear_Scale_Space(img1_32);
|
|
||||||
impl.Feature_Detection(keypoints);
|
|
||||||
|
|
||||||
if (!mask.empty())
|
|
||||||
{
|
|
||||||
cv::KeyPointsFilter::runByPixelsMask(keypoints, mask.getMat());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KAZE::computeImpl(InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors) const
|
void write(FileStorage& fs) const
|
||||||
{
|
{
|
||||||
cv::Mat img = image.getMat();
|
fs << "extended" << (int)extended;
|
||||||
if (img.type() != CV_8UC1)
|
fs << "upright" << (int)upright;
|
||||||
cvtColor(image, img, COLOR_BGR2GRAY);
|
fs << "threshold" << threshold;
|
||||||
|
fs << "octaves" << octaves;
|
||||||
|
fs << "sublevels" << sublevels;
|
||||||
|
fs << "diffusivity" << diffusivity;
|
||||||
|
}
|
||||||
|
|
||||||
Mat img1_32;
|
void read(const FileNode& fn)
|
||||||
img.convertTo(img1_32, CV_32F, 1.0 / 255.0, 0);
|
{
|
||||||
|
extended = (int)fn["extended"] != 0;
|
||||||
|
upright = (int)fn["upright"] != 0;
|
||||||
|
threshold = (float)fn["threshold"];
|
||||||
|
octaves = (int)fn["octaves"];
|
||||||
|
sublevels = (int)fn["sublevels"];
|
||||||
|
diffusivity = (int)fn["diffusivity"];
|
||||||
|
}
|
||||||
|
|
||||||
cv::Mat& desc = descriptors.getMatRef();
|
bool extended;
|
||||||
|
bool upright;
|
||||||
|
float threshold;
|
||||||
|
int octaves;
|
||||||
|
int sublevels;
|
||||||
|
int diffusivity;
|
||||||
|
};
|
||||||
|
|
||||||
KAZEOptions options;
|
Ptr<KAZE> KAZE::create(bool extended, bool upright,
|
||||||
options.img_width = img.cols;
|
float threshold,
|
||||||
options.img_height = img.rows;
|
int octaves, int sublevels,
|
||||||
options.extended = extended;
|
int diffusivity)
|
||||||
options.upright = upright;
|
{
|
||||||
options.dthreshold = threshold;
|
return makePtr<KAZE_Impl>(extended, upright, threshold, octaves, sublevels, diffusivity);
|
||||||
options.omax = octaves;
|
|
||||||
options.nsublevels = sublevels;
|
|
||||||
options.diffusivity = diffusivity;
|
|
||||||
|
|
||||||
KAZEFeatures impl(options);
|
|
||||||
impl.Create_Nonlinear_Scale_Space(img1_32);
|
|
||||||
impl.Feature_Description(keypoints, desc);
|
|
||||||
|
|
||||||
CV_Assert((!desc.rows || desc.cols == descriptorSize()));
|
|
||||||
CV_Assert((!desc.rows || (desc.type() == descriptorType())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,23 +8,8 @@
|
|||||||
#ifndef __OPENCV_FEATURES_2D_AKAZE_CONFIG_H__
|
#ifndef __OPENCV_FEATURES_2D_AKAZE_CONFIG_H__
|
||||||
#define __OPENCV_FEATURES_2D_AKAZE_CONFIG_H__
|
#define __OPENCV_FEATURES_2D_AKAZE_CONFIG_H__
|
||||||
|
|
||||||
/* ************************************************************************* */
|
namespace cv
|
||||||
// OpenCV
|
{
|
||||||
#include "../precomp.hpp"
|
|
||||||
#include <opencv2/features2d.hpp>
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
|
||||||
/// Lookup table for 2d gaussian (sigma = 2.5) where (0,0) is top left and (6,6) is bottom right
|
|
||||||
const float gauss25[7][7] = {
|
|
||||||
{ 0.02546481f, 0.02350698f, 0.01849125f, 0.01239505f, 0.00708017f, 0.00344629f, 0.00142946f },
|
|
||||||
{ 0.02350698f, 0.02169968f, 0.01706957f, 0.01144208f, 0.00653582f, 0.00318132f, 0.00131956f },
|
|
||||||
{ 0.01849125f, 0.01706957f, 0.01342740f, 0.00900066f, 0.00514126f, 0.00250252f, 0.00103800f },
|
|
||||||
{ 0.01239505f, 0.01144208f, 0.00900066f, 0.00603332f, 0.00344629f, 0.00167749f, 0.00069579f },
|
|
||||||
{ 0.00708017f, 0.00653582f, 0.00514126f, 0.00344629f, 0.00196855f, 0.00095820f, 0.00039744f },
|
|
||||||
{ 0.00344629f, 0.00318132f, 0.00250252f, 0.00167749f, 0.00095820f, 0.00046640f, 0.00019346f },
|
|
||||||
{ 0.00142946f, 0.00131956f, 0.00103800f, 0.00069579f, 0.00039744f, 0.00019346f, 0.00008024f }
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/// AKAZE configuration options structure
|
/// AKAZE configuration options structure
|
||||||
struct AKAZEOptions {
|
struct AKAZEOptions {
|
||||||
@ -37,12 +22,12 @@ struct AKAZEOptions {
|
|||||||
, soffset(1.6f)
|
, soffset(1.6f)
|
||||||
, derivative_factor(1.5f)
|
, derivative_factor(1.5f)
|
||||||
, sderivatives(1.0)
|
, sderivatives(1.0)
|
||||||
, diffusivity(cv::DIFF_PM_G2)
|
, diffusivity(KAZE::DIFF_PM_G2)
|
||||||
|
|
||||||
, dthreshold(0.001f)
|
, dthreshold(0.001f)
|
||||||
, min_dthreshold(0.00001f)
|
, min_dthreshold(0.00001f)
|
||||||
|
|
||||||
, descriptor(cv::DESCRIPTOR_MLDB)
|
, descriptor(AKAZE::DESCRIPTOR_MLDB)
|
||||||
, descriptor_size(0)
|
, descriptor_size(0)
|
||||||
, descriptor_channels(3)
|
, descriptor_channels(3)
|
||||||
, descriptor_pattern_size(10)
|
, descriptor_pattern_size(10)
|
||||||
@ -75,4 +60,6 @@ struct AKAZEOptions {
|
|||||||
int kcontrast_nbins; ///< Number of bins for the contrast factor histogram
|
int kcontrast_nbins; ///< Number of bins for the contrast factor histogram
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
* @author Pablo F. Alcantarilla, Jesus Nuevo
|
* @author Pablo F. Alcantarilla, Jesus Nuevo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "../precomp.hpp"
|
||||||
#include "AKAZEFeatures.h"
|
#include "AKAZEFeatures.h"
|
||||||
#include "fed.h"
|
#include "fed.h"
|
||||||
#include "nldiffusion_functions.h"
|
#include "nldiffusion_functions.h"
|
||||||
@ -14,9 +15,9 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
// Namespaces
|
// Namespaces
|
||||||
|
namespace cv
|
||||||
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace cv;
|
|
||||||
using namespace cv::details::kaze;
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/**
|
/**
|
||||||
@ -29,7 +30,7 @@ AKAZEFeatures::AKAZEFeatures(const AKAZEOptions& options) : options_(options) {
|
|||||||
ncycles_ = 0;
|
ncycles_ = 0;
|
||||||
reordering_ = true;
|
reordering_ = true;
|
||||||
|
|
||||||
if (options_.descriptor_size > 0 && options_.descriptor >= cv::DESCRIPTOR_MLDB_UPRIGHT) {
|
if (options_.descriptor_size > 0 && options_.descriptor >= AKAZE::DESCRIPTOR_MLDB_UPRIGHT) {
|
||||||
generateDescriptorSubsample(descriptorSamples_, descriptorBits_, options_.descriptor_size,
|
generateDescriptorSubsample(descriptorSamples_, descriptorBits_, options_.descriptor_size,
|
||||||
options_.descriptor_pattern_size, options_.descriptor_channels);
|
options_.descriptor_pattern_size, options_.descriptor_channels);
|
||||||
}
|
}
|
||||||
@ -60,14 +61,14 @@ void AKAZEFeatures::Allocate_Memory_Evolution(void) {
|
|||||||
|
|
||||||
for (int j = 0; j < options_.nsublevels; j++) {
|
for (int j = 0; j < options_.nsublevels; j++) {
|
||||||
TEvolution step;
|
TEvolution step;
|
||||||
step.Lx = cv::Mat::zeros(level_height, level_width, CV_32F);
|
step.Lx = Mat::zeros(level_height, level_width, CV_32F);
|
||||||
step.Ly = cv::Mat::zeros(level_height, level_width, CV_32F);
|
step.Ly = Mat::zeros(level_height, level_width, CV_32F);
|
||||||
step.Lxx = cv::Mat::zeros(level_height, level_width, CV_32F);
|
step.Lxx = Mat::zeros(level_height, level_width, CV_32F);
|
||||||
step.Lxy = cv::Mat::zeros(level_height, level_width, CV_32F);
|
step.Lxy = Mat::zeros(level_height, level_width, CV_32F);
|
||||||
step.Lyy = cv::Mat::zeros(level_height, level_width, CV_32F);
|
step.Lyy = Mat::zeros(level_height, level_width, CV_32F);
|
||||||
step.Lt = cv::Mat::zeros(level_height, level_width, CV_32F);
|
step.Lt = Mat::zeros(level_height, level_width, CV_32F);
|
||||||
step.Ldet = cv::Mat::zeros(level_height, level_width, CV_32F);
|
step.Ldet = Mat::zeros(level_height, level_width, CV_32F);
|
||||||
step.Lsmooth = cv::Mat::zeros(level_height, level_width, CV_32F);
|
step.Lsmooth = Mat::zeros(level_height, level_width, CV_32F);
|
||||||
step.esigma = options_.soffset*pow(2.f, (float)(j) / (float)(options_.nsublevels) + i);
|
step.esigma = options_.soffset*pow(2.f, (float)(j) / (float)(options_.nsublevels) + i);
|
||||||
step.sigma_size = fRound(step.esigma);
|
step.sigma_size = fRound(step.esigma);
|
||||||
step.etime = 0.5f*(step.esigma*step.esigma);
|
step.etime = 0.5f*(step.esigma*step.esigma);
|
||||||
@ -96,7 +97,7 @@ void AKAZEFeatures::Allocate_Memory_Evolution(void) {
|
|||||||
* @param img Input image for which the nonlinear scale space needs to be created
|
* @param img Input image for which the nonlinear scale space needs to be created
|
||||||
* @return 0 if the nonlinear scale space was created successfully, -1 otherwise
|
* @return 0 if the nonlinear scale space was created successfully, -1 otherwise
|
||||||
*/
|
*/
|
||||||
int AKAZEFeatures::Create_Nonlinear_Scale_Space(const cv::Mat& img)
|
int AKAZEFeatures::Create_Nonlinear_Scale_Space(const Mat& img)
|
||||||
{
|
{
|
||||||
CV_Assert(evolution_.size() > 0);
|
CV_Assert(evolution_.size() > 0);
|
||||||
|
|
||||||
@ -106,8 +107,8 @@ int AKAZEFeatures::Create_Nonlinear_Scale_Space(const cv::Mat& img)
|
|||||||
evolution_[0].Lt.copyTo(evolution_[0].Lsmooth);
|
evolution_[0].Lt.copyTo(evolution_[0].Lsmooth);
|
||||||
|
|
||||||
// Allocate memory for the flow and step images
|
// Allocate memory for the flow and step images
|
||||||
cv::Mat Lflow = cv::Mat::zeros(evolution_[0].Lt.rows, evolution_[0].Lt.cols, CV_32F);
|
Mat Lflow = Mat::zeros(evolution_[0].Lt.rows, evolution_[0].Lt.cols, CV_32F);
|
||||||
cv::Mat Lstep = cv::Mat::zeros(evolution_[0].Lt.rows, evolution_[0].Lt.cols, CV_32F);
|
Mat Lstep = Mat::zeros(evolution_[0].Lt.rows, evolution_[0].Lt.cols, CV_32F);
|
||||||
|
|
||||||
// First compute the kcontrast factor
|
// First compute the kcontrast factor
|
||||||
options_.kcontrast = compute_k_percentile(img, options_.kcontrast_percentile, 1.0f, options_.kcontrast_nbins, 0, 0);
|
options_.kcontrast = compute_k_percentile(img, options_.kcontrast_percentile, 1.0f, options_.kcontrast_nbins, 0, 0);
|
||||||
@ -120,8 +121,8 @@ int AKAZEFeatures::Create_Nonlinear_Scale_Space(const cv::Mat& img)
|
|||||||
options_.kcontrast = options_.kcontrast*0.75f;
|
options_.kcontrast = options_.kcontrast*0.75f;
|
||||||
|
|
||||||
// Allocate memory for the resized flow and step images
|
// Allocate memory for the resized flow and step images
|
||||||
Lflow = cv::Mat::zeros(evolution_[i].Lt.rows, evolution_[i].Lt.cols, CV_32F);
|
Lflow = Mat::zeros(evolution_[i].Lt.rows, evolution_[i].Lt.cols, CV_32F);
|
||||||
Lstep = cv::Mat::zeros(evolution_[i].Lt.rows, evolution_[i].Lt.cols, CV_32F);
|
Lstep = Mat::zeros(evolution_[i].Lt.rows, evolution_[i].Lt.cols, CV_32F);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
evolution_[i - 1].Lt.copyTo(evolution_[i].Lt);
|
evolution_[i - 1].Lt.copyTo(evolution_[i].Lt);
|
||||||
@ -135,16 +136,16 @@ int AKAZEFeatures::Create_Nonlinear_Scale_Space(const cv::Mat& img)
|
|||||||
|
|
||||||
// Compute the conductivity equation
|
// Compute the conductivity equation
|
||||||
switch (options_.diffusivity) {
|
switch (options_.diffusivity) {
|
||||||
case cv::DIFF_PM_G1:
|
case KAZE::DIFF_PM_G1:
|
||||||
pm_g1(evolution_[i].Lx, evolution_[i].Ly, Lflow, options_.kcontrast);
|
pm_g1(evolution_[i].Lx, evolution_[i].Ly, Lflow, options_.kcontrast);
|
||||||
break;
|
break;
|
||||||
case cv::DIFF_PM_G2:
|
case KAZE::DIFF_PM_G2:
|
||||||
pm_g2(evolution_[i].Lx, evolution_[i].Ly, Lflow, options_.kcontrast);
|
pm_g2(evolution_[i].Lx, evolution_[i].Ly, Lflow, options_.kcontrast);
|
||||||
break;
|
break;
|
||||||
case cv::DIFF_WEICKERT:
|
case KAZE::DIFF_WEICKERT:
|
||||||
weickert_diffusivity(evolution_[i].Lx, evolution_[i].Ly, Lflow, options_.kcontrast);
|
weickert_diffusivity(evolution_[i].Lx, evolution_[i].Ly, Lflow, options_.kcontrast);
|
||||||
break;
|
break;
|
||||||
case cv::DIFF_CHARBONNIER:
|
case KAZE::DIFF_CHARBONNIER:
|
||||||
charbonnier_diffusivity(evolution_[i].Lx, evolution_[i].Ly, Lflow, options_.kcontrast);
|
charbonnier_diffusivity(evolution_[i].Lx, evolution_[i].Ly, Lflow, options_.kcontrast);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -154,7 +155,7 @@ int AKAZEFeatures::Create_Nonlinear_Scale_Space(const cv::Mat& img)
|
|||||||
|
|
||||||
// Perform FED n inner steps
|
// Perform FED n inner steps
|
||||||
for (int j = 0; j < nsteps_[i - 1]; j++) {
|
for (int j = 0; j < nsteps_[i - 1]; j++) {
|
||||||
cv::details::kaze::nld_step_scalar(evolution_[i].Lt, Lflow, Lstep, tsteps_[i - 1][j]);
|
nld_step_scalar(evolution_[i].Lt, Lflow, Lstep, tsteps_[i - 1][j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +167,7 @@ int AKAZEFeatures::Create_Nonlinear_Scale_Space(const cv::Mat& img)
|
|||||||
* @brief This method selects interesting keypoints through the nonlinear scale space
|
* @brief This method selects interesting keypoints through the nonlinear scale space
|
||||||
* @param kpts Vector of detected keypoints
|
* @param kpts Vector of detected keypoints
|
||||||
*/
|
*/
|
||||||
void AKAZEFeatures::Feature_Detection(std::vector<cv::KeyPoint>& kpts)
|
void AKAZEFeatures::Feature_Detection(std::vector<KeyPoint>& kpts)
|
||||||
{
|
{
|
||||||
kpts.clear();
|
kpts.clear();
|
||||||
Compute_Determinant_Hessian_Response();
|
Compute_Determinant_Hessian_Response();
|
||||||
@ -175,7 +176,7 @@ void AKAZEFeatures::Feature_Detection(std::vector<cv::KeyPoint>& kpts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
class MultiscaleDerivativesAKAZEInvoker : public cv::ParallelLoopBody
|
class MultiscaleDerivativesAKAZEInvoker : public ParallelLoopBody
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit MultiscaleDerivativesAKAZEInvoker(std::vector<TEvolution>& ev, const AKAZEOptions& opt)
|
explicit MultiscaleDerivativesAKAZEInvoker(std::vector<TEvolution>& ev, const AKAZEOptions& opt)
|
||||||
@ -184,7 +185,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const cv::Range& range) const
|
void operator()(const Range& range) const
|
||||||
{
|
{
|
||||||
std::vector<TEvolution>& evolution = *evolution_;
|
std::vector<TEvolution>& evolution = *evolution_;
|
||||||
|
|
||||||
@ -218,7 +219,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
void AKAZEFeatures::Compute_Multiscale_Derivatives(void)
|
void AKAZEFeatures::Compute_Multiscale_Derivatives(void)
|
||||||
{
|
{
|
||||||
cv::parallel_for_(cv::Range(0, (int)evolution_.size()),
|
parallel_for_(Range(0, (int)evolution_.size()),
|
||||||
MultiscaleDerivativesAKAZEInvoker(evolution_, options_));
|
MultiscaleDerivativesAKAZEInvoker(evolution_, options_));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +253,7 @@ void AKAZEFeatures::Compute_Determinant_Hessian_Response(void) {
|
|||||||
* @brief This method finds extrema in the nonlinear scale space
|
* @brief This method finds extrema in the nonlinear scale space
|
||||||
* @param kpts Vector of detected keypoints
|
* @param kpts Vector of detected keypoints
|
||||||
*/
|
*/
|
||||||
void AKAZEFeatures::Find_Scale_Space_Extrema(std::vector<cv::KeyPoint>& kpts)
|
void AKAZEFeatures::Find_Scale_Space_Extrema(std::vector<KeyPoint>& kpts)
|
||||||
{
|
{
|
||||||
|
|
||||||
float value = 0.0;
|
float value = 0.0;
|
||||||
@ -260,14 +261,14 @@ void AKAZEFeatures::Find_Scale_Space_Extrema(std::vector<cv::KeyPoint>& kpts)
|
|||||||
int npoints = 0, id_repeated = 0;
|
int npoints = 0, id_repeated = 0;
|
||||||
int sigma_size_ = 0, left_x = 0, right_x = 0, up_y = 0, down_y = 0;
|
int sigma_size_ = 0, left_x = 0, right_x = 0, up_y = 0, down_y = 0;
|
||||||
bool is_extremum = false, is_repeated = false, is_out = false;
|
bool is_extremum = false, is_repeated = false, is_out = false;
|
||||||
cv::KeyPoint point;
|
KeyPoint point;
|
||||||
vector<cv::KeyPoint> kpts_aux;
|
vector<KeyPoint> kpts_aux;
|
||||||
|
|
||||||
// Set maximum size
|
// Set maximum size
|
||||||
if (options_.descriptor == cv::DESCRIPTOR_MLDB_UPRIGHT || options_.descriptor == cv::DESCRIPTOR_MLDB) {
|
if (options_.descriptor == AKAZE::DESCRIPTOR_MLDB_UPRIGHT || options_.descriptor == AKAZE::DESCRIPTOR_MLDB) {
|
||||||
smax = 10.0f*sqrtf(2.0f);
|
smax = 10.0f*sqrtf(2.0f);
|
||||||
}
|
}
|
||||||
else if (options_.descriptor == cv::DESCRIPTOR_KAZE_UPRIGHT || options_.descriptor == cv::DESCRIPTOR_KAZE) {
|
else if (options_.descriptor == AKAZE::DESCRIPTOR_KAZE_UPRIGHT || options_.descriptor == AKAZE::DESCRIPTOR_KAZE) {
|
||||||
smax = 12.0f*sqrtf(2.0f);
|
smax = 12.0f*sqrtf(2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,7 +365,7 @@ void AKAZEFeatures::Find_Scale_Space_Extrema(std::vector<cv::KeyPoint>& kpts)
|
|||||||
for (size_t i = 0; i < kpts_aux.size(); i++) {
|
for (size_t i = 0; i < kpts_aux.size(); i++) {
|
||||||
|
|
||||||
is_repeated = false;
|
is_repeated = false;
|
||||||
const cv::KeyPoint& pt = kpts_aux[i];
|
const KeyPoint& pt = kpts_aux[i];
|
||||||
for (size_t j = i + 1; j < kpts_aux.size(); j++) {
|
for (size_t j = i + 1; j < kpts_aux.size(); j++) {
|
||||||
|
|
||||||
// Compare response with the upper scale
|
// Compare response with the upper scale
|
||||||
@ -391,7 +392,7 @@ void AKAZEFeatures::Find_Scale_Space_Extrema(std::vector<cv::KeyPoint>& kpts)
|
|||||||
* @brief This method performs subpixel refinement of the detected keypoints
|
* @brief This method performs subpixel refinement of the detected keypoints
|
||||||
* @param kpts Vector of detected keypoints
|
* @param kpts Vector of detected keypoints
|
||||||
*/
|
*/
|
||||||
void AKAZEFeatures::Do_Subpixel_Refinement(std::vector<cv::KeyPoint>& kpts)
|
void AKAZEFeatures::Do_Subpixel_Refinement(std::vector<KeyPoint>& kpts)
|
||||||
{
|
{
|
||||||
float Dx = 0.0, Dy = 0.0, ratio = 0.0;
|
float Dx = 0.0, Dy = 0.0, ratio = 0.0;
|
||||||
float Dxx = 0.0, Dyy = 0.0, Dxy = 0.0;
|
float Dxx = 0.0, Dyy = 0.0, Dxy = 0.0;
|
||||||
@ -432,7 +433,7 @@ void AKAZEFeatures::Do_Subpixel_Refinement(std::vector<cv::KeyPoint>& kpts)
|
|||||||
b(0) = -Dx;
|
b(0) = -Dx;
|
||||||
b(1) = -Dy;
|
b(1) = -Dy;
|
||||||
|
|
||||||
cv::solve(A, b, dst, DECOMP_LU);
|
solve(A, b, dst, DECOMP_LU);
|
||||||
|
|
||||||
if (fabs(dst(0)) <= 1.0f && fabs(dst(1)) <= 1.0f) {
|
if (fabs(dst(0)) <= 1.0f && fabs(dst(1)) <= 1.0f) {
|
||||||
kpts[i].pt.x = x + dst(0);
|
kpts[i].pt.x = x + dst(0);
|
||||||
@ -455,10 +456,10 @@ void AKAZEFeatures::Do_Subpixel_Refinement(std::vector<cv::KeyPoint>& kpts)
|
|||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
||||||
class SURF_Descriptor_Upright_64_Invoker : public cv::ParallelLoopBody
|
class SURF_Descriptor_Upright_64_Invoker : public ParallelLoopBody
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SURF_Descriptor_Upright_64_Invoker(std::vector<cv::KeyPoint>& kpts, cv::Mat& desc, std::vector<TEvolution>& evolution)
|
SURF_Descriptor_Upright_64_Invoker(std::vector<KeyPoint>& kpts, Mat& desc, std::vector<TEvolution>& evolution)
|
||||||
: keypoints_(&kpts)
|
: keypoints_(&kpts)
|
||||||
, descriptors_(&desc)
|
, descriptors_(&desc)
|
||||||
, evolution_(&evolution)
|
, evolution_(&evolution)
|
||||||
@ -473,18 +474,18 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Get_SURF_Descriptor_Upright_64(const cv::KeyPoint& kpt, float* desc) const;
|
void Get_SURF_Descriptor_Upright_64(const KeyPoint& kpt, float* desc) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<cv::KeyPoint>* keypoints_;
|
std::vector<KeyPoint>* keypoints_;
|
||||||
cv::Mat* descriptors_;
|
Mat* descriptors_;
|
||||||
std::vector<TEvolution>* evolution_;
|
std::vector<TEvolution>* evolution_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SURF_Descriptor_64_Invoker : public cv::ParallelLoopBody
|
class SURF_Descriptor_64_Invoker : public ParallelLoopBody
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SURF_Descriptor_64_Invoker(std::vector<cv::KeyPoint>& kpts, cv::Mat& desc, std::vector<TEvolution>& evolution)
|
SURF_Descriptor_64_Invoker(std::vector<KeyPoint>& kpts, Mat& desc, std::vector<TEvolution>& evolution)
|
||||||
: keypoints_(&kpts)
|
: keypoints_(&kpts)
|
||||||
, descriptors_(&desc)
|
, descriptors_(&desc)
|
||||||
, evolution_(&evolution)
|
, evolution_(&evolution)
|
||||||
@ -500,18 +501,18 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Get_SURF_Descriptor_64(const cv::KeyPoint& kpt, float* desc) const;
|
void Get_SURF_Descriptor_64(const KeyPoint& kpt, float* desc) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<cv::KeyPoint>* keypoints_;
|
std::vector<KeyPoint>* keypoints_;
|
||||||
cv::Mat* descriptors_;
|
Mat* descriptors_;
|
||||||
std::vector<TEvolution>* evolution_;
|
std::vector<TEvolution>* evolution_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MSURF_Upright_Descriptor_64_Invoker : public cv::ParallelLoopBody
|
class MSURF_Upright_Descriptor_64_Invoker : public ParallelLoopBody
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MSURF_Upright_Descriptor_64_Invoker(std::vector<cv::KeyPoint>& kpts, cv::Mat& desc, std::vector<TEvolution>& evolution)
|
MSURF_Upright_Descriptor_64_Invoker(std::vector<KeyPoint>& kpts, Mat& desc, std::vector<TEvolution>& evolution)
|
||||||
: keypoints_(&kpts)
|
: keypoints_(&kpts)
|
||||||
, descriptors_(&desc)
|
, descriptors_(&desc)
|
||||||
, evolution_(&evolution)
|
, evolution_(&evolution)
|
||||||
@ -526,18 +527,18 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Get_MSURF_Upright_Descriptor_64(const cv::KeyPoint& kpt, float* desc) const;
|
void Get_MSURF_Upright_Descriptor_64(const KeyPoint& kpt, float* desc) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<cv::KeyPoint>* keypoints_;
|
std::vector<KeyPoint>* keypoints_;
|
||||||
cv::Mat* descriptors_;
|
Mat* descriptors_;
|
||||||
std::vector<TEvolution>* evolution_;
|
std::vector<TEvolution>* evolution_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MSURF_Descriptor_64_Invoker : public cv::ParallelLoopBody
|
class MSURF_Descriptor_64_Invoker : public ParallelLoopBody
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MSURF_Descriptor_64_Invoker(std::vector<cv::KeyPoint>& kpts, cv::Mat& desc, std::vector<TEvolution>& evolution)
|
MSURF_Descriptor_64_Invoker(std::vector<KeyPoint>& kpts, Mat& desc, std::vector<TEvolution>& evolution)
|
||||||
: keypoints_(&kpts)
|
: keypoints_(&kpts)
|
||||||
, descriptors_(&desc)
|
, descriptors_(&desc)
|
||||||
, evolution_(&evolution)
|
, evolution_(&evolution)
|
||||||
@ -553,18 +554,18 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Get_MSURF_Descriptor_64(const cv::KeyPoint& kpt, float* desc) const;
|
void Get_MSURF_Descriptor_64(const KeyPoint& kpt, float* desc) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<cv::KeyPoint>* keypoints_;
|
std::vector<KeyPoint>* keypoints_;
|
||||||
cv::Mat* descriptors_;
|
Mat* descriptors_;
|
||||||
std::vector<TEvolution>* evolution_;
|
std::vector<TEvolution>* evolution_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Upright_MLDB_Full_Descriptor_Invoker : public cv::ParallelLoopBody
|
class Upright_MLDB_Full_Descriptor_Invoker : public ParallelLoopBody
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Upright_MLDB_Full_Descriptor_Invoker(std::vector<cv::KeyPoint>& kpts, cv::Mat& desc, std::vector<TEvolution>& evolution, AKAZEOptions& options)
|
Upright_MLDB_Full_Descriptor_Invoker(std::vector<KeyPoint>& kpts, Mat& desc, std::vector<TEvolution>& evolution, AKAZEOptions& options)
|
||||||
: keypoints_(&kpts)
|
: keypoints_(&kpts)
|
||||||
, descriptors_(&desc)
|
, descriptors_(&desc)
|
||||||
, evolution_(&evolution)
|
, evolution_(&evolution)
|
||||||
@ -580,24 +581,24 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Get_Upright_MLDB_Full_Descriptor(const cv::KeyPoint& kpt, unsigned char* desc) const;
|
void Get_Upright_MLDB_Full_Descriptor(const KeyPoint& kpt, unsigned char* desc) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<cv::KeyPoint>* keypoints_;
|
std::vector<KeyPoint>* keypoints_;
|
||||||
cv::Mat* descriptors_;
|
Mat* descriptors_;
|
||||||
std::vector<TEvolution>* evolution_;
|
std::vector<TEvolution>* evolution_;
|
||||||
AKAZEOptions* options_;
|
AKAZEOptions* options_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Upright_MLDB_Descriptor_Subset_Invoker : public cv::ParallelLoopBody
|
class Upright_MLDB_Descriptor_Subset_Invoker : public ParallelLoopBody
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Upright_MLDB_Descriptor_Subset_Invoker(std::vector<cv::KeyPoint>& kpts,
|
Upright_MLDB_Descriptor_Subset_Invoker(std::vector<KeyPoint>& kpts,
|
||||||
cv::Mat& desc,
|
Mat& desc,
|
||||||
std::vector<TEvolution>& evolution,
|
std::vector<TEvolution>& evolution,
|
||||||
AKAZEOptions& options,
|
AKAZEOptions& options,
|
||||||
cv::Mat descriptorSamples,
|
Mat descriptorSamples,
|
||||||
cv::Mat descriptorBits)
|
Mat descriptorBits)
|
||||||
: keypoints_(&kpts)
|
: keypoints_(&kpts)
|
||||||
, descriptors_(&desc)
|
, descriptors_(&desc)
|
||||||
, evolution_(&evolution)
|
, evolution_(&evolution)
|
||||||
@ -615,22 +616,22 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Get_Upright_MLDB_Descriptor_Subset(const cv::KeyPoint& kpt, unsigned char* desc) const;
|
void Get_Upright_MLDB_Descriptor_Subset(const KeyPoint& kpt, unsigned char* desc) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<cv::KeyPoint>* keypoints_;
|
std::vector<KeyPoint>* keypoints_;
|
||||||
cv::Mat* descriptors_;
|
Mat* descriptors_;
|
||||||
std::vector<TEvolution>* evolution_;
|
std::vector<TEvolution>* evolution_;
|
||||||
AKAZEOptions* options_;
|
AKAZEOptions* options_;
|
||||||
|
|
||||||
cv::Mat descriptorSamples_; // List of positions in the grids to sample LDB bits from.
|
Mat descriptorSamples_; // List of positions in the grids to sample LDB bits from.
|
||||||
cv::Mat descriptorBits_;
|
Mat descriptorBits_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MLDB_Full_Descriptor_Invoker : public cv::ParallelLoopBody
|
class MLDB_Full_Descriptor_Invoker : public ParallelLoopBody
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MLDB_Full_Descriptor_Invoker(std::vector<cv::KeyPoint>& kpts, cv::Mat& desc, std::vector<TEvolution>& evolution, AKAZEOptions& options)
|
MLDB_Full_Descriptor_Invoker(std::vector<KeyPoint>& kpts, Mat& desc, std::vector<TEvolution>& evolution, AKAZEOptions& options)
|
||||||
: keypoints_(&kpts)
|
: keypoints_(&kpts)
|
||||||
, descriptors_(&desc)
|
, descriptors_(&desc)
|
||||||
, evolution_(&evolution)
|
, evolution_(&evolution)
|
||||||
@ -647,28 +648,28 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Get_MLDB_Full_Descriptor(const cv::KeyPoint& kpt, unsigned char* desc) const;
|
void Get_MLDB_Full_Descriptor(const KeyPoint& kpt, unsigned char* desc) const;
|
||||||
void MLDB_Fill_Values(float* values, int sample_step, int level,
|
void MLDB_Fill_Values(float* values, int sample_step, int level,
|
||||||
float xf, float yf, float co, float si, float scale) const;
|
float xf, float yf, float co, float si, float scale) const;
|
||||||
void MLDB_Binary_Comparisons(float* values, unsigned char* desc,
|
void MLDB_Binary_Comparisons(float* values, unsigned char* desc,
|
||||||
int count, int& dpos) const;
|
int count, int& dpos) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<cv::KeyPoint>* keypoints_;
|
std::vector<KeyPoint>* keypoints_;
|
||||||
cv::Mat* descriptors_;
|
Mat* descriptors_;
|
||||||
std::vector<TEvolution>* evolution_;
|
std::vector<TEvolution>* evolution_;
|
||||||
AKAZEOptions* options_;
|
AKAZEOptions* options_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MLDB_Descriptor_Subset_Invoker : public cv::ParallelLoopBody
|
class MLDB_Descriptor_Subset_Invoker : public ParallelLoopBody
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MLDB_Descriptor_Subset_Invoker(std::vector<cv::KeyPoint>& kpts,
|
MLDB_Descriptor_Subset_Invoker(std::vector<KeyPoint>& kpts,
|
||||||
cv::Mat& desc,
|
Mat& desc,
|
||||||
std::vector<TEvolution>& evolution,
|
std::vector<TEvolution>& evolution,
|
||||||
AKAZEOptions& options,
|
AKAZEOptions& options,
|
||||||
cv::Mat descriptorSamples,
|
Mat descriptorSamples,
|
||||||
cv::Mat descriptorBits)
|
Mat descriptorBits)
|
||||||
: keypoints_(&kpts)
|
: keypoints_(&kpts)
|
||||||
, descriptors_(&desc)
|
, descriptors_(&desc)
|
||||||
, evolution_(&evolution)
|
, evolution_(&evolution)
|
||||||
@ -687,16 +688,16 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Get_MLDB_Descriptor_Subset(const cv::KeyPoint& kpt, unsigned char* desc) const;
|
void Get_MLDB_Descriptor_Subset(const KeyPoint& kpt, unsigned char* desc) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<cv::KeyPoint>* keypoints_;
|
std::vector<KeyPoint>* keypoints_;
|
||||||
cv::Mat* descriptors_;
|
Mat* descriptors_;
|
||||||
std::vector<TEvolution>* evolution_;
|
std::vector<TEvolution>* evolution_;
|
||||||
AKAZEOptions* options_;
|
AKAZEOptions* options_;
|
||||||
|
|
||||||
cv::Mat descriptorSamples_; // List of positions in the grids to sample LDB bits from.
|
Mat descriptorSamples_; // List of positions in the grids to sample LDB bits from.
|
||||||
cv::Mat descriptorBits_;
|
Mat descriptorBits_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -704,7 +705,7 @@ private:
|
|||||||
* @param kpts Vector of detected keypoints
|
* @param kpts Vector of detected keypoints
|
||||||
* @param desc Matrix to store the descriptors
|
* @param desc Matrix to store the descriptors
|
||||||
*/
|
*/
|
||||||
void AKAZEFeatures::Compute_Descriptors(std::vector<cv::KeyPoint>& kpts, cv::Mat& desc)
|
void AKAZEFeatures::Compute_Descriptors(std::vector<KeyPoint>& kpts, Mat& desc)
|
||||||
{
|
{
|
||||||
for(size_t i = 0; i < kpts.size(); i++)
|
for(size_t i = 0; i < kpts.size(); i++)
|
||||||
{
|
{
|
||||||
@ -712,47 +713,47 @@ void AKAZEFeatures::Compute_Descriptors(std::vector<cv::KeyPoint>& kpts, cv::Mat
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate memory for the matrix with the descriptors
|
// Allocate memory for the matrix with the descriptors
|
||||||
if (options_.descriptor < cv::DESCRIPTOR_MLDB_UPRIGHT) {
|
if (options_.descriptor < AKAZE::DESCRIPTOR_MLDB_UPRIGHT) {
|
||||||
desc = cv::Mat::zeros((int)kpts.size(), 64, CV_32FC1);
|
desc = Mat::zeros((int)kpts.size(), 64, CV_32FC1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// We use the full length binary descriptor -> 486 bits
|
// We use the full length binary descriptor -> 486 bits
|
||||||
if (options_.descriptor_size == 0) {
|
if (options_.descriptor_size == 0) {
|
||||||
int t = (6 + 36 + 120)*options_.descriptor_channels;
|
int t = (6 + 36 + 120)*options_.descriptor_channels;
|
||||||
desc = cv::Mat::zeros((int)kpts.size(), (int)ceil(t / 8.), CV_8UC1);
|
desc = Mat::zeros((int)kpts.size(), (int)ceil(t / 8.), CV_8UC1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// We use the random bit selection length binary descriptor
|
// We use the random bit selection length binary descriptor
|
||||||
desc = cv::Mat::zeros((int)kpts.size(), (int)ceil(options_.descriptor_size / 8.), CV_8UC1);
|
desc = Mat::zeros((int)kpts.size(), (int)ceil(options_.descriptor_size / 8.), CV_8UC1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (options_.descriptor)
|
switch (options_.descriptor)
|
||||||
{
|
{
|
||||||
case cv::DESCRIPTOR_KAZE_UPRIGHT: // Upright descriptors, not invariant to rotation
|
case AKAZE::DESCRIPTOR_KAZE_UPRIGHT: // Upright descriptors, not invariant to rotation
|
||||||
{
|
{
|
||||||
cv::parallel_for_(cv::Range(0, (int)kpts.size()), MSURF_Upright_Descriptor_64_Invoker(kpts, desc, evolution_));
|
parallel_for_(Range(0, (int)kpts.size()), MSURF_Upright_Descriptor_64_Invoker(kpts, desc, evolution_));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case cv::DESCRIPTOR_KAZE:
|
case AKAZE::DESCRIPTOR_KAZE:
|
||||||
{
|
{
|
||||||
cv::parallel_for_(cv::Range(0, (int)kpts.size()), MSURF_Descriptor_64_Invoker(kpts, desc, evolution_));
|
parallel_for_(Range(0, (int)kpts.size()), MSURF_Descriptor_64_Invoker(kpts, desc, evolution_));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case cv::DESCRIPTOR_MLDB_UPRIGHT: // Upright descriptors, not invariant to rotation
|
case AKAZE::DESCRIPTOR_MLDB_UPRIGHT: // Upright descriptors, not invariant to rotation
|
||||||
{
|
{
|
||||||
if (options_.descriptor_size == 0)
|
if (options_.descriptor_size == 0)
|
||||||
cv::parallel_for_(cv::Range(0, (int)kpts.size()), Upright_MLDB_Full_Descriptor_Invoker(kpts, desc, evolution_, options_));
|
parallel_for_(Range(0, (int)kpts.size()), Upright_MLDB_Full_Descriptor_Invoker(kpts, desc, evolution_, options_));
|
||||||
else
|
else
|
||||||
cv::parallel_for_(cv::Range(0, (int)kpts.size()), Upright_MLDB_Descriptor_Subset_Invoker(kpts, desc, evolution_, options_, descriptorSamples_, descriptorBits_));
|
parallel_for_(Range(0, (int)kpts.size()), Upright_MLDB_Descriptor_Subset_Invoker(kpts, desc, evolution_, options_, descriptorSamples_, descriptorBits_));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case cv::DESCRIPTOR_MLDB:
|
case AKAZE::DESCRIPTOR_MLDB:
|
||||||
{
|
{
|
||||||
if (options_.descriptor_size == 0)
|
if (options_.descriptor_size == 0)
|
||||||
cv::parallel_for_(cv::Range(0, (int)kpts.size()), MLDB_Full_Descriptor_Invoker(kpts, desc, evolution_, options_));
|
parallel_for_(Range(0, (int)kpts.size()), MLDB_Full_Descriptor_Invoker(kpts, desc, evolution_, options_));
|
||||||
else
|
else
|
||||||
cv::parallel_for_(cv::Range(0, (int)kpts.size()), MLDB_Descriptor_Subset_Invoker(kpts, desc, evolution_, options_, descriptorSamples_, descriptorBits_));
|
parallel_for_(Range(0, (int)kpts.size()), MLDB_Descriptor_Subset_Invoker(kpts, desc, evolution_, options_, descriptorSamples_, descriptorBits_));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -765,7 +766,20 @@ void AKAZEFeatures::Compute_Descriptors(std::vector<cv::KeyPoint>& kpts, cv::Mat
|
|||||||
* @note The orientation is computed using a similar approach as described in the
|
* @note The orientation is computed using a similar approach as described in the
|
||||||
* original SURF method. See Bay et al., Speeded Up Robust Features, ECCV 2006
|
* original SURF method. See Bay et al., Speeded Up Robust Features, ECCV 2006
|
||||||
*/
|
*/
|
||||||
void AKAZEFeatures::Compute_Main_Orientation(cv::KeyPoint& kpt, const std::vector<TEvolution>& evolution_) {
|
void AKAZEFeatures::Compute_Main_Orientation(KeyPoint& kpt, const std::vector<TEvolution>& evolution_)
|
||||||
|
{
|
||||||
|
/* ************************************************************************* */
|
||||||
|
/// Lookup table for 2d gaussian (sigma = 2.5) where (0,0) is top left and (6,6) is bottom right
|
||||||
|
static const float gauss25[7][7] =
|
||||||
|
{
|
||||||
|
{ 0.02546481f, 0.02350698f, 0.01849125f, 0.01239505f, 0.00708017f, 0.00344629f, 0.00142946f },
|
||||||
|
{ 0.02350698f, 0.02169968f, 0.01706957f, 0.01144208f, 0.00653582f, 0.00318132f, 0.00131956f },
|
||||||
|
{ 0.01849125f, 0.01706957f, 0.01342740f, 0.00900066f, 0.00514126f, 0.00250252f, 0.00103800f },
|
||||||
|
{ 0.01239505f, 0.01144208f, 0.00900066f, 0.00603332f, 0.00344629f, 0.00167749f, 0.00069579f },
|
||||||
|
{ 0.00708017f, 0.00653582f, 0.00514126f, 0.00344629f, 0.00196855f, 0.00095820f, 0.00039744f },
|
||||||
|
{ 0.00344629f, 0.00318132f, 0.00250252f, 0.00167749f, 0.00095820f, 0.00046640f, 0.00019346f },
|
||||||
|
{ 0.00142946f, 0.00131956f, 0.00103800f, 0.00069579f, 0.00039744f, 0.00019346f, 0.00008024f }
|
||||||
|
};
|
||||||
|
|
||||||
int ix = 0, iy = 0, idx = 0, s = 0, level = 0;
|
int ix = 0, iy = 0, idx = 0, s = 0, level = 0;
|
||||||
float xf = 0.0, yf = 0.0, gweight = 0.0, ratio = 0.0;
|
float xf = 0.0, yf = 0.0, gweight = 0.0, ratio = 0.0;
|
||||||
@ -840,7 +854,7 @@ void AKAZEFeatures::Compute_Main_Orientation(cv::KeyPoint& kpt, const std::vecto
|
|||||||
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
||||||
* ECCV 2008
|
* ECCV 2008
|
||||||
*/
|
*/
|
||||||
void MSURF_Upright_Descriptor_64_Invoker::Get_MSURF_Upright_Descriptor_64(const cv::KeyPoint& kpt, float *desc) const {
|
void MSURF_Upright_Descriptor_64_Invoker::Get_MSURF_Upright_Descriptor_64(const KeyPoint& kpt, float *desc) const {
|
||||||
|
|
||||||
float dx = 0.0, dy = 0.0, mdx = 0.0, mdy = 0.0, gauss_s1 = 0.0, gauss_s2 = 0.0;
|
float dx = 0.0, dy = 0.0, mdx = 0.0, mdy = 0.0, gauss_s1 = 0.0, gauss_s2 = 0.0;
|
||||||
float rx = 0.0, ry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
float rx = 0.0, ry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
||||||
@ -963,7 +977,7 @@ void MSURF_Upright_Descriptor_64_Invoker::Get_MSURF_Upright_Descriptor_64(const
|
|||||||
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
||||||
* ECCV 2008
|
* ECCV 2008
|
||||||
*/
|
*/
|
||||||
void MSURF_Descriptor_64_Invoker::Get_MSURF_Descriptor_64(const cv::KeyPoint& kpt, float *desc) const {
|
void MSURF_Descriptor_64_Invoker::Get_MSURF_Descriptor_64(const KeyPoint& kpt, float *desc) const {
|
||||||
|
|
||||||
float dx = 0.0, dy = 0.0, mdx = 0.0, mdy = 0.0, gauss_s1 = 0.0, gauss_s2 = 0.0;
|
float dx = 0.0, dy = 0.0, mdx = 0.0, mdy = 0.0, gauss_s1 = 0.0, gauss_s2 = 0.0;
|
||||||
float rx = 0.0, ry = 0.0, rrx = 0.0, rry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
float rx = 0.0, ry = 0.0, rrx = 0.0, rry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
||||||
@ -1087,7 +1101,7 @@ void MSURF_Descriptor_64_Invoker::Get_MSURF_Descriptor_64(const cv::KeyPoint& kp
|
|||||||
* @param kpt Input keypoint
|
* @param kpt Input keypoint
|
||||||
* @param desc Descriptor vector
|
* @param desc Descriptor vector
|
||||||
*/
|
*/
|
||||||
void Upright_MLDB_Full_Descriptor_Invoker::Get_Upright_MLDB_Full_Descriptor(const cv::KeyPoint& kpt, unsigned char *desc) const {
|
void Upright_MLDB_Full_Descriptor_Invoker::Get_Upright_MLDB_Full_Descriptor(const KeyPoint& kpt, unsigned char *desc) const {
|
||||||
|
|
||||||
float di = 0.0, dx = 0.0, dy = 0.0;
|
float di = 0.0, dx = 0.0, dy = 0.0;
|
||||||
float ri = 0.0, rx = 0.0, ry = 0.0, xf = 0.0, yf = 0.0;
|
float ri = 0.0, rx = 0.0, ry = 0.0, xf = 0.0, yf = 0.0;
|
||||||
@ -1100,9 +1114,9 @@ void Upright_MLDB_Full_Descriptor_Invoker::Get_Upright_MLDB_Full_Descriptor(cons
|
|||||||
const std::vector<TEvolution>& evolution = *evolution_;
|
const std::vector<TEvolution>& evolution = *evolution_;
|
||||||
|
|
||||||
// Matrices for the M-LDB descriptor
|
// Matrices for the M-LDB descriptor
|
||||||
cv::Mat values_1 = cv::Mat::zeros(4, options.descriptor_channels, CV_32FC1);
|
Mat values_1 = Mat::zeros(4, options.descriptor_channels, CV_32FC1);
|
||||||
cv::Mat values_2 = cv::Mat::zeros(9, options.descriptor_channels, CV_32FC1);
|
Mat values_2 = Mat::zeros(9, options.descriptor_channels, CV_32FC1);
|
||||||
cv::Mat values_3 = cv::Mat::zeros(16, options.descriptor_channels, CV_32FC1);
|
Mat values_3 = Mat::zeros(16, options.descriptor_channels, CV_32FC1);
|
||||||
|
|
||||||
// Get the information from the keypoint
|
// Get the information from the keypoint
|
||||||
ratio = (float)(1 << kpt.octave);
|
ratio = (float)(1 << kpt.octave);
|
||||||
@ -1381,7 +1395,7 @@ void MLDB_Full_Descriptor_Invoker::MLDB_Binary_Comparisons(float* values, unsign
|
|||||||
* @param kpt Input keypoint
|
* @param kpt Input keypoint
|
||||||
* @param desc Descriptor vector
|
* @param desc Descriptor vector
|
||||||
*/
|
*/
|
||||||
void MLDB_Full_Descriptor_Invoker::Get_MLDB_Full_Descriptor(const cv::KeyPoint& kpt, unsigned char *desc) const {
|
void MLDB_Full_Descriptor_Invoker::Get_MLDB_Full_Descriptor(const KeyPoint& kpt, unsigned char *desc) const {
|
||||||
|
|
||||||
const int max_channels = 3;
|
const int max_channels = 3;
|
||||||
CV_Assert(options_->descriptor_channels <= max_channels);
|
CV_Assert(options_->descriptor_channels <= max_channels);
|
||||||
@ -1414,7 +1428,7 @@ void MLDB_Full_Descriptor_Invoker::Get_MLDB_Full_Descriptor(const cv::KeyPoint&
|
|||||||
* @param kpt Input keypoint
|
* @param kpt Input keypoint
|
||||||
* @param desc Descriptor vector
|
* @param desc Descriptor vector
|
||||||
*/
|
*/
|
||||||
void MLDB_Descriptor_Subset_Invoker::Get_MLDB_Descriptor_Subset(const cv::KeyPoint& kpt, unsigned char *desc) const {
|
void MLDB_Descriptor_Subset_Invoker::Get_MLDB_Descriptor_Subset(const KeyPoint& kpt, unsigned char *desc) const {
|
||||||
|
|
||||||
float di = 0.f, dx = 0.f, dy = 0.f;
|
float di = 0.f, dx = 0.f, dy = 0.f;
|
||||||
float rx = 0.f, ry = 0.f;
|
float rx = 0.f, ry = 0.f;
|
||||||
@ -1435,7 +1449,7 @@ void MLDB_Descriptor_Subset_Invoker::Get_MLDB_Descriptor_Subset(const cv::KeyPoi
|
|||||||
float si = sin(angle);
|
float si = sin(angle);
|
||||||
|
|
||||||
// Allocate memory for the matrix of values
|
// Allocate memory for the matrix of values
|
||||||
cv::Mat values = cv::Mat_<float>::zeros((4 + 9 + 16)*options.descriptor_channels, 1);
|
Mat values = Mat_<float>::zeros((4 + 9 + 16)*options.descriptor_channels, 1);
|
||||||
|
|
||||||
// Sample everything, but only do the comparisons
|
// Sample everything, but only do the comparisons
|
||||||
vector<int> steps(3);
|
vector<int> steps(3);
|
||||||
@ -1508,7 +1522,7 @@ void MLDB_Descriptor_Subset_Invoker::Get_MLDB_Descriptor_Subset(const cv::KeyPoi
|
|||||||
* @param kpt Input keypoint
|
* @param kpt Input keypoint
|
||||||
* @param desc Descriptor vector
|
* @param desc Descriptor vector
|
||||||
*/
|
*/
|
||||||
void Upright_MLDB_Descriptor_Subset_Invoker::Get_Upright_MLDB_Descriptor_Subset(const cv::KeyPoint& kpt, unsigned char *desc) const {
|
void Upright_MLDB_Descriptor_Subset_Invoker::Get_Upright_MLDB_Descriptor_Subset(const KeyPoint& kpt, unsigned char *desc) const {
|
||||||
|
|
||||||
float di = 0.0f, dx = 0.0f, dy = 0.0f;
|
float di = 0.0f, dx = 0.0f, dy = 0.0f;
|
||||||
float rx = 0.0f, ry = 0.0f;
|
float rx = 0.0f, ry = 0.0f;
|
||||||
@ -1526,7 +1540,7 @@ void Upright_MLDB_Descriptor_Subset_Invoker::Get_Upright_MLDB_Descriptor_Subset(
|
|||||||
float xf = kpt.pt.x / ratio;
|
float xf = kpt.pt.x / ratio;
|
||||||
|
|
||||||
// Allocate memory for the matrix of values
|
// Allocate memory for the matrix of values
|
||||||
Mat values = cv::Mat_<float>::zeros((4 + 9 + 16)*options.descriptor_channels, 1);
|
Mat values = Mat_<float>::zeros((4 + 9 + 16)*options.descriptor_channels, 1);
|
||||||
|
|
||||||
vector<int> steps(3);
|
vector<int> steps(3);
|
||||||
steps.at(0) = options.descriptor_pattern_size;
|
steps.at(0) = options.descriptor_pattern_size;
|
||||||
@ -1600,7 +1614,7 @@ void Upright_MLDB_Descriptor_Subset_Invoker::Get_Upright_MLDB_Descriptor_Subset(
|
|||||||
* @note The function keeps the 18 bits (3-channels by 6 comparisons) of the
|
* @note The function keeps the 18 bits (3-channels by 6 comparisons) of the
|
||||||
* coarser grid, since it provides the most robust estimations
|
* coarser grid, since it provides the most robust estimations
|
||||||
*/
|
*/
|
||||||
void generateDescriptorSubsample(cv::Mat& sampleList, cv::Mat& comparisons, int nbits,
|
void generateDescriptorSubsample(Mat& sampleList, Mat& comparisons, int nbits,
|
||||||
int pattern_size, int nchannels) {
|
int pattern_size, int nchannels) {
|
||||||
|
|
||||||
int ssz = 0;
|
int ssz = 0;
|
||||||
@ -1702,3 +1716,5 @@ void generateDescriptorSubsample(cv::Mat& sampleList, cv::Mat& comparisons, int
|
|||||||
sampleList = samples.rowRange(0, count).clone();
|
sampleList = samples.rowRange(0, count).clone();
|
||||||
comparisons = comps.rowRange(0, nbits).clone();
|
comparisons = comps.rowRange(0, nbits).clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -11,10 +11,12 @@
|
|||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
// Includes
|
// Includes
|
||||||
#include "../precomp.hpp"
|
|
||||||
#include "AKAZEConfig.h"
|
#include "AKAZEConfig.h"
|
||||||
#include "TEvolution.h"
|
#include "TEvolution.h"
|
||||||
|
|
||||||
|
namespace cv
|
||||||
|
{
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
// AKAZE Class Declaration
|
// AKAZE Class Declaration
|
||||||
class AKAZEFeatures {
|
class AKAZEFeatures {
|
||||||
@ -59,4 +61,6 @@ public:
|
|||||||
void generateDescriptorSubsample(cv::Mat& sampleList, cv::Mat& comparisons,
|
void generateDescriptorSubsample(cv::Mat& sampleList, cv::Mat& comparisons,
|
||||||
int nbits, int pattern_size, int nchannels);
|
int nbits, int pattern_size, int nchannels);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,12 +12,14 @@
|
|||||||
#include "../precomp.hpp"
|
#include "../precomp.hpp"
|
||||||
#include <opencv2/features2d.hpp>
|
#include <opencv2/features2d.hpp>
|
||||||
|
|
||||||
|
namespace cv
|
||||||
|
{
|
||||||
//*************************************************************************************
|
//*************************************************************************************
|
||||||
|
|
||||||
struct KAZEOptions {
|
struct KAZEOptions {
|
||||||
|
|
||||||
KAZEOptions()
|
KAZEOptions()
|
||||||
: diffusivity(cv::DIFF_PM_G2)
|
: diffusivity(KAZE::DIFF_PM_G2)
|
||||||
|
|
||||||
, soffset(1.60f)
|
, soffset(1.60f)
|
||||||
, omax(4)
|
, omax(4)
|
||||||
@ -49,4 +51,6 @@ struct KAZEOptions {
|
|||||||
bool extended;
|
bool extended;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,14 +20,15 @@
|
|||||||
* @date Jan 21, 2012
|
* @date Jan 21, 2012
|
||||||
* @author Pablo F. Alcantarilla
|
* @author Pablo F. Alcantarilla
|
||||||
*/
|
*/
|
||||||
|
#include "../precomp.hpp"
|
||||||
#include "KAZEFeatures.h"
|
#include "KAZEFeatures.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
namespace cv
|
||||||
|
{
|
||||||
|
|
||||||
// Namespaces
|
// Namespaces
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace cv;
|
|
||||||
using namespace cv::details::kaze;
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/**
|
/**
|
||||||
@ -52,18 +53,19 @@ KAZEFeatures::KAZEFeatures(KAZEOptions& options)
|
|||||||
void KAZEFeatures::Allocate_Memory_Evolution(void) {
|
void KAZEFeatures::Allocate_Memory_Evolution(void) {
|
||||||
|
|
||||||
// Allocate the dimension of the matrices for the evolution
|
// Allocate the dimension of the matrices for the evolution
|
||||||
for (int i = 0; i <= options_.omax - 1; i++) {
|
for (int i = 0; i <= options_.omax - 1; i++)
|
||||||
for (int j = 0; j <= options_.nsublevels - 1; j++) {
|
{
|
||||||
|
for (int j = 0; j <= options_.nsublevels - 1; j++)
|
||||||
|
{
|
||||||
TEvolution aux;
|
TEvolution aux;
|
||||||
aux.Lx = cv::Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
aux.Lx = Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
||||||
aux.Ly = cv::Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
aux.Ly = Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
||||||
aux.Lxx = cv::Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
aux.Lxx = Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
||||||
aux.Lxy = cv::Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
aux.Lxy = Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
||||||
aux.Lyy = cv::Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
aux.Lyy = Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
||||||
aux.Lt = cv::Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
aux.Lt = Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
||||||
aux.Lsmooth = cv::Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
aux.Lsmooth = Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
||||||
aux.Ldet = cv::Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
aux.Ldet = Mat::zeros(options_.img_height, options_.img_width, CV_32F);
|
||||||
aux.esigma = options_.soffset*pow((float)2.0f, (float)(j) / (float)(options_.nsublevels)+i);
|
aux.esigma = options_.soffset*pow((float)2.0f, (float)(j) / (float)(options_.nsublevels)+i);
|
||||||
aux.etime = 0.5f*(aux.esigma*aux.esigma);
|
aux.etime = 0.5f*(aux.esigma*aux.esigma);
|
||||||
aux.sigma_size = fRound(aux.esigma);
|
aux.sigma_size = fRound(aux.esigma);
|
||||||
@ -74,7 +76,8 @@ void KAZEFeatures::Allocate_Memory_Evolution(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate memory for the FED number of cycles and time steps
|
// Allocate memory for the FED number of cycles and time steps
|
||||||
for (size_t i = 1; i < evolution_.size(); i++) {
|
for (size_t i = 1; i < evolution_.size(); i++)
|
||||||
|
{
|
||||||
int naux = 0;
|
int naux = 0;
|
||||||
vector<float> tau;
|
vector<float> tau;
|
||||||
float ttime = 0.0;
|
float ttime = 0.0;
|
||||||
@ -92,7 +95,7 @@ void KAZEFeatures::Allocate_Memory_Evolution(void) {
|
|||||||
* @param img Input image for which the nonlinear scale space needs to be created
|
* @param img Input image for which the nonlinear scale space needs to be created
|
||||||
* @return 0 if the nonlinear scale space was created successfully. -1 otherwise
|
* @return 0 if the nonlinear scale space was created successfully. -1 otherwise
|
||||||
*/
|
*/
|
||||||
int KAZEFeatures::Create_Nonlinear_Scale_Space(const cv::Mat &img)
|
int KAZEFeatures::Create_Nonlinear_Scale_Space(const Mat &img)
|
||||||
{
|
{
|
||||||
CV_Assert(evolution_.size() > 0);
|
CV_Assert(evolution_.size() > 0);
|
||||||
|
|
||||||
@ -105,12 +108,12 @@ int KAZEFeatures::Create_Nonlinear_Scale_Space(const cv::Mat &img)
|
|||||||
Compute_KContrast(evolution_[0].Lt, options_.kcontrast_percentille);
|
Compute_KContrast(evolution_[0].Lt, options_.kcontrast_percentille);
|
||||||
|
|
||||||
// Allocate memory for the flow and step images
|
// Allocate memory for the flow and step images
|
||||||
cv::Mat Lflow = cv::Mat::zeros(evolution_[0].Lt.rows, evolution_[0].Lt.cols, CV_32F);
|
Mat Lflow = Mat::zeros(evolution_[0].Lt.rows, evolution_[0].Lt.cols, CV_32F);
|
||||||
cv::Mat Lstep = cv::Mat::zeros(evolution_[0].Lt.rows, evolution_[0].Lt.cols, CV_32F);
|
Mat Lstep = Mat::zeros(evolution_[0].Lt.rows, evolution_[0].Lt.cols, CV_32F);
|
||||||
|
|
||||||
// Now generate the rest of evolution levels
|
// Now generate the rest of evolution levels
|
||||||
for (size_t i = 1; i < evolution_.size(); i++) {
|
for (size_t i = 1; i < evolution_.size(); i++)
|
||||||
|
{
|
||||||
evolution_[i - 1].Lt.copyTo(evolution_[i].Lt);
|
evolution_[i - 1].Lt.copyTo(evolution_[i].Lt);
|
||||||
gaussian_2D_convolution(evolution_[i - 1].Lt, evolution_[i].Lsmooth, 0, 0, options_.sderivatives);
|
gaussian_2D_convolution(evolution_[i - 1].Lt, evolution_[i].Lsmooth, 0, 0, options_.sderivatives);
|
||||||
|
|
||||||
@ -119,21 +122,17 @@ int KAZEFeatures::Create_Nonlinear_Scale_Space(const cv::Mat &img)
|
|||||||
Scharr(evolution_[i].Lsmooth, evolution_[i].Ly, CV_32F, 0, 1, 1, 0, BORDER_DEFAULT);
|
Scharr(evolution_[i].Lsmooth, evolution_[i].Ly, CV_32F, 0, 1, 1, 0, BORDER_DEFAULT);
|
||||||
|
|
||||||
// Compute the conductivity equation
|
// Compute the conductivity equation
|
||||||
if (options_.diffusivity == cv::DIFF_PM_G1) {
|
if (options_.diffusivity == KAZE::DIFF_PM_G1)
|
||||||
pm_g1(evolution_[i].Lx, evolution_[i].Ly, Lflow, options_.kcontrast);
|
pm_g1(evolution_[i].Lx, evolution_[i].Ly, Lflow, options_.kcontrast);
|
||||||
}
|
else if (options_.diffusivity == KAZE::DIFF_PM_G2)
|
||||||
else if (options_.diffusivity == cv::DIFF_PM_G2) {
|
|
||||||
pm_g2(evolution_[i].Lx, evolution_[i].Ly, Lflow, options_.kcontrast);
|
pm_g2(evolution_[i].Lx, evolution_[i].Ly, Lflow, options_.kcontrast);
|
||||||
}
|
else if (options_.diffusivity == KAZE::DIFF_WEICKERT)
|
||||||
else if (options_.diffusivity == cv::DIFF_WEICKERT) {
|
|
||||||
weickert_diffusivity(evolution_[i].Lx, evolution_[i].Ly, Lflow, options_.kcontrast);
|
weickert_diffusivity(evolution_[i].Lx, evolution_[i].Ly, Lflow, options_.kcontrast);
|
||||||
}
|
|
||||||
|
|
||||||
// Perform FED n inner steps
|
// Perform FED n inner steps
|
||||||
for (int j = 0; j < nsteps_[i - 1]; j++) {
|
for (int j = 0; j < nsteps_[i - 1]; j++)
|
||||||
nld_step_scalar(evolution_[i].Lt, Lflow, Lstep, tsteps_[i - 1][j]);
|
nld_step_scalar(evolution_[i].Lt, Lflow, Lstep, tsteps_[i - 1][j]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -144,7 +143,7 @@ int KAZEFeatures::Create_Nonlinear_Scale_Space(const cv::Mat &img)
|
|||||||
* @param img Input image
|
* @param img Input image
|
||||||
* @param kpercentile Percentile of the gradient histogram
|
* @param kpercentile Percentile of the gradient histogram
|
||||||
*/
|
*/
|
||||||
void KAZEFeatures::Compute_KContrast(const cv::Mat &img, const float &kpercentile)
|
void KAZEFeatures::Compute_KContrast(const Mat &img, const float &kpercentile)
|
||||||
{
|
{
|
||||||
options_.kcontrast = compute_k_percentile(img, kpercentile, options_.sderivatives, options_.kcontrast_bins, 0, 0);
|
options_.kcontrast = compute_k_percentile(img, kpercentile, options_.sderivatives, options_.kcontrast_bins, 0, 0);
|
||||||
}
|
}
|
||||||
@ -181,7 +180,7 @@ void KAZEFeatures::Compute_Detector_Response(void)
|
|||||||
* @brief This method selects interesting keypoints through the nonlinear scale space
|
* @brief This method selects interesting keypoints through the nonlinear scale space
|
||||||
* @param kpts Vector of keypoints
|
* @param kpts Vector of keypoints
|
||||||
*/
|
*/
|
||||||
void KAZEFeatures::Feature_Detection(std::vector<cv::KeyPoint>& kpts)
|
void KAZEFeatures::Feature_Detection(std::vector<KeyPoint>& kpts)
|
||||||
{
|
{
|
||||||
kpts.clear();
|
kpts.clear();
|
||||||
Compute_Detector_Response();
|
Compute_Detector_Response();
|
||||||
@ -190,14 +189,14 @@ void KAZEFeatures::Feature_Detection(std::vector<cv::KeyPoint>& kpts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
class MultiscaleDerivativesKAZEInvoker : public cv::ParallelLoopBody
|
class MultiscaleDerivativesKAZEInvoker : public ParallelLoopBody
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit MultiscaleDerivativesKAZEInvoker(std::vector<TEvolution>& ev) : evolution_(&ev)
|
explicit MultiscaleDerivativesKAZEInvoker(std::vector<TEvolution>& ev) : evolution_(&ev)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const cv::Range& range) const
|
void operator()(const Range& range) const
|
||||||
{
|
{
|
||||||
std::vector<TEvolution>& evolution = *evolution_;
|
std::vector<TEvolution>& evolution = *evolution_;
|
||||||
for (int i = range.start; i < range.end; i++)
|
for (int i = range.start; i < range.end; i++)
|
||||||
@ -226,54 +225,59 @@ private:
|
|||||||
*/
|
*/
|
||||||
void KAZEFeatures::Compute_Multiscale_Derivatives(void)
|
void KAZEFeatures::Compute_Multiscale_Derivatives(void)
|
||||||
{
|
{
|
||||||
cv::parallel_for_(cv::Range(0, (int)evolution_.size()),
|
parallel_for_(Range(0, (int)evolution_.size()),
|
||||||
MultiscaleDerivativesKAZEInvoker(evolution_));
|
MultiscaleDerivativesKAZEInvoker(evolution_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
class FindExtremumKAZEInvoker : public cv::ParallelLoopBody
|
class FindExtremumKAZEInvoker : public ParallelLoopBody
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit FindExtremumKAZEInvoker(std::vector<TEvolution>& ev, std::vector<std::vector<cv::KeyPoint> >& kpts_par,
|
explicit FindExtremumKAZEInvoker(std::vector<TEvolution>& ev, std::vector<std::vector<KeyPoint> >& kpts_par,
|
||||||
const KAZEOptions& options) : evolution_(&ev), kpts_par_(&kpts_par), options_(options)
|
const KAZEOptions& options) : evolution_(&ev), kpts_par_(&kpts_par), options_(options)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const cv::Range& range) const
|
void operator()(const Range& range) const
|
||||||
{
|
{
|
||||||
std::vector<TEvolution>& evolution = *evolution_;
|
std::vector<TEvolution>& evolution = *evolution_;
|
||||||
std::vector<std::vector<cv::KeyPoint> >& kpts_par = *kpts_par_;
|
std::vector<std::vector<KeyPoint> >& kpts_par = *kpts_par_;
|
||||||
for (int i = range.start; i < range.end; i++)
|
for (int i = range.start; i < range.end; i++)
|
||||||
{
|
{
|
||||||
float value = 0.0;
|
float value = 0.0;
|
||||||
bool is_extremum = false;
|
bool is_extremum = false;
|
||||||
|
|
||||||
for (int ix = 1; ix < options_.img_height - 1; ix++) {
|
for (int ix = 1; ix < options_.img_height - 1; ix++)
|
||||||
for (int jx = 1; jx < options_.img_width - 1; jx++) {
|
{
|
||||||
|
for (int jx = 1; jx < options_.img_width - 1; jx++)
|
||||||
|
{
|
||||||
is_extremum = false;
|
is_extremum = false;
|
||||||
value = *(evolution[i].Ldet.ptr<float>(ix)+jx);
|
value = *(evolution[i].Ldet.ptr<float>(ix)+jx);
|
||||||
|
|
||||||
// Filter the points with the detector threshold
|
// Filter the points with the detector threshold
|
||||||
if (value > options_.dthreshold) {
|
if (value > options_.dthreshold)
|
||||||
if (value >= *(evolution[i].Ldet.ptr<float>(ix)+jx - 1)) {
|
{
|
||||||
|
if (value >= *(evolution[i].Ldet.ptr<float>(ix)+jx - 1))
|
||||||
|
{
|
||||||
// First check on the same scale
|
// First check on the same scale
|
||||||
if (check_maximum_neighbourhood(evolution[i].Ldet, 1, value, ix, jx, 1)) {
|
if (check_maximum_neighbourhood(evolution[i].Ldet, 1, value, ix, jx, 1))
|
||||||
|
{
|
||||||
// Now check on the lower scale
|
// Now check on the lower scale
|
||||||
if (check_maximum_neighbourhood(evolution[i - 1].Ldet, 1, value, ix, jx, 0)) {
|
if (check_maximum_neighbourhood(evolution[i - 1].Ldet, 1, value, ix, jx, 0))
|
||||||
|
{
|
||||||
// Now check on the upper scale
|
// Now check on the upper scale
|
||||||
if (check_maximum_neighbourhood(evolution[i + 1].Ldet, 1, value, ix, jx, 0)) {
|
if (check_maximum_neighbourhood(evolution[i + 1].Ldet, 1, value, ix, jx, 0))
|
||||||
is_extremum = true;
|
is_extremum = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Add the point of interest!!
|
// Add the point of interest!!
|
||||||
if (is_extremum == true) {
|
if (is_extremum)
|
||||||
cv::KeyPoint point;
|
{
|
||||||
|
KeyPoint point;
|
||||||
point.pt.x = (float)jx;
|
point.pt.x = (float)jx;
|
||||||
point.pt.y = (float)ix;
|
point.pt.y = (float)ix;
|
||||||
point.response = fabs(value);
|
point.response = fabs(value);
|
||||||
@ -293,7 +297,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<TEvolution>* evolution_;
|
std::vector<TEvolution>* evolution_;
|
||||||
std::vector<std::vector<cv::KeyPoint> >* kpts_par_;
|
std::vector<std::vector<KeyPoint> >* kpts_par_;
|
||||||
KAZEOptions options_;
|
KAZEOptions options_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -304,7 +308,7 @@ private:
|
|||||||
* @param kpts Vector of keypoints
|
* @param kpts Vector of keypoints
|
||||||
* @note We compute features for each of the nonlinear scale space level in a different processing thread
|
* @note We compute features for each of the nonlinear scale space level in a different processing thread
|
||||||
*/
|
*/
|
||||||
void KAZEFeatures::Determinant_Hessian(std::vector<cv::KeyPoint>& kpts)
|
void KAZEFeatures::Determinant_Hessian(std::vector<KeyPoint>& kpts)
|
||||||
{
|
{
|
||||||
int level = 0;
|
int level = 0;
|
||||||
float dist = 0.0, smax = 3.0;
|
float dist = 0.0, smax = 3.0;
|
||||||
@ -325,12 +329,14 @@ void KAZEFeatures::Determinant_Hessian(std::vector<cv::KeyPoint>& kpts)
|
|||||||
kpts_par_.push_back(aux);
|
kpts_par_.push_back(aux);
|
||||||
}
|
}
|
||||||
|
|
||||||
cv::parallel_for_(cv::Range(1, (int)evolution_.size()-1),
|
parallel_for_(Range(1, (int)evolution_.size()-1),
|
||||||
FindExtremumKAZEInvoker(evolution_, kpts_par_, options_));
|
FindExtremumKAZEInvoker(evolution_, kpts_par_, options_));
|
||||||
|
|
||||||
// Now fill the vector of keypoints!!!
|
// Now fill the vector of keypoints!!!
|
||||||
for (int i = 0; i < (int)kpts_par_.size(); i++) {
|
for (int i = 0; i < (int)kpts_par_.size(); i++)
|
||||||
for (int j = 0; j < (int)kpts_par_[i].size(); j++) {
|
{
|
||||||
|
for (int j = 0; j < (int)kpts_par_[i].size(); j++)
|
||||||
|
{
|
||||||
level = i + 1;
|
level = i + 1;
|
||||||
is_extremum = true;
|
is_extremum = true;
|
||||||
is_repeated = false;
|
is_repeated = false;
|
||||||
@ -388,7 +394,7 @@ void KAZEFeatures::Determinant_Hessian(std::vector<cv::KeyPoint>& kpts)
|
|||||||
* @brief This method performs subpixel refinement of the detected keypoints
|
* @brief This method performs subpixel refinement of the detected keypoints
|
||||||
* @param kpts Vector of detected keypoints
|
* @param kpts Vector of detected keypoints
|
||||||
*/
|
*/
|
||||||
void KAZEFeatures::Do_Subpixel_Refinement(std::vector<cv::KeyPoint> &kpts) {
|
void KAZEFeatures::Do_Subpixel_Refinement(std::vector<KeyPoint> &kpts) {
|
||||||
|
|
||||||
int step = 1;
|
int step = 1;
|
||||||
int x = 0, y = 0;
|
int x = 0, y = 0;
|
||||||
@ -482,10 +488,10 @@ void KAZEFeatures::Do_Subpixel_Refinement(std::vector<cv::KeyPoint> &kpts) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
class KAZE_Descriptor_Invoker : public cv::ParallelLoopBody
|
class KAZE_Descriptor_Invoker : public ParallelLoopBody
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
KAZE_Descriptor_Invoker(std::vector<cv::KeyPoint> &kpts, cv::Mat &desc, std::vector<TEvolution>& evolution, const KAZEOptions& options)
|
KAZE_Descriptor_Invoker(std::vector<KeyPoint> &kpts, Mat &desc, std::vector<TEvolution>& evolution, const KAZEOptions& options)
|
||||||
: kpts_(&kpts)
|
: kpts_(&kpts)
|
||||||
, desc_(&desc)
|
, desc_(&desc)
|
||||||
, evolution_(&evolution)
|
, evolution_(&evolution)
|
||||||
@ -497,10 +503,10 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator() (const cv::Range& range) const
|
void operator() (const Range& range) const
|
||||||
{
|
{
|
||||||
std::vector<cv::KeyPoint> &kpts = *kpts_;
|
std::vector<KeyPoint> &kpts = *kpts_;
|
||||||
cv::Mat &desc = *desc_;
|
Mat &desc = *desc_;
|
||||||
std::vector<TEvolution> &evolution = *evolution_;
|
std::vector<TEvolution> &evolution = *evolution_;
|
||||||
|
|
||||||
for (int i = range.start; i < range.end; i++)
|
for (int i = range.start; i < range.end; i++)
|
||||||
@ -526,13 +532,13 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
void Get_KAZE_Upright_Descriptor_64(const cv::KeyPoint& kpt, float* desc) const;
|
void Get_KAZE_Upright_Descriptor_64(const KeyPoint& kpt, float* desc) const;
|
||||||
void Get_KAZE_Descriptor_64(const cv::KeyPoint& kpt, float* desc) const;
|
void Get_KAZE_Descriptor_64(const KeyPoint& kpt, float* desc) const;
|
||||||
void Get_KAZE_Upright_Descriptor_128(const cv::KeyPoint& kpt, float* desc) const;
|
void Get_KAZE_Upright_Descriptor_128(const KeyPoint& kpt, float* desc) const;
|
||||||
void Get_KAZE_Descriptor_128(const cv::KeyPoint& kpt, float *desc) const;
|
void Get_KAZE_Descriptor_128(const KeyPoint& kpt, float *desc) const;
|
||||||
|
|
||||||
std::vector<cv::KeyPoint> * kpts_;
|
std::vector<KeyPoint> * kpts_;
|
||||||
cv::Mat * desc_;
|
Mat * desc_;
|
||||||
std::vector<TEvolution> * evolution_;
|
std::vector<TEvolution> * evolution_;
|
||||||
KAZEOptions options_;
|
KAZEOptions options_;
|
||||||
};
|
};
|
||||||
@ -543,7 +549,7 @@ private:
|
|||||||
* @param kpts Vector of keypoints
|
* @param kpts Vector of keypoints
|
||||||
* @param desc Matrix with the feature descriptors
|
* @param desc Matrix with the feature descriptors
|
||||||
*/
|
*/
|
||||||
void KAZEFeatures::Feature_Description(std::vector<cv::KeyPoint> &kpts, cv::Mat &desc)
|
void KAZEFeatures::Feature_Description(std::vector<KeyPoint> &kpts, Mat &desc)
|
||||||
{
|
{
|
||||||
for(size_t i = 0; i < kpts.size(); i++)
|
for(size_t i = 0; i < kpts.size(); i++)
|
||||||
{
|
{
|
||||||
@ -558,7 +564,7 @@ void KAZEFeatures::Feature_Description(std::vector<cv::KeyPoint> &kpts, cv::Mat
|
|||||||
desc = Mat::zeros((int)kpts.size(), 64, CV_32FC1);
|
desc = Mat::zeros((int)kpts.size(), 64, CV_32FC1);
|
||||||
}
|
}
|
||||||
|
|
||||||
cv::parallel_for_(cv::Range(0, (int)kpts.size()), KAZE_Descriptor_Invoker(kpts, desc, evolution_, options_));
|
parallel_for_(Range(0, (int)kpts.size()), KAZE_Descriptor_Invoker(kpts, desc, evolution_, options_));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
@ -568,7 +574,7 @@ void KAZEFeatures::Feature_Description(std::vector<cv::KeyPoint> &kpts, cv::Mat
|
|||||||
* @note The orientation is computed using a similar approach as described in the
|
* @note The orientation is computed using a similar approach as described in the
|
||||||
* original SURF method. See Bay et al., Speeded Up Robust Features, ECCV 2006
|
* original SURF method. See Bay et al., Speeded Up Robust Features, ECCV 2006
|
||||||
*/
|
*/
|
||||||
void KAZEFeatures::Compute_Main_Orientation(cv::KeyPoint &kpt, const std::vector<TEvolution>& evolution_, const KAZEOptions& options)
|
void KAZEFeatures::Compute_Main_Orientation(KeyPoint &kpt, const std::vector<TEvolution>& evolution_, const KAZEOptions& options)
|
||||||
{
|
{
|
||||||
int ix = 0, iy = 0, idx = 0, s = 0, level = 0;
|
int ix = 0, iy = 0, idx = 0, s = 0, level = 0;
|
||||||
float xf = 0.0, yf = 0.0, gweight = 0.0;
|
float xf = 0.0, yf = 0.0, gweight = 0.0;
|
||||||
@ -647,7 +653,7 @@ void KAZEFeatures::Compute_Main_Orientation(cv::KeyPoint &kpt, const std::vector
|
|||||||
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
||||||
* ECCV 2008
|
* ECCV 2008
|
||||||
*/
|
*/
|
||||||
void KAZE_Descriptor_Invoker::Get_KAZE_Upright_Descriptor_64(const cv::KeyPoint &kpt, float *desc) const
|
void KAZE_Descriptor_Invoker::Get_KAZE_Upright_Descriptor_64(const KeyPoint &kpt, float *desc) const
|
||||||
{
|
{
|
||||||
float dx = 0.0, dy = 0.0, mdx = 0.0, mdy = 0.0, gauss_s1 = 0.0, gauss_s2 = 0.0;
|
float dx = 0.0, dy = 0.0, mdx = 0.0, mdy = 0.0, gauss_s1 = 0.0, gauss_s2 = 0.0;
|
||||||
float rx = 0.0, ry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
float rx = 0.0, ry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
||||||
@ -775,7 +781,7 @@ void KAZE_Descriptor_Invoker::Get_KAZE_Upright_Descriptor_64(const cv::KeyPoint
|
|||||||
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
||||||
* ECCV 2008
|
* ECCV 2008
|
||||||
*/
|
*/
|
||||||
void KAZE_Descriptor_Invoker::Get_KAZE_Descriptor_64(const cv::KeyPoint &kpt, float *desc) const
|
void KAZE_Descriptor_Invoker::Get_KAZE_Descriptor_64(const KeyPoint &kpt, float *desc) const
|
||||||
{
|
{
|
||||||
float dx = 0.0, dy = 0.0, mdx = 0.0, mdy = 0.0, gauss_s1 = 0.0, gauss_s2 = 0.0;
|
float dx = 0.0, dy = 0.0, mdx = 0.0, mdy = 0.0, gauss_s1 = 0.0, gauss_s2 = 0.0;
|
||||||
float rx = 0.0, ry = 0.0, rrx = 0.0, rry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
float rx = 0.0, ry = 0.0, rrx = 0.0, rry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
||||||
@ -904,7 +910,7 @@ void KAZE_Descriptor_Invoker::Get_KAZE_Descriptor_64(const cv::KeyPoint &kpt, fl
|
|||||||
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
||||||
* ECCV 2008
|
* ECCV 2008
|
||||||
*/
|
*/
|
||||||
void KAZE_Descriptor_Invoker::Get_KAZE_Upright_Descriptor_128(const cv::KeyPoint &kpt, float *desc) const
|
void KAZE_Descriptor_Invoker::Get_KAZE_Upright_Descriptor_128(const KeyPoint &kpt, float *desc) const
|
||||||
{
|
{
|
||||||
float gauss_s1 = 0.0, gauss_s2 = 0.0;
|
float gauss_s1 = 0.0, gauss_s2 = 0.0;
|
||||||
float rx = 0.0, ry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
float rx = 0.0, ry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
||||||
@ -1056,7 +1062,7 @@ void KAZE_Descriptor_Invoker::Get_KAZE_Upright_Descriptor_128(const cv::KeyPoint
|
|||||||
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
* from Agrawal et al., CenSurE: Center Surround Extremas for Realtime Feature Detection and Matching,
|
||||||
* ECCV 2008
|
* ECCV 2008
|
||||||
*/
|
*/
|
||||||
void KAZE_Descriptor_Invoker::Get_KAZE_Descriptor_128(const cv::KeyPoint &kpt, float *desc) const
|
void KAZE_Descriptor_Invoker::Get_KAZE_Descriptor_128(const KeyPoint &kpt, float *desc) const
|
||||||
{
|
{
|
||||||
float gauss_s1 = 0.0, gauss_s2 = 0.0;
|
float gauss_s1 = 0.0, gauss_s2 = 0.0;
|
||||||
float rx = 0.0, ry = 0.0, rrx = 0.0, rry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
float rx = 0.0, ry = 0.0, rrx = 0.0, rry = 0.0, len = 0.0, xf = 0.0, yf = 0.0, ys = 0.0, xs = 0.0;
|
||||||
@ -1202,3 +1208,5 @@ void KAZE_Descriptor_Invoker::Get_KAZE_Descriptor_128(const cv::KeyPoint &kpt, f
|
|||||||
desc[i] /= len;
|
desc[i] /= len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -17,10 +17,13 @@
|
|||||||
#include "fed.h"
|
#include "fed.h"
|
||||||
#include "TEvolution.h"
|
#include "TEvolution.h"
|
||||||
|
|
||||||
|
namespace cv
|
||||||
|
{
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
// KAZE Class Declaration
|
// KAZE Class Declaration
|
||||||
class KAZEFeatures {
|
class KAZEFeatures
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// Parameters of the Nonlinear diffusion class
|
/// Parameters of the Nonlinear diffusion class
|
||||||
@ -56,4 +59,6 @@ public:
|
|||||||
void Do_Subpixel_Refinement(std::vector<cv::KeyPoint>& kpts);
|
void Do_Subpixel_Refinement(std::vector<cv::KeyPoint>& kpts);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,10 +8,13 @@
|
|||||||
#ifndef __OPENCV_FEATURES_2D_TEVOLUTION_H__
|
#ifndef __OPENCV_FEATURES_2D_TEVOLUTION_H__
|
||||||
#define __OPENCV_FEATURES_2D_TEVOLUTION_H__
|
#define __OPENCV_FEATURES_2D_TEVOLUTION_H__
|
||||||
|
|
||||||
|
namespace cv
|
||||||
|
{
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/// KAZE/A-KAZE nonlinear diffusion filtering evolution
|
/// KAZE/A-KAZE nonlinear diffusion filtering evolution
|
||||||
struct TEvolution {
|
struct TEvolution
|
||||||
|
{
|
||||||
TEvolution() {
|
TEvolution() {
|
||||||
etime = 0.0f;
|
etime = 0.0f;
|
||||||
esigma = 0.0f;
|
esigma = 0.0f;
|
||||||
@ -20,11 +23,11 @@ struct TEvolution {
|
|||||||
sigma_size = 0;
|
sigma_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cv::Mat Lx, Ly; ///< First order spatial derivatives
|
Mat Lx, Ly; ///< First order spatial derivatives
|
||||||
cv::Mat Lxx, Lxy, Lyy; ///< Second order spatial derivatives
|
Mat Lxx, Lxy, Lyy; ///< Second order spatial derivatives
|
||||||
cv::Mat Lt; ///< Evolution image
|
Mat Lt; ///< Evolution image
|
||||||
cv::Mat Lsmooth; ///< Smoothed image
|
Mat Lsmooth; ///< Smoothed image
|
||||||
cv::Mat Ldet; ///< Detector response
|
Mat Ldet; ///< Detector response
|
||||||
float etime; ///< Evolution time
|
float etime; ///< Evolution time
|
||||||
float esigma; ///< Evolution sigma. For linear diffusion t = sigma^2 / 2
|
float esigma; ///< Evolution sigma. For linear diffusion t = sigma^2 / 2
|
||||||
int octave; ///< Image octave
|
int octave; ///< Image octave
|
||||||
@ -32,4 +35,6 @@ struct TEvolution {
|
|||||||
int sigma_size; ///< Integer esigma. For computing the feature detector responses
|
int sigma_size; ///< Integer esigma. For computing the feature detector responses
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -22,21 +22,20 @@
|
|||||||
* @author Pablo F. Alcantarilla
|
* @author Pablo F. Alcantarilla
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "../precomp.hpp"
|
||||||
#include "nldiffusion_functions.h"
|
#include "nldiffusion_functions.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
// Namespaces
|
// Namespaces
|
||||||
using namespace std;
|
|
||||||
using namespace cv;
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
||||||
namespace cv {
|
namespace cv
|
||||||
namespace details {
|
{
|
||||||
namespace kaze {
|
using namespace std;
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/**
|
/**
|
||||||
* @brief This function smoothes an image with a Gaussian kernel
|
* @brief This function smoothes an image with a Gaussian kernel
|
||||||
* @param src Input image
|
* @param src Input image
|
||||||
* @param dst Output image
|
* @param dst Output image
|
||||||
@ -44,7 +43,7 @@ namespace cv {
|
|||||||
* @param ksize_y Kernel size in Y-direction (vertical)
|
* @param ksize_y Kernel size in Y-direction (vertical)
|
||||||
* @param sigma Kernel standard deviation
|
* @param sigma Kernel standard deviation
|
||||||
*/
|
*/
|
||||||
void gaussian_2D_convolution(const cv::Mat& src, cv::Mat& dst, int ksize_x, int ksize_y, float sigma) {
|
void gaussian_2D_convolution(const cv::Mat& src, cv::Mat& dst, int ksize_x, int ksize_y, float sigma) {
|
||||||
|
|
||||||
int ksize_x_ = 0, ksize_y_ = 0;
|
int ksize_x_ = 0, ksize_y_ = 0;
|
||||||
|
|
||||||
@ -65,10 +64,10 @@ namespace cv {
|
|||||||
|
|
||||||
// Perform the Gaussian Smoothing with border replication
|
// Perform the Gaussian Smoothing with border replication
|
||||||
GaussianBlur(src, dst, Size(ksize_x_, ksize_y_), sigma, sigma, BORDER_REPLICATE);
|
GaussianBlur(src, dst, Size(ksize_x_, ksize_y_), sigma, sigma, BORDER_REPLICATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/**
|
/**
|
||||||
* @brief This function computes image derivatives with Scharr kernel
|
* @brief This function computes image derivatives with Scharr kernel
|
||||||
* @param src Input image
|
* @param src Input image
|
||||||
* @param dst Output image
|
* @param dst Output image
|
||||||
@ -79,12 +78,12 @@ namespace cv {
|
|||||||
* A Scheme for Coherence-Enhancing Diffusion Filtering with Optimized Rotation Invariance,
|
* A Scheme for Coherence-Enhancing Diffusion Filtering with Optimized Rotation Invariance,
|
||||||
* Journal of Visual Communication and Image Representation 2002
|
* Journal of Visual Communication and Image Representation 2002
|
||||||
*/
|
*/
|
||||||
void image_derivatives_scharr(const cv::Mat& src, cv::Mat& dst, int xorder, int yorder) {
|
void image_derivatives_scharr(const cv::Mat& src, cv::Mat& dst, int xorder, int yorder) {
|
||||||
Scharr(src, dst, CV_32F, xorder, yorder, 1.0, 0, BORDER_DEFAULT);
|
Scharr(src, dst, CV_32F, xorder, yorder, 1.0, 0, BORDER_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/**
|
/**
|
||||||
* @brief This function computes the Perona and Malik conductivity coefficient g1
|
* @brief This function computes the Perona and Malik conductivity coefficient g1
|
||||||
* g1 = exp(-|dL|^2/k^2)
|
* g1 = exp(-|dL|^2/k^2)
|
||||||
* @param Lx First order image derivative in X-direction (horizontal)
|
* @param Lx First order image derivative in X-direction (horizontal)
|
||||||
@ -92,7 +91,7 @@ namespace cv {
|
|||||||
* @param dst Output image
|
* @param dst Output image
|
||||||
* @param k Contrast factor parameter
|
* @param k Contrast factor parameter
|
||||||
*/
|
*/
|
||||||
void pm_g1(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k) {
|
void pm_g1(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k) {
|
||||||
|
|
||||||
Size sz = Lx.size();
|
Size sz = Lx.size();
|
||||||
float inv_k = 1.0f / (k*k);
|
float inv_k = 1.0f / (k*k);
|
||||||
@ -108,10 +107,10 @@ namespace cv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
exp(dst, dst);
|
exp(dst, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/**
|
/**
|
||||||
* @brief This function computes the Perona and Malik conductivity coefficient g2
|
* @brief This function computes the Perona and Malik conductivity coefficient g2
|
||||||
* g2 = 1 / (1 + dL^2 / k^2)
|
* g2 = 1 / (1 + dL^2 / k^2)
|
||||||
* @param Lx First order image derivative in X-direction (horizontal)
|
* @param Lx First order image derivative in X-direction (horizontal)
|
||||||
@ -119,7 +118,7 @@ namespace cv {
|
|||||||
* @param dst Output image
|
* @param dst Output image
|
||||||
* @param k Contrast factor parameter
|
* @param k Contrast factor parameter
|
||||||
*/
|
*/
|
||||||
void pm_g2(const cv::Mat &Lx, const cv::Mat& Ly, cv::Mat& dst, float k) {
|
void pm_g2(const cv::Mat &Lx, const cv::Mat& Ly, cv::Mat& dst, float k) {
|
||||||
|
|
||||||
Size sz = Lx.size();
|
Size sz = Lx.size();
|
||||||
dst.create(sz, Lx.type());
|
dst.create(sz, Lx.type());
|
||||||
@ -133,9 +132,9 @@ namespace cv {
|
|||||||
dst_row[x] = 1.0f / (1.0f + ((Lx_row[x] * Lx_row[x] + Ly_row[x] * Ly_row[x]) * k2inv));
|
dst_row[x] = 1.0f / (1.0f + ((Lx_row[x] * Lx_row[x] + Ly_row[x] * Ly_row[x]) * k2inv));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/**
|
/**
|
||||||
* @brief This function computes Weickert conductivity coefficient gw
|
* @brief This function computes Weickert conductivity coefficient gw
|
||||||
* @param Lx First order image derivative in X-direction (horizontal)
|
* @param Lx First order image derivative in X-direction (horizontal)
|
||||||
* @param Ly First order image derivative in Y-direction (vertical)
|
* @param Ly First order image derivative in Y-direction (vertical)
|
||||||
@ -145,7 +144,7 @@ namespace cv {
|
|||||||
* Applications of nonlinear diffusion in image processing and computer vision,
|
* Applications of nonlinear diffusion in image processing and computer vision,
|
||||||
* Proceedings of Algorithmy 2000
|
* Proceedings of Algorithmy 2000
|
||||||
*/
|
*/
|
||||||
void weickert_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k) {
|
void weickert_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k) {
|
||||||
|
|
||||||
Size sz = Lx.size();
|
Size sz = Lx.size();
|
||||||
float inv_k = 1.0f / (k*k);
|
float inv_k = 1.0f / (k*k);
|
||||||
@ -163,22 +162,22 @@ namespace cv {
|
|||||||
|
|
||||||
exp(dst, dst);
|
exp(dst, dst);
|
||||||
dst = 1.0 - dst;
|
dst = 1.0 - dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/**
|
/**
|
||||||
* @brief This function computes Charbonnier conductivity coefficient gc
|
* @brief This function computes Charbonnier conductivity coefficient gc
|
||||||
* gc = 1 / sqrt(1 + dL^2 / k^2)
|
* gc = 1 / sqrt(1 + dL^2 / k^2)
|
||||||
* @param Lx First order image derivative in X-direction (horizontal)
|
* @param Lx First order image derivative in X-direction (horizontal)
|
||||||
* @param Ly First order image derivative in Y-direction (vertical)
|
* @param Ly First order image derivative in Y-direction (vertical)
|
||||||
* @param dst Output image
|
* @param dst Output image
|
||||||
* @param k Contrast factor parameter
|
* @param k Contrast factor parameter
|
||||||
* @note For more information check the following paper: J. Weickert
|
* @note For more information check the following paper: J. Weickert
|
||||||
* Applications of nonlinear diffusion in image processing and computer vision,
|
* Applications of nonlinear diffusion in image processing and computer vision,
|
||||||
* Proceedings of Algorithmy 2000
|
* Proceedings of Algorithmy 2000
|
||||||
*/
|
*/
|
||||||
void charbonnier_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k) {
|
void charbonnier_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k) {
|
||||||
|
|
||||||
Size sz = Lx.size();
|
Size sz = Lx.size();
|
||||||
float inv_k = 1.0f / (k*k);
|
float inv_k = 1.0f / (k*k);
|
||||||
@ -193,11 +192,11 @@ namespace cv {
|
|||||||
dst_row[x] = 1.0f / den;
|
dst_row[x] = 1.0f / den;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/**
|
/**
|
||||||
* @brief This function computes a good empirical value for the k contrast factor
|
* @brief This function computes a good empirical value for the k contrast factor
|
||||||
* given an input image, the percentile (0-1), the gradient scale and the number of
|
* given an input image, the percentile (0-1), the gradient scale and the number of
|
||||||
* bins in the histogram
|
* bins in the histogram
|
||||||
@ -209,7 +208,7 @@ namespace cv {
|
|||||||
* @param ksize_y Kernel size in Y-direction (vertical) for the Gaussian smoothing kernel
|
* @param ksize_y Kernel size in Y-direction (vertical) for the Gaussian smoothing kernel
|
||||||
* @return k contrast factor
|
* @return k contrast factor
|
||||||
*/
|
*/
|
||||||
float compute_k_percentile(const cv::Mat& img, float perc, float gscale, int nbins, int ksize_x, int ksize_y) {
|
float compute_k_percentile(const cv::Mat& img, float perc, float gscale, int nbins, int ksize_x, int ksize_y) {
|
||||||
|
|
||||||
int nbin = 0, nelements = 0, nthreshold = 0, k = 0;
|
int nbin = 0, nelements = 0, nthreshold = 0, k = 0;
|
||||||
float kperc = 0.0, modg = 0.0;
|
float kperc = 0.0, modg = 0.0;
|
||||||
@ -281,10 +280,10 @@ namespace cv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return kperc;
|
return kperc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/**
|
/**
|
||||||
* @brief This function computes Scharr image derivatives
|
* @brief This function computes Scharr image derivatives
|
||||||
* @param src Input image
|
* @param src Input image
|
||||||
* @param dst Output image
|
* @param dst Output image
|
||||||
@ -292,14 +291,14 @@ namespace cv {
|
|||||||
* @param yorder Derivative order in Y-direction (vertical)
|
* @param yorder Derivative order in Y-direction (vertical)
|
||||||
* @param scale Scale factor for the derivative size
|
* @param scale Scale factor for the derivative size
|
||||||
*/
|
*/
|
||||||
void compute_scharr_derivatives(const cv::Mat& src, cv::Mat& dst, int xorder, int yorder, int scale) {
|
void compute_scharr_derivatives(const cv::Mat& src, cv::Mat& dst, int xorder, int yorder, int scale) {
|
||||||
Mat kx, ky;
|
Mat kx, ky;
|
||||||
compute_derivative_kernels(kx, ky, xorder, yorder, scale);
|
compute_derivative_kernels(kx, ky, xorder, yorder, scale);
|
||||||
sepFilter2D(src, dst, CV_32F, kx, ky);
|
sepFilter2D(src, dst, CV_32F, kx, ky);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/**
|
/**
|
||||||
* @brief Compute derivative kernels for sizes different than 3
|
* @brief Compute derivative kernels for sizes different than 3
|
||||||
* @param _kx Horizontal kernel ues
|
* @param _kx Horizontal kernel ues
|
||||||
* @param _ky Vertical kernel values
|
* @param _ky Vertical kernel values
|
||||||
@ -307,7 +306,7 @@ namespace cv {
|
|||||||
* @param dy Derivative order in Y-direction (vertical)
|
* @param dy Derivative order in Y-direction (vertical)
|
||||||
* @param scale_ Scale factor or derivative size
|
* @param scale_ Scale factor or derivative size
|
||||||
*/
|
*/
|
||||||
void compute_derivative_kernels(cv::OutputArray _kx, cv::OutputArray _ky, int dx, int dy, int scale) {
|
void compute_derivative_kernels(cv::OutputArray _kx, cv::OutputArray _ky, int dx, int dy, int scale) {
|
||||||
|
|
||||||
int ksize = 3 + 2 * (scale - 1);
|
int ksize = 3 + 2 * (scale - 1);
|
||||||
|
|
||||||
@ -340,11 +339,11 @@ namespace cv {
|
|||||||
Mat temp(kernel->rows, kernel->cols, CV_32F, &kerI[0]);
|
Mat temp(kernel->rows, kernel->cols, CV_32F, &kerI[0]);
|
||||||
temp.copyTo(*kernel);
|
temp.copyTo(*kernel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Nld_Step_Scalar_Invoker : public cv::ParallelLoopBody
|
class Nld_Step_Scalar_Invoker : public cv::ParallelLoopBody
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Nld_Step_Scalar_Invoker(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, float _stepsize)
|
Nld_Step_Scalar_Invoker(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, float _stepsize)
|
||||||
: _Ld(&Ld)
|
: _Ld(&Ld)
|
||||||
, _c(&c)
|
, _c(&c)
|
||||||
@ -385,25 +384,25 @@ namespace cv {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
cv::Mat * _Ld;
|
cv::Mat * _Ld;
|
||||||
const cv::Mat * _c;
|
const cv::Mat * _c;
|
||||||
cv::Mat * _Lstep;
|
cv::Mat * _Lstep;
|
||||||
float stepsize;
|
float stepsize;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/**
|
/**
|
||||||
* @brief This function performs a scalar non-linear diffusion step
|
* @brief This function performs a scalar non-linear diffusion step
|
||||||
* @param Ld2 Output image in the evolution
|
* @param Ld2 Output image in the evolution
|
||||||
* @param c Conductivity image
|
* @param c Conductivity image
|
||||||
* @param Lstep Previous image in the evolution
|
* @param Lstep Previous image in the evolution
|
||||||
* @param stepsize The step size in time units
|
* @param stepsize The step size in time units
|
||||||
* @note Forward Euler Scheme 3x3 stencil
|
* @note Forward Euler Scheme 3x3 stencil
|
||||||
* The function c is a scalar value that depends on the gradient norm
|
* The function c is a scalar value that depends on the gradient norm
|
||||||
* dL_by_ds = d(c dL_by_dx)_by_dx + d(c dL_by_dy)_by_dy
|
* dL_by_ds = d(c dL_by_dx)_by_dx + d(c dL_by_dy)_by_dy
|
||||||
*/
|
*/
|
||||||
void nld_step_scalar(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, float stepsize) {
|
void nld_step_scalar(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, float stepsize) {
|
||||||
|
|
||||||
cv::parallel_for_(cv::Range(1, Lstep.rows - 1), Nld_Step_Scalar_Invoker(Ld, c, Lstep, stepsize), (double)Ld.total()/(1 << 16));
|
cv::parallel_for_(cv::Range(1, Lstep.rows - 1), Nld_Step_Scalar_Invoker(Ld, c, Lstep, stepsize), (double)Ld.total()/(1 << 16));
|
||||||
|
|
||||||
@ -464,24 +463,24 @@ namespace cv {
|
|||||||
ldcur = ldnxt;
|
ldcur = ldnxt;
|
||||||
}
|
}
|
||||||
Ld += Lstep;
|
Ld += Lstep;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/**
|
/**
|
||||||
* @brief This function downsamples the input image using OpenCV resize
|
* @brief This function downsamples the input image using OpenCV resize
|
||||||
* @param img Input image to be downsampled
|
* @param img Input image to be downsampled
|
||||||
* @param dst Output image with half of the resolution of the input image
|
* @param dst Output image with half of the resolution of the input image
|
||||||
*/
|
*/
|
||||||
void halfsample_image(const cv::Mat& src, cv::Mat& dst) {
|
void halfsample_image(const cv::Mat& src, cv::Mat& dst) {
|
||||||
|
|
||||||
// Make sure the destination image is of the right size
|
// Make sure the destination image is of the right size
|
||||||
CV_Assert(src.cols / 2 == dst.cols);
|
CV_Assert(src.cols / 2 == dst.cols);
|
||||||
CV_Assert(src.rows / 2 == dst.rows);
|
CV_Assert(src.rows / 2 == dst.rows);
|
||||||
resize(src, dst, dst.size(), 0, 0, cv::INTER_AREA);
|
resize(src, dst, dst.size(), 0, 0, cv::INTER_AREA);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
/**
|
/**
|
||||||
* @brief This function checks if a given pixel is a maximum in a local neighbourhood
|
* @brief This function checks if a given pixel is a maximum in a local neighbourhood
|
||||||
* @param img Input image where we will perform the maximum search
|
* @param img Input image where we will perform the maximum search
|
||||||
* @param dsize Half size of the neighbourhood
|
* @param dsize Half size of the neighbourhood
|
||||||
@ -491,7 +490,7 @@ namespace cv {
|
|||||||
* @param same_img Flag to indicate if the image value at (x,y) is in the input image
|
* @param same_img Flag to indicate if the image value at (x,y) is in the input image
|
||||||
* @return 1->is maximum, 0->otherwise
|
* @return 1->is maximum, 0->otherwise
|
||||||
*/
|
*/
|
||||||
bool check_maximum_neighbourhood(const cv::Mat& img, int dsize, float value, int row, int col, bool same_img) {
|
bool check_maximum_neighbourhood(const cv::Mat& img, int dsize, float value, int row, int col, bool same_img) {
|
||||||
|
|
||||||
bool response = true;
|
bool response = true;
|
||||||
|
|
||||||
@ -517,7 +516,6 @@ namespace cv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -11,43 +11,37 @@
|
|||||||
#ifndef __OPENCV_FEATURES_2D_NLDIFFUSION_FUNCTIONS_H__
|
#ifndef __OPENCV_FEATURES_2D_NLDIFFUSION_FUNCTIONS_H__
|
||||||
#define __OPENCV_FEATURES_2D_NLDIFFUSION_FUNCTIONS_H__
|
#define __OPENCV_FEATURES_2D_NLDIFFUSION_FUNCTIONS_H__
|
||||||
|
|
||||||
/* ************************************************************************* */
|
|
||||||
// Includes
|
|
||||||
#include "../precomp.hpp"
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
// Declaration of functions
|
// Declaration of functions
|
||||||
|
|
||||||
namespace cv {
|
namespace cv
|
||||||
namespace details {
|
{
|
||||||
namespace kaze {
|
|
||||||
|
|
||||||
// Gaussian 2D convolution
|
// Gaussian 2D convolution
|
||||||
void gaussian_2D_convolution(const cv::Mat& src, cv::Mat& dst, int ksize_x, int ksize_y, float sigma);
|
void gaussian_2D_convolution(const cv::Mat& src, cv::Mat& dst, int ksize_x, int ksize_y, float sigma);
|
||||||
|
|
||||||
// Diffusivity functions
|
// Diffusivity functions
|
||||||
void pm_g1(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k);
|
void pm_g1(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k);
|
||||||
void pm_g2(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k);
|
void pm_g2(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k);
|
||||||
void weickert_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k);
|
void weickert_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k);
|
||||||
void charbonnier_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k);
|
void charbonnier_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k);
|
||||||
|
|
||||||
float compute_k_percentile(const cv::Mat& img, float perc, float gscale, int nbins, int ksize_x, int ksize_y);
|
float compute_k_percentile(const cv::Mat& img, float perc, float gscale, int nbins, int ksize_x, int ksize_y);
|
||||||
|
|
||||||
// Image derivatives
|
// Image derivatives
|
||||||
void compute_scharr_derivatives(const cv::Mat& src, cv::Mat& dst, int xorder, int yorder, int scale);
|
void compute_scharr_derivatives(const cv::Mat& src, cv::Mat& dst, int xorder, int yorder, int scale);
|
||||||
void compute_derivative_kernels(cv::OutputArray _kx, cv::OutputArray _ky, int dx, int dy, int scale);
|
void compute_derivative_kernels(cv::OutputArray _kx, cv::OutputArray _ky, int dx, int dy, int scale);
|
||||||
void image_derivatives_scharr(const cv::Mat& src, cv::Mat& dst, int xorder, int yorder);
|
void image_derivatives_scharr(const cv::Mat& src, cv::Mat& dst, int xorder, int yorder);
|
||||||
|
|
||||||
// Nonlinear diffusion filtering scalar step
|
// Nonlinear diffusion filtering scalar step
|
||||||
void nld_step_scalar(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, float stepsize);
|
void nld_step_scalar(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, float stepsize);
|
||||||
|
|
||||||
// For non-maxima suppresion
|
// For non-maxima suppresion
|
||||||
bool check_maximum_neighbourhood(const cv::Mat& img, int dsize, float value, int row, int col, bool same_img);
|
bool check_maximum_neighbourhood(const cv::Mat& img, int dsize, float value, int row, int col, bool same_img);
|
||||||
|
|
||||||
|
// Image downsampling
|
||||||
|
void halfsample_image(const cv::Mat& src, cv::Mat& dst);
|
||||||
|
|
||||||
// Image downsampling
|
|
||||||
void halfsample_image(const cv::Mat& src, cv::Mat& dst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -38,6 +38,10 @@
|
|||||||
#include "opencl_kernels_features2d.hpp"
|
#include "opencl_kernels_features2d.hpp"
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
|
#ifndef CV_IMPL_ADD
|
||||||
|
#define CV_IMPL_ADD(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace cv
|
namespace cv
|
||||||
@ -100,12 +104,12 @@ ocl_ICAngles(const UMat& imgbuf, const UMat& layerinfo,
|
|||||||
static bool
|
static bool
|
||||||
ocl_computeOrbDescriptors(const UMat& imgbuf, const UMat& layerInfo,
|
ocl_computeOrbDescriptors(const UMat& imgbuf, const UMat& layerInfo,
|
||||||
const UMat& keypoints, UMat& desc, const UMat& pattern,
|
const UMat& keypoints, UMat& desc, const UMat& pattern,
|
||||||
int nkeypoints, int dsize, int WTA_K)
|
int nkeypoints, int dsize, int wta_k)
|
||||||
{
|
{
|
||||||
size_t globalSize[] = {nkeypoints};
|
size_t globalSize[] = {nkeypoints};
|
||||||
|
|
||||||
ocl::Kernel desc_ker("ORB_computeDescriptor", ocl::features2d::orb_oclsrc,
|
ocl::Kernel desc_ker("ORB_computeDescriptor", ocl::features2d::orb_oclsrc,
|
||||||
format("-D ORB_DESCRIPTORS -D WTA_K=%d", WTA_K));
|
format("-D ORB_DESCRIPTORS -D WTA_K=%d", wta_k));
|
||||||
if( desc_ker.empty() )
|
if( desc_ker.empty() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -209,7 +213,7 @@ static void ICAngles(const Mat& img, const std::vector<Rect>& layerinfo,
|
|||||||
static void
|
static void
|
||||||
computeOrbDescriptors( const Mat& imagePyramid, const std::vector<Rect>& layerInfo,
|
computeOrbDescriptors( const Mat& imagePyramid, const std::vector<Rect>& layerInfo,
|
||||||
const std::vector<float>& layerScale, std::vector<KeyPoint>& keypoints,
|
const std::vector<float>& layerScale, std::vector<KeyPoint>& keypoints,
|
||||||
Mat& descriptors, const std::vector<Point>& _pattern, int dsize, int WTA_K )
|
Mat& descriptors, const std::vector<Point>& _pattern, int dsize, int wta_k )
|
||||||
{
|
{
|
||||||
int step = (int)imagePyramid.step;
|
int step = (int)imagePyramid.step;
|
||||||
int j, i, nkeypoints = (int)keypoints.size();
|
int j, i, nkeypoints = (int)keypoints.size();
|
||||||
@ -248,7 +252,7 @@ computeOrbDescriptors( const Mat& imagePyramid, const std::vector<Rect>& layerIn
|
|||||||
center[iy*step + ix+1]*x*(1-y) + center[(iy+1)*step + ix+1]*x*y))
|
center[iy*step + ix+1]*x*(1-y) + center[(iy+1)*step + ix+1]*x*y))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if( WTA_K == 2 )
|
if( wta_k == 2 )
|
||||||
{
|
{
|
||||||
for (i = 0; i < dsize; ++i, pattern += 16)
|
for (i = 0; i < dsize; ++i, pattern += 16)
|
||||||
{
|
{
|
||||||
@ -273,7 +277,7 @@ computeOrbDescriptors( const Mat& imagePyramid, const std::vector<Rect>& layerIn
|
|||||||
desc[i] = (uchar)val;
|
desc[i] = (uchar)val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( WTA_K == 3 )
|
else if( wta_k == 3 )
|
||||||
{
|
{
|
||||||
for (i = 0; i < dsize; ++i, pattern += 12)
|
for (i = 0; i < dsize; ++i, pattern += 12)
|
||||||
{
|
{
|
||||||
@ -293,7 +297,7 @@ computeOrbDescriptors( const Mat& imagePyramid, const std::vector<Rect>& layerIn
|
|||||||
desc[i] = (uchar)val;
|
desc[i] = (uchar)val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( WTA_K == 4 )
|
else if( wta_k == 4 )
|
||||||
{
|
{
|
||||||
for (i = 0; i < dsize; ++i, pattern += 16)
|
for (i = 0; i < dsize; ++i, pattern += 16)
|
||||||
{
|
{
|
||||||
@ -334,7 +338,7 @@ computeOrbDescriptors( const Mat& imagePyramid, const std::vector<Rect>& layerIn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
CV_Error( Error::StsBadSize, "Wrong WTA_K. It can be only 2, 3 or 4." );
|
CV_Error( Error::StsBadSize, "Wrong wta_k. It can be only 2, 3 or 4." );
|
||||||
#undef GET_VALUE
|
#undef GET_VALUE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -645,43 +649,106 @@ static inline float getScale(int level, int firstLevel, double scaleFactor)
|
|||||||
return (float)std::pow(scaleFactor, (double)(level - firstLevel));
|
return (float)std::pow(scaleFactor, (double)(level - firstLevel));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constructor
|
|
||||||
* @param detector_params parameters to use
|
class ORB_Impl : public ORB
|
||||||
*/
|
{
|
||||||
ORB::ORB(int _nfeatures, float _scaleFactor, int _nlevels, int _edgeThreshold,
|
public:
|
||||||
|
explicit ORB_Impl(int _nfeatures, float _scaleFactor, int _nlevels, int _edgeThreshold,
|
||||||
int _firstLevel, int _WTA_K, int _scoreType, int _patchSize, int _fastThreshold) :
|
int _firstLevel, int _WTA_K, int _scoreType, int _patchSize, int _fastThreshold) :
|
||||||
nfeatures(_nfeatures), scaleFactor(_scaleFactor), nlevels(_nlevels),
|
nfeatures(_nfeatures), scaleFactor(_scaleFactor), nlevels(_nlevels),
|
||||||
edgeThreshold(_edgeThreshold), firstLevel(_firstLevel), WTA_K(_WTA_K),
|
edgeThreshold(_edgeThreshold), firstLevel(_firstLevel), wta_k(_WTA_K),
|
||||||
scoreType(_scoreType), patchSize(_patchSize), fastThreshold(_fastThreshold)
|
scoreType(_scoreType), patchSize(_patchSize), fastThreshold(_fastThreshold)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
void set(int prop, double value)
|
||||||
|
{
|
||||||
|
if( prop == NFEATURES )
|
||||||
|
nfeatures = cvRound(value);
|
||||||
|
else if( prop == SCALE_FACTOR )
|
||||||
|
scaleFactor = value;
|
||||||
|
else if( prop == NLEVELS )
|
||||||
|
nlevels = cvRound(value);
|
||||||
|
else if( prop == EDGE_THRESHOLD )
|
||||||
|
edgeThreshold = cvRound(value);
|
||||||
|
else if( prop == FIRST_LEVEL )
|
||||||
|
firstLevel = cvRound(value);
|
||||||
|
else if( prop == WTA_K )
|
||||||
|
wta_k = cvRound(value);
|
||||||
|
else if( prop == SCORE_TYPE )
|
||||||
|
scoreType = cvRound(value);
|
||||||
|
else if( prop == PATCH_SIZE )
|
||||||
|
patchSize = cvRound(value);
|
||||||
|
else if( prop == FAST_THRESHOLD )
|
||||||
|
fastThreshold = cvRound(value);
|
||||||
|
else
|
||||||
|
CV_Error(Error::StsBadArg, "");
|
||||||
|
}
|
||||||
|
|
||||||
int ORB::descriptorSize() const
|
double get(int prop) const
|
||||||
|
{
|
||||||
|
double value = 0;
|
||||||
|
if( prop == NFEATURES )
|
||||||
|
value = nfeatures;
|
||||||
|
else if( prop == SCALE_FACTOR )
|
||||||
|
value = scaleFactor;
|
||||||
|
else if( prop == NLEVELS )
|
||||||
|
value = nlevels;
|
||||||
|
else if( prop == EDGE_THRESHOLD )
|
||||||
|
value = edgeThreshold;
|
||||||
|
else if( prop == FIRST_LEVEL )
|
||||||
|
value = firstLevel;
|
||||||
|
else if( prop == WTA_K )
|
||||||
|
value = wta_k;
|
||||||
|
else if( prop == SCORE_TYPE )
|
||||||
|
value = scoreType;
|
||||||
|
else if( prop == PATCH_SIZE )
|
||||||
|
value = patchSize;
|
||||||
|
else if( prop == FAST_THRESHOLD )
|
||||||
|
value = fastThreshold;
|
||||||
|
else
|
||||||
|
CV_Error(Error::StsBadArg, "");
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the descriptor size in bytes
|
||||||
|
int descriptorSize() const;
|
||||||
|
// returns the descriptor type
|
||||||
|
int descriptorType() const;
|
||||||
|
// returns the default norm type
|
||||||
|
int defaultNorm() const;
|
||||||
|
|
||||||
|
// Compute the ORB_Impl features and descriptors on an image
|
||||||
|
void detectAndCompute( InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints,
|
||||||
|
OutputArray descriptors, bool useProvidedKeypoints=false );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
int nfeatures;
|
||||||
|
double scaleFactor;
|
||||||
|
int nlevels;
|
||||||
|
int edgeThreshold;
|
||||||
|
int firstLevel;
|
||||||
|
int wta_k;
|
||||||
|
int scoreType;
|
||||||
|
int patchSize;
|
||||||
|
int fastThreshold;
|
||||||
|
};
|
||||||
|
|
||||||
|
int ORB_Impl::descriptorSize() const
|
||||||
{
|
{
|
||||||
return kBytes;
|
return kBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ORB::descriptorType() const
|
int ORB_Impl::descriptorType() const
|
||||||
{
|
{
|
||||||
return CV_8U;
|
return CV_8U;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ORB::defaultNorm() const
|
int ORB_Impl::defaultNorm() const
|
||||||
{
|
{
|
||||||
return NORM_HAMMING;
|
return NORM_HAMMING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compute the ORB features and descriptors on an image
|
|
||||||
* @param img the image to compute the features and descriptors on
|
|
||||||
* @param mask the mask to apply
|
|
||||||
* @param keypoints the resulting keypoints
|
|
||||||
*/
|
|
||||||
void ORB::operator()(InputArray image, InputArray mask, std::vector<KeyPoint>& keypoints) const
|
|
||||||
{
|
|
||||||
(*this)(image, mask, keypoints, noArray(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void uploadORBKeypoints(const std::vector<KeyPoint>& src, std::vector<Vec3i>& buf, OutputArray dst)
|
static void uploadORBKeypoints(const std::vector<KeyPoint>& src, std::vector<Vec3i>& buf, OutputArray dst)
|
||||||
{
|
{
|
||||||
size_t i, n = src.size();
|
size_t i, n = src.size();
|
||||||
@ -716,7 +783,7 @@ static void uploadORBKeypoints(const std::vector<KeyPoint>& src,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Compute the ORB keypoints on an image
|
/** Compute the ORB_Impl keypoints on an image
|
||||||
* @param image_pyramid the image pyramid to compute the features and descriptors on
|
* @param image_pyramid the image pyramid to compute the features and descriptors on
|
||||||
* @param mask_pyramid the masks to apply at every level
|
* @param mask_pyramid the masks to apply at every level
|
||||||
* @param keypoints the resulting keypoints, clustered per level
|
* @param keypoints the resulting keypoints, clustered per level
|
||||||
@ -781,14 +848,16 @@ static void computeKeyPoints(const Mat& imagePyramid,
|
|||||||
Mat mask = maskPyramid.empty() ? Mat() : maskPyramid(layerInfo[level]);
|
Mat mask = maskPyramid.empty() ? Mat() : maskPyramid(layerInfo[level]);
|
||||||
|
|
||||||
// Detect FAST features, 20 is a good threshold
|
// Detect FAST features, 20 is a good threshold
|
||||||
FastFeatureDetector fd(fastThreshold, true);
|
{
|
||||||
fd.detect(img, keypoints, mask);
|
Ptr<FastFeatureDetector> fd = FastFeatureDetector::create(fastThreshold, true);
|
||||||
|
fd->detect(img, keypoints, mask);
|
||||||
|
}
|
||||||
|
|
||||||
// Remove keypoints very close to the border
|
// Remove keypoints very close to the border
|
||||||
KeyPointsFilter::runByImageBorder(keypoints, img.size(), edgeThreshold);
|
KeyPointsFilter::runByImageBorder(keypoints, img.size(), edgeThreshold);
|
||||||
|
|
||||||
// Keep more points than necessary as FAST does not give amazing corners
|
// Keep more points than necessary as FAST does not give amazing corners
|
||||||
KeyPointsFilter::retainBest(keypoints, scoreType == ORB::HARRIS_SCORE ? 2 * featuresNum : featuresNum);
|
KeyPointsFilter::retainBest(keypoints, scoreType == ORB_Impl::HARRIS_SCORE ? 2 * featuresNum : featuresNum);
|
||||||
|
|
||||||
nkeypoints = (int)keypoints.size();
|
nkeypoints = (int)keypoints.size();
|
||||||
counters[level] = nkeypoints;
|
counters[level] = nkeypoints;
|
||||||
@ -814,7 +883,7 @@ static void computeKeyPoints(const Mat& imagePyramid,
|
|||||||
UMat ukeypoints, uresponses(1, nkeypoints, CV_32F);
|
UMat ukeypoints, uresponses(1, nkeypoints, CV_32F);
|
||||||
|
|
||||||
// Select best features using the Harris cornerness (better scoring than FAST)
|
// Select best features using the Harris cornerness (better scoring than FAST)
|
||||||
if( scoreType == ORB::HARRIS_SCORE )
|
if( scoreType == ORB_Impl::HARRIS_SCORE )
|
||||||
{
|
{
|
||||||
if( useOCL )
|
if( useOCL )
|
||||||
{
|
{
|
||||||
@ -888,7 +957,7 @@ static void computeKeyPoints(const Mat& imagePyramid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Compute the ORB features and descriptors on an image
|
/** Compute the ORB_Impl features and descriptors on an image
|
||||||
* @param img the image to compute the features and descriptors on
|
* @param img the image to compute the features and descriptors on
|
||||||
* @param mask the mask to apply
|
* @param mask the mask to apply
|
||||||
* @param keypoints the resulting keypoints
|
* @param keypoints the resulting keypoints
|
||||||
@ -896,8 +965,9 @@ static void computeKeyPoints(const Mat& imagePyramid,
|
|||||||
* @param do_keypoints if true, the keypoints are computed, otherwise used as an input
|
* @param do_keypoints if true, the keypoints are computed, otherwise used as an input
|
||||||
* @param do_descriptors if true, also computes the descriptors
|
* @param do_descriptors if true, also computes the descriptors
|
||||||
*/
|
*/
|
||||||
void ORB::operator()( InputArray _image, InputArray _mask, std::vector<KeyPoint>& keypoints,
|
void ORB_Impl::detectAndCompute( InputArray _image, InputArray _mask,
|
||||||
OutputArray _descriptors, bool useProvidedKeypoints ) const
|
std::vector<KeyPoint>& keypoints,
|
||||||
|
OutputArray _descriptors, bool useProvidedKeypoints )
|
||||||
{
|
{
|
||||||
CV_Assert(patchSize >= 2);
|
CV_Assert(patchSize >= 2);
|
||||||
|
|
||||||
@ -1081,14 +1151,14 @@ void ORB::operator()( InputArray _image, InputArray _mask, std::vector<KeyPoint>
|
|||||||
makeRandomPattern(patchSize, patternbuf, npoints);
|
makeRandomPattern(patchSize, patternbuf, npoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
CV_Assert( WTA_K == 2 || WTA_K == 3 || WTA_K == 4 );
|
CV_Assert( wta_k == 2 || wta_k == 3 || wta_k == 4 );
|
||||||
|
|
||||||
if( WTA_K == 2 )
|
if( wta_k == 2 )
|
||||||
std::copy(pattern0, pattern0 + npoints, std::back_inserter(pattern));
|
std::copy(pattern0, pattern0 + npoints, std::back_inserter(pattern));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int ntuples = descriptorSize()*4;
|
int ntuples = descriptorSize()*4;
|
||||||
initializeOrbPattern(pattern0, pattern, ntuples, WTA_K, npoints);
|
initializeOrbPattern(pattern0, pattern, ntuples, wta_k, npoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
for( level = 0; level < nLevels; level++ )
|
for( level = 0; level < nLevels; level++ )
|
||||||
@ -1111,7 +1181,7 @@ void ORB::operator()( InputArray _image, InputArray _mask, std::vector<KeyPoint>
|
|||||||
UMat udescriptors = _descriptors.getUMat();
|
UMat udescriptors = _descriptors.getUMat();
|
||||||
useOCL = ocl_computeOrbDescriptors(uimagePyramid, ulayerInfo,
|
useOCL = ocl_computeOrbDescriptors(uimagePyramid, ulayerInfo,
|
||||||
ukeypoints, udescriptors, upattern,
|
ukeypoints, udescriptors, upattern,
|
||||||
nkeypoints, dsize, WTA_K);
|
nkeypoints, dsize, wta_k);
|
||||||
if(useOCL)
|
if(useOCL)
|
||||||
{
|
{
|
||||||
CV_IMPL_ADD(CV_IMPL_OCL);
|
CV_IMPL_ADD(CV_IMPL_OCL);
|
||||||
@ -1122,20 +1192,16 @@ void ORB::operator()( InputArray _image, InputArray _mask, std::vector<KeyPoint>
|
|||||||
{
|
{
|
||||||
Mat descriptors = _descriptors.getMat();
|
Mat descriptors = _descriptors.getMat();
|
||||||
computeOrbDescriptors(imagePyramid, layerInfo, layerScale,
|
computeOrbDescriptors(imagePyramid, layerInfo, layerScale,
|
||||||
keypoints, descriptors, pattern, dsize, WTA_K);
|
keypoints, descriptors, pattern, dsize, wta_k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ORB::detectImpl( InputArray image, std::vector<KeyPoint>& keypoints, InputArray mask) const
|
Ptr<ORB> ORB::create(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold,
|
||||||
|
int firstLevel, int wta_k, int scoreType, int patchSize, int fastThreshold)
|
||||||
{
|
{
|
||||||
(*this)(image.getMat(), mask.getMat(), keypoints, noArray(), false);
|
return makePtr<ORB_Impl>(nfeatures, scaleFactor, nlevels, edgeThreshold,
|
||||||
|
firstLevel, wta_k, scoreType, patchSize, fastThreshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ORB::computeImpl( InputArray image, std::vector<KeyPoint>& keypoints, OutputArray descriptors) const
|
|
||||||
{
|
|
||||||
(*this)(image, Mat(), keypoints, descriptors, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ void CV_BRISKTest::run( int )
|
|||||||
cvtColor(image1, gray1, COLOR_BGR2GRAY);
|
cvtColor(image1, gray1, COLOR_BGR2GRAY);
|
||||||
cvtColor(image2, gray2, COLOR_BGR2GRAY);
|
cvtColor(image2, gray2, COLOR_BGR2GRAY);
|
||||||
|
|
||||||
Ptr<FeatureDetector> detector = Algorithm::create<FeatureDetector>("Feature2D.BRISK");
|
Ptr<FeatureDetector> detector = BRISK::create();
|
||||||
|
|
||||||
vector<KeyPoint> keypoints1;
|
vector<KeyPoint> keypoints1;
|
||||||
vector<KeyPoint> keypoints2;
|
vector<KeyPoint> keypoints2;
|
||||||
|
@ -106,8 +106,6 @@ public:
|
|||||||
|
|
||||||
~CV_DescriptorExtractorTest()
|
~CV_DescriptorExtractorTest()
|
||||||
{
|
{
|
||||||
if(!detector.empty())
|
|
||||||
detector.release();
|
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
virtual void createDescriptorExtractor() {}
|
virtual void createDescriptorExtractor() {}
|
||||||
@ -314,31 +312,34 @@ private:
|
|||||||
|
|
||||||
TEST( Features2d_DescriptorExtractor_BRISK, regression )
|
TEST( Features2d_DescriptorExtractor_BRISK, regression )
|
||||||
{
|
{
|
||||||
CV_DescriptorExtractorTest<Hamming> test( "descriptor-brisk", (CV_DescriptorExtractorTest<Hamming>::DistanceType)2.f,
|
CV_DescriptorExtractorTest<Hamming> test( "descriptor-brisk",
|
||||||
DescriptorExtractor::create("BRISK") );
|
(CV_DescriptorExtractorTest<Hamming>::DistanceType)2.f,
|
||||||
|
BRISK::create() );
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST( Features2d_DescriptorExtractor_ORB, regression )
|
TEST( Features2d_DescriptorExtractor_ORB, regression )
|
||||||
{
|
{
|
||||||
// TODO adjust the parameters below
|
// TODO adjust the parameters below
|
||||||
CV_DescriptorExtractorTest<Hamming> test( "descriptor-orb", (CV_DescriptorExtractorTest<Hamming>::DistanceType)12.f,
|
CV_DescriptorExtractorTest<Hamming> test( "descriptor-orb",
|
||||||
DescriptorExtractor::create("ORB") );
|
(CV_DescriptorExtractorTest<Hamming>::DistanceType)12.f,
|
||||||
|
ORB::create() );
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST( Features2d_DescriptorExtractor_KAZE, regression )
|
TEST( Features2d_DescriptorExtractor_KAZE, regression )
|
||||||
{
|
{
|
||||||
CV_DescriptorExtractorTest< L2<float> > test( "descriptor-kaze", 0.03f,
|
CV_DescriptorExtractorTest< L2<float> > test( "descriptor-kaze", 0.03f,
|
||||||
DescriptorExtractor::create("KAZE"),
|
KAZE::create(),
|
||||||
L2<float>(), FeatureDetector::create("KAZE"));
|
L2<float>(), KAZE::create() );
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST( Features2d_DescriptorExtractor_AKAZE, regression )
|
TEST( Features2d_DescriptorExtractor_AKAZE, regression )
|
||||||
{
|
{
|
||||||
CV_DescriptorExtractorTest<Hamming> test( "descriptor-akaze", (CV_DescriptorExtractorTest<Hamming>::DistanceType)12.f,
|
CV_DescriptorExtractorTest<Hamming> test( "descriptor-akaze",
|
||||||
DescriptorExtractor::create("AKAZE"),
|
(CV_DescriptorExtractorTest<Hamming>::DistanceType)12.f,
|
||||||
Hamming(), FeatureDetector::create("AKAZE"));
|
AKAZE::create(),
|
||||||
|
Hamming(), AKAZE::create());
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
@ -249,48 +249,50 @@ void CV_FeatureDetectorTest::run( int /*start_from*/ )
|
|||||||
|
|
||||||
TEST( Features2d_Detector_BRISK, regression )
|
TEST( Features2d_Detector_BRISK, regression )
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorTest test( "detector-brisk", FeatureDetector::create("BRISK") );
|
CV_FeatureDetectorTest test( "detector-brisk", BRISK::create() );
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST( Features2d_Detector_FAST, regression )
|
TEST( Features2d_Detector_FAST, regression )
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorTest test( "detector-fast", FeatureDetector::create("FAST") );
|
CV_FeatureDetectorTest test( "detector-fast", FastFeatureDetector::create() );
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST( Features2d_Detector_GFTT, regression )
|
TEST( Features2d_Detector_GFTT, regression )
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorTest test( "detector-gftt", FeatureDetector::create("GFTT") );
|
CV_FeatureDetectorTest test( "detector-gftt", GFTTDetector::create() );
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST( Features2d_Detector_Harris, regression )
|
TEST( Features2d_Detector_Harris, regression )
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorTest test( "detector-harris", FeatureDetector::create("HARRIS") );
|
Ptr<FeatureDetector> gftt = GFTTDetector::create();
|
||||||
|
gftt->set(GFTTDetector::USE_HARRIS_DETECTOR, 1);
|
||||||
|
CV_FeatureDetectorTest test( "detector-harris", gftt);
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST( Features2d_Detector_MSER, DISABLED_regression )
|
TEST( Features2d_Detector_MSER, DISABLED_regression )
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorTest test( "detector-mser", FeatureDetector::create("MSER") );
|
CV_FeatureDetectorTest test( "detector-mser", MSER::create() );
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST( Features2d_Detector_ORB, regression )
|
TEST( Features2d_Detector_ORB, regression )
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorTest test( "detector-orb", FeatureDetector::create("ORB") );
|
CV_FeatureDetectorTest test( "detector-orb", ORB::create() );
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST( Features2d_Detector_KAZE, regression )
|
TEST( Features2d_Detector_KAZE, regression )
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorTest test( "detector-kaze", FeatureDetector::create("KAZE") );
|
CV_FeatureDetectorTest test( "detector-kaze", KAZE::create() );
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST( Features2d_Detector_AKAZE, regression )
|
TEST( Features2d_Detector_AKAZE, regression )
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorTest test( "detector-akaze", FeatureDetector::create("AKAZE") );
|
CV_FeatureDetectorTest test( "detector-akaze", AKAZE::create() );
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
#include "test_precomp.hpp"
|
#include "test_precomp.hpp"
|
||||||
#include "opencv2/highgui.hpp"
|
#include "opencv2/highgui.hpp"
|
||||||
|
#include "opencv2/core/core_c.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace cv;
|
using namespace cv;
|
||||||
@ -61,7 +62,6 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void run(int)
|
virtual void run(int)
|
||||||
{
|
{
|
||||||
cv::initModule_features2d();
|
|
||||||
CV_Assert(detector);
|
CV_Assert(detector);
|
||||||
string imgFilename = string(ts->get_data_path()) + FEATURES2D_DIR + "/" + IMAGE_FILENAME;
|
string imgFilename = string(ts->get_data_path()) + FEATURES2D_DIR + "/" + IMAGE_FILENAME;
|
||||||
|
|
||||||
@ -121,51 +121,54 @@ protected:
|
|||||||
|
|
||||||
TEST(Features2d_Detector_Keypoints_BRISK, validation)
|
TEST(Features2d_Detector_Keypoints_BRISK, validation)
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorKeypointsTest test(Algorithm::create<FeatureDetector>("Feature2D.BRISK"));
|
CV_FeatureDetectorKeypointsTest test(BRISK::create());
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Features2d_Detector_Keypoints_FAST, validation)
|
TEST(Features2d_Detector_Keypoints_FAST, validation)
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorKeypointsTest test(Algorithm::create<FeatureDetector>("Feature2D.FAST"));
|
CV_FeatureDetectorKeypointsTest test(FastFeatureDetector::create());
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Features2d_Detector_Keypoints_HARRIS, validation)
|
TEST(Features2d_Detector_Keypoints_HARRIS, validation)
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorKeypointsTest test(Algorithm::create<FeatureDetector>("Feature2D.HARRIS"));
|
|
||||||
|
CV_FeatureDetectorKeypointsTest test(GFTTDetector::create(1000, 0.01, 1, 3, true, 0.04));
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Features2d_Detector_Keypoints_GFTT, validation)
|
TEST(Features2d_Detector_Keypoints_GFTT, validation)
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorKeypointsTest test(Algorithm::create<FeatureDetector>("Feature2D.GFTT"));
|
Ptr<FeatureDetector> gftt = GFTTDetector::create();
|
||||||
|
gftt->set(GFTTDetector::USE_HARRIS_DETECTOR, 1);
|
||||||
|
CV_FeatureDetectorKeypointsTest test(gftt);
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Features2d_Detector_Keypoints_MSER, validation)
|
TEST(Features2d_Detector_Keypoints_MSER, validation)
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorKeypointsTest test(Algorithm::create<FeatureDetector>("Feature2D.MSER"));
|
CV_FeatureDetectorKeypointsTest test(MSER::create());
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Features2d_Detector_Keypoints_ORB, validation)
|
TEST(Features2d_Detector_Keypoints_ORB, validation)
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorKeypointsTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"));
|
CV_FeatureDetectorKeypointsTest test(ORB::create());
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Features2d_Detector_Keypoints_KAZE, validation)
|
TEST(Features2d_Detector_Keypoints_KAZE, validation)
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorKeypointsTest test(Algorithm::create<FeatureDetector>("Feature2D.KAZE"));
|
CV_FeatureDetectorKeypointsTest test(KAZE::create());
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Features2d_Detector_Keypoints_AKAZE, validation)
|
TEST(Features2d_Detector_Keypoints_AKAZE, validation)
|
||||||
{
|
{
|
||||||
CV_FeatureDetectorKeypointsTest test_kaze(cv::Ptr<FeatureDetector>(new cv::AKAZE(cv::DESCRIPTOR_KAZE)));
|
CV_FeatureDetectorKeypointsTest test_kaze(AKAZE::create(AKAZE::DESCRIPTOR_KAZE));
|
||||||
test_kaze.safe_run();
|
test_kaze.safe_run();
|
||||||
|
|
||||||
CV_FeatureDetectorKeypointsTest test_mldb(cv::Ptr<FeatureDetector>(new cv::AKAZE(cv::DESCRIPTOR_MLDB)));
|
CV_FeatureDetectorKeypointsTest test_mldb(AKAZE::create(AKAZE::DESCRIPTOR_MLDB));
|
||||||
test_mldb.safe_run();
|
test_mldb.safe_run();
|
||||||
}
|
}
|
||||||
|
@ -532,12 +532,14 @@ void CV_DescriptorMatcherTest::run( int )
|
|||||||
|
|
||||||
TEST( Features2d_DescriptorMatcher_BruteForce, regression )
|
TEST( Features2d_DescriptorMatcher_BruteForce, regression )
|
||||||
{
|
{
|
||||||
CV_DescriptorMatcherTest test( "descriptor-matcher-brute-force", Algorithm::create<DescriptorMatcher>("DescriptorMatcher.BFMatcher"), 0.01f );
|
CV_DescriptorMatcherTest test( "descriptor-matcher-brute-force",
|
||||||
|
DescriptorMatcher::create("BruteForce"), 0.01f );
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST( Features2d_DescriptorMatcher_FlannBased, regression )
|
TEST( Features2d_DescriptorMatcher_FlannBased, regression )
|
||||||
{
|
{
|
||||||
CV_DescriptorMatcherTest test( "descriptor-matcher-flann-based", Algorithm::create<DescriptorMatcher>("DescriptorMatcher.FlannBasedMatcher"), 0.04f );
|
CV_DescriptorMatcherTest test( "descriptor-matcher-flann-based",
|
||||||
|
DescriptorMatcher::create("FlannBased"), 0.04f );
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,8 @@
|
|||||||
#include "test_precomp.hpp"
|
#include "test_precomp.hpp"
|
||||||
#include "opencv2/imgproc/imgproc_c.h"
|
#include "opencv2/imgproc/imgproc_c.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -205,3 +207,5 @@ void CV_MserTest::run(int)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(Features2d_MSER, DISABLED_regression) { CV_MserTest test; test.safe_run(); }
|
TEST(Features2d_MSER, DISABLED_regression) { CV_MserTest test; test.safe_run(); }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -47,10 +47,8 @@ using namespace cv;
|
|||||||
|
|
||||||
TEST(Features2D_ORB, _1996)
|
TEST(Features2D_ORB, _1996)
|
||||||
{
|
{
|
||||||
Ptr<FeatureDetector> fd = FeatureDetector::create("ORB");
|
Ptr<FeatureDetector> fd = ORB::create(10000, 1.2f, 8, 31, 0, 2, ORB::HARRIS_SCORE, 31, 20);
|
||||||
fd->set("nFeatures", 10000);//setting a higher maximum to make effect of threshold visible
|
Ptr<DescriptorExtractor> de = fd;
|
||||||
fd->set("fastThreshold", 20);//more features than the default
|
|
||||||
Ptr<DescriptorExtractor> de = DescriptorExtractor::create("ORB");
|
|
||||||
|
|
||||||
Mat image = imread(string(cvtest::TS::ptr()->get_data_path()) + "shared/lena.png");
|
Mat image = imread(string(cvtest::TS::ptr()->get_data_path()) + "shared/lena.png");
|
||||||
ASSERT_FALSE(image.empty());
|
ASSERT_FALSE(image.empty());
|
||||||
|
@ -595,7 +595,7 @@ protected:
|
|||||||
|
|
||||||
TEST(Features2d_RotationInvariance_Detector_BRISK, regression)
|
TEST(Features2d_RotationInvariance_Detector_BRISK, regression)
|
||||||
{
|
{
|
||||||
DetectorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.BRISK"),
|
DetectorRotationInvarianceTest test(BRISK::create(),
|
||||||
0.32f,
|
0.32f,
|
||||||
0.76f);
|
0.76f);
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
@ -603,7 +603,7 @@ TEST(Features2d_RotationInvariance_Detector_BRISK, regression)
|
|||||||
|
|
||||||
TEST(Features2d_RotationInvariance_Detector_ORB, regression)
|
TEST(Features2d_RotationInvariance_Detector_ORB, regression)
|
||||||
{
|
{
|
||||||
DetectorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"),
|
DetectorRotationInvarianceTest test(ORB::create(),
|
||||||
0.47f,
|
0.47f,
|
||||||
0.76f);
|
0.76f);
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
@ -615,19 +615,15 @@ TEST(Features2d_RotationInvariance_Detector_ORB, regression)
|
|||||||
|
|
||||||
TEST(Features2d_RotationInvariance_Descriptor_BRISK, regression)
|
TEST(Features2d_RotationInvariance_Descriptor_BRISK, regression)
|
||||||
{
|
{
|
||||||
DescriptorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.BRISK"),
|
Ptr<Feature2D> f2d = BRISK::create();
|
||||||
Algorithm::create<DescriptorExtractor>("Feature2D.BRISK"),
|
DescriptorRotationInvarianceTest test(f2d, f2d, f2d->defaultNorm(), 0.99f);
|
||||||
Algorithm::create<DescriptorExtractor>("Feature2D.BRISK")->defaultNorm(),
|
|
||||||
0.99f);
|
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Features2d_RotationInvariance_Descriptor_ORB, regression)
|
TEST(Features2d_RotationInvariance_Descriptor_ORB, regression)
|
||||||
{
|
{
|
||||||
DescriptorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"),
|
Ptr<Feature2D> f2d = ORB::create();
|
||||||
Algorithm::create<DescriptorExtractor>("Feature2D.ORB"),
|
DescriptorRotationInvarianceTest test(f2d, f2d, f2d->defaultNorm(), 0.99f);
|
||||||
Algorithm::create<DescriptorExtractor>("Feature2D.ORB")->defaultNorm(),
|
|
||||||
0.99f);
|
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -646,25 +642,19 @@ TEST(Features2d_RotationInvariance_Descriptor_ORB, regression)
|
|||||||
|
|
||||||
TEST(Features2d_ScaleInvariance_Detector_BRISK, regression)
|
TEST(Features2d_ScaleInvariance_Detector_BRISK, regression)
|
||||||
{
|
{
|
||||||
DetectorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.BRISK"),
|
DetectorScaleInvarianceTest test(BRISK::create(), 0.08f, 0.49f);
|
||||||
0.08f,
|
|
||||||
0.49f);
|
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Features2d_ScaleInvariance_Detector_KAZE, regression)
|
TEST(Features2d_ScaleInvariance_Detector_KAZE, regression)
|
||||||
{
|
{
|
||||||
DetectorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.KAZE"),
|
DetectorScaleInvarianceTest test(KAZE::create(), 0.08f, 0.49f);
|
||||||
0.08f,
|
|
||||||
0.49f);
|
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Features2d_ScaleInvariance_Detector_AKAZE, regression)
|
TEST(Features2d_ScaleInvariance_Detector_AKAZE, regression)
|
||||||
{
|
{
|
||||||
DetectorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.AKAZE"),
|
DetectorScaleInvarianceTest test(AKAZE::create(), 0.08f, 0.49f);
|
||||||
0.08f,
|
|
||||||
0.49f);
|
|
||||||
test.safe_run();
|
test.safe_run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,67 +90,69 @@ public:
|
|||||||
//not supported: SimpleBlob, Dense
|
//not supported: SimpleBlob, Dense
|
||||||
CV_WRAP static javaFeatureDetector* create( int detectorType )
|
CV_WRAP static javaFeatureDetector* create( int detectorType )
|
||||||
{
|
{
|
||||||
String name;
|
//String name;
|
||||||
if (detectorType > DYNAMICDETECTOR)
|
if (detectorType > DYNAMICDETECTOR)
|
||||||
{
|
{
|
||||||
name = "Dynamic";
|
//name = "Dynamic";
|
||||||
detectorType -= DYNAMICDETECTOR;
|
detectorType -= DYNAMICDETECTOR;
|
||||||
}
|
}
|
||||||
if (detectorType > PYRAMIDDETECTOR)
|
if (detectorType > PYRAMIDDETECTOR)
|
||||||
{
|
{
|
||||||
name = "Pyramid";
|
//name = "Pyramid";
|
||||||
detectorType -= PYRAMIDDETECTOR;
|
detectorType -= PYRAMIDDETECTOR;
|
||||||
}
|
}
|
||||||
if (detectorType > GRIDDETECTOR)
|
if (detectorType > GRIDDETECTOR)
|
||||||
{
|
{
|
||||||
name = "Grid";
|
//name = "Grid";
|
||||||
detectorType -= GRIDDETECTOR;
|
detectorType -= GRIDDETECTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ptr<FeatureDetector> fd;
|
||||||
switch(detectorType)
|
switch(detectorType)
|
||||||
{
|
{
|
||||||
case FAST:
|
case FAST:
|
||||||
name = name + "FAST";
|
fd = FastFeatureDetector::create();
|
||||||
break;
|
|
||||||
case STAR:
|
|
||||||
name = name + "STAR";
|
|
||||||
break;
|
|
||||||
case SIFT:
|
|
||||||
name = name + "SIFT";
|
|
||||||
break;
|
|
||||||
case SURF:
|
|
||||||
name = name + "SURF";
|
|
||||||
break;
|
break;
|
||||||
|
//case STAR:
|
||||||
|
// fd = xfeatures2d::StarDetector::create();
|
||||||
|
// break;
|
||||||
|
//case SIFT:
|
||||||
|
// name = name + "SIFT";
|
||||||
|
// break;
|
||||||
|
//case SURF:
|
||||||
|
// name = name + "SURF";
|
||||||
|
// break;
|
||||||
case ORB:
|
case ORB:
|
||||||
name = name + "ORB";
|
fd = ORB::create();
|
||||||
break;
|
break;
|
||||||
case MSER:
|
case MSER:
|
||||||
name = name + "MSER";
|
fd = MSER::create();
|
||||||
break;
|
break;
|
||||||
case GFTT:
|
case GFTT:
|
||||||
name = name + "GFTT";
|
fd = GFTTDetector::create();
|
||||||
break;
|
break;
|
||||||
case HARRIS:
|
case HARRIS:
|
||||||
name = name + "HARRIS";
|
fd = GFTTDetector::create();
|
||||||
|
fd->set(GFTTDetector::USE_HARRIS_DETECTOR, 1);
|
||||||
break;
|
break;
|
||||||
case SIMPLEBLOB:
|
case SIMPLEBLOB:
|
||||||
name = name + "SimpleBlob";
|
fd = SimpleBlobDetector::create();
|
||||||
break;
|
|
||||||
case DENSE:
|
|
||||||
name = name + "Dense";
|
|
||||||
break;
|
break;
|
||||||
|
//case DENSE:
|
||||||
|
// name = name + "Dense";
|
||||||
|
// break;
|
||||||
case BRISK:
|
case BRISK:
|
||||||
name = name + "BRISK";
|
fd = BRISK::create();
|
||||||
break;
|
break;
|
||||||
case AKAZE:
|
case AKAZE:
|
||||||
name = name + "AKAZE";
|
fd = AKAZE::create();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
CV_Error( Error::StsBadArg, "Specified feature detector type is not supported." );
|
CV_Error( Error::StsBadArg, "Specified feature detector type is not supported." );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new javaFeatureDetector(FeatureDetector::create(name));
|
return new javaFeatureDetector(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
CV_WRAP void write( const String& fileName ) const
|
CV_WRAP void write( const String& fileName ) const
|
||||||
@ -332,43 +334,44 @@ public:
|
|||||||
//not supported: Calonder
|
//not supported: Calonder
|
||||||
CV_WRAP static javaDescriptorExtractor* create( int extractorType )
|
CV_WRAP static javaDescriptorExtractor* create( int extractorType )
|
||||||
{
|
{
|
||||||
String name;
|
//String name;
|
||||||
|
|
||||||
if (extractorType > OPPONENTEXTRACTOR)
|
if (extractorType > OPPONENTEXTRACTOR)
|
||||||
{
|
{
|
||||||
name = "Opponent";
|
//name = "Opponent";
|
||||||
extractorType -= OPPONENTEXTRACTOR;
|
extractorType -= OPPONENTEXTRACTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ptr<DescriptorExtractor> de;
|
||||||
switch(extractorType)
|
switch(extractorType)
|
||||||
{
|
{
|
||||||
case SIFT:
|
//case SIFT:
|
||||||
name = name + "SIFT";
|
// name = name + "SIFT";
|
||||||
break;
|
// break;
|
||||||
case SURF:
|
//case SURF:
|
||||||
name = name + "SURF";
|
// name = name + "SURF";
|
||||||
break;
|
// break;
|
||||||
case ORB:
|
case ORB:
|
||||||
name = name + "ORB";
|
de = ORB::create();
|
||||||
break;
|
|
||||||
case BRIEF:
|
|
||||||
name = name + "BRIEF";
|
|
||||||
break;
|
break;
|
||||||
|
//case BRIEF:
|
||||||
|
// name = name + "BRIEF";
|
||||||
|
// break;
|
||||||
case BRISK:
|
case BRISK:
|
||||||
name = name + "BRISK";
|
de = BRISK::create();
|
||||||
break;
|
|
||||||
case FREAK:
|
|
||||||
name = name + "FREAK";
|
|
||||||
break;
|
break;
|
||||||
|
//case FREAK:
|
||||||
|
// name = name + "FREAK";
|
||||||
|
// break;
|
||||||
case AKAZE:
|
case AKAZE:
|
||||||
name = name + "AKAZE";
|
de = AKAZE::create();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
CV_Error( Error::StsBadArg, "Specified descriptor extractor type is not supported." );
|
CV_Error( Error::StsBadArg, "Specified descriptor extractor type is not supported." );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new javaDescriptorExtractor(DescriptorExtractor::create(name));
|
return new javaDescriptorExtractor(de);
|
||||||
}
|
}
|
||||||
|
|
||||||
CV_WRAP void write( const String& fileName ) const
|
CV_WRAP void write( const String& fileName ) const
|
||||||
|
@ -24,15 +24,9 @@ JNI_OnLoad(JavaVM* vm, void* )
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
bool init = true;
|
bool init = true;
|
||||||
#ifdef HAVE_OPENCV_FEATURES2D
|
|
||||||
init &= cv::initModule_features2d();
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_OPENCV_VIDEO
|
#ifdef HAVE_OPENCV_VIDEO
|
||||||
init &= cv::initModule_video();
|
init &= cv::initModule_video();
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_OPENCV_CONTRIB
|
|
||||||
init &= cv::initModule_contrib();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(!init)
|
if(!init)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -91,7 +91,7 @@ class Hackathon244Tests(NewOpenCVTests):
|
|||||||
self.assertEqual(cv2.countNonZero(inliers), pattern_size[0]*pattern_size[1])
|
self.assertEqual(cv2.countNonZero(inliers), pattern_size[0]*pattern_size[1])
|
||||||
|
|
||||||
def test_fast(self):
|
def test_fast(self):
|
||||||
fd = cv2.FastFeatureDetector(30, True)
|
fd = cv2.FastFeatureDetector_create(30, True)
|
||||||
img = self.get_sample("samples/cpp/right02.jpg", 0)
|
img = self.get_sample("samples/cpp/right02.jpg", 0)
|
||||||
img = cv2.medianBlur(img, 3)
|
img = cv2.medianBlur(img, 3)
|
||||||
imgc = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
|
imgc = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
|
||||||
|
@ -48,8 +48,7 @@ using namespace cv::cuda;
|
|||||||
|
|
||||||
#ifdef HAVE_OPENCV_XFEATURES2D
|
#ifdef HAVE_OPENCV_XFEATURES2D
|
||||||
#include "opencv2/xfeatures2d.hpp"
|
#include "opencv2/xfeatures2d.hpp"
|
||||||
|
using xfeatures2d::SURF;
|
||||||
static bool makeUseOfXfeatures2d = xfeatures2d::initModule_xfeatures2d();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -321,30 +320,34 @@ void FeaturesFinder::operator ()(InputArray image, ImageFeatures &features, cons
|
|||||||
SurfFeaturesFinder::SurfFeaturesFinder(double hess_thresh, int num_octaves, int num_layers,
|
SurfFeaturesFinder::SurfFeaturesFinder(double hess_thresh, int num_octaves, int num_layers,
|
||||||
int num_octaves_descr, int num_layers_descr)
|
int num_octaves_descr, int num_layers_descr)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_OPENCV_XFEATURES2D
|
||||||
if (num_octaves_descr == num_octaves && num_layers_descr == num_layers)
|
if (num_octaves_descr == num_octaves && num_layers_descr == num_layers)
|
||||||
{
|
{
|
||||||
surf = Algorithm::create<Feature2D>("Feature2D.SURF");
|
surf = SURF::create();
|
||||||
if( !surf )
|
if( !surf )
|
||||||
CV_Error( Error::StsNotImplemented, "OpenCV was built without SURF support" );
|
CV_Error( Error::StsNotImplemented, "OpenCV was built without SURF support" );
|
||||||
surf->set("hessianThreshold", hess_thresh);
|
surf->set(SURF::HESSIAN_THRESHOLD, hess_thresh);
|
||||||
surf->set("nOctaves", num_octaves);
|
surf->set(SURF::NOCTAVES, num_octaves);
|
||||||
surf->set("nOctaveLayers", num_layers);
|
surf->set(SURF::NOCTAVE_LAYERS, num_layers);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
detector_ = Algorithm::create<FeatureDetector>("Feature2D.SURF");
|
detector_ = SURF::create();
|
||||||
extractor_ = Algorithm::create<DescriptorExtractor>("Feature2D.SURF");
|
extractor_ = SURF::create();
|
||||||
|
|
||||||
if( !detector_ || !extractor_ )
|
if( !detector_ || !extractor_ )
|
||||||
CV_Error( Error::StsNotImplemented, "OpenCV was built without SURF support" );
|
CV_Error( Error::StsNotImplemented, "OpenCV was built without SURF support" );
|
||||||
|
|
||||||
detector_->set("hessianThreshold", hess_thresh);
|
detector_->set(SURF::HESSIAN_THRESHOLD, hess_thresh);
|
||||||
detector_->set("nOctaves", num_octaves);
|
detector_->set(SURF::NOCTAVES, num_octaves);
|
||||||
detector_->set("nOctaveLayers", num_layers);
|
detector_->set(SURF::NOCTAVE_LAYERS, num_layers);
|
||||||
|
|
||||||
extractor_->set("nOctaves", num_octaves_descr);
|
extractor_->set(SURF::NOCTAVES, num_octaves_descr);
|
||||||
extractor_->set("nOctaveLayers", num_layers_descr);
|
extractor_->set(SURF::NOCTAVE_LAYERS, num_layers_descr);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
CV_Error( Error::StsNotImplemented, "OpenCV was built without SURF support" );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfFeaturesFinder::find(InputArray image, ImageFeatures &features)
|
void SurfFeaturesFinder::find(InputArray image, ImageFeatures &features)
|
||||||
@ -367,7 +370,7 @@ void SurfFeaturesFinder::find(InputArray image, ImageFeatures &features)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
UMat descriptors;
|
UMat descriptors;
|
||||||
(*surf)(gray_image, Mat(), features.keypoints, descriptors);
|
surf->detectAndCompute(gray_image, Mat(), features.keypoints, descriptors);
|
||||||
features.descriptors = descriptors.reshape(1, (int)features.keypoints.size());
|
features.descriptors = descriptors.reshape(1, (int)features.keypoints.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -375,7 +378,7 @@ void SurfFeaturesFinder::find(InputArray image, ImageFeatures &features)
|
|||||||
OrbFeaturesFinder::OrbFeaturesFinder(Size _grid_size, int n_features, float scaleFactor, int nlevels)
|
OrbFeaturesFinder::OrbFeaturesFinder(Size _grid_size, int n_features, float scaleFactor, int nlevels)
|
||||||
{
|
{
|
||||||
grid_size = _grid_size;
|
grid_size = _grid_size;
|
||||||
orb = makePtr<ORB>(n_features * (99 + grid_size.area())/100/grid_size.area(), scaleFactor, nlevels);
|
orb = ORB::create(n_features * (99 + grid_size.area())/100/grid_size.area(), scaleFactor, nlevels);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OrbFeaturesFinder::find(InputArray image, ImageFeatures &features)
|
void OrbFeaturesFinder::find(InputArray image, ImageFeatures &features)
|
||||||
@ -395,7 +398,7 @@ void OrbFeaturesFinder::find(InputArray image, ImageFeatures &features)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (grid_size.area() == 1)
|
if (grid_size.area() == 1)
|
||||||
(*orb)(gray_image, Mat(), features.keypoints, features.descriptors);
|
orb->detectAndCompute(gray_image, Mat(), features.keypoints, features.descriptors);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
features.keypoints.clear();
|
features.keypoints.clear();
|
||||||
@ -425,7 +428,7 @@ void OrbFeaturesFinder::find(InputArray image, ImageFeatures &features)
|
|||||||
// << " gray_image_part.dims=" << gray_image_part.dims << ", "
|
// << " gray_image_part.dims=" << gray_image_part.dims << ", "
|
||||||
// << " gray_image_part.data=" << ((size_t)gray_image_part.data) << "\n");
|
// << " gray_image_part.data=" << ((size_t)gray_image_part.data) << "\n");
|
||||||
|
|
||||||
(*orb)(gray_image_part, UMat(), points, descriptors);
|
orb->detectAndCompute(gray_image_part, UMat(), points, descriptors);
|
||||||
|
|
||||||
features.keypoints.reserve(features.keypoints.size() + points.size());
|
features.keypoints.reserve(features.keypoints.size() + points.size());
|
||||||
for (std::vector<KeyPoint>::iterator kp = points.begin(); kp != points.end(); ++kp)
|
for (std::vector<KeyPoint>::iterator kp = points.begin(); kp != points.end(); ++kp)
|
||||||
|
@ -671,7 +671,7 @@ Mat ToFileMotionWriter::estimate(const Mat &frame0, const Mat &frame1, bool *ok)
|
|||||||
KeypointBasedMotionEstimator::KeypointBasedMotionEstimator(Ptr<MotionEstimatorBase> estimator)
|
KeypointBasedMotionEstimator::KeypointBasedMotionEstimator(Ptr<MotionEstimatorBase> estimator)
|
||||||
: ImageMotionEstimatorBase(estimator->motionModel()), motionEstimator_(estimator)
|
: ImageMotionEstimatorBase(estimator->motionModel()), motionEstimator_(estimator)
|
||||||
{
|
{
|
||||||
setDetector(makePtr<GoodFeaturesToTrackDetector>());
|
setDetector(GFTTDetector::create());
|
||||||
setOpticalFlowEstimator(makePtr<SparsePyrLkOptFlowEstimator>());
|
setOpticalFlowEstimator(makePtr<SparsePyrLkOptFlowEstimator>());
|
||||||
setOutlierRejector(makePtr<NullOutlierRejector>());
|
setOutlierRejector(makePtr<NullOutlierRejector>());
|
||||||
}
|
}
|
||||||
|
@ -47,12 +47,6 @@ bool cv::initAll()
|
|||||||
return true
|
return true
|
||||||
#ifdef HAVE_OPENCV_VIDEO
|
#ifdef HAVE_OPENCV_VIDEO
|
||||||
&& initModule_video()
|
&& initModule_video()
|
||||||
#endif
|
|
||||||
#ifdef HAVE_OPENCV_FEATURES2D
|
|
||||||
&& initModule_features2d()
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_OPENCV_XFEATURES2D
|
|
||||||
&& xfeatures2d::initModule_xfeatures2d()
|
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@ JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_FindF
|
|||||||
Mat& mRgb = *(Mat*)addrRgba;
|
Mat& mRgb = *(Mat*)addrRgba;
|
||||||
vector<KeyPoint> v;
|
vector<KeyPoint> v;
|
||||||
|
|
||||||
FastFeatureDetector detector(50);
|
Ptr<FeatureDetector> detector = FastFeatureDetector::create(50);
|
||||||
detector.detect(mGr, v);
|
detector->detect(mGr, v);
|
||||||
for( unsigned int i = 0; i < v.size(); i++ )
|
for( unsigned int i = 0; i < v.size(); i++ )
|
||||||
{
|
{
|
||||||
const KeyPoint& kp = v[i];
|
const KeyPoint& kp = v[i];
|
||||||
|
@ -19,23 +19,23 @@ public:
|
|||||||
RobustMatcher() : ratio_(0.8f)
|
RobustMatcher() : ratio_(0.8f)
|
||||||
{
|
{
|
||||||
// ORB is the default feature
|
// ORB is the default feature
|
||||||
detector_ = new cv::OrbFeatureDetector();
|
detector_ = cv::ORB::create();
|
||||||
extractor_ = new cv::OrbDescriptorExtractor();
|
extractor_ = cv::ORB::create();
|
||||||
|
|
||||||
// BruteFroce matcher with Norm Hamming is the default matcher
|
// BruteFroce matcher with Norm Hamming is the default matcher
|
||||||
matcher_ = new cv::BFMatcher(cv::NORM_HAMMING, false);
|
matcher_ = cv::makePtr<cv::BFMatcher>((int)cv::NORM_HAMMING, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
virtual ~RobustMatcher();
|
virtual ~RobustMatcher();
|
||||||
|
|
||||||
// Set the feature detector
|
// Set the feature detector
|
||||||
void setFeatureDetector(cv::FeatureDetector * detect) { detector_ = detect; }
|
void setFeatureDetector(const cv::Ptr<cv::FeatureDetector>& detect) { detector_ = detect; }
|
||||||
|
|
||||||
// Set the descriptor extractor
|
// Set the descriptor extractor
|
||||||
void setDescriptorExtractor(cv::DescriptorExtractor * desc) { extractor_ = desc; }
|
void setDescriptorExtractor(const cv::Ptr<cv::DescriptorExtractor>& desc) { extractor_ = desc; }
|
||||||
|
|
||||||
// Set the matcher
|
// Set the matcher
|
||||||
void setDescriptorMatcher(cv::DescriptorMatcher * match) { matcher_ = match; }
|
void setDescriptorMatcher(const cv::Ptr<cv::DescriptorMatcher>& match) { matcher_ = match; }
|
||||||
|
|
||||||
// Compute the keypoints of an image
|
// Compute the keypoints of an image
|
||||||
void computeKeyPoints( const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints);
|
void computeKeyPoints( const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints);
|
||||||
@ -69,11 +69,11 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// pointer to the feature point detector object
|
// pointer to the feature point detector object
|
||||||
cv::FeatureDetector * detector_;
|
cv::Ptr<cv::FeatureDetector> detector_;
|
||||||
// pointer to the feature descriptor extractor object
|
// pointer to the feature descriptor extractor object
|
||||||
cv::DescriptorExtractor * extractor_;
|
cv::Ptr<cv::DescriptorExtractor> extractor_;
|
||||||
// pointer to the matcher object
|
// pointer to the matcher object
|
||||||
cv::DescriptorMatcher * matcher_;
|
cv::Ptr<cv::DescriptorMatcher> matcher_;
|
||||||
// max ratio between 1st and 2nd NN
|
// max ratio between 1st and 2nd NN
|
||||||
float ratio_;
|
float ratio_;
|
||||||
};
|
};
|
||||||
|
@ -18,11 +18,14 @@
|
|||||||
|
|
||||||
/** GLOBAL VARIABLES **/
|
/** GLOBAL VARIABLES **/
|
||||||
|
|
||||||
std::string tutorial_path = "../../samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/"; // path to tutorial
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
std::string video_read_path = tutorial_path + "Data/box.mp4"; // recorded video
|
string tutorial_path = "../../samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/"; // path to tutorial
|
||||||
std::string yml_read_path = tutorial_path + "Data/cookies_ORB.yml"; // 3dpts + descriptors
|
|
||||||
std::string ply_read_path = tutorial_path + "Data/box.ply"; // mesh
|
string video_read_path = tutorial_path + "Data/box.mp4"; // recorded video
|
||||||
|
string yml_read_path = tutorial_path + "Data/cookies_ORB.yml"; // 3dpts + descriptors
|
||||||
|
string ply_read_path = tutorial_path + "Data/box.ply"; // mesh
|
||||||
|
|
||||||
// Intrinsic camera parameters: UVC WEBCAM
|
// Intrinsic camera parameters: UVC WEBCAM
|
||||||
double f = 55; // focal length in mm
|
double f = 55; // focal length in mm
|
||||||
@ -35,15 +38,15 @@ double params_WEBCAM[] = { width*f/sx, // fx
|
|||||||
height/2}; // cy
|
height/2}; // cy
|
||||||
|
|
||||||
// Some basic colors
|
// Some basic colors
|
||||||
cv::Scalar red(0, 0, 255);
|
Scalar red(0, 0, 255);
|
||||||
cv::Scalar green(0,255,0);
|
Scalar green(0,255,0);
|
||||||
cv::Scalar blue(255,0,0);
|
Scalar blue(255,0,0);
|
||||||
cv::Scalar yellow(0,255,255);
|
Scalar yellow(0,255,255);
|
||||||
|
|
||||||
|
|
||||||
// Robust Matcher parameters
|
// Robust Matcher parameters
|
||||||
int numKeyPoints = 2000; // number of detected keypoints
|
int numKeyPoints = 2000; // number of detected keypoints
|
||||||
float ratio = 0.70f; // ratio test
|
float ratioTest = 0.70f; // ratio test
|
||||||
bool fast_match = true; // fastRobustMatch() or robustMatch()
|
bool fast_match = true; // fastRobustMatch() or robustMatch()
|
||||||
|
|
||||||
// RANSAC parameters
|
// RANSAC parameters
|
||||||
@ -55,16 +58,16 @@ double confidence = 0.95; // ransac successful confidence.
|
|||||||
int minInliersKalman = 30; // Kalman threshold updating
|
int minInliersKalman = 30; // Kalman threshold updating
|
||||||
|
|
||||||
// PnP parameters
|
// PnP parameters
|
||||||
int pnpMethod = cv::SOLVEPNP_ITERATIVE;
|
int pnpMethod = SOLVEPNP_ITERATIVE;
|
||||||
|
|
||||||
|
|
||||||
/** Functions headers **/
|
/** Functions headers **/
|
||||||
void help();
|
void help();
|
||||||
void initKalmanFilter( cv::KalmanFilter &KF, int nStates, int nMeasurements, int nInputs, double dt);
|
void initKalmanFilter( KalmanFilter &KF, int nStates, int nMeasurements, int nInputs, double dt);
|
||||||
void updateKalmanFilter( cv::KalmanFilter &KF, cv::Mat &measurements,
|
void updateKalmanFilter( KalmanFilter &KF, Mat &measurements,
|
||||||
cv::Mat &translation_estimated, cv::Mat &rotation_estimated );
|
Mat &translation_estimated, Mat &rotation_estimated );
|
||||||
void fillMeasurements( cv::Mat &measurements,
|
void fillMeasurements( Mat &measurements,
|
||||||
const cv::Mat &translation_measured, const cv::Mat &rotation_measured);
|
const Mat &translation_measured, const Mat &rotation_measured);
|
||||||
|
|
||||||
|
|
||||||
/** Main program **/
|
/** Main program **/
|
||||||
@ -73,7 +76,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
help();
|
help();
|
||||||
|
|
||||||
const cv::String keys =
|
const String keys =
|
||||||
"{help h | | print this message }"
|
"{help h | | print this message }"
|
||||||
"{video v | | path to recorded video }"
|
"{video v | | path to recorded video }"
|
||||||
"{model | | path to yml model }"
|
"{model | | path to yml model }"
|
||||||
@ -87,7 +90,7 @@ int main(int argc, char *argv[])
|
|||||||
"{method pnp |0 | PnP method: (0) ITERATIVE - (1) EPNP - (2) P3P - (3) DLS}"
|
"{method pnp |0 | PnP method: (0) ITERATIVE - (1) EPNP - (2) P3P - (3) DLS}"
|
||||||
"{fast f |true | use of robust fast match }"
|
"{fast f |true | use of robust fast match }"
|
||||||
;
|
;
|
||||||
cv::CommandLineParser parser(argc, argv, keys);
|
CommandLineParser parser(argc, argv, keys);
|
||||||
|
|
||||||
if (parser.has("help"))
|
if (parser.has("help"))
|
||||||
{
|
{
|
||||||
@ -96,11 +99,11 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
video_read_path = parser.get<std::string>("video").size() > 0 ? parser.get<std::string>("video") : video_read_path;
|
video_read_path = parser.get<string>("video").size() > 0 ? parser.get<string>("video") : video_read_path;
|
||||||
yml_read_path = parser.get<std::string>("model").size() > 0 ? parser.get<std::string>("model") : yml_read_path;
|
yml_read_path = parser.get<string>("model").size() > 0 ? parser.get<string>("model") : yml_read_path;
|
||||||
ply_read_path = parser.get<std::string>("mesh").size() > 0 ? parser.get<std::string>("mesh") : ply_read_path;
|
ply_read_path = parser.get<string>("mesh").size() > 0 ? parser.get<string>("mesh") : ply_read_path;
|
||||||
numKeyPoints = !parser.has("keypoints") ? parser.get<int>("keypoints") : numKeyPoints;
|
numKeyPoints = !parser.has("keypoints") ? parser.get<int>("keypoints") : numKeyPoints;
|
||||||
ratio = !parser.has("ratio") ? parser.get<float>("ratio") : ratio;
|
ratioTest = !parser.has("ratio") ? parser.get<float>("ratio") : ratioTest;
|
||||||
fast_match = !parser.has("fast") ? parser.get<bool>("fast") : fast_match;
|
fast_match = !parser.has("fast") ? parser.get<bool>("fast") : fast_match;
|
||||||
iterationsCount = !parser.has("iterations") ? parser.get<int>("iterations") : iterationsCount;
|
iterationsCount = !parser.has("iterations") ? parser.get<int>("iterations") : iterationsCount;
|
||||||
reprojectionError = !parser.has("error") ? parser.get<float>("error") : reprojectionError;
|
reprojectionError = !parser.has("error") ? parser.get<float>("error") : reprojectionError;
|
||||||
@ -120,45 +123,45 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
RobustMatcher rmatcher; // instantiate RobustMatcher
|
RobustMatcher rmatcher; // instantiate RobustMatcher
|
||||||
|
|
||||||
cv::FeatureDetector * detector = new cv::OrbFeatureDetector(numKeyPoints); // instatiate ORB feature detector
|
Ptr<FeatureDetector> orb = ORB::create();
|
||||||
cv::DescriptorExtractor * extractor = new cv::OrbDescriptorExtractor(); // instatiate ORB descriptor extractor
|
|
||||||
|
|
||||||
rmatcher.setFeatureDetector(detector); // set feature detector
|
rmatcher.setFeatureDetector(orb); // set feature detector
|
||||||
rmatcher.setDescriptorExtractor(extractor); // set descriptor extractor
|
rmatcher.setDescriptorExtractor(orb); // set descriptor extractor
|
||||||
|
|
||||||
cv::Ptr<cv::flann::IndexParams> indexParams = cv::makePtr<cv::flann::LshIndexParams>(6, 12, 1); // instantiate LSH index parameters
|
Ptr<flann::IndexParams> indexParams = makePtr<flann::LshIndexParams>(6, 12, 1); // instantiate LSH index parameters
|
||||||
cv::Ptr<cv::flann::SearchParams> searchParams = cv::makePtr<cv::flann::SearchParams>(50); // instantiate flann search parameters
|
Ptr<flann::SearchParams> searchParams = makePtr<flann::SearchParams>(50); // instantiate flann search parameters
|
||||||
|
|
||||||
cv::DescriptorMatcher * matcher = new cv::FlannBasedMatcher(indexParams, searchParams); // instantiate FlannBased matcher
|
// instantiate FlannBased matcher
|
||||||
|
Ptr<DescriptorMatcher> matcher = makePtr<FlannBasedMatcher>(indexParams, searchParams);
|
||||||
rmatcher.setDescriptorMatcher(matcher); // set matcher
|
rmatcher.setDescriptorMatcher(matcher); // set matcher
|
||||||
rmatcher.setRatio(ratio); // set ratio test parameter
|
rmatcher.setRatio(ratioTest); // set ratio test parameter
|
||||||
|
|
||||||
cv::KalmanFilter KF; // instantiate Kalman Filter
|
KalmanFilter KF; // instantiate Kalman Filter
|
||||||
int nStates = 18; // the number of states
|
int nStates = 18; // the number of states
|
||||||
int nMeasurements = 6; // the number of measured states
|
int nMeasurements = 6; // the number of measured states
|
||||||
int nInputs = 0; // the number of control actions
|
int nInputs = 0; // the number of control actions
|
||||||
double dt = 0.125; // time between measurements (1/FPS)
|
double dt = 0.125; // time between measurements (1/FPS)
|
||||||
|
|
||||||
initKalmanFilter(KF, nStates, nMeasurements, nInputs, dt); // init function
|
initKalmanFilter(KF, nStates, nMeasurements, nInputs, dt); // init function
|
||||||
cv::Mat measurements(nMeasurements, 1, CV_64F); measurements.setTo(cv::Scalar(0));
|
Mat measurements(nMeasurements, 1, CV_64F); measurements.setTo(Scalar(0));
|
||||||
bool good_measurement = false;
|
bool good_measurement = false;
|
||||||
|
|
||||||
|
|
||||||
// Get the MODEL INFO
|
// Get the MODEL INFO
|
||||||
std::vector<cv::Point3f> list_points3d_model = model.get_points3d(); // list with model 3D coordinates
|
vector<Point3f> list_points3d_model = model.get_points3d(); // list with model 3D coordinates
|
||||||
cv::Mat descriptors_model = model.get_descriptors(); // list with descriptors of each 3D coordinate
|
Mat descriptors_model = model.get_descriptors(); // list with descriptors of each 3D coordinate
|
||||||
|
|
||||||
|
|
||||||
// Create & Open Window
|
// Create & Open Window
|
||||||
cv::namedWindow("REAL TIME DEMO", cv::WINDOW_KEEPRATIO);
|
namedWindow("REAL TIME DEMO", WINDOW_KEEPRATIO);
|
||||||
|
|
||||||
|
|
||||||
cv::VideoCapture cap; // instantiate VideoCapture
|
VideoCapture cap; // instantiate VideoCapture
|
||||||
cap.open(video_read_path); // open a recorded video
|
cap.open(video_read_path); // open a recorded video
|
||||||
|
|
||||||
if(!cap.isOpened()) // check if we succeeded
|
if(!cap.isOpened()) // check if we succeeded
|
||||||
{
|
{
|
||||||
std::cout << "Could not open the camera device" << std::endl;
|
cout << "Could not open the camera device" << endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,9 +178,9 @@ int main(int argc, char *argv[])
|
|||||||
// start the clock
|
// start the clock
|
||||||
time(&start);
|
time(&start);
|
||||||
|
|
||||||
cv::Mat frame, frame_vis;
|
Mat frame, frame_vis;
|
||||||
|
|
||||||
while(cap.read(frame) && cv::waitKey(30) != 27) // capture frame until ESC is pressed
|
while(cap.read(frame) && waitKey(30) != 27) // capture frame until ESC is pressed
|
||||||
{
|
{
|
||||||
|
|
||||||
frame_vis = frame.clone(); // refresh visualisation frame
|
frame_vis = frame.clone(); // refresh visualisation frame
|
||||||
@ -185,8 +188,8 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
// -- Step 1: Robust matching between model descriptors and scene descriptors
|
// -- Step 1: Robust matching between model descriptors and scene descriptors
|
||||||
|
|
||||||
std::vector<cv::DMatch> good_matches; // to obtain the 3D points of the model
|
vector<DMatch> good_matches; // to obtain the 3D points of the model
|
||||||
std::vector<cv::KeyPoint> keypoints_scene; // to obtain the 2D points of the scene
|
vector<KeyPoint> keypoints_scene; // to obtain the 2D points of the scene
|
||||||
|
|
||||||
|
|
||||||
if(fast_match)
|
if(fast_match)
|
||||||
@ -201,13 +204,13 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
// -- Step 2: Find out the 2D/3D correspondences
|
// -- Step 2: Find out the 2D/3D correspondences
|
||||||
|
|
||||||
std::vector<cv::Point3f> list_points3d_model_match; // container for the model 3D coordinates found in the scene
|
vector<Point3f> list_points3d_model_match; // container for the model 3D coordinates found in the scene
|
||||||
std::vector<cv::Point2f> list_points2d_scene_match; // container for the model 2D coordinates found in the scene
|
vector<Point2f> list_points2d_scene_match; // container for the model 2D coordinates found in the scene
|
||||||
|
|
||||||
for(unsigned int match_index = 0; match_index < good_matches.size(); ++match_index)
|
for(unsigned int match_index = 0; match_index < good_matches.size(); ++match_index)
|
||||||
{
|
{
|
||||||
cv::Point3f point3d_model = list_points3d_model[ good_matches[match_index].trainIdx ]; // 3D point from model
|
Point3f point3d_model = list_points3d_model[ good_matches[match_index].trainIdx ]; // 3D point from model
|
||||||
cv::Point2f point2d_scene = keypoints_scene[ good_matches[match_index].queryIdx ].pt; // 2D point from the scene
|
Point2f point2d_scene = keypoints_scene[ good_matches[match_index].queryIdx ].pt; // 2D point from the scene
|
||||||
list_points3d_model_match.push_back(point3d_model); // add 3D point
|
list_points3d_model_match.push_back(point3d_model); // add 3D point
|
||||||
list_points2d_scene_match.push_back(point2d_scene); // add 2D point
|
list_points2d_scene_match.push_back(point2d_scene); // add 2D point
|
||||||
}
|
}
|
||||||
@ -216,8 +219,8 @@ int main(int argc, char *argv[])
|
|||||||
draw2DPoints(frame_vis, list_points2d_scene_match, red);
|
draw2DPoints(frame_vis, list_points2d_scene_match, red);
|
||||||
|
|
||||||
|
|
||||||
cv::Mat inliers_idx;
|
Mat inliers_idx;
|
||||||
std::vector<cv::Point2f> list_points2d_inliers;
|
vector<Point2f> list_points2d_inliers;
|
||||||
|
|
||||||
if(good_matches.size() > 0) // None matches, then RANSAC crashes
|
if(good_matches.size() > 0) // None matches, then RANSAC crashes
|
||||||
{
|
{
|
||||||
@ -231,7 +234,7 @@ int main(int argc, char *argv[])
|
|||||||
for(int inliers_index = 0; inliers_index < inliers_idx.rows; ++inliers_index)
|
for(int inliers_index = 0; inliers_index < inliers_idx.rows; ++inliers_index)
|
||||||
{
|
{
|
||||||
int n = inliers_idx.at<int>(inliers_index); // i-inlier
|
int n = inliers_idx.at<int>(inliers_index); // i-inlier
|
||||||
cv::Point2f point2d = list_points2d_scene_match[n]; // i-inlier point 2D
|
Point2f point2d = list_points2d_scene_match[n]; // i-inlier point 2D
|
||||||
list_points2d_inliers.push_back(point2d); // add i-inlier to list
|
list_points2d_inliers.push_back(point2d); // add i-inlier to list
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,11 +251,11 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
|
|
||||||
// Get the measured translation
|
// Get the measured translation
|
||||||
cv::Mat translation_measured(3, 1, CV_64F);
|
Mat translation_measured(3, 1, CV_64F);
|
||||||
translation_measured = pnp_detection.get_t_matrix();
|
translation_measured = pnp_detection.get_t_matrix();
|
||||||
|
|
||||||
// Get the measured rotation
|
// Get the measured rotation
|
||||||
cv::Mat rotation_measured(3, 3, CV_64F);
|
Mat rotation_measured(3, 3, CV_64F);
|
||||||
rotation_measured = pnp_detection.get_R_matrix();
|
rotation_measured = pnp_detection.get_R_matrix();
|
||||||
|
|
||||||
// fill the measurements vector
|
// fill the measurements vector
|
||||||
@ -263,8 +266,8 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Instantiate estimated translation and rotation
|
// Instantiate estimated translation and rotation
|
||||||
cv::Mat translation_estimated(3, 1, CV_64F);
|
Mat translation_estimated(3, 1, CV_64F);
|
||||||
cv::Mat rotation_estimated(3, 3, CV_64F);
|
Mat rotation_estimated(3, 3, CV_64F);
|
||||||
|
|
||||||
// update the Kalman filter with good measurements
|
// update the Kalman filter with good measurements
|
||||||
updateKalmanFilter( KF, measurements,
|
updateKalmanFilter( KF, measurements,
|
||||||
@ -288,11 +291,11 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
float l = 5;
|
float l = 5;
|
||||||
std::vector<cv::Point2f> pose_points2d;
|
vector<Point2f> pose_points2d;
|
||||||
pose_points2d.push_back(pnp_detection_est.backproject3DPoint(cv::Point3f(0,0,0))); // axis center
|
pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(0,0,0))); // axis center
|
||||||
pose_points2d.push_back(pnp_detection_est.backproject3DPoint(cv::Point3f(l,0,0))); // axis x
|
pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(l,0,0))); // axis x
|
||||||
pose_points2d.push_back(pnp_detection_est.backproject3DPoint(cv::Point3f(0,l,0))); // axis y
|
pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(0,l,0))); // axis y
|
||||||
pose_points2d.push_back(pnp_detection_est.backproject3DPoint(cv::Point3f(0,0,l))); // axis z
|
pose_points2d.push_back(pnp_detection_est.backproject3DPoint(Point3f(0,0,l))); // axis z
|
||||||
draw3DCoordinateAxes(frame_vis, pose_points2d); // draw axes
|
draw3DCoordinateAxes(frame_vis, pose_points2d); // draw axes
|
||||||
|
|
||||||
// FRAME RATE
|
// FRAME RATE
|
||||||
@ -316,49 +319,49 @@ int main(int argc, char *argv[])
|
|||||||
// Draw some debug text
|
// Draw some debug text
|
||||||
int inliers_int = inliers_idx.rows;
|
int inliers_int = inliers_idx.rows;
|
||||||
int outliers_int = (int)good_matches.size() - inliers_int;
|
int outliers_int = (int)good_matches.size() - inliers_int;
|
||||||
std::string inliers_str = IntToString(inliers_int);
|
string inliers_str = IntToString(inliers_int);
|
||||||
std::string outliers_str = IntToString(outliers_int);
|
string outliers_str = IntToString(outliers_int);
|
||||||
std::string n = IntToString((int)good_matches.size());
|
string n = IntToString((int)good_matches.size());
|
||||||
std::string text = "Found " + inliers_str + " of " + n + " matches";
|
string text = "Found " + inliers_str + " of " + n + " matches";
|
||||||
std::string text2 = "Inliers: " + inliers_str + " - Outliers: " + outliers_str;
|
string text2 = "Inliers: " + inliers_str + " - Outliers: " + outliers_str;
|
||||||
|
|
||||||
drawText(frame_vis, text, green);
|
drawText(frame_vis, text, green);
|
||||||
drawText2(frame_vis, text2, red);
|
drawText2(frame_vis, text2, red);
|
||||||
|
|
||||||
cv::imshow("REAL TIME DEMO", frame_vis);
|
imshow("REAL TIME DEMO", frame_vis);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close and Destroy Window
|
// Close and Destroy Window
|
||||||
cv::destroyWindow("REAL TIME DEMO");
|
destroyWindow("REAL TIME DEMO");
|
||||||
|
|
||||||
std::cout << "GOODBYE ..." << std::endl;
|
cout << "GOODBYE ..." << endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************************************************/
|
/**********************************************************************************************************/
|
||||||
void help()
|
void help()
|
||||||
{
|
{
|
||||||
std::cout
|
cout
|
||||||
<< "--------------------------------------------------------------------------" << std::endl
|
<< "--------------------------------------------------------------------------" << endl
|
||||||
<< "This program shows how to detect an object given its 3D textured model. You can choose to "
|
<< "This program shows how to detect an object given its 3D textured model. You can choose to "
|
||||||
<< "use a recorded video or the webcam." << std::endl
|
<< "use a recorded video or the webcam." << endl
|
||||||
<< "Usage:" << std::endl
|
<< "Usage:" << endl
|
||||||
<< "./cpp-tutorial-pnp_detection -help" << std::endl
|
<< "./cpp-tutorial-pnp_detection -help" << endl
|
||||||
<< "Keys:" << std::endl
|
<< "Keys:" << endl
|
||||||
<< "'esc' - to quit." << std::endl
|
<< "'esc' - to quit." << endl
|
||||||
<< "--------------------------------------------------------------------------" << std::endl
|
<< "--------------------------------------------------------------------------" << endl
|
||||||
<< std::endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************************************************/
|
/**********************************************************************************************************/
|
||||||
void initKalmanFilter(cv::KalmanFilter &KF, int nStates, int nMeasurements, int nInputs, double dt)
|
void initKalmanFilter(KalmanFilter &KF, int nStates, int nMeasurements, int nInputs, double dt)
|
||||||
{
|
{
|
||||||
|
|
||||||
KF.init(nStates, nMeasurements, nInputs, CV_64F); // init Kalman Filter
|
KF.init(nStates, nMeasurements, nInputs, CV_64F); // init Kalman Filter
|
||||||
|
|
||||||
cv::setIdentity(KF.processNoiseCov, cv::Scalar::all(1e-5)); // set process noise
|
setIdentity(KF.processNoiseCov, Scalar::all(1e-5)); // set process noise
|
||||||
cv::setIdentity(KF.measurementNoiseCov, cv::Scalar::all(1e-2)); // set measurement noise
|
setIdentity(KF.measurementNoiseCov, Scalar::all(1e-2)); // set measurement noise
|
||||||
cv::setIdentity(KF.errorCovPost, cv::Scalar::all(1)); // error covariance
|
setIdentity(KF.errorCovPost, Scalar::all(1)); // error covariance
|
||||||
|
|
||||||
|
|
||||||
/** DYNAMIC MODEL **/
|
/** DYNAMIC MODEL **/
|
||||||
@ -424,15 +427,15 @@ void initKalmanFilter(cv::KalmanFilter &KF, int nStates, int nMeasurements, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************************************************/
|
/**********************************************************************************************************/
|
||||||
void updateKalmanFilter( cv::KalmanFilter &KF, cv::Mat &measurement,
|
void updateKalmanFilter( KalmanFilter &KF, Mat &measurement,
|
||||||
cv::Mat &translation_estimated, cv::Mat &rotation_estimated )
|
Mat &translation_estimated, Mat &rotation_estimated )
|
||||||
{
|
{
|
||||||
|
|
||||||
// First predict, to update the internal statePre variable
|
// First predict, to update the internal statePre variable
|
||||||
cv::Mat prediction = KF.predict();
|
Mat prediction = KF.predict();
|
||||||
|
|
||||||
// The "correct" phase that is going to use the predicted value and our measurement
|
// The "correct" phase that is going to use the predicted value and our measurement
|
||||||
cv::Mat estimated = KF.correct(measurement);
|
Mat estimated = KF.correct(measurement);
|
||||||
|
|
||||||
// Estimated translation
|
// Estimated translation
|
||||||
translation_estimated.at<double>(0) = estimated.at<double>(0);
|
translation_estimated.at<double>(0) = estimated.at<double>(0);
|
||||||
@ -440,7 +443,7 @@ void updateKalmanFilter( cv::KalmanFilter &KF, cv::Mat &measurement,
|
|||||||
translation_estimated.at<double>(2) = estimated.at<double>(2);
|
translation_estimated.at<double>(2) = estimated.at<double>(2);
|
||||||
|
|
||||||
// Estimated euler angles
|
// Estimated euler angles
|
||||||
cv::Mat eulers_estimated(3, 1, CV_64F);
|
Mat eulers_estimated(3, 1, CV_64F);
|
||||||
eulers_estimated.at<double>(0) = estimated.at<double>(9);
|
eulers_estimated.at<double>(0) = estimated.at<double>(9);
|
||||||
eulers_estimated.at<double>(1) = estimated.at<double>(10);
|
eulers_estimated.at<double>(1) = estimated.at<double>(10);
|
||||||
eulers_estimated.at<double>(2) = estimated.at<double>(11);
|
eulers_estimated.at<double>(2) = estimated.at<double>(11);
|
||||||
@ -451,11 +454,11 @@ void updateKalmanFilter( cv::KalmanFilter &KF, cv::Mat &measurement,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************************************************/
|
/**********************************************************************************************************/
|
||||||
void fillMeasurements( cv::Mat &measurements,
|
void fillMeasurements( Mat &measurements,
|
||||||
const cv::Mat &translation_measured, const cv::Mat &rotation_measured)
|
const Mat &translation_measured, const Mat &rotation_measured)
|
||||||
{
|
{
|
||||||
// Convert rotation matrix to euler angles
|
// Convert rotation matrix to euler angles
|
||||||
cv::Mat measured_eulers(3, 1, CV_64F);
|
Mat measured_eulers(3, 1, CV_64F);
|
||||||
measured_eulers = rot2euler(rotation_measured);
|
measured_eulers = rot2euler(rotation_measured);
|
||||||
|
|
||||||
// Set measurement to predict
|
// Set measurement to predict
|
||||||
|
@ -13,13 +13,16 @@
|
|||||||
#include "ModelRegistration.h"
|
#include "ModelRegistration.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using namespace cv;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
/** GLOBAL VARIABLES **/
|
/** GLOBAL VARIABLES **/
|
||||||
|
|
||||||
std::string tutorial_path = "../../samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/"; // path to tutorial
|
string tutorial_path = "../../samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/"; // path to tutorial
|
||||||
|
|
||||||
std::string img_path = tutorial_path + "Data/resized_IMG_3875.JPG"; // image to register
|
string img_path = tutorial_path + "Data/resized_IMG_3875.JPG"; // image to register
|
||||||
std::string ply_read_path = tutorial_path + "Data/box.ply"; // object mesh
|
string ply_read_path = tutorial_path + "Data/box.ply"; // object mesh
|
||||||
std::string write_path = tutorial_path + "Data/cookies_ORB.yml"; // output file
|
string write_path = tutorial_path + "Data/cookies_ORB.yml"; // output file
|
||||||
|
|
||||||
// Boolean the know if the registration it's done
|
// Boolean the know if the registration it's done
|
||||||
bool end_registration = false;
|
bool end_registration = false;
|
||||||
@ -39,10 +42,10 @@ int n = 8;
|
|||||||
int pts[] = {1, 2, 3, 4, 5, 6, 7, 8}; // 3 -> 4
|
int pts[] = {1, 2, 3, 4, 5, 6, 7, 8}; // 3 -> 4
|
||||||
|
|
||||||
// Some basic colors
|
// Some basic colors
|
||||||
cv::Scalar red(0, 0, 255);
|
Scalar red(0, 0, 255);
|
||||||
cv::Scalar green(0,255,0);
|
Scalar green(0,255,0);
|
||||||
cv::Scalar blue(255,0,0);
|
Scalar blue(255,0,0);
|
||||||
cv::Scalar yellow(0,255,255);
|
Scalar yellow(0,255,255);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CREATE MODEL REGISTRATION OBJECT
|
* CREATE MODEL REGISTRATION OBJECT
|
||||||
@ -61,13 +64,13 @@ void help();
|
|||||||
// Mouse events for model registration
|
// Mouse events for model registration
|
||||||
static void onMouseModelRegistration( int event, int x, int y, int, void* )
|
static void onMouseModelRegistration( int event, int x, int y, int, void* )
|
||||||
{
|
{
|
||||||
if ( event == cv::EVENT_LBUTTONUP )
|
if ( event == EVENT_LBUTTONUP )
|
||||||
{
|
{
|
||||||
int n_regist = registration.getNumRegist();
|
int n_regist = registration.getNumRegist();
|
||||||
int n_vertex = pts[n_regist];
|
int n_vertex = pts[n_regist];
|
||||||
|
|
||||||
cv::Point2f point_2d = cv::Point2f((float)x,(float)y);
|
Point2f point_2d = Point2f((float)x,(float)y);
|
||||||
cv::Point3f point_3d = mesh.getVertex(n_vertex-1);
|
Point3f point_3d = mesh.getVertex(n_vertex-1);
|
||||||
|
|
||||||
bool is_registrable = registration.is_registrable();
|
bool is_registrable = registration.is_registrable();
|
||||||
if (is_registrable)
|
if (is_registrable)
|
||||||
@ -92,23 +95,23 @@ int main()
|
|||||||
|
|
||||||
//Instantiate robust matcher: detector, extractor, matcher
|
//Instantiate robust matcher: detector, extractor, matcher
|
||||||
RobustMatcher rmatcher;
|
RobustMatcher rmatcher;
|
||||||
cv::FeatureDetector * detector = new cv::OrbFeatureDetector(numKeyPoints);
|
Ptr<FeatureDetector> detector = ORB::create(numKeyPoints);
|
||||||
rmatcher.setFeatureDetector(detector);
|
rmatcher.setFeatureDetector(detector);
|
||||||
|
|
||||||
/** GROUND TRUTH OF THE FIRST IMAGE **/
|
/** GROUND TRUTH OF THE FIRST IMAGE **/
|
||||||
|
|
||||||
// Create & Open Window
|
// Create & Open Window
|
||||||
cv::namedWindow("MODEL REGISTRATION", cv::WINDOW_KEEPRATIO);
|
namedWindow("MODEL REGISTRATION", WINDOW_KEEPRATIO);
|
||||||
|
|
||||||
// Set up the mouse events
|
// Set up the mouse events
|
||||||
cv::setMouseCallback("MODEL REGISTRATION", onMouseModelRegistration, 0 );
|
setMouseCallback("MODEL REGISTRATION", onMouseModelRegistration, 0 );
|
||||||
|
|
||||||
// Open the image to register
|
// Open the image to register
|
||||||
cv::Mat img_in = cv::imread(img_path, cv::IMREAD_COLOR);
|
Mat img_in = imread(img_path, IMREAD_COLOR);
|
||||||
cv::Mat img_vis = img_in.clone();
|
Mat img_vis = img_in.clone();
|
||||||
|
|
||||||
if (!img_in.data) {
|
if (!img_in.data) {
|
||||||
std::cout << "Could not open or find the image" << std::endl;
|
cout << "Could not open or find the image" << endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,18 +119,18 @@ int main()
|
|||||||
int num_registrations = n;
|
int num_registrations = n;
|
||||||
registration.setNumMax(num_registrations);
|
registration.setNumMax(num_registrations);
|
||||||
|
|
||||||
std::cout << "Click the box corners ..." << std::endl;
|
cout << "Click the box corners ..." << endl;
|
||||||
std::cout << "Waiting ..." << std::endl;
|
cout << "Waiting ..." << endl;
|
||||||
|
|
||||||
// Loop until all the points are registered
|
// Loop until all the points are registered
|
||||||
while ( cv::waitKey(30) < 0 )
|
while ( waitKey(30) < 0 )
|
||||||
{
|
{
|
||||||
// Refresh debug image
|
// Refresh debug image
|
||||||
img_vis = img_in.clone();
|
img_vis = img_in.clone();
|
||||||
|
|
||||||
// Current registered points
|
// Current registered points
|
||||||
std::vector<cv::Point2f> list_points2d = registration.get_points2d();
|
vector<Point2f> list_points2d = registration.get_points2d();
|
||||||
std::vector<cv::Point3f> list_points3d = registration.get_points3d();
|
vector<Point3f> list_points3d = registration.get_points3d();
|
||||||
|
|
||||||
// Draw current registered points
|
// Draw current registered points
|
||||||
drawPoints(img_vis, list_points2d, list_points3d, red);
|
drawPoints(img_vis, list_points2d, list_points3d, red);
|
||||||
@ -139,7 +142,7 @@ int main()
|
|||||||
// Draw debug text
|
// Draw debug text
|
||||||
int n_regist = registration.getNumRegist();
|
int n_regist = registration.getNumRegist();
|
||||||
int n_vertex = pts[n_regist];
|
int n_vertex = pts[n_regist];
|
||||||
cv::Point3f current_poin3d = mesh.getVertex(n_vertex-1);
|
Point3f current_poin3d = mesh.getVertex(n_vertex-1);
|
||||||
|
|
||||||
drawQuestion(img_vis, current_poin3d, green);
|
drawQuestion(img_vis, current_poin3d, green);
|
||||||
drawCounter(img_vis, registration.getNumRegist(), registration.getNumMax(), red);
|
drawCounter(img_vis, registration.getNumRegist(), registration.getNumMax(), red);
|
||||||
@ -153,43 +156,43 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Show the image
|
// Show the image
|
||||||
cv::imshow("MODEL REGISTRATION", img_vis);
|
imshow("MODEL REGISTRATION", img_vis);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** COMPUTE CAMERA POSE **/
|
/** COMPUTE CAMERA POSE **/
|
||||||
|
|
||||||
std::cout << "COMPUTING POSE ..." << std::endl;
|
cout << "COMPUTING POSE ..." << endl;
|
||||||
|
|
||||||
// The list of registered points
|
// The list of registered points
|
||||||
std::vector<cv::Point2f> list_points2d = registration.get_points2d();
|
vector<Point2f> list_points2d = registration.get_points2d();
|
||||||
std::vector<cv::Point3f> list_points3d = registration.get_points3d();
|
vector<Point3f> list_points3d = registration.get_points3d();
|
||||||
|
|
||||||
// Estimate pose given the registered points
|
// Estimate pose given the registered points
|
||||||
bool is_correspondence = pnp_registration.estimatePose(list_points3d, list_points2d, cv::SOLVEPNP_ITERATIVE);
|
bool is_correspondence = pnp_registration.estimatePose(list_points3d, list_points2d, SOLVEPNP_ITERATIVE);
|
||||||
if ( is_correspondence )
|
if ( is_correspondence )
|
||||||
{
|
{
|
||||||
std::cout << "Correspondence found" << std::endl;
|
cout << "Correspondence found" << endl;
|
||||||
|
|
||||||
// Compute all the 2D points of the mesh to verify the algorithm and draw it
|
// Compute all the 2D points of the mesh to verify the algorithm and draw it
|
||||||
std::vector<cv::Point2f> list_points2d_mesh = pnp_registration.verify_points(&mesh);
|
vector<Point2f> list_points2d_mesh = pnp_registration.verify_points(&mesh);
|
||||||
draw2DPoints(img_vis, list_points2d_mesh, green);
|
draw2DPoints(img_vis, list_points2d_mesh, green);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Correspondence not found" << std::endl << std::endl;
|
cout << "Correspondence not found" << endl << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show the image
|
// Show the image
|
||||||
cv::imshow("MODEL REGISTRATION", img_vis);
|
imshow("MODEL REGISTRATION", img_vis);
|
||||||
|
|
||||||
// Show image until ESC pressed
|
// Show image until ESC pressed
|
||||||
cv::waitKey(0);
|
waitKey(0);
|
||||||
|
|
||||||
|
|
||||||
/** COMPUTE 3D of the image Keypoints **/
|
/** COMPUTE 3D of the image Keypoints **/
|
||||||
|
|
||||||
// Containers for keypoints and descriptors of the model
|
// Containers for keypoints and descriptors of the model
|
||||||
std::vector<cv::KeyPoint> keypoints_model;
|
vector<KeyPoint> keypoints_model;
|
||||||
cv::Mat descriptors;
|
Mat descriptors;
|
||||||
|
|
||||||
// Compute keypoints and descriptors
|
// Compute keypoints and descriptors
|
||||||
rmatcher.computeKeyPoints(img_in, keypoints_model);
|
rmatcher.computeKeyPoints(img_in, keypoints_model);
|
||||||
@ -197,8 +200,8 @@ int main()
|
|||||||
|
|
||||||
// Check if keypoints are on the surface of the registration image and add to the model
|
// Check if keypoints are on the surface of the registration image and add to the model
|
||||||
for (unsigned int i = 0; i < keypoints_model.size(); ++i) {
|
for (unsigned int i = 0; i < keypoints_model.size(); ++i) {
|
||||||
cv::Point2f point2d(keypoints_model[i].pt);
|
Point2f point2d(keypoints_model[i].pt);
|
||||||
cv::Point3f point3d;
|
Point3f point3d;
|
||||||
bool on_surface = pnp_registration.backproject2DPoint(&mesh, point2d, point3d);
|
bool on_surface = pnp_registration.backproject2DPoint(&mesh, point2d, point3d);
|
||||||
if (on_surface)
|
if (on_surface)
|
||||||
{
|
{
|
||||||
@ -219,12 +222,12 @@ int main()
|
|||||||
img_vis = img_in.clone();
|
img_vis = img_in.clone();
|
||||||
|
|
||||||
// The list of the points2d of the model
|
// The list of the points2d of the model
|
||||||
std::vector<cv::Point2f> list_points_in = model.get_points2d_in();
|
vector<Point2f> list_points_in = model.get_points2d_in();
|
||||||
std::vector<cv::Point2f> list_points_out = model.get_points2d_out();
|
vector<Point2f> list_points_out = model.get_points2d_out();
|
||||||
|
|
||||||
// Draw some debug text
|
// Draw some debug text
|
||||||
std::string num = IntToString((int)list_points_in.size());
|
string num = IntToString((int)list_points_in.size());
|
||||||
std::string text = "There are " + num + " inliers";
|
string text = "There are " + num + " inliers";
|
||||||
drawText(img_vis, text, green);
|
drawText(img_vis, text, green);
|
||||||
|
|
||||||
// Draw some debug text
|
// Draw some debug text
|
||||||
@ -240,26 +243,26 @@ int main()
|
|||||||
draw2DPoints(img_vis, list_points_out, red);
|
draw2DPoints(img_vis, list_points_out, red);
|
||||||
|
|
||||||
// Show the image
|
// Show the image
|
||||||
cv::imshow("MODEL REGISTRATION", img_vis);
|
imshow("MODEL REGISTRATION", img_vis);
|
||||||
|
|
||||||
// Wait until ESC pressed
|
// Wait until ESC pressed
|
||||||
cv::waitKey(0);
|
waitKey(0);
|
||||||
|
|
||||||
// Close and Destroy Window
|
// Close and Destroy Window
|
||||||
cv::destroyWindow("MODEL REGISTRATION");
|
destroyWindow("MODEL REGISTRATION");
|
||||||
|
|
||||||
std::cout << "GOODBYE" << std::endl;
|
cout << "GOODBYE" << endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************************************************/
|
/**********************************************************************************************************/
|
||||||
void help()
|
void help()
|
||||||
{
|
{
|
||||||
std::cout
|
cout
|
||||||
<< "--------------------------------------------------------------------------" << std::endl
|
<< "--------------------------------------------------------------------------" << endl
|
||||||
<< "This program shows how to create your 3D textured model. " << std::endl
|
<< "This program shows how to create your 3D textured model. " << endl
|
||||||
<< "Usage:" << std::endl
|
<< "Usage:" << endl
|
||||||
<< "./cpp-tutorial-pnp_registration" << std::endl
|
<< "./cpp-tutorial-pnp_registration" << endl
|
||||||
<< "--------------------------------------------------------------------------" << std::endl
|
<< "--------------------------------------------------------------------------" << endl
|
||||||
<< std::endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,9 @@ int main(void)
|
|||||||
vector<KeyPoint> kpts1, kpts2;
|
vector<KeyPoint> kpts1, kpts2;
|
||||||
Mat desc1, desc2;
|
Mat desc1, desc2;
|
||||||
|
|
||||||
AKAZE akaze;
|
Ptr<AKAZE> akaze = AKAZE::create();
|
||||||
akaze(img1, noArray(), kpts1, desc1);
|
akaze->detectAndCompute(img1, noArray(), kpts1, desc1);
|
||||||
akaze(img2, noArray(), kpts2, desc2);
|
akaze->detectAndCompute(img2, noArray(), kpts2, desc2);
|
||||||
|
|
||||||
BFMatcher matcher(NORM_HAMMING);
|
BFMatcher matcher(NORM_HAMMING);
|
||||||
vector< vector<DMatch> > nn_matches;
|
vector< vector<DMatch> > nn_matches;
|
||||||
|
@ -41,7 +41,7 @@ protected:
|
|||||||
void Tracker::setFirstFrame(const Mat frame, vector<Point2f> bb, string title, Stats& stats)
|
void Tracker::setFirstFrame(const Mat frame, vector<Point2f> bb, string title, Stats& stats)
|
||||||
{
|
{
|
||||||
first_frame = frame.clone();
|
first_frame = frame.clone();
|
||||||
(*detector)(first_frame, noArray(), first_kp, first_desc);
|
detector->detectAndCompute(first_frame, noArray(), first_kp, first_desc);
|
||||||
stats.keypoints = (int)first_kp.size();
|
stats.keypoints = (int)first_kp.size();
|
||||||
drawBoundingBox(first_frame, bb);
|
drawBoundingBox(first_frame, bb);
|
||||||
putText(first_frame, title, Point(0, 60), FONT_HERSHEY_PLAIN, 5, Scalar::all(0), 4);
|
putText(first_frame, title, Point(0, 60), FONT_HERSHEY_PLAIN, 5, Scalar::all(0), 4);
|
||||||
@ -52,7 +52,7 @@ Mat Tracker::process(const Mat frame, Stats& stats)
|
|||||||
{
|
{
|
||||||
vector<KeyPoint> kp;
|
vector<KeyPoint> kp;
|
||||||
Mat desc;
|
Mat desc;
|
||||||
(*detector)(frame, noArray(), kp, desc);
|
detector->detectAndCompute(frame, noArray(), kp, desc);
|
||||||
stats.keypoints = (int)kp.size();
|
stats.keypoints = (int)kp.size();
|
||||||
|
|
||||||
vector< vector<DMatch> > matches;
|
vector< vector<DMatch> > matches;
|
||||||
@ -135,9 +135,9 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
fs["bounding_box"] >> bb;
|
fs["bounding_box"] >> bb;
|
||||||
Ptr<Feature2D> akaze = Feature2D::create("AKAZE");
|
Ptr<Feature2D> akaze = AKAZE::create();
|
||||||
akaze->set("threshold", akaze_thresh);
|
akaze->set("threshold", akaze_thresh);
|
||||||
Ptr<Feature2D> orb = Feature2D::create("ORB");
|
Ptr<Feature2D> orb = ORB::create();
|
||||||
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");
|
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");
|
||||||
Tracker akaze_tracker(akaze, matcher);
|
Tracker akaze_tracker(akaze, matcher);
|
||||||
Tracker orb_tracker(orb, matcher);
|
Tracker orb_tracker(orb, matcher);
|
||||||
|
@ -227,7 +227,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Ptr<KeypointBasedMotionEstimator> kbest = makePtr<KeypointBasedMotionEstimator>(est);
|
Ptr<KeypointBasedMotionEstimator> kbest = makePtr<KeypointBasedMotionEstimator>(est);
|
||||||
kbest->setDetector(makePtr<GoodFeaturesToTrackDetector>(argi(prefix + "nkps")));
|
kbest->setDetector(GFTTDetector::create(argi(prefix + "nkps")));
|
||||||
kbest->setOutlierRejector(outlierRejector);
|
kbest->setOutlierRejector(outlierRejector);
|
||||||
return kbest;
|
return kbest;
|
||||||
}
|
}
|
||||||
@ -268,7 +268,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Ptr<KeypointBasedMotionEstimator> kbest = makePtr<KeypointBasedMotionEstimator>(est);
|
Ptr<KeypointBasedMotionEstimator> kbest = makePtr<KeypointBasedMotionEstimator>(est);
|
||||||
kbest->setDetector(makePtr<GoodFeaturesToTrackDetector>(argi(prefix + "nkps")));
|
kbest->setDetector(GFTTDetector::create(argi(prefix + "nkps")));
|
||||||
kbest->setOutlierRejector(outlierRejector);
|
kbest->setOutlierRejector(outlierRejector);
|
||||||
return kbest;
|
return kbest;
|
||||||
}
|
}
|
||||||
|
@ -129,12 +129,12 @@ cv::Mat OcvImageProcessing::MainPage::ApplyFindFeaturesFilter(const cv::Mat& ima
|
|||||||
{
|
{
|
||||||
cv::Mat result;
|
cv::Mat result;
|
||||||
cv::Mat intermediateMat;
|
cv::Mat intermediateMat;
|
||||||
cv::FastFeatureDetector detector(50);
|
cv::Ptr<cv::FeatureDetector> detector = cv::FastFeatureDetector::create(50);
|
||||||
std::vector<cv::KeyPoint> features;
|
std::vector<cv::KeyPoint> features;
|
||||||
|
|
||||||
image.copyTo(result);
|
image.copyTo(result);
|
||||||
cv::cvtColor(image, intermediateMat, CV_RGBA2GRAY);
|
cv::cvtColor(image, intermediateMat, CV_RGBA2GRAY);
|
||||||
detector.detect(intermediateMat, features);
|
detector->detect(intermediateMat, features);
|
||||||
|
|
||||||
for( unsigned int i = 0; i < std::min(features.size(), (size_t)50); i++ )
|
for( unsigned int i = 0; i < std::min(features.size(), (size_t)50); i++ )
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user