Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
e406dfee
Commit
e406dfee
authored
Nov 22, 2010
by
Maria Dimashova
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactored features2d and sample on matching to many images
parent
cf0d9da6
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1600 additions
and
1006 deletions
+1600
-1006
features2d.hpp
modules/features2d/include/opencv2/features2d/features2d.hpp
+483
-433
bagofwords.cpp
modules/features2d/src/bagofwords.cpp
+37
-0
brief.cpp
modules/features2d/src/brief.cpp
+353
-327
descriptors.cpp
modules/features2d/src/descriptors.cpp
+78
-19
detectors.cpp
modules/features2d/src/detectors.cpp
+102
-44
matchers.cpp
modules/features2d/src/matchers.cpp
+360
-95
matching_to_many_images.cpp
samples/cpp/matching_to_many_images.cpp
+176
-80
query.png
samples/cpp/matching_to_many_images/query.png
+0
-0
1.png
samples/cpp/matching_to_many_images/train/1.png
+0
-0
2.png
samples/cpp/matching_to_many_images/train/2.png
+0
-0
3.png
samples/cpp/matching_to_many_images/train/3.png
+0
-0
trainImages.txt
samples/cpp/matching_to_many_images/train/trainImages.txt
+3
-0
afeatures2d.cpp
tests/cv/src/afeatures2d.cpp
+8
-8
No files found.
modules/features2d/include/opencv2/features2d/features2d.hpp
View file @
e406dfee
...
...
@@ -1231,34 +1231,34 @@ protected:
class
CV_EXPORTS
FeatureDetector
{
public
:
virtual
~
FeatureDetector
()
{}
virtual
~
FeatureDetector
()
;
/*
* Detect keypoints in an image. Must be implemented by the subclass.
*
* 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.
*/
v
irtual
void
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
=
0
;
v
oid
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
/*
* Detect keypoints in an image set.
*
* images Image collection.
* pointCollection Collection of keypoints detected in an input images.
* masks Masks for each input image.
* images Image collection.
* 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
(
const
vector
<
Mat
>&
image
Collection
,
vector
<
vector
<
KeyPoint
>
>&
pointCollection
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
()
)
const
;
void
detect
(
const
vector
<
Mat
>&
image
s
,
vector
<
vector
<
KeyPoint
>
>&
keypoints
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
()
)
const
;
virtual
void
read
(
const
FileNode
&
)
{}
virtual
void
write
(
FileStorage
&
)
const
{}
// Read detector object from a file node
virtual
void
read
(
const
FileNode
&
);
// Read detector object from a file node
virtual
void
write
(
FileStorage
&
)
const
;
protected
:
virtual
void
detectImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
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.
*/
...
...
@@ -1268,13 +1268,13 @@ protected:
class
CV_EXPORTS
FastFeatureDetector
:
public
FeatureDetector
{
public
:
FastFeatureDetector
(
int
_threshold
=
1
,
bool
_nonmaxSuppression
=
true
);
virtual
void
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
FastFeatureDetector
(
int
threshold
=
10
,
bool
nonmaxSuppression
=
true
);
virtual
void
read
(
const
FileNode
&
fn
);
virtual
void
write
(
FileStorage
&
fs
)
const
;
protected
:
virtual
void
detectImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
int
threshold
;
bool
nonmaxSuppression
;
};
...
...
@@ -1283,102 +1283,123 @@ protected:
class
CV_EXPORTS
GoodFeaturesToTrackDetector
:
public
FeatureDetector
{
public
:
GoodFeaturesToTrackDetector
(
int
_maxCorners
,
double
_qualityLevel
,
double
_minDistance
,
int
_blockSize
=
3
,
bool
_useHarrisDetector
=
false
,
double
_k
=
0.04
);
virtual
void
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
class
CV_EXPORTS
Params
{
public
:
Params
(
int
maxCorners
=
1000
,
double
qualityLevel
=
0.01
,
double
minDistance
=
1.
,
int
blockSize
=
3
,
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
=
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
:
int
maxCorners
;
double
qualityLevel
;
double
minDistance
;
int
blockSize
;
bool
useHarrisDetector
;
double
k
;
virtual
void
detectImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
Params
params
;
};
class
CV_EXPORTS
MserFeatureDetector
:
public
FeatureDetector
{
public
:
MserFeatureDetector
(
CvMSERParams
params
=
cvMSERParams
()
);
MserFeatureDetector
(
CvMSERParams
params
=
cvMSERParams
()
);
MserFeatureDetector
(
int
delta
,
int
minArea
,
int
maxArea
,
double
maxVariation
,
double
minDiversity
,
int
maxEvolution
,
double
areaThreshold
,
double
minMargin
,
int
edgeBlurSize
);
virtual
void
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
virtual
void
read
(
const
FileNode
&
fn
);
virtual
void
write
(
FileStorage
&
fs
)
const
;
protected
:
virtual
void
detectImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
MSER
mser
;
};
class
CV_EXPORTS
StarFeatureDetector
:
public
FeatureDetector
{
public
:
StarFeatureDetector
(
int
maxSize
=
16
,
int
responseThreshold
=
30
,
int
lineThresholdProjected
=
10
,
StarFeatureDetector
(
const
CvStarDetectorParams
&
params
=
cvStarDetectorParams
()
);
StarFeatureDetector
(
int
maxSize
,
int
responseThreshold
=
30
,
int
lineThresholdProjected
=
10
,
int
lineThresholdBinarized
=
8
,
int
suppressNonmaxSize
=
5
);
virtual
void
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
virtual
void
read
(
const
FileNode
&
fn
);
virtual
void
write
(
FileStorage
&
fs
)
const
;
protected
:
virtual
void
detectImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
StarDetector
star
;
};
class
CV_EXPORTS
SiftFeatureDetector
:
public
FeatureDetector
{
public
:
SiftFeatureDetector
(
double
threshold
=
SIFT
::
DetectorParams
::
GET_DEFAULT_THRESHOLD
(),
double
edgeThreshold
=
SIFT
::
DetectorParams
::
GET_DEFAULT_EDGE_THRESHOLD
(),
SiftFeatureDetector
(
const
SIFT
::
DetectorParams
&
detectorParams
=
SIFT
::
DetectorParams
(),
const
SIFT
::
CommonParams
&
commonParams
=
SIFT
::
CommonParams
()
);
SiftFeatureDetector
(
double
threshold
,
double
edgeThreshold
,
int
nOctaves
=
SIFT
::
CommonParams
::
DEFAULT_NOCTAVES
,
int
nOctaveLayers
=
SIFT
::
CommonParams
::
DEFAULT_NOCTAVE_LAYERS
,
int
firstOctave
=
SIFT
::
CommonParams
::
DEFAULT_FIRST_OCTAVE
,
int
angleMode
=
SIFT
::
CommonParams
::
FIRST_ANGLE
);
virtual
void
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
virtual
void
read
(
const
FileNode
&
fn
);
virtual
void
write
(
FileStorage
&
fs
)
const
;
protected
:
virtual
void
detectImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
SIFT
sift
;
};
class
CV_EXPORTS
SurfFeatureDetector
:
public
FeatureDetector
{
public
:
SurfFeatureDetector
(
double
hessianThreshold
=
400.
,
int
octaves
=
3
,
int
octaveLayers
=
4
);
virtual
void
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
SurfFeatureDetector
(
double
hessianThreshold
=
400.
,
int
octaves
=
3
,
int
octaveLayers
=
4
);
virtual
void
read
(
const
FileNode
&
fn
);
virtual
void
write
(
FileStorage
&
fs
)
const
;
protected
:
virtual
void
detectImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
SURF
surf
;
};
class
CV_EXPORTS
DenseFeatureDetector
:
public
FeatureDetector
{
public
:
DenseFeatureDetector
()
:
initFeatureScale
(
1
),
featureScaleLevels
(
1
),
featureScaleMul
(
0.1
f
),
initXyStep
(
6
),
initImgBound
(
0
),
varyXyStepWithScale
(
true
),
varyImgBoundWithScale
(
false
)
{}
DenseFeatureDetector
(
float
_initFeatureScale
,
int
_featureScaleLevels
=
1
,
float
_featureScaleMul
=
0.1
f
,
int
_initXyStep
=
6
,
int
_initImgBound
=
0
,
bool
_varyXyStepWithScale
=
true
,
bool
_varyImgBoundWithScale
=
false
)
:
initFeatureScale
(
_initFeatureScale
),
featureScaleLevels
(
_featureScaleLevels
),
featureScaleMul
(
_featureScaleMul
),
initXyStep
(
_initXyStep
),
initImgBound
(
_initImgBound
),
varyXyStepWithScale
(
_varyXyStepWithScale
),
varyImgBoundWithScale
(
_varyImgBoundWithScale
)
{}
virtual
void
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
// todo read/write
protected
:
float
initFeatureScale
;
int
featureScaleLevels
;
float
featureScaleMul
;
class
CV_EXPORTS
Params
{
public
:
Params
(
float
initFeatureScale
=
1.
f
,
int
featureScaleLevels
=
1
,
float
featureScaleMul
=
0.1
f
,
int
initXyStep
=
6
,
int
initImgBound
=
0
,
bool
varyXyStepWithScale
=
true
,
bool
varyImgBoundWithScale
=
false
);
float
initFeatureScale
;
int
featureScaleLevels
;
float
featureScaleMul
;
int
initXyStep
;
int
initImgBound
;
bool
varyXyStepWithScale
;
bool
varyImgBoundWithScale
;
};
DenseFeatureDetector
(
const
DenseFeatureDetector
::
Params
&
params
=
DenseFeatureDetector
::
Params
()
);
// TODO implement read/write
int
initXyStep
;
int
initImgBound
;
protected
:
virtual
void
detectImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
bool
varyXyStepWithScale
;
bool
varyImgBoundWithScale
;
Params
params
;
};
/*
...
...
@@ -1397,13 +1418,12 @@ public:
*/
GridAdaptedFeatureDetector
(
const
Ptr
<
FeatureDetector
>&
detector
,
int
maxTotalKeypoints
,
int
gridRows
=
4
,
int
gridCols
=
4
);
virtual
void
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
// todo read/write
virtual
void
read
(
const
FileNode
&
)
{}
virtual
void
write
(
FileStorage
&
)
const
{}
// TODO implement read/write
protected
:
virtual
void
detectImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
Ptr
<
FeatureDetector
>
detector
;
int
maxTotalKeypoints
;
int
gridRows
;
...
...
@@ -1418,13 +1438,12 @@ class CV_EXPORTS PyramidAdaptedFeatureDetector : public FeatureDetector
{
public
:
PyramidAdaptedFeatureDetector
(
const
Ptr
<
FeatureDetector
>&
detector
,
int
levels
=
2
);
virtual
void
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
// todo read/write
virtual
void
read
(
const
FileNode
&
)
{}
virtual
void
write
(
FileStorage
&
)
const
{}
// TODO implement read/write
protected
:
virtual
void
detectImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
=
Mat
()
)
const
;
Ptr
<
FeatureDetector
>
detector
;
int
levels
;
};
...
...
@@ -1450,38 +1469,39 @@ CV_EXPORTS Ptr<FeatureDetector> createFeatureDetector( const string& detectorTyp
class
CV_EXPORTS
DescriptorExtractor
{
public
:
virtual
~
DescriptorExtractor
()
{}
virtual
~
DescriptorExtractor
();
/*
* Compute the descriptors for a set of keypoints in an image.
* Must be implemented by the subclass.
*
* image The image.
* keypoints The keypoints. Keypoints for which a descriptor cannot be computed are removed.
* descriptors
The
descriptors. Row i is the descriptor for keypoint i.
* 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.
*/
v
irtual
void
compute
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
=
0
;
v
oid
compute
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
;
/*
* Compute the descriptors for a keypoints collection detected in image collection.
*
*
imageCollection Image collection
.
*
pointCollection Keypoints collection. pointCollection[i] is keypoints detected in imageCollection[i]
.
* desc
Collection Descriptor collection. descCollection[i] is descriptors computed for pointCollection
[i].
*
images Image collection.
*
keypoints Input keypoints collection. keypoints[i] is keypoints detected in images[i]
.
*
Keypoints for which a descriptor cannot be computed are removed
.
* desc
riptors Descriptor collection. descriptors[i] is descriptors computed for keypoints
[i].
*/
void
compute
(
const
vector
<
Mat
>&
image
Collection
,
vector
<
vector
<
KeyPoint
>
>&
pointCollection
,
vector
<
Mat
>&
descCollection
)
const
;
void
compute
(
const
vector
<
Mat
>&
image
s
,
vector
<
vector
<
KeyPoint
>
>&
keypoints
,
vector
<
Mat
>&
descriptors
)
const
;
virtual
void
read
(
const
FileNode
&
)
{}
virtual
void
write
(
FileStorage
&
)
const
{}
virtual
void
read
(
const
FileNode
&
)
;
virtual
void
write
(
FileStorage
&
)
const
;
virtual
int
descriptorSize
()
const
=
0
;
virtual
int
descriptorType
()
const
=
0
;
protected
:
virtual
void
computeImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
=
0
;
/*
* Remove keypoints within border
_p
ixels of an image edge.
* Remove keypoints within border
P
ixels of an image edge.
*/
static
void
removeBorderKeypoints
(
vector
<
KeyPoint
>&
keypoints
,
Size
imageSize
,
int
border
Pixels
);
Size
imageSize
,
int
border
Size
);
};
/*
...
...
@@ -1490,21 +1510,23 @@ protected:
class
CV_EXPORTS
SiftDescriptorExtractor
:
public
DescriptorExtractor
{
public
:
SiftDescriptorExtractor
(
double
magnification
=
SIFT
::
DescriptorParams
::
GET_DEFAULT_MAGNIFICATION
(),
bool
isNormalize
=
true
,
bool
recalculateAngles
=
true
,
SiftDescriptorExtractor
(
const
SIFT
::
DescriptorParams
&
descriptorParams
=
SIFT
::
DescriptorParams
(),
const
SIFT
::
CommonParams
&
commonParams
=
SIFT
::
CommonParams
()
);
SiftDescriptorExtractor
(
double
magnification
,
bool
isNormalize
=
true
,
bool
recalculateAngles
=
true
,
int
nOctaves
=
SIFT
::
CommonParams
::
DEFAULT_NOCTAVES
,
int
nOctaveLayers
=
SIFT
::
CommonParams
::
DEFAULT_NOCTAVE_LAYERS
,
int
firstOctave
=
SIFT
::
CommonParams
::
DEFAULT_FIRST_OCTAVE
,
int
angleMode
=
SIFT
::
CommonParams
::
FIRST_ANGLE
);
virtual
void
compute
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
;
virtual
void
read
(
const
FileNode
&
fn
);
virtual
void
write
(
FileStorage
&
fs
)
const
;
virtual
int
descriptorSize
()
const
{
return
sift
.
descriptorSize
();
}
virtual
int
descriptorType
()
const
{
return
CV_32FC1
;
}
virtual
int
descriptorSize
()
const
;
virtual
int
descriptorType
()
const
;
protected
:
virtual
void
computeImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
;
SIFT
sift
;
};
...
...
@@ -1514,17 +1536,17 @@ protected:
class
CV_EXPORTS
SurfDescriptorExtractor
:
public
DescriptorExtractor
{
public
:
SurfDescriptorExtractor
(
int
nOctaves
=
4
,
int
nOctaveLayers
=
2
,
bool
extended
=
false
);
SurfDescriptorExtractor
(
int
nOctaves
=
4
,
int
nOctaveLayers
=
2
,
bool
extended
=
false
);
virtual
void
compute
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
;
virtual
void
read
(
const
FileNode
&
fn
);
virtual
void
write
(
FileStorage
&
fs
)
const
;
virtual
int
descriptorSize
()
const
{
return
surf
.
descriptorSize
();
}
virtual
int
descriptorType
()
const
{
return
CV_32FC1
;
}
virtual
int
descriptorSize
()
const
;
virtual
int
descriptorType
()
const
;
protected
:
virtual
void
computeImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
;
SURF
surf
;
};
...
...
@@ -1537,7 +1559,6 @@ class CV_EXPORTS CalonderDescriptorExtractor : public DescriptorExtractor
public
:
CalonderDescriptorExtractor
(
const
string
&
classifierFile
);
virtual
void
compute
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
;
virtual
void
read
(
const
FileNode
&
fn
);
virtual
void
write
(
FileStorage
&
fs
)
const
;
...
...
@@ -1545,6 +1566,8 @@ public:
virtual
int
descriptorType
()
const
{
return
DataType
<
T
>::
type
;
}
protected
:
virtual
void
computeImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
;
RTreeClassifier
classifier_
;
static
const
int
BORDER_SIZE
=
16
;
};
...
...
@@ -1556,23 +1579,24 @@ CalonderDescriptorExtractor<T>::CalonderDescriptorExtractor(const std::string& c
}
template
<
typename
T
>
void
CalonderDescriptorExtractor
<
T
>::
compute
(
const
cv
::
Mat
&
image
,
void
CalonderDescriptorExtractor
<
T
>::
compute
Impl
(
const
cv
::
Mat
&
image
,
std
::
vector
<
cv
::
KeyPoint
>&
keypoints
,
cv
::
Mat
&
descriptors
)
const
{
// Cannot compute descriptors for keypoints on the image border.
removeBorderKeypoints
(
keypoints
,
image
.
size
(),
BORDER_SIZE
);
// Cannot compute descriptors for keypoints on the image border.
removeBorderKeypoints
(
keypoints
,
image
.
size
(),
BORDER_SIZE
);
/// @todo Check 16-byte aligned
descriptors
.
create
(
keypoints
.
size
(),
classifier_
.
classes
(),
cv
::
DataType
<
T
>::
type
);
/// @todo Check 16-byte aligned
descriptors
.
create
(
keypoints
.
size
(),
classifier_
.
classes
(),
cv
::
DataType
<
T
>::
type
);
int
patchSize
=
RandomizedTree
::
PATCH_SIZE
;
int
offset
=
patchSize
/
2
;
for
(
size_t
i
=
0
;
i
<
keypoints
.
size
();
++
i
)
{
cv
::
Point2f
pt
=
keypoints
[
i
].
pt
;
IplImage
ipl
=
image
(
Rect
((
int
)(
pt
.
x
-
offset
),
(
int
)(
pt
.
y
-
offset
),
patchSize
,
patchSize
)
);
classifier_
.
getSignature
(
&
ipl
,
descriptors
.
ptr
<
T
>
(
i
));
}
int
patchSize
=
RandomizedTree
::
PATCH_SIZE
;
int
offset
=
patchSize
/
2
;
for
(
size_t
i
=
0
;
i
<
keypoints
.
size
();
++
i
)
{
cv
::
Point2f
pt
=
keypoints
[
i
].
pt
;
IplImage
ipl
=
image
(
Rect
((
int
)(
pt
.
x
-
offset
),
(
int
)(
pt
.
y
-
offset
),
patchSize
,
patchSize
)
);
classifier_
.
getSignature
(
&
ipl
,
descriptors
.
ptr
<
T
>
(
i
));
}
}
template
<
typename
T
>
...
...
@@ -1595,18 +1619,18 @@ void CalonderDescriptorExtractor<T>::write( FileStorage& ) const
class
CV_EXPORTS
OpponentColorDescriptorExtractor
:
public
DescriptorExtractor
{
public
:
OpponentColorDescriptorExtractor
(
const
Ptr
<
DescriptorExtractor
>&
dextractor
);
virtual
void
compute
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
;
OpponentColorDescriptorExtractor
(
const
Ptr
<
DescriptorExtractor
>&
descriptorExtractor
);
virtual
void
read
(
const
FileNode
&
);
virtual
void
write
(
FileStorage
&
)
const
;
virtual
int
descriptorSize
()
const
{
return
3
*
dextractor
->
descriptorSize
();
}
virtual
int
descriptorType
()
const
{
return
dextractor
->
descriptorType
();
}
virtual
int
descriptorSize
()
const
;
virtual
int
descriptorType
()
const
;
protected
:
Ptr
<
DescriptorExtractor
>
dextractor
;
virtual
void
computeImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
;
Ptr
<
DescriptorExtractor
>
descriptorExtractor
;
};
/*
...
...
@@ -1615,98 +1639,24 @@ protected:
class
CV_EXPORTS
BriefDescriptorExtractor
:
public
DescriptorExtractor
{
public
:
BriefDescriptorExtractor
(
int
bytes
=
32
);
static
const
int
PATCH_SIZE
=
48
;
static
const
int
KERNEL_SIZE
=
9
;
virtual
void
compute
(
const
Mat
&
image
,
std
::
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
;
BriefDescriptorExtractor
(
int
bytes
=
32
)
;
virtual
int
descriptorSize
()
const
{
return
bytes_
;
}
virtual
int
descriptorType
()
const
{
return
CV_8UC1
;
}
virtual
int
descriptorSize
()
const
;
virtual
int
descriptorType
()
const
;
/// @todo read and write for brief
//virtual void read(const FileNode& fn);
//virtual void write(FileStorage& fs) const;
/// @todo read and write for brief
protected
:
static
const
int
PATCH_SIZE
=
48
;
static
const
int
KERNEL_SIZE
=
9
;
int
bytes_
;
typedef
void
(
*
PixelTestFn
)(
const
Mat
&
,
const
std
::
vector
<
KeyPoint
>&
,
Mat
&
);
PixelTestFn
test_fn_
;
static
int
smoothedSum
(
const
Mat
&
sum
,
const
KeyPoint
&
pt
,
int
y
,
int
x
);
static
void
pixelTests16
(
const
Mat
&
sum
,
const
std
::
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
);
static
void
pixelTests32
(
const
Mat
&
sum
,
const
std
::
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
);
static
void
pixelTests64
(
const
Mat
&
sum
,
const
std
::
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
);
};
inline
int
BriefDescriptorExtractor
::
smoothedSum
(
const
Mat
&
sum
,
const
KeyPoint
&
pt
,
int
y
,
int
x
)
{
static
const
int
HALF_KERNEL
=
KERNEL_SIZE
/
2
;
int
img_y
=
(
int
)(
pt
.
pt
.
y
+
0.5
)
+
y
;
int
img_x
=
(
int
)(
pt
.
pt
.
x
+
0.5
)
+
x
;
return
sum
.
at
<
int
>
(
img_y
+
HALF_KERNEL
+
1
,
img_x
+
HALF_KERNEL
+
1
)
-
sum
.
at
<
int
>
(
img_y
+
HALF_KERNEL
+
1
,
img_x
-
HALF_KERNEL
)
-
sum
.
at
<
int
>
(
img_y
-
HALF_KERNEL
,
img_x
+
HALF_KERNEL
+
1
)
+
sum
.
at
<
int
>
(
img_y
-
HALF_KERNEL
,
img_x
-
HALF_KERNEL
);
}
struct
CV_EXPORTS
HammingLUT
{
typedef
unsigned
char
ValueType
;
typedef
int
ResultType
;
ResultType
operator
()(
const
unsigned
char
*
a
,
const
unsigned
char
*
b
,
int
size
)
const
{
ResultType
result
=
0
;
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
result
+=
byteBitsLookUp
(
a
[
i
]
^
b
[
i
]);
}
return
result
;
}
/** \brief given a byte, count the bits using a compile time generated look up table
* \param b the byte to count bits. The look up table has an entry for all
* values of b, where that entry is the number of bits.
* \return the number of bits in byte b
*/
static
unsigned
char
byteBitsLookUp
(
unsigned
char
b
);
};
virtual
void
computeImpl
(
const
Mat
&
image
,
std
::
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
;
#if __GNUC__
/// Hamming distance functor
/// @todo Variable-length version, maybe default size=0 and specialize
/// @todo Need to choose C/SSE4 at runtime, but amortize this at matcher level for efficiency...
//template<int size>
struct
Hamming
{
typedef
unsigned
char
ValueType
;
typedef
int
ResultType
;
typedef
void
(
*
PixelTestFn
)(
const
Mat
&
,
const
std
::
vector
<
KeyPoint
>&
,
Mat
&
);
ResultType
operator
()(
const
unsigned
char
*
a
,
const
unsigned
char
*
b
,
int
size
)
const
{
/// @todo Non-GCC-specific version
ResultType
result
=
0
;
for
(
int
i
=
0
;
i
<
size
;
i
+=
sizeof
(
unsigned
long
))
{
unsigned
long
a2
=
*
reinterpret_cast
<
const
unsigned
long
*>
(
a
+
i
);
unsigned
long
b2
=
*
reinterpret_cast
<
const
unsigned
long
*>
(
b
+
i
);
result
+=
__builtin_popcountl
(
a2
^
b2
);
}
return
result
;
}
int
bytes_
;
PixelTestFn
test_fn_
;
};
#else
typedef
HammingLUT
Hamming
;
#endif
CV_EXPORTS
Ptr
<
DescriptorExtractor
>
createDescriptorExtractor
(
const
string
&
descriptorExtractorType
);
...
...
@@ -1766,6 +1716,57 @@ struct CV_EXPORTS L1
}
};
/*
* Hamming distance (city block distance) functor
*/
struct
CV_EXPORTS
HammingLUT
{
typedef
unsigned
char
ValueType
;
typedef
int
ResultType
;
ResultType
operator
()(
const
unsigned
char
*
a
,
const
unsigned
char
*
b
,
int
size
)
const
{
ResultType
result
=
0
;
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
result
+=
byteBitsLookUp
(
a
[
i
]
^
b
[
i
]);
}
return
result
;
}
/** \brief given a byte, count the bits using a compile time generated look up table
* \param b the byte to count bits. The look up table has an entry for all
* values of b, where that entry is the number of bits.
* \return the number of bits in byte b
*/
static
unsigned
char
byteBitsLookUp
(
unsigned
char
b
);
};
#if __GNUC__
/// Hamming distance functor
/// @todo Variable-length version, maybe default size=0 and specialize
/// @todo Need to choose C/SSE4 at runtime, but amortize this at matcher level for efficiency...
struct
Hamming
{
typedef
unsigned
char
ValueType
;
typedef
int
ResultType
;
ResultType
operator
()(
const
unsigned
char
*
a
,
const
unsigned
char
*
b
,
int
size
)
const
{
/// @todo Non-GCC-specific version
ResultType
result
=
0
;
for
(
int
i
=
0
;
i
<
size
;
i
+=
sizeof
(
unsigned
long
))
{
unsigned
long
a2
=
*
reinterpret_cast
<
const
unsigned
long
*>
(
a
+
i
);
unsigned
long
b2
=
*
reinterpret_cast
<
const
unsigned
long
*>
(
b
+
i
);
result
+=
__builtin_popcountl
(
a2
^
b2
);
}
return
result
;
}
};
#else
typedef
HammingLUT
Hamming
;
#endif
/****************************************************************************************\
* DMatch *
...
...
@@ -1783,7 +1784,7 @@ struct CV_EXPORTS DMatch
int
queryIdx
;
// query descriptor index
int
trainIdx
;
// train descriptor index
int
imgIdx
;
// train image index
int
imgIdx
;
// train image index
float
distance
;
...
...
@@ -1803,111 +1804,126 @@ struct CV_EXPORTS DMatch
class
CV_EXPORTS
DescriptorMatcher
{
public
:
virtual
~
DescriptorMatcher
()
{}
/*
virtual
~
DescriptorMatcher
();
/*
* Add descriptors to train descriptor collection.
* desc
Collection Descriptors to add. Each descCollection[i] is
from one image.
* desc
riptors Descriptors to add. Each descriptors[i] is a descriptors set
from one image.
*/
virtual
void
add
(
const
vector
<
Mat
>&
desc
Collection
);
virtual
void
add
(
const
vector
<
Mat
>&
desc
riptors
);
/*
* Get
descriptor
collection.
* Get
train descriptors
collection.
*/
const
vector
<
Mat
>&
getTrainDesc
Collection
()
const
{
return
trainDescCollection
;
}
const
vector
<
Mat
>&
getTrainDesc
riptors
()
const
;
/*
* Clear
inner data (train image collection)
.
* Clear
train descriptors collection
.
*/
virtual
void
clear
();
virtual
bool
supportMask
()
=
0
;
/*
* Return true if there are not train descriptors in collection.
*/
bool
empty
()
const
;
/*
* Return true if the matcher supports mask in match methods.
*/
virtual
bool
isMaskSupported
()
const
=
0
;
/*
* Train matcher (e.g. train flann index)
* Train matcher (e.g. train flann index).
* In all methods to match the method train() is run every time before matching.
* Some descriptor matchers (e.g. BruteForceMatcher) have empty implementation
* of this method, other matchers realy train their inner structures
* (e.g. FlannBasedMatcher trains flann::Index). So nonempty implementation
* of train() should check the class object state and do traing/retraining
* only if the state requires that (e.g. FlannBasedMatcher trains flann::Index
* if it has not trained yet or if new descriptors have been added to the train
* collection).
*/
virtual
void
train
()
=
0
;
virtual
void
train
();
/*
* Group of methods to match descriptors from image pair.
* Method train() is run in this methods.
*/
// Find one best match for each query descriptor (if mask is empty).
void
match
(
const
Mat
&
queryDescs
,
const
Mat
&
trainDescs
,
vector
<
DMatch
>&
matches
,
const
Mat
&
mask
=
Mat
()
)
const
;
// Find knn best matches for each query descriptor (in increasing order of distances).
// compactResult is used when mask is not empty. If compactResult is false matches vector will have the same size as queryDescs rows.
// If compactResult is true matches vector will not contain matches for fully masked out query descriptors.
void
knnMatch
(
const
Mat
&
queryDescs
,
const
Mat
&
trainDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
void
match
(
const
Mat
&
queryDescriptors
,
const
Mat
&
trainDescriptors
,
vector
<
DMatch
>&
matches
,
const
Mat
&
mask
=
Mat
()
)
const
;
// Find k best matches for each query descriptor (in increasing order of distances).
// compactResult is used when mask is not empty. If compactResult is false matches
// vector will have the same size as queryDescriptors rows. If compactResult is true
// matches vector will not contain matches for fully masked out query descriptors.
void
knnMatch
(
const
Mat
&
queryDescriptors
,
const
Mat
&
trainDescriptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
k
,
const
Mat
&
mask
=
Mat
(),
bool
compactResult
=
false
)
const
;
// Find best matches for each query descriptor which have distance less than maxDistance (in increasing order of distances).
void
radiusMatch
(
const
Mat
&
queryDescs
,
const
Mat
&
trainDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
// Find best matches for each query descriptor which have distance less than
// maxDistance (in increasing order of distances).
void
radiusMatch
(
const
Mat
&
queryDescriptors
,
const
Mat
&
trainDescriptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
Mat
&
mask
=
Mat
(),
bool
compactResult
=
false
)
const
;
/*
* Group of methods to match descriptors from one image to image set.
* See description of similar methods for matching image pair above.
*/
void
match
(
const
Mat
&
queryDescs
,
vector
<
DMatch
>&
matches
,
void
match
(
const
Mat
&
queryDesc
riptor
s
,
vector
<
DMatch
>&
matches
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
()
);
void
knnMatch
(
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
void
knnMatch
(
const
Mat
&
queryDescriptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
k
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
(),
bool
compactResult
=
false
);
void
radiusMatch
(
const
Mat
&
queryDescriptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
(),
bool
compactResult
=
false
);
void
radiusMatch
(
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
(),
bool
compactResult
=
false
);
// Reads matcher object from a file node
virtual
void
read
(
const
FileNode
&
)
{}
virtual
void
read
(
const
FileNode
&
);
// Writes matcher object to a file storage
virtual
void
write
(
FileStorage
&
)
const
{}
virtual
void
write
(
FileStorage
&
)
const
;
// Clone the matcher. If emptyTrainData is false the method create deep copy of the object, i.e. copies
// both parameters and train data. If emptyTrainData is true the method create object copy with current parameters
// but with empty train data.
virtual
Ptr
<
DescriptorMatcher
>
clone
(
bool
emptyTrainData
=
false
)
const
=
0
;
protected
:
/*
* Class to work with descriptors from several images as with one merged matrix.
* It is used e.g. in FlannBasedMatcher
* It is used e.g. in FlannBasedMatcher
.
*/
class
CV_EXPORTS
DescriptorCollection
{
public
:
DescriptorCollection
()
{}
virtual
~
DescriptorCollection
()
{}
DescriptorCollection
();
DescriptorCollection
(
const
DescriptorCollection
&
collection
);
virtual
~
DescriptorCollection
();
//
descCollection will be merged to dmatrix here
void
set
(
const
vector
<
Mat
>&
desc
Collection
);
//
Vector of matrices "descriptors" will be merged to one matrix "mergedDescriptors" here.
void
set
(
const
vector
<
Mat
>&
desc
riptors
);
virtual
void
clear
();
const
Mat
&
getDescriptors
()
const
{
return
dmatrix
;
}
const
Mat
&
getDescriptors
()
const
;
const
Mat
getDescriptor
(
int
imgIdx
,
int
localDescIdx
)
const
;
const
Mat
getDescriptor
(
int
globalDescIdx
)
const
;
void
getLocalIdx
(
int
globalDescIdx
,
int
&
imgIdx
,
int
&
localDescIdx
)
const
;
int
size
()
const
{
return
dmatrix
.
rows
;
}
int
size
()
const
;
protected
:
Mat
dmatrix
;
Mat
mergedDescriptors
;
vector
<
int
>
startIdxs
;
};
// create matcher clone with current parameters but with empty data
virtual
Ptr
<
DescriptorMatcher
>
cloneWithoutData
()
const
=
0
;
virtual
void
knnMatchImpl
(
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
=
0
;
virtual
void
radiusMatchImpl
(
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
=
0
;
// In fact the matching is implemented only by the following two methods. These methods suppose
// that the class object has been trained already. Public match methods call these methods
// after calling train().
virtual
void
knnMatchImpl
(
const
Mat
&
queryDescriptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
k
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
(),
bool
compactResult
=
false
)
=
0
;
virtual
void
radiusMatchImpl
(
const
Mat
&
queryDescriptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
(),
bool
compactResult
=
false
)
=
0
;
static
bool
possibleMatch
(
const
Mat
&
mask
,
int
index_1
,
int
index_2
)
{
return
mask
.
empty
()
||
mask
.
at
<
uchar
>
(
index_1
,
index_2
);
}
static
bool
maskedOut
(
const
vector
<
Mat
>&
masks
,
int
queryDescIdx
)
{
size_t
outCount
=
0
;
for
(
size_t
i
=
0
;
i
<
masks
.
size
();
i
++
)
{
if
(
!
masks
[
i
].
empty
()
&&
(
countNonZero
(
masks
[
i
].
row
(
queryDescIdx
))
==
0
)
)
outCount
++
;
}
static
bool
isPossibleMatch
(
const
Mat
&
mask
,
int
queryIdx
,
int
trainIdx
);
static
bool
isMaskedOut
(
const
vector
<
Mat
>&
masks
,
int
queryIdx
);
return
!
masks
.
empty
()
&&
outCount
==
masks
.
size
()
;
}
static
Mat
clone_op
(
Mat
m
)
{
return
m
.
clone
();
}
void
checkMasks
(
const
vector
<
Mat
>&
masks
,
int
queryDescriptorsCount
)
const
;
// Collection of descriptors from train images.
vector
<
Mat
>
trainDescCollection
;
};
...
...
@@ -1927,64 +1943,78 @@ public:
BruteForceMatcher
(
Distance
d
=
Distance
()
)
:
distance
(
d
)
{}
virtual
~
BruteForceMatcher
()
{}
virtual
void
train
()
{}
virtual
bool
supportMask
()
{
return
true
;
}
virtual
bool
isMaskSupported
()
const
{
return
true
;
}
virtual
Ptr
<
DescriptorMatcher
>
clone
(
bool
emptyTrainData
=
false
)
const
;
protected
:
virtual
Ptr
<
DescriptorMatcher
>
cloneWithoutData
()
const
{
return
new
BruteForceMatcher
(
distance
);
}
virtual
void
knnMatchImpl
(
const
Mat
&
queryDescriptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
k
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
(),
bool
compactResult
=
false
);
virtual
void
radiusMatchImpl
(
const
Mat
&
queryDescriptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
(),
bool
compactResult
=
false
);
virtual
void
knnMatchImpl
(
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
virtual
void
radiusMatchImpl
(
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
Distance
distance
;
private
:
/*
* Next two methods are used to implement specialization
* Next two methods are used to implement specialization
.
*/
static
void
bf
KnnMatchImpl
(
BruteForceMatcher
<
Distance
>&
matcher
,
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
static
void
bf
RadiusMatchImpl
(
BruteForceMatcher
<
Distance
>&
matcher
,
const
Mat
&
queryDesc
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
static
void
common
KnnMatchImpl
(
BruteForceMatcher
<
Distance
>&
matcher
,
const
Mat
&
queryDescriptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
k
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
static
void
common
RadiusMatchImpl
(
BruteForceMatcher
<
Distance
>&
matcher
,
const
Mat
&
queryDescriptor
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
};
template
<
class
Distance
>
void
BruteForceMatcher
<
Distance
>::
knnMatchImpl
(
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
Ptr
<
DescriptorMatcher
>
BruteForceMatcher
<
Distance
>::
clone
(
bool
emptyTrainData
)
const
{
BruteForceMatcher
*
matcher
=
new
BruteForceMatcher
(
distance
);
if
(
!
emptyTrainData
)
{
transform
(
trainDescCollection
.
begin
(),
trainDescCollection
.
end
(),
matcher
->
trainDescCollection
.
begin
(),
clone_op
);
}
return
matcher
;
}
template
<
class
Distance
>
void
BruteForceMatcher
<
Distance
>::
knnMatchImpl
(
const
Mat
&
queryDescriptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
k
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
{
bfKnnMatchImpl
(
*
this
,
queryDescs
,
matches
,
knn
,
masks
,
compactResult
);
commonKnnMatchImpl
(
*
this
,
queryDescriptors
,
matches
,
k
,
masks
,
compactResult
);
}
template
<
class
Distance
>
void
BruteForceMatcher
<
Distance
>::
radiusMatchImpl
(
const
Mat
&
queryDesc
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
void
BruteForceMatcher
<
Distance
>::
radiusMatchImpl
(
const
Mat
&
queryDesc
riptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
{
bfRadiusMatchImpl
(
*
this
,
queryDesc
s
,
matches
,
maxDistance
,
masks
,
compactResult
);
commonRadiusMatchImpl
(
*
this
,
queryDescriptor
s
,
matches
,
maxDistance
,
masks
,
compactResult
);
}
template
<
class
Distance
>
inline
void
BruteForceMatcher
<
Distance
>::
bf
KnnMatchImpl
(
BruteForceMatcher
<
Distance
>&
matcher
,
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
inline
void
BruteForceMatcher
<
Distance
>::
common
KnnMatchImpl
(
BruteForceMatcher
<
Distance
>&
matcher
,
const
Mat
&
queryDesc
riptor
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
{
typedef
typename
Distance
::
ValueType
ValueType
;
typedef
typename
Distance
::
ResultType
DistanceType
;
CV_Assert
(
DataType
<
ValueType
>::
type
==
queryDescs
.
type
()
||
queryDescs
.
empty
()
);
CV_Assert
(
masks
.
empty
()
||
masks
.
size
()
==
matcher
.
trainDescCollection
.
size
()
);
int
dimension
=
queryDescs
.
cols
;
matches
.
reserve
(
queryDescs
.
rows
);
CV_DbgAssert
(
!
queryDescriptors
.
empty
()
);
CV_Assert
(
DataType
<
ValueType
>::
type
==
queryDescriptors
.
type
()
);
int
dimension
=
queryDescriptors
.
cols
;
matches
.
reserve
(
queryDescriptors
.
rows
);
size_t
imgCount
=
matcher
.
trainDescCollection
.
size
();
vector
<
Mat
>
allDists
(
imgCount
);
// distances between one query descriptor and all train descriptors
for
(
size_t
i
=
0
;
i
<
imgCount
;
i
++
)
allDists
[
i
]
=
Mat
(
1
,
matcher
.
trainDescCollection
[
i
].
rows
,
DataType
<
DistanceType
>::
type
);
if
(
matcher
.
trainDescCollection
[
i
].
rows
)
allDists
[
i
]
=
Mat
(
1
,
matcher
.
trainDescCollection
[
i
].
rows
,
DataType
<
DistanceType
>::
type
);
for
(
int
qIdx
=
0
;
qIdx
<
queryDescs
.
rows
;
qIdx
++
)
for
(
int
qIdx
=
0
;
qIdx
<
queryDesc
riptor
s
.
rows
;
qIdx
++
)
{
if
(
matcher
.
m
askedOut
(
masks
,
qIdx
)
)
if
(
matcher
.
isM
askedOut
(
masks
,
qIdx
)
)
{
if
(
!
compactResult
)
// push empty vector
matches
.
push_back
(
vector
<
DMatch
>
()
);
...
...
@@ -1994,17 +2024,15 @@ inline void BruteForceMatcher<Distance>::bfKnnMatchImpl( BruteForceMatcher<Dista
// 1. compute distances between i-th query descriptor and all train descriptors
for
(
size_t
iIdx
=
0
;
iIdx
<
imgCount
;
iIdx
++
)
{
CV_Assert
(
masks
.
empty
()
||
masks
[
iIdx
].
empty
()
||
(
masks
[
iIdx
].
rows
==
queryDescs
.
rows
&&
masks
[
iIdx
].
cols
==
matcher
.
trainDescCollection
[
iIdx
].
rows
&&
masks
[
iIdx
].
type
()
==
CV_8UC1
)
);
CV_Assert
(
DataType
<
ValueType
>::
type
==
matcher
.
trainDescCollection
[
iIdx
].
type
()
||
matcher
.
trainDescCollection
[
iIdx
].
empty
()
);
CV_Assert
(
queryDescs
.
cols
==
matcher
.
trainDescCollection
[
iIdx
].
cols
);
CV_Assert
(
queryDescriptors
.
cols
==
matcher
.
trainDescCollection
[
iIdx
].
cols
||
matcher
.
trainDescCollection
[
iIdx
].
empty
()
);
const
ValueType
*
d1
=
(
const
ValueType
*
)(
queryDesc
s
.
data
+
queryDesc
s
.
step
*
qIdx
);
const
ValueType
*
d1
=
(
const
ValueType
*
)(
queryDesc
riptors
.
data
+
queryDescriptor
s
.
step
*
qIdx
);
allDists
[
iIdx
].
setTo
(
Scalar
::
all
(
std
::
numeric_limits
<
DistanceType
>::
max
())
);
for
(
int
tIdx
=
0
;
tIdx
<
matcher
.
trainDescCollection
[
iIdx
].
rows
;
tIdx
++
)
{
if
(
masks
.
empty
()
||
matcher
.
p
ossibleMatch
(
masks
[
iIdx
],
qIdx
,
tIdx
)
)
if
(
masks
.
empty
()
||
matcher
.
isP
ossibleMatch
(
masks
[
iIdx
],
qIdx
,
tIdx
)
)
{
const
ValueType
*
d2
=
(
const
ValueType
*
)(
matcher
.
trainDescCollection
[
iIdx
].
data
+
matcher
.
trainDescCollection
[
iIdx
].
step
*
tIdx
);
...
...
@@ -2013,20 +2041,23 @@ inline void BruteForceMatcher<Distance>::bfKnnMatchImpl( BruteForceMatcher<Dista
}
}
// 2. choose k
nn
nearest matches for query[i]
// 2. choose k nearest matches for query[i]
matches
.
push_back
(
vector
<
DMatch
>
()
);
vector
<
vector
<
DMatch
>
>::
reverse_iterator
curMatches
=
matches
.
rbegin
();
for
(
int
k
=
0
;
k
<
knn
;
k
++
)
{
DMatch
bestMatch
;
bestMatch
.
distance
=
std
::
numeric_limits
<
DistanceType
>::
max
();
bestMatch
.
distance
=
std
::
numeric_limits
<
float
>::
max
();
for
(
size_t
iIdx
=
0
;
iIdx
<
imgCount
;
iIdx
++
)
{
double
minVal
;
Point
minLoc
;
minMaxLoc
(
allDists
[
iIdx
],
&
minVal
,
0
,
&
minLoc
,
0
);
if
(
minVal
<
bestMatch
.
distance
)
bestMatch
=
DMatch
(
qIdx
,
minLoc
.
x
,
iIdx
,
minVal
);
if
(
!
allDists
[
iIdx
].
empty
()
)
{
double
minVal
;
Point
minLoc
;
minMaxLoc
(
allDists
[
iIdx
],
&
minVal
,
0
,
&
minLoc
,
0
);
if
(
minVal
<
bestMatch
.
distance
)
bestMatch
=
DMatch
(
qIdx
,
minLoc
.
x
,
iIdx
,
(
float
)
minVal
);
}
}
if
(
bestMatch
.
trainIdx
==
-
1
)
break
;
...
...
@@ -2041,22 +2072,22 @@ inline void BruteForceMatcher<Distance>::bfKnnMatchImpl( BruteForceMatcher<Dista
}
template
<
class
Distance
>
inline
void
BruteForceMatcher
<
Distance
>::
bf
RadiusMatchImpl
(
BruteForceMatcher
<
Distance
>&
matcher
,
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
inline
void
BruteForceMatcher
<
Distance
>::
common
RadiusMatchImpl
(
BruteForceMatcher
<
Distance
>&
matcher
,
const
Mat
&
queryDesc
riptor
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
{
typedef
typename
Distance
::
ValueType
ValueType
;
typedef
typename
Distance
::
ResultType
DistanceType
;
CV_Assert
(
DataType
<
ValueType
>::
type
==
queryDescs
.
type
()
||
queryDesc
s
.
empty
()
);
CV_Assert
(
masks
.
empty
()
||
masks
.
size
()
==
matcher
.
trainDescCollection
.
siz
e
()
);
int
dimension
=
queryDescs
.
cols
;
matches
.
reserve
(
queryDescs
.
rows
);
CV_DbgAssert
(
!
queryDescriptor
s
.
empty
()
);
CV_Assert
(
DataType
<
ValueType
>::
type
==
queryDescriptors
.
typ
e
()
);
int
dimension
=
queryDesc
riptor
s
.
cols
;
matches
.
reserve
(
queryDesc
riptor
s
.
rows
);
size_t
imgCount
=
matcher
.
trainDescCollection
.
size
();
for
(
int
qIdx
=
0
;
qIdx
<
queryDescs
.
rows
;
qIdx
++
)
for
(
int
qIdx
=
0
;
qIdx
<
queryDesc
riptor
s
.
rows
;
qIdx
++
)
{
if
(
matcher
.
m
askedOut
(
masks
,
qIdx
)
)
if
(
matcher
.
isM
askedOut
(
masks
,
qIdx
)
)
{
if
(
!
compactResult
)
// push empty vector
matches
.
push_back
(
vector
<
DMatch
>
()
);
...
...
@@ -2067,23 +2098,21 @@ inline void BruteForceMatcher<Distance>::bfRadiusMatchImpl( BruteForceMatcher<Di
vector
<
vector
<
DMatch
>
>::
reverse_iterator
curMatches
=
matches
.
rbegin
();
for
(
size_t
iIdx
=
0
;
iIdx
<
imgCount
;
iIdx
++
)
{
CV_Assert
(
masks
.
empty
()
||
masks
[
iIdx
].
empty
()
||
(
masks
[
iIdx
].
rows
==
queryDescs
.
rows
&&
masks
[
iIdx
].
cols
==
matcher
.
trainDescCollection
[
iIdx
].
rows
&&
masks
[
iIdx
].
type
()
==
CV_8UC1
)
);
CV_Assert
(
DataType
<
ValueType
>::
type
==
matcher
.
trainDescCollection
[
iIdx
].
type
()
||
matcher
.
trainDescCollection
[
iIdx
].
empty
()
);
CV_Assert
(
queryDescs
.
cols
==
matcher
.
trainDescCollection
[
iIdx
].
cols
);
CV_Assert
(
queryDescriptors
.
cols
==
matcher
.
trainDescCollection
[
iIdx
].
cols
||
matcher
.
trainDescCollection
[
iIdx
].
empty
()
);
const
ValueType
*
d1
=
(
const
ValueType
*
)(
queryDesc
s
.
data
+
queryDesc
s
.
step
*
qIdx
);
const
ValueType
*
d1
=
(
const
ValueType
*
)(
queryDesc
riptors
.
data
+
queryDescriptor
s
.
step
*
qIdx
);
for
(
int
tIdx
=
0
;
tIdx
<
matcher
.
trainDescCollection
[
iIdx
].
rows
;
tIdx
++
)
{
if
(
masks
.
empty
()
||
matcher
.
p
ossibleMatch
(
masks
[
iIdx
],
qIdx
,
tIdx
)
)
if
(
masks
.
empty
()
||
matcher
.
isP
ossibleMatch
(
masks
[
iIdx
],
qIdx
,
tIdx
)
)
{
const
ValueType
*
d2
=
(
const
ValueType
*
)(
matcher
.
trainDescCollection
[
iIdx
].
data
+
matcher
.
trainDescCollection
[
iIdx
].
step
*
tIdx
);
DistanceType
d
=
matcher
.
distance
(
d1
,
d2
,
dimension
);
if
(
d
<
maxDistance
)
curMatches
->
push_back
(
DMatch
(
qIdx
,
tIdx
,
iIdx
,
d
)
);
curMatches
->
push_back
(
DMatch
(
qIdx
,
tIdx
,
iIdx
,
(
float
)
d
)
);
}
}
}
...
...
@@ -2096,11 +2125,11 @@ inline void BruteForceMatcher<Distance>::bfRadiusMatchImpl( BruteForceMatcher<Di
* BruteForceMatcher L2 specialization
*/
template
<>
void
BruteForceMatcher
<
L2
<
float
>
>::
knnMatchImpl
(
const
Mat
&
queryDesc
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
void
BruteForceMatcher
<
L2
<
float
>
>::
knnMatchImpl
(
const
Mat
&
queryDesc
riptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
k
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
template
<>
void
BruteForceMatcher
<
L2
<
float
>
>::
radiusMatchImpl
(
const
Mat
&
queryDesc
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
void
BruteForceMatcher
<
L2
<
float
>
>::
radiusMatchImpl
(
const
Mat
&
queryDesc
riptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
/*
* Flann based matcher
...
...
@@ -2108,26 +2137,27 @@ void BruteForceMatcher<L2<float> >::radiusMatchImpl( const Mat& queryDescs, vect
class
CV_EXPORTS
FlannBasedMatcher
:
public
DescriptorMatcher
{
public
:
FlannBasedMatcher
(
const
Ptr
<
flann
::
IndexParams
>&
_
indexParams
=
new
flann
::
KDTreeIndexParams
(),
const
Ptr
<
flann
::
SearchParams
>&
_
searchParams
=
new
flann
::
SearchParams
()
);
FlannBasedMatcher
(
const
Ptr
<
flann
::
IndexParams
>&
indexParams
=
new
flann
::
KDTreeIndexParams
(),
const
Ptr
<
flann
::
SearchParams
>&
searchParams
=
new
flann
::
SearchParams
()
);
virtual
void
add
(
const
vector
<
Mat
>&
desc
Collection
);
virtual
void
add
(
const
vector
<
Mat
>&
desc
riptors
);
virtual
void
clear
();
virtual
void
train
();
virtual
bool
supportMask
()
{
return
false
;
}
protected
:
virtual
Ptr
<
DescriptorMatcher
>
cloneWithoutData
()
const
{
return
new
FlannBasedMatcher
(
indexParams
,
searchParams
);
}
// masks is ignored (unsupported)
virtual
void
knnMatchImpl
(
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
virtual
void
radiusMatchImpl
(
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
virtual
bool
isMaskSupported
()
const
;
virtual
Ptr
<
DescriptorMatcher
>
clone
(
bool
emptyTrainData
=
false
)
const
;
static
void
convertToDMatches
(
const
DescriptorCollection
&
collection
,
const
Mat
&
indices
,
const
Mat
&
dists
,
protected
:
static
void
convertToDMatches
(
const
DescriptorCollection
&
descriptors
,
const
Mat
&
indices
,
const
Mat
&
distances
,
vector
<
vector
<
DMatch
>
>&
matches
);
virtual
void
knnMatchImpl
(
const
Mat
&
queryDescriptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
k
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
(),
bool
compactResult
=
false
);
virtual
void
radiusMatchImpl
(
const
Mat
&
queryDescriptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
(),
bool
compactResult
=
false
);
Ptr
<
flann
::
IndexParams
>
indexParams
;
Ptr
<
flann
::
SearchParams
>
searchParams
;
Ptr
<
flann
::
Index
>
flannIndex
;
...
...
@@ -2151,81 +2181,106 @@ typedef GenericDescriptorMatcher GenericDescriptorMatch;
class
CV_EXPORTS
GenericDescriptorMatcher
{
public
:
GenericDescriptorMatcher
()
{}
virtual
~
GenericDescriptorMatcher
()
{}
GenericDescriptorMatcher
()
;
virtual
~
GenericDescriptorMatcher
()
;
/*
* Set train collection: images and keypoints from them.
* imgCollection Image collection.
* pointCollection Keypoint collection detected on imgCollection.
* Add train collection: images and keypoints from them.
* images A set of train images.
* ketpoints Keypoint collection that have been detected on train images.
*
* Keypoints for which a descriptor cannot be computed are removed. Such keypoints
* must be filtered in this method befor adding keypoints to train collection "trainPointCollection".
* If inheritor class need perform such prefiltering the method add() must be overloaded.
* In the other class methods programmer has access to the train keypoints by a constant link.
*/
virtual
void
add
(
const
vector
<
Mat
>&
im
gCollection
,
vector
<
vector
<
KeyPoint
>
>&
pointCollection
);
virtual
void
add
(
const
vector
<
Mat
>&
im
ages
,
vector
<
vector
<
KeyPoint
>
>&
keypoints
);
const
vector
<
Mat
>&
getTrainIm
gCollection
()
const
{
return
trainPointCollection
.
getImages
();
}
const
vector
<
vector
<
KeyPoint
>
>&
getTrain
PointCollection
()
const
{
return
trainPointCollection
.
getKeypoints
();
}
const
vector
<
Mat
>&
getTrainIm
ages
()
const
;
const
vector
<
vector
<
KeyPoint
>
>&
getTrain
Keypoints
()
const
;
// Clears keypoints storing in collection
/*
* Clear images and keypoints storing in train collection.
*/
virtual
void
clear
();
virtual
void
train
()
=
0
;
virtual
bool
supportMask
()
=
0
;
/*
* Returns true if matcher supports mask to match descriptors.
*/
virtual
bool
isMaskSupported
()
=
0
;
/*
* Train some inner structures (e.g. flann index or decision trees).
* train() methods is run every time in matching methods. So the method implementation
* should has a check whether these inner structures need be trained/retrained or not.
*/
virtual
void
train
();
/*
* Classifies query keypoints.
* queryImage The query image
* query
P
oints Keypoints from the query image
* query
Keyp
oints Keypoints from the query image
* trainImage The train image
* train
P
oints Keypoints from the train image
* train
Keyp
oints Keypoints from the train image
*/
// Classify keypoints from query image under one train image.
virtual
void
classify
(
const
Mat
&
queryImage
,
vector
<
KeyPoint
>&
query
P
oints
,
const
Mat
&
trainImage
,
vector
<
KeyPoint
>&
train
P
oints
)
const
;
virtual
void
classify
(
const
Mat
&
queryImage
,
vector
<
KeyPoint
>&
query
Keyp
oints
,
const
Mat
&
trainImage
,
vector
<
KeyPoint
>&
train
Keyp
oints
)
const
;
// Classify keypoints from query image under train image collection.
virtual
void
classify
(
const
Mat
&
queryImage
,
vector
<
KeyPoint
>&
query
P
oints
);
virtual
void
classify
(
const
Mat
&
queryImage
,
vector
<
KeyPoint
>&
query
Keyp
oints
);
/*
* Group of methods to match keypoints from image pair.
* Keypoints for which a descriptor cannot be computed are removed.
* train() method is called here.
*/
// Find one best match for each query descriptor (if mask is empty).
void
match
(
const
Mat
&
queryIm
g
,
vector
<
KeyPoint
>&
queryP
oints
,
const
Mat
&
trainIm
g
,
vector
<
KeyPoint
>&
trainP
oints
,
void
match
(
const
Mat
&
queryIm
age
,
vector
<
KeyPoint
>&
queryKeyp
oints
,
const
Mat
&
trainIm
age
,
vector
<
KeyPoint
>&
trainKeyp
oints
,
vector
<
DMatch
>&
matches
,
const
Mat
&
mask
=
Mat
()
)
const
;
// Find knn best matches for each query keypoint (in increasing order of distances).
// compactResult is used when mask is not empty. If compactResult is false matches vector will have the same size as queryDescs rows.
// Find k best matches for each query keypoint (in increasing order of distances).
// compactResult is used when mask is not empty. If compactResult is false matches
// vector will have the same size as queryDescriptors rows.
// If compactResult is true matches vector will not contain matches for fully masked out query descriptors.
void
knnMatch
(
const
Mat
&
queryImg
,
vector
<
KeyPoint
>&
queryPoints
,
const
Mat
&
trainImg
,
vector
<
KeyPoint
>&
trainPoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
const
Mat
&
mask
=
Mat
(),
bool
compactResult
=
false
)
const
;
void
knnMatch
(
const
Mat
&
queryImage
,
vector
<
KeyPoint
>&
queryKeypoints
,
const
Mat
&
trainImage
,
vector
<
KeyPoint
>&
trainKeypoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
k
,
const
Mat
&
mask
=
Mat
(),
bool
compactResult
=
false
)
const
;
// Find best matches for each query descriptor which have distance less than maxDistance (in increasing order of distances).
void
radiusMatch
(
const
Mat
&
queryImg
,
vector
<
KeyPoint
>&
queryPoints
,
const
Mat
&
trainImg
,
vector
<
KeyPoint
>&
trainPoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
Mat
&
mask
=
Mat
(),
bool
compactResult
=
false
)
const
;
void
radiusMatch
(
const
Mat
&
queryImage
,
vector
<
KeyPoint
>&
queryKeypoints
,
const
Mat
&
trainImage
,
vector
<
KeyPoint
>&
trainKeypoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
Mat
&
mask
=
Mat
(),
bool
compactResult
=
false
)
const
;
/*
* Group of methods to match keypoints from one image to image set.
* See description of similar methods for matching image pair above.
*/
void
match
(
const
Mat
&
queryIm
g
,
vector
<
KeyPoint
>&
queryP
oints
,
void
match
(
const
Mat
&
queryIm
age
,
vector
<
KeyPoint
>&
queryKeyp
oints
,
vector
<
DMatch
>&
matches
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
()
);
void
knnMatch
(
const
Mat
&
queryImg
,
vector
<
KeyPoint
>&
queryPoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
(),
bool
compactResult
=
false
);
void
radiusMatch
(
const
Mat
&
queryImg
,
vector
<
KeyPoint
>&
queryPoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
(),
bool
compactResult
=
false
);
void
knnMatch
(
const
Mat
&
queryImage
,
vector
<
KeyPoint
>&
queryKeypoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
k
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
(),
bool
compactResult
=
false
);
void
radiusMatch
(
const
Mat
&
queryImage
,
vector
<
KeyPoint
>&
queryKeypoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
=
vector
<
Mat
>
(),
bool
compactResult
=
false
);
// Reads matcher object from a file node
virtual
void
read
(
const
FileNode
&
)
{}
virtual
void
read
(
const
FileNode
&
);
// Writes matcher object to a file storage
virtual
void
write
(
FileStorage
&
)
const
{}
virtual
void
write
(
FileStorage
&
)
const
;
protected
:
virtual
Ptr
<
GenericDescriptorMatcher
>
createEmptyMatcherCopy
()
const
=
0
;
// Clone the matcher. If emptyTrainData is false the method create deep copy of the object, i.e. copies
// both parameters and train data. If emptyTrainData is true the method create object copy with current parameters
// but with empty train data.
virtual
Ptr
<
GenericDescriptorMatcher
>
clone
(
bool
emptyTrainData
=
false
)
const
=
0
;
virtual
void
knnMatchImpl
(
const
Mat
&
queryImg
,
vector
<
KeyPoint
>&
queryPoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
protected
:
// In fact the matching is implemented only by the following two methods. These methods suppose
// that the class object has been trained already. Public match methods call these methods
// after calling train().
virtual
void
knnMatchImpl
(
const
Mat
&
queryImage
,
vector
<
KeyPoint
>&
queryKeypoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
k
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
=
0
;
virtual
void
radiusMatchImpl
(
const
Mat
&
queryIm
g
,
vector
<
KeyPoint
>&
queryP
oints
,
virtual
void
radiusMatchImpl
(
const
Mat
&
queryIm
age
,
vector
<
KeyPoint
>&
queryKeyp
oints
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
=
0
;
/*
...
...
@@ -2234,32 +2289,34 @@ protected:
class
CV_EXPORTS
KeyPointCollection
{
public
:
KeyPointCollection
()
:
size
(
0
)
{}
void
add
(
const
vector
<
Mat
>&
_images
,
const
vector
<
vector
<
KeyPoint
>
>&
_points
);
KeyPointCollection
();
KeyPointCollection
(
const
KeyPointCollection
&
collection
);
void
add
(
const
vector
<
Mat
>&
images
,
const
vector
<
vector
<
KeyPoint
>
>&
keypoints
);
void
clear
();
// Returns the total number of keypoints in the collection
size_t
pointCount
()
const
{
return
size
;
}
size_t
imageCount
()
const
{
return
images
.
size
();
}
size_t
keypointCount
()
const
;
size_t
imageCount
()
const
;
const
vector
<
vector
<
KeyPoint
>
>&
getKeypoints
()
const
{
return
points
;
}
const
vector
<
KeyPoint
>&
getKeypoints
(
int
imgIdx
)
const
{
CV_Assert
(
imgIdx
<
(
int
)
imageCount
()
);
return
points
[
imgIdx
];
}
const
vector
<
vector
<
KeyPoint
>
>&
getKeypoints
()
const
;
const
vector
<
KeyPoint
>&
getKeypoints
(
int
imgIdx
)
const
;
const
KeyPoint
&
getKeyPoint
(
int
imgIdx
,
int
localPointIdx
)
const
;
const
KeyPoint
&
getKeyPoint
(
int
globalPointIdx
)
const
;
void
getLocalIdx
(
int
globalPointIdx
,
int
&
imgIdx
,
int
&
localPointIdx
)
const
;
const
vector
<
Mat
>&
getImages
()
const
{
return
images
;
}
const
Mat
&
getImage
(
int
imgIdx
)
const
{
CV_Assert
(
imgIdx
<
(
int
)
imageCount
()
);
return
images
[
imgIdx
];
}
const
vector
<
Mat
>&
getImages
()
const
;
const
Mat
&
getImage
(
int
imgIdx
)
const
;
protected
:
int
size
;
int
pointCount
;
vector
<
Mat
>
images
;
vector
<
vector
<
KeyPoint
>
>
points
;
// global indices of the first points in each image,
// startIndices.size() = points.size()
vector
<
vector
<
KeyPoint
>
>
keypoints
;
// global indices of the first points in each image, startIndices.size() = keypoints.size()
vector
<
int
>
startIndices
;
private
:
static
Mat
clone_op
(
Mat
m
)
{
return
m
.
clone
();
}
};
KeyPointCollection
trainPointCollection
;
...
...
@@ -2274,7 +2331,7 @@ typedef OneWayDescriptorMatcher OneWayDescriptorMatch;
class
CV_EXPORTS
OneWayDescriptorMatcher
:
public
GenericDescriptorMatcher
{
public
:
class
Params
class
CV_EXPORTS
Params
{
public
:
static
const
int
POSE_COUNT
=
500
;
...
...
@@ -2284,16 +2341,12 @@ public:
static
float
GET_MAX_SCALE
()
{
return
1.5
f
;
}
static
float
GET_STEP_SCALE
()
{
return
1.2
f
;
}
Params
(
int
_poseCount
=
POSE_COUNT
,
Size
_patchSize
=
Size
(
PATCH_WIDTH
,
PATCH_HEIGHT
),
string
_pcaFilename
=
string
(),
string
_trainPath
=
string
(),
string
_trainImagesList
=
string
(),
float
_minScale
=
GET_MIN_SCALE
(),
float
_maxScale
=
GET_MAX_SCALE
(),
float
_stepScale
=
GET_STEP_SCALE
()
)
:
poseCount
(
_poseCount
),
patchSize
(
_patchSize
),
pcaFilename
(
_pcaFilename
),
trainPath
(
_trainPath
),
trainImagesList
(
_trainImagesList
),
minScale
(
_minScale
),
maxScale
(
_maxScale
),
stepScale
(
_stepScale
)
{}
Params
(
int
poseCount
=
POSE_COUNT
,
Size
patchSize
=
Size
(
PATCH_WIDTH
,
PATCH_HEIGHT
),
string
pcaFilename
=
string
(),
string
trainPath
=
string
(),
string
trainImagesList
=
string
(),
float
minScale
=
GET_MIN_SCALE
(),
float
maxScale
=
GET_MAX_SCALE
(),
float
stepScale
=
GET_STEP_SCALE
()
);
int
poseCount
;
Size
patchSize
;
...
...
@@ -2304,38 +2357,34 @@ public:
float
minScale
,
maxScale
,
stepScale
;
};
// Equivalent to calling PointMatchOneWay() followed by Initialize(_params)
OneWayDescriptorMatcher
(
const
Params
&
_params
=
Params
()
);
OneWayDescriptorMatcher
(
const
Params
&
params
=
Params
()
);
virtual
~
OneWayDescriptorMatcher
();
void
initialize
(
const
Params
&
_params
,
const
Ptr
<
OneWayDescriptorBase
>&
_
base
=
Ptr
<
OneWayDescriptorBase
>
()
);
void
initialize
(
const
Params
&
params
,
const
Ptr
<
OneWayDescriptorBase
>&
base
=
Ptr
<
OneWayDescriptorBase
>
()
);
// Clears keypoints storing in collection and OneWayDescriptorBase
virtual
void
clear
();
virtual
void
clear
();
virtual
void
train
();
virtual
bool
supportMask
()
{
return
false
;
}
virtual
bool
isMaskSupported
();
// Reads match object from a file node
virtual
void
read
(
const
FileNode
&
fn
);
// Writes match object to a file storage
virtual
void
write
(
FileStorage
&
fs
)
const
;
protected
:
virtual
Ptr
<
GenericDescriptorMatcher
>
createEmptyMatcherCopy
()
const
{
return
new
OneWayDescriptorMatcher
(
params
);
}
virtual
Ptr
<
GenericDescriptorMatcher
>
clone
(
bool
emptyTrainData
=
false
)
const
;
protected
:
// Matches a set of keypoints from a single image of the training set. A rectangle with a center in a keypoint
// and size (patch_width/2*scale, patch_height/2*scale) is cropped from the source image for each
// keypoint. scale is iterated from DescriptorOneWayParams::min_scale to DescriptorOneWayParams::max_scale.
// The minimum distance to each training patch with all its affine poses is found over all scales.
// The class ID of a match is returned for each keypoint. The distance is calculated over PCA components
// loaded with DescriptorOneWay::Initialize, kd tree is used for finding minimum distances.
virtual
void
knnMatchImpl
(
const
Mat
&
queryIm
g
,
vector
<
KeyPoint
>&
queryP
oints
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
k
nn
,
virtual
void
knnMatchImpl
(
const
Mat
&
queryIm
age
,
vector
<
KeyPoint
>&
queryKeyp
oints
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
k
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
virtual
void
radiusMatchImpl
(
const
Mat
&
queryIm
g
,
vector
<
KeyPoint
>&
queryP
oints
,
virtual
void
radiusMatchImpl
(
const
Mat
&
queryIm
age
,
vector
<
KeyPoint
>&
queryKeyp
oints
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
...
...
@@ -2356,16 +2405,16 @@ public:
class
CV_EXPORTS
Params
{
public
:
Params
(
int
_
nclasses
=
0
,
int
_
patchSize
=
FernClassifier
::
PATCH_SIZE
,
int
_
signatureSize
=
FernClassifier
::
DEFAULT_SIGNATURE_SIZE
,
int
_
nstructs
=
FernClassifier
::
DEFAULT_STRUCTS
,
int
_
structSize
=
FernClassifier
::
DEFAULT_STRUCT_SIZE
,
int
_
nviews
=
FernClassifier
::
DEFAULT_VIEWS
,
int
_
compressionMethod
=
FernClassifier
::
COMPRESSION_NONE
,
Params
(
int
nclasses
=
0
,
int
patchSize
=
FernClassifier
::
PATCH_SIZE
,
int
signatureSize
=
FernClassifier
::
DEFAULT_SIGNATURE_SIZE
,
int
nstructs
=
FernClassifier
::
DEFAULT_STRUCTS
,
int
structSize
=
FernClassifier
::
DEFAULT_STRUCT_SIZE
,
int
nviews
=
FernClassifier
::
DEFAULT_VIEWS
,
int
compressionMethod
=
FernClassifier
::
COMPRESSION_NONE
,
const
PatchGenerator
&
patchGenerator
=
PatchGenerator
()
);
Params
(
const
string
&
_
filename
);
Params
(
const
string
&
filename
);
int
nclasses
;
int
patchSize
;
...
...
@@ -2379,25 +2428,25 @@ public:
string
filename
;
};
FernDescriptorMatcher
(
const
Params
&
_
params
=
Params
()
);
FernDescriptorMatcher
(
const
Params
&
params
=
Params
()
);
virtual
~
FernDescriptorMatcher
();
virtual
void
clear
();
virtual
void
train
();
virtual
bool
supportMask
()
{
return
false
;
}
virtual
bool
isMaskSupported
();
virtual
void
read
(
const
FileNode
&
fn
);
virtual
void
write
(
FileStorage
&
fs
)
const
;
protected
:
virtual
Ptr
<
GenericDescriptorMatcher
>
createEmptyMatcherCopy
()
const
{
return
new
FernDescriptorMatcher
(
params
);
}
virtual
Ptr
<
GenericDescriptorMatcher
>
clone
(
bool
emptyTrainData
=
false
)
const
;
virtual
void
knnMatchImpl
(
const
Mat
&
queryImg
,
vector
<
KeyPoint
>&
queryPoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
protected
:
virtual
void
knnMatchImpl
(
const
Mat
&
queryImage
,
vector
<
KeyPoint
>&
queryKeypoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
k
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
virtual
void
radiusMatchImpl
(
const
Mat
&
queryIm
g
,
vector
<
KeyPoint
>&
queryP
oints
,
virtual
void
radiusMatchImpl
(
const
Mat
&
queryIm
age
,
vector
<
KeyPoint
>&
queryKeyp
oints
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
...
...
@@ -2425,9 +2474,8 @@ typedef VectorDescriptorMatcher VectorDescriptorMatch;
class
CV_EXPORTS
VectorDescriptorMatcher
:
public
GenericDescriptorMatcher
{
public
:
VectorDescriptorMatcher
(
const
Ptr
<
DescriptorExtractor
>&
_extractor
,
const
Ptr
<
DescriptorMatcher
>&
_matcher
)
:
extractor
(
_extractor
),
matcher
(
_matcher
)
{
CV_Assert
(
!
extractor
.
empty
()
&&
!
matcher
.
empty
()
);
}
virtual
~
VectorDescriptorMatcher
()
{}
VectorDescriptorMatcher
(
const
Ptr
<
DescriptorExtractor
>&
extractor
,
const
Ptr
<
DescriptorMatcher
>&
matcher
);
virtual
~
VectorDescriptorMatcher
();
virtual
void
add
(
const
vector
<
Mat
>&
imgCollection
,
vector
<
vector
<
KeyPoint
>
>&
pointCollection
);
...
...
@@ -2436,18 +2484,18 @@ public:
virtual
void
train
();
virtual
bool
supportMask
()
{
return
matcher
->
supportMask
();
}
virtual
bool
isMaskSupported
();
virtual
void
read
(
const
FileNode
&
fn
);
virtual
void
write
(
FileStorage
&
fs
)
const
;
protected
:
virtual
Ptr
<
GenericDescriptorMatcher
>
createEmptyMatcherCopy
()
const
{
return
new
VectorDescriptorMatcher
(
extractor
,
matcher
);
}
virtual
Ptr
<
GenericDescriptorMatcher
>
clone
(
bool
emptyTrainData
=
false
)
const
;
virtual
void
knnMatchImpl
(
const
Mat
&
queryImg
,
vector
<
KeyPoint
>&
queryPoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
protected
:
virtual
void
knnMatchImpl
(
const
Mat
&
queryImage
,
vector
<
KeyPoint
>&
queryKeypoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
k
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
virtual
void
radiusMatchImpl
(
const
Mat
&
queryIm
g
,
vector
<
KeyPoint
>&
queryP
oints
,
virtual
void
radiusMatchImpl
(
const
Mat
&
queryIm
age
,
vector
<
KeyPoint
>&
queryKeyp
oints
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
);
...
...
@@ -2520,12 +2568,12 @@ CV_EXPORTS void evaluateGenericDescriptorMatcher( const Mat& img1, const Mat& im
class
CV_EXPORTS
BOWTrainer
{
public
:
BOWTrainer
()
{}
virtual
~
BOWTrainer
()
{}
BOWTrainer
()
;
virtual
~
BOWTrainer
()
;
void
add
(
const
Mat
&
descriptors
);
const
vector
<
Mat
>&
getDescriptors
()
const
{
return
descriptors
;
}
int
descripotorsCount
()
const
{
return
descriptors
.
empty
()
?
0
:
size
;
}
const
vector
<
Mat
>&
getDescriptors
()
const
;
int
descripotorsCount
()
const
;
virtual
void
clear
();
...
...
@@ -2552,7 +2600,7 @@ class CV_EXPORTS BOWKMeansTrainer : public BOWTrainer
public
:
BOWKMeansTrainer
(
int
clusterCount
,
const
TermCriteria
&
termcrit
=
TermCriteria
(),
int
attempts
=
3
,
int
flags
=
KMEANS_PP_CENTERS
);
virtual
~
BOWKMeansTrainer
()
{}
virtual
~
BOWKMeansTrainer
()
;
// Returns trained vocabulary (i.e. cluster centers).
virtual
Mat
cluster
()
const
;
...
...
@@ -2574,14 +2622,16 @@ class CV_EXPORTS BOWImgDescriptorExtractor
public
:
BOWImgDescriptorExtractor
(
const
Ptr
<
DescriptorExtractor
>&
dextractor
,
const
Ptr
<
DescriptorMatcher
>&
dmatcher
);
virtual
~
BOWImgDescriptorExtractor
()
{}
virtual
~
BOWImgDescriptorExtractor
()
;
void
setVocabulary
(
const
Mat
&
vocabulary
);
const
Mat
&
getVocabulary
()
const
{
return
vocabulary
;
}
const
Mat
&
getVocabulary
()
const
;
void
compute
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
imgDescriptor
,
vector
<
vector
<
int
>
>*
pointIdxsOfClusters
=
0
,
Mat
*
descriptors
=
0
);
//not constant because DescriptorMatcher::match is not constant
int
descriptorSize
()
const
{
return
vocabulary
.
empty
()
?
0
:
vocabulary
.
rows
;
}
int
descriptorType
()
const
{
return
CV_32FC1
;
}
vector
<
vector
<
int
>
>*
pointIdxsOfClusters
=
0
,
Mat
*
descriptors
=
0
);
// compute() is not constant because DescriptorMatcher::match is not constant
int
descriptorSize
()
const
;
int
descriptorType
()
const
;
protected
:
Mat
vocabulary
;
...
...
modules/features2d/src/bagofwords.cpp
View file @
e406dfee
...
...
@@ -46,6 +46,12 @@ using namespace std;
namespace
cv
{
BOWTrainer
::
BOWTrainer
()
{}
BOWTrainer
::~
BOWTrainer
()
{}
void
BOWTrainer
::
add
(
const
Mat
&
_descriptors
)
{
CV_Assert
(
!
_descriptors
.
empty
()
);
...
...
@@ -63,6 +69,16 @@ void BOWTrainer::add( const Mat& _descriptors )
descriptors
.
push_back
(
_descriptors
);
}
const
vector
<
Mat
>&
BOWTrainer
::
getDescriptors
()
const
{
return
descriptors
;
}
int
BOWTrainer
::
descripotorsCount
()
const
{
return
descriptors
.
empty
()
?
0
:
size
;
}
void
BOWTrainer
::
clear
()
{
descriptors
.
clear
();
...
...
@@ -91,6 +107,9 @@ Mat BOWKMeansTrainer::cluster() const
return
cluster
(
mergedDescriptors
);
}
BOWKMeansTrainer
::~
BOWKMeansTrainer
()
{}
Mat
BOWKMeansTrainer
::
cluster
(
const
Mat
&
descriptors
)
const
{
Mat
labels
,
vocabulary
;
...
...
@@ -104,6 +123,9 @@ BOWImgDescriptorExtractor::BOWImgDescriptorExtractor( const Ptr<DescriptorExtrac
dextractor
(
_dextractor
),
dmatcher
(
_dmatcher
)
{}
BOWImgDescriptorExtractor
::~
BOWImgDescriptorExtractor
()
{}
void
BOWImgDescriptorExtractor
::
setVocabulary
(
const
Mat
&
_vocabulary
)
{
dmatcher
->
clear
();
...
...
@@ -111,6 +133,11 @@ void BOWImgDescriptorExtractor::setVocabulary( const Mat& _vocabulary )
dmatcher
->
add
(
vector
<
Mat
>
(
1
,
vocabulary
)
);
}
const
Mat
&
BOWImgDescriptorExtractor
::
getVocabulary
()
const
{
return
vocabulary
;
}
void
BOWImgDescriptorExtractor
::
compute
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
imgDescriptor
,
vector
<
vector
<
int
>
>*
pointIdxsOfClusters
,
Mat
*
_descriptors
)
{
...
...
@@ -153,4 +180,14 @@ void BOWImgDescriptorExtractor::compute( const Mat& image, vector<KeyPoint>& key
imgDescriptor
/=
descriptors
.
rows
;
}
int
BOWImgDescriptorExtractor
::
descriptorSize
()
const
{
return
vocabulary
.
empty
()
?
0
:
vocabulary
.
rows
;
}
int
BOWImgDescriptorExtractor
::
descriptorType
()
const
{
return
CV_32FC1
;
}
}
modules/features2d/src/brief.cpp
View file @
e406dfee
...
...
@@ -44,78 +44,101 @@
#include <algorithm>
#include <vector>
namespace
cv
using
namespace
cv
;
inline
int
smoothedSum
(
const
Mat
&
sum
,
const
KeyPoint
&
pt
,
int
y
,
int
x
)
{
static
const
int
HALF_KERNEL
=
BriefDescriptorExtractor
::
KERNEL_SIZE
/
2
;
BriefDescriptorExtractor
::
BriefDescriptorExtractor
(
int
bytes
)
:
bytes_
(
bytes
),
test_fn_
(
NULL
)
int
img_y
=
(
int
)(
pt
.
pt
.
y
+
0.5
)
+
y
;
int
img_x
=
(
int
)(
pt
.
pt
.
x
+
0.5
)
+
x
;
return
sum
.
at
<
int
>
(
img_y
+
HALF_KERNEL
+
1
,
img_x
+
HALF_KERNEL
+
1
)
-
sum
.
at
<
int
>
(
img_y
+
HALF_KERNEL
+
1
,
img_x
-
HALF_KERNEL
)
-
sum
.
at
<
int
>
(
img_y
-
HALF_KERNEL
,
img_x
+
HALF_KERNEL
+
1
)
+
sum
.
at
<
int
>
(
img_y
-
HALF_KERNEL
,
img_x
-
HALF_KERNEL
);
}
void
pixelTests16
(
const
Mat
&
sum
,
const
std
::
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
{
switch
(
bytes
)
{
case
16
:
test_fn_
=
pixelTests16
;
break
;
case
32
:
test_fn_
=
pixelTests32
;
break
;
case
64
:
test_fn_
=
pixelTests64
;
break
;
default
:
CV_Error
(
CV_StsBadArg
,
"bytes must be 16, 32, or 64"
);
}
for
(
int
i
=
0
;
i
<
(
int
)
keypoints
.
size
();
++
i
)
{
uchar
*
desc
=
descriptors
.
ptr
(
i
);
const
KeyPoint
&
pt
=
keypoints
[
i
];
#include "generated_16.i"
}
}
void
BriefDescriptorExtractor
::
compute
(
const
Mat
&
image
,
std
::
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
void
pixelTests32
(
const
Mat
&
sum
,
const
std
::
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
{
// Construct integral image for fast smoothing (box filter)
Mat
sum
;
///TODO allow the user to pass in a precomputed integral image
//if(image.type() == CV_32S)
// sum = image;
//else
integral
(
image
,
sum
,
CV_32S
);
for
(
int
i
=
0
;
i
<
(
int
)
keypoints
.
size
();
++
i
)
{
uchar
*
desc
=
descriptors
.
ptr
(
i
);
const
KeyPoint
&
pt
=
keypoints
[
i
];
//Remove keypoints very close to the border
removeBorderKeypoints
(
keypoints
,
image
.
size
(),
PATCH_SIZE
/
2
+
KERNEL_SIZE
/
2
);
#include "generated_32.i"
}
}
void
pixelTests64
(
const
Mat
&
sum
,
const
std
::
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
{
for
(
int
i
=
0
;
i
<
(
int
)
keypoints
.
size
();
++
i
)
{
uchar
*
desc
=
descriptors
.
ptr
(
i
);
const
KeyPoint
&
pt
=
keypoints
[
i
];
descriptors
=
Mat
::
zeros
(
keypoints
.
size
(),
bytes_
,
CV_8U
);
test_fn_
(
sum
,
keypoints
,
descriptors
);
#include "generated_64.i"
}
}
void
BriefDescriptorExtractor
::
pixelTests16
(
const
Mat
&
sum
,
const
std
::
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
namespace
cv
{
for
(
int
i
=
0
;
i
<
(
int
)
keypoints
.
size
();
++
i
)
{
uchar
*
desc
=
descriptors
.
ptr
(
i
);
const
KeyPoint
&
pt
=
keypoints
[
i
];
#include "generated_16.i"
}
BriefDescriptorExtractor
::
BriefDescriptorExtractor
(
int
bytes
)
:
bytes_
(
bytes
),
test_fn_
(
NULL
)
{
switch
(
bytes
)
{
case
16
:
test_fn_
=
pixelTests16
;
break
;
case
32
:
test_fn_
=
pixelTests32
;
break
;
case
64
:
test_fn_
=
pixelTests64
;
break
;
default
:
CV_Error
(
CV_StsBadArg
,
"bytes must be 16, 32, or 64"
);
}
}
void
BriefDescriptorExtractor
::
pixelTests32
(
const
Mat
&
sum
,
const
std
::
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
int
BriefDescriptorExtractor
::
descriptorSize
()
const
{
for
(
int
i
=
0
;
i
<
(
int
)
keypoints
.
size
();
++
i
)
{
uchar
*
desc
=
descriptors
.
ptr
(
i
);
const
KeyPoint
&
pt
=
keypoints
[
i
];
return
bytes_
;
}
#include "generated_32.i"
}
int
BriefDescriptorExtractor
::
descriptorType
()
const
{
return
CV_8UC1
;
}
void
BriefDescriptorExtractor
::
pixelTests64
(
const
Mat
&
sum
,
const
std
::
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
void
BriefDescriptorExtractor
::
computeImpl
(
const
Mat
&
image
,
std
::
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
{
for
(
int
i
=
0
;
i
<
(
int
)
keypoints
.
size
();
++
i
)
{
uchar
*
desc
=
descriptors
.
ptr
(
i
);
const
KeyPoint
&
pt
=
keypoints
[
i
];
// Construct integral image for fast smoothing (box filter)
Mat
sum
;
#include "generated_64.i"
}
///TODO allow the user to pass in a precomputed integral image
//if(image.type() == CV_32S)
// sum = image;
//else
integral
(
image
,
sum
,
CV_32S
);
//Remove keypoints very close to the border
removeBorderKeypoints
(
keypoints
,
image
.
size
(),
PATCH_SIZE
/
2
+
KERNEL_SIZE
/
2
);
descriptors
=
Mat
::
zeros
(
keypoints
.
size
(),
bytes_
,
CV_8U
);
test_fn_
(
sum
,
keypoints
,
descriptors
);
}
/**
...
...
@@ -125,282 +148,285 @@ void BriefDescriptorExtractor::pixelTests64(const Mat& sum, const std::vector<Ke
template
<
unsigned
char
b
>
struct
ByteBits
{
/**
* number of bits in the byte given by the template constant
*/
enum
{
COUNT
=
((
b
>>
0
)
&
1
)
+
((
b
>>
1
)
&
1
)
+
((
b
>>
2
)
&
1
)
+
((
b
>>
3
)
&
1
)
+
((
b
>>
4
)
&
1
)
+
((
b
>>
5
)
&
1
)
+
((
b
>>
6
)
&
1
)
+
((
b
>>
7
)
&
1
)
};
/**
* number of bits in the byte given by the template constant
*/
enum
{
COUNT
=
((
b
>>
0
)
&
1
)
+
((
b
>>
1
)
&
1
)
+
((
b
>>
2
)
&
1
)
+
((
b
>>
3
)
&
1
)
+
((
b
>>
4
)
&
1
)
+
((
b
>>
5
)
&
1
)
+
((
b
>>
6
)
&
1
)
+
((
b
>>
7
)
&
1
)
};
};
unsigned
char
HammingLUT
::
byteBitsLookUp
(
unsigned
char
b
){
static
const
unsigned
char
table
[
256
]
=
{
ByteBits
<
0
>::
COUNT
,
ByteBits
<
1
>::
COUNT
,
ByteBits
<
2
>::
COUNT
,
ByteBits
<
3
>::
COUNT
,
ByteBits
<
4
>::
COUNT
,
ByteBits
<
5
>::
COUNT
,
ByteBits
<
6
>::
COUNT
,
ByteBits
<
7
>::
COUNT
,
ByteBits
<
8
>::
COUNT
,
ByteBits
<
9
>::
COUNT
,
ByteBits
<
10
>::
COUNT
,
ByteBits
<
11
>::
COUNT
,
ByteBits
<
12
>::
COUNT
,
ByteBits
<
13
>::
COUNT
,
ByteBits
<
14
>::
COUNT
,
ByteBits
<
15
>::
COUNT
,
ByteBits
<
16
>::
COUNT
,
ByteBits
<
17
>::
COUNT
,
ByteBits
<
18
>::
COUNT
,
ByteBits
<
19
>::
COUNT
,
ByteBits
<
20
>::
COUNT
,
ByteBits
<
21
>::
COUNT
,
ByteBits
<
22
>::
COUNT
,
ByteBits
<
23
>::
COUNT
,
ByteBits
<
24
>::
COUNT
,
ByteBits
<
25
>::
COUNT
,
ByteBits
<
26
>::
COUNT
,
ByteBits
<
27
>::
COUNT
,
ByteBits
<
28
>::
COUNT
,
ByteBits
<
29
>::
COUNT
,
ByteBits
<
30
>::
COUNT
,
ByteBits
<
31
>::
COUNT
,
ByteBits
<
32
>::
COUNT
,
ByteBits
<
33
>::
COUNT
,
ByteBits
<
34
>::
COUNT
,
ByteBits
<
35
>::
COUNT
,
ByteBits
<
36
>::
COUNT
,
ByteBits
<
37
>::
COUNT
,
ByteBits
<
38
>::
COUNT
,
ByteBits
<
39
>::
COUNT
,
ByteBits
<
40
>::
COUNT
,
ByteBits
<
41
>::
COUNT
,
ByteBits
<
42
>::
COUNT
,
ByteBits
<
43
>::
COUNT
,
ByteBits
<
44
>::
COUNT
,
ByteBits
<
45
>::
COUNT
,
ByteBits
<
46
>::
COUNT
,
ByteBits
<
47
>::
COUNT
,
ByteBits
<
48
>::
COUNT
,
ByteBits
<
49
>::
COUNT
,
ByteBits
<
50
>::
COUNT
,
ByteBits
<
51
>::
COUNT
,
ByteBits
<
52
>::
COUNT
,
ByteBits
<
53
>::
COUNT
,
ByteBits
<
54
>::
COUNT
,
ByteBits
<
55
>::
COUNT
,
ByteBits
<
56
>::
COUNT
,
ByteBits
<
57
>::
COUNT
,
ByteBits
<
58
>::
COUNT
,
ByteBits
<
59
>::
COUNT
,
ByteBits
<
60
>::
COUNT
,
ByteBits
<
61
>::
COUNT
,
ByteBits
<
62
>::
COUNT
,
ByteBits
<
63
>::
COUNT
,
ByteBits
<
64
>::
COUNT
,
ByteBits
<
65
>::
COUNT
,
ByteBits
<
66
>::
COUNT
,
ByteBits
<
67
>::
COUNT
,
ByteBits
<
68
>::
COUNT
,
ByteBits
<
69
>::
COUNT
,
ByteBits
<
70
>::
COUNT
,
ByteBits
<
71
>::
COUNT
,
ByteBits
<
72
>::
COUNT
,
ByteBits
<
73
>::
COUNT
,
ByteBits
<
74
>::
COUNT
,
ByteBits
<
75
>::
COUNT
,
ByteBits
<
76
>::
COUNT
,
ByteBits
<
77
>::
COUNT
,
ByteBits
<
78
>::
COUNT
,
ByteBits
<
79
>::
COUNT
,
ByteBits
<
80
>::
COUNT
,
ByteBits
<
81
>::
COUNT
,
ByteBits
<
82
>::
COUNT
,
ByteBits
<
83
>::
COUNT
,
ByteBits
<
84
>::
COUNT
,
ByteBits
<
85
>::
COUNT
,
ByteBits
<
86
>::
COUNT
,
ByteBits
<
87
>::
COUNT
,
ByteBits
<
88
>::
COUNT
,
ByteBits
<
89
>::
COUNT
,
ByteBits
<
90
>::
COUNT
,
ByteBits
<
91
>::
COUNT
,
ByteBits
<
92
>::
COUNT
,
ByteBits
<
93
>::
COUNT
,
ByteBits
<
94
>::
COUNT
,
ByteBits
<
95
>::
COUNT
,
ByteBits
<
96
>::
COUNT
,
ByteBits
<
97
>::
COUNT
,
ByteBits
<
98
>::
COUNT
,
ByteBits
<
99
>::
COUNT
,
ByteBits
<
100
>::
COUNT
,
ByteBits
<
101
>::
COUNT
,
ByteBits
<
102
>::
COUNT
,
ByteBits
<
103
>::
COUNT
,
ByteBits
<
104
>::
COUNT
,
ByteBits
<
105
>::
COUNT
,
ByteBits
<
106
>::
COUNT
,
ByteBits
<
107
>::
COUNT
,
ByteBits
<
108
>::
COUNT
,
ByteBits
<
109
>::
COUNT
,
ByteBits
<
110
>::
COUNT
,
ByteBits
<
111
>::
COUNT
,
ByteBits
<
112
>::
COUNT
,
ByteBits
<
113
>::
COUNT
,
ByteBits
<
114
>::
COUNT
,
ByteBits
<
115
>::
COUNT
,
ByteBits
<
116
>::
COUNT
,
ByteBits
<
117
>::
COUNT
,
ByteBits
<
118
>::
COUNT
,
ByteBits
<
119
>::
COUNT
,
ByteBits
<
120
>::
COUNT
,
ByteBits
<
121
>::
COUNT
,
ByteBits
<
122
>::
COUNT
,
ByteBits
<
123
>::
COUNT
,
ByteBits
<
124
>::
COUNT
,
ByteBits
<
125
>::
COUNT
,
ByteBits
<
126
>::
COUNT
,
ByteBits
<
127
>::
COUNT
,
ByteBits
<
128
>::
COUNT
,
ByteBits
<
129
>::
COUNT
,
ByteBits
<
130
>::
COUNT
,
ByteBits
<
131
>::
COUNT
,
ByteBits
<
132
>::
COUNT
,
ByteBits
<
133
>::
COUNT
,
ByteBits
<
134
>::
COUNT
,
ByteBits
<
135
>::
COUNT
,
ByteBits
<
136
>::
COUNT
,
ByteBits
<
137
>::
COUNT
,
ByteBits
<
138
>::
COUNT
,
ByteBits
<
139
>::
COUNT
,
ByteBits
<
140
>::
COUNT
,
ByteBits
<
141
>::
COUNT
,
ByteBits
<
142
>::
COUNT
,
ByteBits
<
143
>::
COUNT
,
ByteBits
<
144
>::
COUNT
,
ByteBits
<
145
>::
COUNT
,
ByteBits
<
146
>::
COUNT
,
ByteBits
<
147
>::
COUNT
,
ByteBits
<
148
>::
COUNT
,
ByteBits
<
149
>::
COUNT
,
ByteBits
<
150
>::
COUNT
,
ByteBits
<
151
>::
COUNT
,
ByteBits
<
152
>::
COUNT
,
ByteBits
<
153
>::
COUNT
,
ByteBits
<
154
>::
COUNT
,
ByteBits
<
155
>::
COUNT
,
ByteBits
<
156
>::
COUNT
,
ByteBits
<
157
>::
COUNT
,
ByteBits
<
158
>::
COUNT
,
ByteBits
<
159
>::
COUNT
,
ByteBits
<
160
>::
COUNT
,
ByteBits
<
161
>::
COUNT
,
ByteBits
<
162
>::
COUNT
,
ByteBits
<
163
>::
COUNT
,
ByteBits
<
164
>::
COUNT
,
ByteBits
<
165
>::
COUNT
,
ByteBits
<
166
>::
COUNT
,
ByteBits
<
167
>::
COUNT
,
ByteBits
<
168
>::
COUNT
,
ByteBits
<
169
>::
COUNT
,
ByteBits
<
170
>::
COUNT
,
ByteBits
<
171
>::
COUNT
,
ByteBits
<
172
>::
COUNT
,
ByteBits
<
173
>::
COUNT
,
ByteBits
<
174
>::
COUNT
,
ByteBits
<
175
>::
COUNT
,
ByteBits
<
176
>::
COUNT
,
ByteBits
<
177
>::
COUNT
,
ByteBits
<
178
>::
COUNT
,
ByteBits
<
179
>::
COUNT
,
ByteBits
<
180
>::
COUNT
,
ByteBits
<
181
>::
COUNT
,
ByteBits
<
182
>::
COUNT
,
ByteBits
<
183
>::
COUNT
,
ByteBits
<
184
>::
COUNT
,
ByteBits
<
185
>::
COUNT
,
ByteBits
<
186
>::
COUNT
,
ByteBits
<
187
>::
COUNT
,
ByteBits
<
188
>::
COUNT
,
ByteBits
<
189
>::
COUNT
,
ByteBits
<
190
>::
COUNT
,
ByteBits
<
191
>::
COUNT
,
ByteBits
<
192
>::
COUNT
,
ByteBits
<
193
>::
COUNT
,
ByteBits
<
194
>::
COUNT
,
ByteBits
<
195
>::
COUNT
,
ByteBits
<
196
>::
COUNT
,
ByteBits
<
197
>::
COUNT
,
ByteBits
<
198
>::
COUNT
,
ByteBits
<
199
>::
COUNT
,
ByteBits
<
200
>::
COUNT
,
ByteBits
<
201
>::
COUNT
,
ByteBits
<
202
>::
COUNT
,
ByteBits
<
203
>::
COUNT
,
ByteBits
<
204
>::
COUNT
,
ByteBits
<
205
>::
COUNT
,
ByteBits
<
206
>::
COUNT
,
ByteBits
<
207
>::
COUNT
,
ByteBits
<
208
>::
COUNT
,
ByteBits
<
209
>::
COUNT
,
ByteBits
<
210
>::
COUNT
,
ByteBits
<
211
>::
COUNT
,
ByteBits
<
212
>::
COUNT
,
ByteBits
<
213
>::
COUNT
,
ByteBits
<
214
>::
COUNT
,
ByteBits
<
215
>::
COUNT
,
ByteBits
<
216
>::
COUNT
,
ByteBits
<
217
>::
COUNT
,
ByteBits
<
218
>::
COUNT
,
ByteBits
<
219
>::
COUNT
,
ByteBits
<
220
>::
COUNT
,
ByteBits
<
221
>::
COUNT
,
ByteBits
<
222
>::
COUNT
,
ByteBits
<
223
>::
COUNT
,
ByteBits
<
224
>::
COUNT
,
ByteBits
<
225
>::
COUNT
,
ByteBits
<
226
>::
COUNT
,
ByteBits
<
227
>::
COUNT
,
ByteBits
<
228
>::
COUNT
,
ByteBits
<
229
>::
COUNT
,
ByteBits
<
230
>::
COUNT
,
ByteBits
<
231
>::
COUNT
,
ByteBits
<
232
>::
COUNT
,
ByteBits
<
233
>::
COUNT
,
ByteBits
<
234
>::
COUNT
,
ByteBits
<
235
>::
COUNT
,
ByteBits
<
236
>::
COUNT
,
ByteBits
<
237
>::
COUNT
,
ByteBits
<
238
>::
COUNT
,
ByteBits
<
239
>::
COUNT
,
ByteBits
<
240
>::
COUNT
,
ByteBits
<
241
>::
COUNT
,
ByteBits
<
242
>::
COUNT
,
ByteBits
<
243
>::
COUNT
,
ByteBits
<
244
>::
COUNT
,
ByteBits
<
245
>::
COUNT
,
ByteBits
<
246
>::
COUNT
,
ByteBits
<
247
>::
COUNT
,
ByteBits
<
248
>::
COUNT
,
ByteBits
<
249
>::
COUNT
,
ByteBits
<
250
>::
COUNT
,
ByteBits
<
251
>::
COUNT
,
ByteBits
<
252
>::
COUNT
,
ByteBits
<
253
>::
COUNT
,
ByteBits
<
254
>::
COUNT
,
ByteBits
<
255
>::
COUNT
};
return
table
[
b
];
unsigned
char
HammingLUT
::
byteBitsLookUp
(
unsigned
char
b
)
{
static
const
unsigned
char
table
[
256
]
=
{
ByteBits
<
0
>::
COUNT
,
ByteBits
<
1
>::
COUNT
,
ByteBits
<
2
>::
COUNT
,
ByteBits
<
3
>::
COUNT
,
ByteBits
<
4
>::
COUNT
,
ByteBits
<
5
>::
COUNT
,
ByteBits
<
6
>::
COUNT
,
ByteBits
<
7
>::
COUNT
,
ByteBits
<
8
>::
COUNT
,
ByteBits
<
9
>::
COUNT
,
ByteBits
<
10
>::
COUNT
,
ByteBits
<
11
>::
COUNT
,
ByteBits
<
12
>::
COUNT
,
ByteBits
<
13
>::
COUNT
,
ByteBits
<
14
>::
COUNT
,
ByteBits
<
15
>::
COUNT
,
ByteBits
<
16
>::
COUNT
,
ByteBits
<
17
>::
COUNT
,
ByteBits
<
18
>::
COUNT
,
ByteBits
<
19
>::
COUNT
,
ByteBits
<
20
>::
COUNT
,
ByteBits
<
21
>::
COUNT
,
ByteBits
<
22
>::
COUNT
,
ByteBits
<
23
>::
COUNT
,
ByteBits
<
24
>::
COUNT
,
ByteBits
<
25
>::
COUNT
,
ByteBits
<
26
>::
COUNT
,
ByteBits
<
27
>::
COUNT
,
ByteBits
<
28
>::
COUNT
,
ByteBits
<
29
>::
COUNT
,
ByteBits
<
30
>::
COUNT
,
ByteBits
<
31
>::
COUNT
,
ByteBits
<
32
>::
COUNT
,
ByteBits
<
33
>::
COUNT
,
ByteBits
<
34
>::
COUNT
,
ByteBits
<
35
>::
COUNT
,
ByteBits
<
36
>::
COUNT
,
ByteBits
<
37
>::
COUNT
,
ByteBits
<
38
>::
COUNT
,
ByteBits
<
39
>::
COUNT
,
ByteBits
<
40
>::
COUNT
,
ByteBits
<
41
>::
COUNT
,
ByteBits
<
42
>::
COUNT
,
ByteBits
<
43
>::
COUNT
,
ByteBits
<
44
>::
COUNT
,
ByteBits
<
45
>::
COUNT
,
ByteBits
<
46
>::
COUNT
,
ByteBits
<
47
>::
COUNT
,
ByteBits
<
48
>::
COUNT
,
ByteBits
<
49
>::
COUNT
,
ByteBits
<
50
>::
COUNT
,
ByteBits
<
51
>::
COUNT
,
ByteBits
<
52
>::
COUNT
,
ByteBits
<
53
>::
COUNT
,
ByteBits
<
54
>::
COUNT
,
ByteBits
<
55
>::
COUNT
,
ByteBits
<
56
>::
COUNT
,
ByteBits
<
57
>::
COUNT
,
ByteBits
<
58
>::
COUNT
,
ByteBits
<
59
>::
COUNT
,
ByteBits
<
60
>::
COUNT
,
ByteBits
<
61
>::
COUNT
,
ByteBits
<
62
>::
COUNT
,
ByteBits
<
63
>::
COUNT
,
ByteBits
<
64
>::
COUNT
,
ByteBits
<
65
>::
COUNT
,
ByteBits
<
66
>::
COUNT
,
ByteBits
<
67
>::
COUNT
,
ByteBits
<
68
>::
COUNT
,
ByteBits
<
69
>::
COUNT
,
ByteBits
<
70
>::
COUNT
,
ByteBits
<
71
>::
COUNT
,
ByteBits
<
72
>::
COUNT
,
ByteBits
<
73
>::
COUNT
,
ByteBits
<
74
>::
COUNT
,
ByteBits
<
75
>::
COUNT
,
ByteBits
<
76
>::
COUNT
,
ByteBits
<
77
>::
COUNT
,
ByteBits
<
78
>::
COUNT
,
ByteBits
<
79
>::
COUNT
,
ByteBits
<
80
>::
COUNT
,
ByteBits
<
81
>::
COUNT
,
ByteBits
<
82
>::
COUNT
,
ByteBits
<
83
>::
COUNT
,
ByteBits
<
84
>::
COUNT
,
ByteBits
<
85
>::
COUNT
,
ByteBits
<
86
>::
COUNT
,
ByteBits
<
87
>::
COUNT
,
ByteBits
<
88
>::
COUNT
,
ByteBits
<
89
>::
COUNT
,
ByteBits
<
90
>::
COUNT
,
ByteBits
<
91
>::
COUNT
,
ByteBits
<
92
>::
COUNT
,
ByteBits
<
93
>::
COUNT
,
ByteBits
<
94
>::
COUNT
,
ByteBits
<
95
>::
COUNT
,
ByteBits
<
96
>::
COUNT
,
ByteBits
<
97
>::
COUNT
,
ByteBits
<
98
>::
COUNT
,
ByteBits
<
99
>::
COUNT
,
ByteBits
<
100
>::
COUNT
,
ByteBits
<
101
>::
COUNT
,
ByteBits
<
102
>::
COUNT
,
ByteBits
<
103
>::
COUNT
,
ByteBits
<
104
>::
COUNT
,
ByteBits
<
105
>::
COUNT
,
ByteBits
<
106
>::
COUNT
,
ByteBits
<
107
>::
COUNT
,
ByteBits
<
108
>::
COUNT
,
ByteBits
<
109
>::
COUNT
,
ByteBits
<
110
>::
COUNT
,
ByteBits
<
111
>::
COUNT
,
ByteBits
<
112
>::
COUNT
,
ByteBits
<
113
>::
COUNT
,
ByteBits
<
114
>::
COUNT
,
ByteBits
<
115
>::
COUNT
,
ByteBits
<
116
>::
COUNT
,
ByteBits
<
117
>::
COUNT
,
ByteBits
<
118
>::
COUNT
,
ByteBits
<
119
>::
COUNT
,
ByteBits
<
120
>::
COUNT
,
ByteBits
<
121
>::
COUNT
,
ByteBits
<
122
>::
COUNT
,
ByteBits
<
123
>::
COUNT
,
ByteBits
<
124
>::
COUNT
,
ByteBits
<
125
>::
COUNT
,
ByteBits
<
126
>::
COUNT
,
ByteBits
<
127
>::
COUNT
,
ByteBits
<
128
>::
COUNT
,
ByteBits
<
129
>::
COUNT
,
ByteBits
<
130
>::
COUNT
,
ByteBits
<
131
>::
COUNT
,
ByteBits
<
132
>::
COUNT
,
ByteBits
<
133
>::
COUNT
,
ByteBits
<
134
>::
COUNT
,
ByteBits
<
135
>::
COUNT
,
ByteBits
<
136
>::
COUNT
,
ByteBits
<
137
>::
COUNT
,
ByteBits
<
138
>::
COUNT
,
ByteBits
<
139
>::
COUNT
,
ByteBits
<
140
>::
COUNT
,
ByteBits
<
141
>::
COUNT
,
ByteBits
<
142
>::
COUNT
,
ByteBits
<
143
>::
COUNT
,
ByteBits
<
144
>::
COUNT
,
ByteBits
<
145
>::
COUNT
,
ByteBits
<
146
>::
COUNT
,
ByteBits
<
147
>::
COUNT
,
ByteBits
<
148
>::
COUNT
,
ByteBits
<
149
>::
COUNT
,
ByteBits
<
150
>::
COUNT
,
ByteBits
<
151
>::
COUNT
,
ByteBits
<
152
>::
COUNT
,
ByteBits
<
153
>::
COUNT
,
ByteBits
<
154
>::
COUNT
,
ByteBits
<
155
>::
COUNT
,
ByteBits
<
156
>::
COUNT
,
ByteBits
<
157
>::
COUNT
,
ByteBits
<
158
>::
COUNT
,
ByteBits
<
159
>::
COUNT
,
ByteBits
<
160
>::
COUNT
,
ByteBits
<
161
>::
COUNT
,
ByteBits
<
162
>::
COUNT
,
ByteBits
<
163
>::
COUNT
,
ByteBits
<
164
>::
COUNT
,
ByteBits
<
165
>::
COUNT
,
ByteBits
<
166
>::
COUNT
,
ByteBits
<
167
>::
COUNT
,
ByteBits
<
168
>::
COUNT
,
ByteBits
<
169
>::
COUNT
,
ByteBits
<
170
>::
COUNT
,
ByteBits
<
171
>::
COUNT
,
ByteBits
<
172
>::
COUNT
,
ByteBits
<
173
>::
COUNT
,
ByteBits
<
174
>::
COUNT
,
ByteBits
<
175
>::
COUNT
,
ByteBits
<
176
>::
COUNT
,
ByteBits
<
177
>::
COUNT
,
ByteBits
<
178
>::
COUNT
,
ByteBits
<
179
>::
COUNT
,
ByteBits
<
180
>::
COUNT
,
ByteBits
<
181
>::
COUNT
,
ByteBits
<
182
>::
COUNT
,
ByteBits
<
183
>::
COUNT
,
ByteBits
<
184
>::
COUNT
,
ByteBits
<
185
>::
COUNT
,
ByteBits
<
186
>::
COUNT
,
ByteBits
<
187
>::
COUNT
,
ByteBits
<
188
>::
COUNT
,
ByteBits
<
189
>::
COUNT
,
ByteBits
<
190
>::
COUNT
,
ByteBits
<
191
>::
COUNT
,
ByteBits
<
192
>::
COUNT
,
ByteBits
<
193
>::
COUNT
,
ByteBits
<
194
>::
COUNT
,
ByteBits
<
195
>::
COUNT
,
ByteBits
<
196
>::
COUNT
,
ByteBits
<
197
>::
COUNT
,
ByteBits
<
198
>::
COUNT
,
ByteBits
<
199
>::
COUNT
,
ByteBits
<
200
>::
COUNT
,
ByteBits
<
201
>::
COUNT
,
ByteBits
<
202
>::
COUNT
,
ByteBits
<
203
>::
COUNT
,
ByteBits
<
204
>::
COUNT
,
ByteBits
<
205
>::
COUNT
,
ByteBits
<
206
>::
COUNT
,
ByteBits
<
207
>::
COUNT
,
ByteBits
<
208
>::
COUNT
,
ByteBits
<
209
>::
COUNT
,
ByteBits
<
210
>::
COUNT
,
ByteBits
<
211
>::
COUNT
,
ByteBits
<
212
>::
COUNT
,
ByteBits
<
213
>::
COUNT
,
ByteBits
<
214
>::
COUNT
,
ByteBits
<
215
>::
COUNT
,
ByteBits
<
216
>::
COUNT
,
ByteBits
<
217
>::
COUNT
,
ByteBits
<
218
>::
COUNT
,
ByteBits
<
219
>::
COUNT
,
ByteBits
<
220
>::
COUNT
,
ByteBits
<
221
>::
COUNT
,
ByteBits
<
222
>::
COUNT
,
ByteBits
<
223
>::
COUNT
,
ByteBits
<
224
>::
COUNT
,
ByteBits
<
225
>::
COUNT
,
ByteBits
<
226
>::
COUNT
,
ByteBits
<
227
>::
COUNT
,
ByteBits
<
228
>::
COUNT
,
ByteBits
<
229
>::
COUNT
,
ByteBits
<
230
>::
COUNT
,
ByteBits
<
231
>::
COUNT
,
ByteBits
<
232
>::
COUNT
,
ByteBits
<
233
>::
COUNT
,
ByteBits
<
234
>::
COUNT
,
ByteBits
<
235
>::
COUNT
,
ByteBits
<
236
>::
COUNT
,
ByteBits
<
237
>::
COUNT
,
ByteBits
<
238
>::
COUNT
,
ByteBits
<
239
>::
COUNT
,
ByteBits
<
240
>::
COUNT
,
ByteBits
<
241
>::
COUNT
,
ByteBits
<
242
>::
COUNT
,
ByteBits
<
243
>::
COUNT
,
ByteBits
<
244
>::
COUNT
,
ByteBits
<
245
>::
COUNT
,
ByteBits
<
246
>::
COUNT
,
ByteBits
<
247
>::
COUNT
,
ByteBits
<
248
>::
COUNT
,
ByteBits
<
249
>::
COUNT
,
ByteBits
<
250
>::
COUNT
,
ByteBits
<
251
>::
COUNT
,
ByteBits
<
252
>::
COUNT
,
ByteBits
<
253
>::
COUNT
,
ByteBits
<
254
>::
COUNT
,
ByteBits
<
255
>::
COUNT
};
return
table
[
b
];
}
}
// namespace cv
modules/features2d/src/descriptors.cpp
View file @
e406dfee
...
...
@@ -67,6 +67,21 @@ struct RoiPredicate
float
minX
,
minY
,
maxX
,
maxY
;
};
DescriptorExtractor
::~
DescriptorExtractor
()
{}
void
DescriptorExtractor
::
compute
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
{
if
(
image
.
empty
()
||
keypoints
.
empty
()
)
return
;
// Check keypoints are in image. Do filter bad points here?
//for( size_t i = 0; i < keypoints.size(); i++ )
// CV_Assert( Rect(0,0, image.cols, image.rows).contains(keypoints[i].pt) );
computeImpl
(
image
,
keypoints
,
descriptors
);
}
void
DescriptorExtractor
::
compute
(
const
vector
<
Mat
>&
imageCollection
,
vector
<
vector
<
KeyPoint
>
>&
pointCollection
,
vector
<
Mat
>&
descCollection
)
const
{
descCollection
.
resize
(
imageCollection
.
size
()
);
...
...
@@ -74,27 +89,42 @@ void DescriptorExtractor::compute( const vector<Mat>& imageCollection, vector<ve
compute
(
imageCollection
[
i
],
pointCollection
[
i
],
descCollection
[
i
]
);
}
void
DescriptorExtractor
::
read
(
const
FileNode
&
)
{}
void
DescriptorExtractor
::
write
(
FileStorage
&
)
const
{}
void
DescriptorExtractor
::
removeBorderKeypoints
(
vector
<
KeyPoint
>&
keypoints
,
Size
imageSize
,
int
border
Pixels
)
Size
imageSize
,
int
border
Size
)
{
keypoints
.
erase
(
remove_if
(
keypoints
.
begin
(),
keypoints
.
end
(),
RoiPredicate
((
float
)
borderPixels
,
(
float
)
borderPixels
,
(
float
)(
imageSize
.
width
-
borderPixels
),
(
float
)(
imageSize
.
height
-
borderPixels
))),
keypoints
.
end
());
if
(
borderSize
>
0
)
{
keypoints
.
erase
(
remove_if
(
keypoints
.
begin
(),
keypoints
.
end
(),
RoiPredicate
((
float
)
borderSize
,
(
float
)
borderSize
,
(
float
)(
imageSize
.
width
-
borderSize
),
(
float
)(
imageSize
.
height
-
borderSize
))),
keypoints
.
end
()
);
}
}
/****************************************************************************************\
* SiftDescriptorExtractor *
\****************************************************************************************/
SiftDescriptorExtractor
::
SiftDescriptorExtractor
(
const
SIFT
::
DescriptorParams
&
descriptorParams
,
const
SIFT
::
CommonParams
&
commonParams
)
:
sift
(
descriptorParams
.
magnification
,
descriptorParams
.
isNormalize
,
descriptorParams
.
recalculateAngles
,
commonParams
.
nOctaves
,
commonParams
.
nOctaveLayers
,
commonParams
.
firstOctave
,
commonParams
.
angleMode
)
{}
SiftDescriptorExtractor
::
SiftDescriptorExtractor
(
double
magnification
,
bool
isNormalize
,
bool
recalculateAngles
,
int
nOctaves
,
int
nOctaveLayers
,
int
firstOctave
,
int
angleMode
)
:
sift
(
magnification
,
isNormalize
,
recalculateAngles
,
nOctaves
,
nOctaveLayers
,
firstOctave
,
angleMode
)
{}
void
SiftDescriptorExtractor
::
compute
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
void
SiftDescriptorExtractor
::
compute
Impl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
{
bool
useProvidedKeypoints
=
true
;
Mat
grayImage
=
image
;
...
...
@@ -131,6 +161,16 @@ void SiftDescriptorExtractor::write (FileStorage &fs) const
fs
<<
"angleMode"
<<
commParams
.
angleMode
;
}
int
SiftDescriptorExtractor
::
descriptorSize
()
const
{
return
sift
.
descriptorSize
();
}
int
SiftDescriptorExtractor
::
descriptorType
()
const
{
return
CV_32FC1
;
}
/****************************************************************************************\
* SurfDescriptorExtractor *
\****************************************************************************************/
...
...
@@ -139,9 +179,9 @@ SurfDescriptorExtractor::SurfDescriptorExtractor( int nOctaves,
:
surf
(
0.0
,
nOctaves
,
nOctaveLayers
,
extended
)
{}
void
SurfDescriptorExtractor
::
compute
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
void
SurfDescriptorExtractor
::
compute
Impl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
{
// Compute descriptors for given keypoints
vector
<
float
>
_descriptors
;
...
...
@@ -175,11 +215,21 @@ void SurfDescriptorExtractor::write( FileStorage &fs ) const
fs
<<
"extended"
<<
surf
.
extended
;
}
int
SurfDescriptorExtractor
::
descriptorSize
()
const
{
return
surf
.
descriptorSize
();
}
int
SurfDescriptorExtractor
::
descriptorType
()
const
{
return
CV_32FC1
;
}
/****************************************************************************************\
* OpponentColorDescriptorExtractor *
\****************************************************************************************/
OpponentColorDescriptorExtractor
::
OpponentColorDescriptorExtractor
(
const
Ptr
<
DescriptorExtractor
>&
_dextractor
)
:
de
xtractor
(
_de
xtractor
)
OpponentColorDescriptorExtractor
::
OpponentColorDescriptorExtractor
(
const
Ptr
<
DescriptorExtractor
>&
_de
scriptorE
xtractor
)
:
de
scriptorExtractor
(
_descriptorE
xtractor
)
{}
void
convertBGRImageToOpponentColorSpace
(
const
Mat
&
bgrImage
,
vector
<
Mat
>&
opponentChannels
)
...
...
@@ -246,33 +296,42 @@ void convertBGRImageToOpponentColorSpace( const Mat& bgrImage, vector<Mat>& oppo
}
}
void
OpponentColorDescriptorExtractor
::
compute
(
const
Mat
&
bgrImage
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
void
OpponentColorDescriptorExtractor
::
compute
Impl
(
const
Mat
&
bgrImage
,
vector
<
KeyPoint
>&
keypoints
,
Mat
&
descriptors
)
const
{
vector
<
Mat
>
opponentChannels
;
convertBGRImageToOpponentColorSpace
(
bgrImage
,
opponentChannels
);
// Compute descriptors three times, once for each Opponent channel
// and concatenate into a single color surf descriptor
int
descriptorSize
=
dextractor
->
descriptorSize
();
int
descriptorSize
=
de
scriptorE
xtractor
->
descriptorSize
();
descriptors
.
create
(
static_cast
<
int
>
(
keypoints
.
size
()),
3
*
descriptorSize
,
CV_32FC1
);
for
(
int
i
=
0
;
i
<
3
/*channel count*/
;
i
++
)
{
CV_Assert
(
opponentChannels
[
i
].
type
()
==
CV_8UC1
);
Mat
opponentDescriptors
=
descriptors
.
colRange
(
i
*
descriptorSize
,
(
i
+
1
)
*
descriptorSize
);
dextractor
->
compute
(
opponentChannels
[
i
],
keypoints
,
opponentDescriptors
);
de
scriptorE
xtractor
->
compute
(
opponentChannels
[
i
],
keypoints
,
opponentDescriptors
);
}
}
void
OpponentColorDescriptorExtractor
::
read
(
const
FileNode
&
fn
)
{
de
xtractor
->
read
(
fn
);
de
scriptorExtractor
->
read
(
fn
);
}
void
OpponentColorDescriptorExtractor
::
write
(
FileStorage
&
fs
)
const
{
dextractor
->
write
(
fs
);
descriptorExtractor
->
write
(
fs
);
}
int
OpponentColorDescriptorExtractor
::
descriptorSize
()
const
{
return
3
*
descriptorExtractor
->
descriptorSize
();
}
int
OpponentColorDescriptorExtractor
::
descriptorType
()
const
{
return
descriptorExtractor
->
descriptorType
();
}
/****************************************************************************************\
* Factory function for descriptor extractor creating *
\****************************************************************************************/
...
...
modules/features2d/src/detectors.cpp
View file @
e406dfee
...
...
@@ -61,6 +61,21 @@ struct MaskPredicate
const
Mat
&
mask
;
};
FeatureDetector
::~
FeatureDetector
()
{}
void
FeatureDetector
::
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
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
(
const
vector
<
Mat
>&
imageCollection
,
vector
<
vector
<
KeyPoint
>
>&
pointCollection
,
const
vector
<
Mat
>&
masks
)
const
{
pointCollection
.
resize
(
imageCollection
.
size
()
);
...
...
@@ -76,6 +91,12 @@ void FeatureDetector::removeInvalidPoints( const Mat& mask, vector<KeyPoint>& ke
keypoints
.
erase
(
remove_if
(
keypoints
.
begin
(),
keypoints
.
end
(),
MaskPredicate
(
mask
)),
keypoints
.
end
());
};
void
FeatureDetector
::
read
(
const
FileNode
&
)
{}
void
FeatureDetector
::
write
(
FileStorage
&
)
const
{}
/*
* FastFeatureDetector
*/
...
...
@@ -95,7 +116,7 @@ void FastFeatureDetector::write (FileStorage& fs) const
fs
<<
"nonmaxSuppression"
<<
nonmaxSuppression
;
}
void
FastFeatureDetector
::
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
void
FastFeatureDetector
::
detect
Impl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
{
Mat
grayImage
=
image
;
if
(
image
.
type
()
!=
CV_8U
)
cvtColor
(
image
,
grayImage
,
CV_BGR2GRAY
);
...
...
@@ -106,14 +127,13 @@ void FastFeatureDetector::detect( const Mat& image, vector<KeyPoint>& keypoints,
/*
* GoodFeaturesToTrackDetector
*/
GoodFeaturesToTrackDetector
::
GoodFeaturesToTrackDetector
(
int
_maxCorners
,
double
_qualityLevel
,
\
double
_minDistance
,
int
_blockSize
,
bool
_useHarrisDetector
,
double
_k
)
:
maxCorners
(
_maxCorners
),
qualityLevel
(
_qualityLevel
),
minDistance
(
_minDistance
),
blockSize
(
_blockSize
),
useHarrisDetector
(
_useHarrisDetector
),
k
(
_k
)
GoodFeaturesToTrackDetector
::
Params
::
Params
(
int
_maxCorners
,
double
_qualityLevel
,
double
_minDistance
,
int
_blockSize
,
bool
_useHarrisDetector
,
double
_k
)
:
maxCorners
(
_maxCorners
),
qualityLevel
(
_qualityLevel
),
minDistance
(
_minDistance
),
blockSize
(
_blockSize
),
useHarrisDetector
(
_useHarrisDetector
),
k
(
_k
)
{}
void
GoodFeaturesToTrackDetector
::
read
(
const
FileNode
&
fn
)
void
GoodFeaturesToTrackDetector
::
Params
::
read
(
const
FileNode
&
fn
)
{
maxCorners
=
fn
[
"maxCorners"
];
qualityLevel
=
fn
[
"qualityLevel"
];
...
...
@@ -123,7 +143,7 @@ void GoodFeaturesToTrackDetector::read (const FileNode& fn)
k
=
fn
[
"k"
];
}
void
GoodFeaturesToTrackDetector
::
write
(
FileStorage
&
fs
)
const
void
GoodFeaturesToTrackDetector
::
Params
::
write
(
FileStorage
&
fs
)
const
{
fs
<<
"maxCorners"
<<
maxCorners
;
fs
<<
"qualityLevel"
<<
qualityLevel
;
...
...
@@ -133,20 +153,40 @@ void GoodFeaturesToTrackDetector::write (FileStorage& fs) const
fs
<<
"k"
<<
k
;
}
void
GoodFeaturesToTrackDetector
::
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
GoodFeaturesToTrackDetector
::
GoodFeaturesToTrackDetector
(
const
Params
&
_params
)
:
params
(
_params
)
{}
GoodFeaturesToTrackDetector
::
GoodFeaturesToTrackDetector
(
int
maxCorners
,
double
qualityLevel
,
double
minDistance
,
int
blockSize
,
bool
useHarrisDetector
,
double
k
)
{
params
=
Params
(
maxCorners
,
qualityLevel
,
minDistance
,
blockSize
,
useHarrisDetector
,
k
);
}
void
GoodFeaturesToTrackDetector
::
read
(
const
FileNode
&
fn
)
{
params
.
read
(
fn
);
}
void
GoodFeaturesToTrackDetector
::
write
(
FileStorage
&
fs
)
const
{
params
.
write
(
fs
);
}
void
GoodFeaturesToTrackDetector
::
detectImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
{
Mat
grayImage
=
image
;
if
(
image
.
type
()
!=
CV_8U
)
cvtColor
(
image
,
grayImage
,
CV_BGR2GRAY
);
vector
<
Point2f
>
corners
;
goodFeaturesToTrack
(
grayImage
,
corners
,
maxCorners
,
qualityLevel
,
minDistance
,
mask
,
blockSize
,
useHarrisDetector
,
k
);
goodFeaturesToTrack
(
grayImage
,
corners
,
params
.
maxCorners
,
params
.
qualityLevel
,
params
.
minDistance
,
mask
,
params
.
blockSize
,
params
.
useHarrisDetector
,
params
.
k
);
keypoints
.
resize
(
corners
.
size
());
vector
<
Point2f
>::
const_iterator
corner_it
=
corners
.
begin
();
vector
<
KeyPoint
>::
iterator
keypoint_it
=
keypoints
.
begin
();
for
(
;
corner_it
!=
corners
.
end
();
++
corner_it
,
++
keypoint_it
)
{
*
keypoint_it
=
KeyPoint
(
*
corner_it
,
(
float
)
blockSize
);
*
keypoint_it
=
KeyPoint
(
*
corner_it
,
(
float
)
params
.
blockSize
);
}
}
...
...
@@ -198,13 +238,12 @@ void MserFeatureDetector::write (FileStorage& fs) const
}
void
MserFeatureDetector
::
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
void
MserFeatureDetector
::
detect
Impl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
{
vector
<
vector
<
Point
>
>
msers
;
mser
(
image
,
msers
,
mask
);
keypoints
.
clear
();
vector
<
vector
<
Point
>
>::
const_iterator
contour_it
=
msers
.
begin
();
for
(
;
contour_it
!=
msers
.
end
();
++
contour_it
)
{
...
...
@@ -220,6 +259,12 @@ void MserFeatureDetector::detect( const Mat& image, vector<KeyPoint>& keypoints,
/*
* StarFeatureDetector
*/
StarFeatureDetector
::
StarFeatureDetector
(
const
CvStarDetectorParams
&
params
)
:
star
(
params
.
maxSize
,
params
.
responseThreshold
,
params
.
lineThresholdProjected
,
params
.
lineThresholdBinarized
,
params
.
suppressNonmaxSize
)
{}
StarFeatureDetector
::
StarFeatureDetector
(
int
maxSize
,
int
responseThreshold
,
int
lineThresholdProjected
,
int
lineThresholdBinarized
,
...
...
@@ -251,7 +296,7 @@ void StarFeatureDetector::write (FileStorage& fs) const
fs
<<
"suppressNonmaxSize"
<<
star
.
suppressNonmaxSize
;
}
void
StarFeatureDetector
::
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
void
StarFeatureDetector
::
detect
Impl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
{
Mat
grayImage
=
image
;
if
(
image
.
type
()
!=
CV_8U
)
cvtColor
(
image
,
grayImage
,
CV_BGR2GRAY
);
...
...
@@ -263,13 +308,20 @@ void StarFeatureDetector::detect( const Mat& image, vector<KeyPoint>& keypoints,
/*
* SiftFeatureDetector
*/
SiftFeatureDetector
::
SiftFeatureDetector
(
double
threshold
,
double
edgeThreshold
,
int
nOctaves
,
int
nOctaveLayers
,
int
firstOctave
,
int
angleMode
)
:
SiftFeatureDetector
::
SiftFeatureDetector
(
const
SIFT
::
DetectorParams
&
detectorParams
,
const
SIFT
::
CommonParams
&
commonParams
)
:
sift
(
detectorParams
.
threshold
,
detectorParams
.
edgeThreshold
,
commonParams
.
nOctaves
,
commonParams
.
nOctaveLayers
,
commonParams
.
firstOctave
,
commonParams
.
angleMode
)
{
}
SiftFeatureDetector
::
SiftFeatureDetector
(
double
threshold
,
double
edgeThreshold
,
int
nOctaves
,
int
nOctaveLayers
,
int
firstOctave
,
int
angleMode
)
:
sift
(
threshold
,
edgeThreshold
,
nOctaves
,
nOctaveLayers
,
firstOctave
,
angleMode
)
{
}
void
SiftFeatureDetector
::
read
(
const
FileNode
&
fn
)
void
SiftFeatureDetector
::
read
(
const
FileNode
&
fn
)
{
double
threshold
=
fn
[
"threshold"
];
double
edgeThreshold
=
fn
[
"edgeThreshold"
];
...
...
@@ -296,7 +348,7 @@ void SiftFeatureDetector::write (FileStorage& fs) const
}
void
SiftFeatureDetector
::
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
void
SiftFeatureDetector
::
detect
Impl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
{
Mat
grayImage
=
image
;
if
(
image
.
type
()
!=
CV_8U
)
cvtColor
(
image
,
grayImage
,
CV_BGR2GRAY
);
...
...
@@ -329,7 +381,7 @@ void SurfFeatureDetector::write (FileStorage& fs) const
fs
<<
"octaveLayers"
<<
surf
.
nOctaveLayers
;
}
void
SurfFeatureDetector
::
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
void
SurfFeatureDetector
::
detect
Impl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
{
Mat
grayImage
=
image
;
if
(
image
.
type
()
!=
CV_8U
)
cvtColor
(
image
,
grayImage
,
CV_BGR2GRAY
);
...
...
@@ -340,14 +392,24 @@ void SurfFeatureDetector::detect( const Mat& image, vector<KeyPoint>& keypoints,
/*
* DenseFeatureDetector
*/
void
DenseFeatureDetector
::
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
{
keypoints
.
clear
();
DenseFeatureDetector
::
Params
::
Params
(
float
_initFeatureScale
,
int
_featureScaleLevels
,
float
_featureScaleMul
,
int
_initXyStep
,
int
_initImgBound
,
bool
_varyXyStepWithScale
,
bool
_varyImgBoundWithScale
)
:
initFeatureScale
(
_initFeatureScale
),
featureScaleLevels
(
_featureScaleLevels
),
featureScaleMul
(
_featureScaleMul
),
initXyStep
(
_initXyStep
),
initImgBound
(
_initImgBound
),
varyXyStepWithScale
(
_varyXyStepWithScale
),
varyImgBoundWithScale
(
_varyImgBoundWithScale
)
{}
DenseFeatureDetector
::
DenseFeatureDetector
(
const
DenseFeatureDetector
::
Params
&
_params
)
:
params
(
_params
)
{}
float
curScale
=
initFeatureScale
;
int
curStep
=
initXyStep
;
int
curBound
=
initImgBound
;
for
(
int
curLevel
=
0
;
curLevel
<
featureScaleLevels
;
curLevel
++
)
void
DenseFeatureDetector
::
detectImpl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
{
float
curScale
=
params
.
initFeatureScale
;
int
curStep
=
params
.
initXyStep
;
int
curBound
=
params
.
initImgBound
;
for
(
int
curLevel
=
0
;
curLevel
<
params
.
featureScaleLevels
;
curLevel
++
)
{
for
(
int
x
=
curBound
;
x
<
image
.
cols
-
curBound
;
x
+=
curStep
)
{
...
...
@@ -357,9 +419,9 @@ void DenseFeatureDetector::detect( const Mat& image, vector<KeyPoint>& keypoints
}
}
curScale
=
curScale
*
featureScaleMul
;
if
(
varyXyStepWithScale
)
curStep
=
static_cast
<
int
>
(
curStep
*
featureScaleMul
+
0.5
f
);
if
(
varyImgBoundWithScale
)
curBound
=
static_cast
<
int
>
(
curBound
*
featureScaleMul
+
0.5
f
);
curScale
=
curScale
*
params
.
featureScaleMul
;
if
(
params
.
varyXyStepWithScale
)
curStep
=
static_cast
<
int
>
(
curStep
*
params
.
featureScaleMul
+
0.5
f
);
if
(
params
.
varyImgBoundWithScale
)
curBound
=
static_cast
<
int
>
(
curBound
*
params
.
featureScaleMul
+
0.5
f
);
}
removeInvalidPoints
(
mask
,
keypoints
);
...
...
@@ -391,9 +453,8 @@ void keepStrongest( int N, vector<KeyPoint>& keypoints )
}
}
void
GridAdaptedFeatureDetector
::
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
void
GridAdaptedFeatureDetector
::
detect
Impl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
{
keypoints
.
clear
();
keypoints
.
reserve
(
maxTotalKeypoints
);
int
maxPerCell
=
maxTotalKeypoints
/
(
gridRows
*
gridCols
);
...
...
@@ -430,7 +491,7 @@ PyramidAdaptedFeatureDetector::PyramidAdaptedFeatureDetector( const Ptr<FeatureD
:
detector
(
_detector
),
levels
(
_levels
)
{}
void
PyramidAdaptedFeatureDetector
::
detect
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
void
PyramidAdaptedFeatureDetector
::
detect
Impl
(
const
Mat
&
image
,
vector
<
KeyPoint
>&
keypoints
,
const
Mat
&
mask
)
const
{
Mat
src
=
image
;
for
(
int
l
=
0
,
multiplier
=
1
;
l
<=
levels
;
++
l
,
multiplier
*=
2
)
...
...
@@ -463,12 +524,11 @@ Ptr<FeatureDetector> createFeatureDetector( const string& detectorType )
FeatureDetector
*
fd
=
0
;
if
(
!
detectorType
.
compare
(
"FAST"
)
)
{
fd
=
new
FastFeatureDetector
(
10
/*threshold*/
,
true
/*nonmax_suppression*/
);
fd
=
new
FastFeatureDetector
();
}
else
if
(
!
detectorType
.
compare
(
"STAR"
)
)
{
fd
=
new
StarFeatureDetector
(
16
/*max_size*/
,
5
/*response_threshold*/
,
10
/*line_threshold_projected*/
,
8
/*line_threshold_binarized*/
,
5
/*suppress_nonmax_size*/
);
fd
=
new
StarFeatureDetector
();
}
else
if
(
!
detectorType
.
compare
(
"SIFT"
)
)
{
...
...
@@ -477,23 +537,21 @@ Ptr<FeatureDetector> createFeatureDetector( const string& detectorType )
}
else
if
(
!
detectorType
.
compare
(
"SURF"
)
)
{
fd
=
new
SurfFeatureDetector
(
400.
/*hessian_threshold*/
,
3
/*octaves*/
,
4
/*octave_layers*/
);
fd
=
new
SurfFeatureDetector
();
}
else
if
(
!
detectorType
.
compare
(
"MSER"
)
)
{
fd
=
new
MserFeatureDetector
(
5
/*delta*/
,
60
/*min_area*/
,
14400
/*_max_area*/
,
0.25
f
/*max_variation*/
,
0.2
/*min_diversity*/
,
200
/*max_evolution*/
,
1.01
/*area_threshold*/
,
0.003
/*min_margin*/
,
5
/*edge_blur_size*/
);
fd
=
new
MserFeatureDetector
();
}
else
if
(
!
detectorType
.
compare
(
"GFTT"
)
)
{
fd
=
new
GoodFeaturesToTrackDetector
(
1000
/*maxCorners*/
,
0.01
/*qualityLevel*/
,
1.
/*minDistance*/
,
3
/*int _blockSize*/
,
false
/*useHarrisDetector*/
,
0.04
/*k*/
);
fd
=
new
GoodFeaturesToTrackDetector
();
}
else
if
(
!
detectorType
.
compare
(
"HARRIS"
)
)
{
fd
=
new
GoodFeaturesToTrackDetector
(
1000
/*maxCorners*/
,
0.01
/*qualityLevel*/
,
1.
/*minDistance*/
,
3
/*int _blockSize*/
,
true
/*useHarrisDetector*/
,
0.04
/*k*/
);
GoodFeaturesToTrackDetector
::
Params
params
;
params
.
useHarrisDetector
=
true
;
fd
=
new
GoodFeaturesToTrackDetector
(
params
);
}
return
fd
;
}
...
...
modules/features2d/src/matchers.cpp
View file @
e406dfee
...
...
@@ -71,11 +71,23 @@ Mat windowedMatchingMask( const vector<KeyPoint>& keypoints1, const vector<KeyPo
/****************************************************************************************\
* DescriptorMatcher *
\****************************************************************************************/
void
DescriptorMatcher
::
DescriptorCollection
::
set
(
const
vector
<
Mat
>&
descCollection
)
DescriptorMatcher
::
DescriptorCollection
::
DescriptorCollection
()
{}
DescriptorMatcher
::
DescriptorCollection
::
DescriptorCollection
(
const
DescriptorCollection
&
collection
)
{
mergedDescriptors
=
collection
.
mergedDescriptors
.
clone
();
copy
(
collection
.
startIdxs
.
begin
(),
collection
.
startIdxs
.
begin
(),
startIdxs
.
begin
()
);
}
DescriptorMatcher
::
DescriptorCollection
::~
DescriptorCollection
()
{}
void
DescriptorMatcher
::
DescriptorCollection
::
set
(
const
vector
<
Mat
>&
descriptors
)
{
clear
();
size_t
imageCount
=
desc
Collection
.
size
();
size_t
imageCount
=
desc
riptors
.
size
();
CV_Assert
(
imageCount
>
0
);
startIdxs
.
resize
(
imageCount
);
...
...
@@ -86,35 +98,35 @@ void DescriptorMatcher::DescriptorCollection::set( const vector<Mat>& descCollec
for
(
size_t
i
=
1
;
i
<
imageCount
;
i
++
)
{
int
s
=
0
;
if
(
!
desc
Collection
[
i
-
1
].
empty
()
)
if
(
!
desc
riptors
[
i
-
1
].
empty
()
)
{
dim
=
desc
Collection
[
i
-
1
].
cols
;
type
=
desc
Collection
[
i
-
1
].
type
();
s
=
desc
Collection
[
i
-
1
].
rows
;
dim
=
desc
riptors
[
i
-
1
].
cols
;
type
=
desc
riptors
[
i
-
1
].
type
();
s
=
desc
riptors
[
i
-
1
].
rows
;
}
startIdxs
[
i
]
=
startIdxs
[
i
-
1
]
+
s
;
}
if
(
imageCount
==
1
)
{
if
(
desc
Collection
[
0
].
empty
()
)
return
;
if
(
desc
riptors
[
0
].
empty
()
)
return
;
dim
=
desc
Collection
[
0
].
cols
;
type
=
desc
Collection
[
0
].
type
();
dim
=
desc
riptors
[
0
].
cols
;
type
=
desc
riptors
[
0
].
type
();
}
assert
(
dim
>
0
);
int
count
=
startIdxs
[
imageCount
-
1
]
+
desc
Collection
[
imageCount
-
1
].
rows
;
int
count
=
startIdxs
[
imageCount
-
1
]
+
desc
riptors
[
imageCount
-
1
].
rows
;
if
(
count
>
0
)
{
dmatrix
.
create
(
count
,
dim
,
type
);
mergedDescriptors
.
create
(
count
,
dim
,
type
);
for
(
size_t
i
=
0
;
i
<
imageCount
;
i
++
)
{
if
(
!
desc
Collection
[
i
].
empty
()
)
if
(
!
desc
riptors
[
i
].
empty
()
)
{
CV_Assert
(
desc
Collection
[
i
].
cols
==
dim
&&
descCollection
[
i
].
type
()
==
type
);
Mat
m
=
dmatrix
.
rowRange
(
startIdxs
[
i
],
startIdxs
[
i
]
+
descCollection
[
i
].
rows
);
desc
Collection
[
i
].
copyTo
(
m
);
CV_Assert
(
desc
riptors
[
i
].
cols
==
dim
&&
descriptors
[
i
].
type
()
==
type
);
Mat
m
=
mergedDescriptors
.
rowRange
(
startIdxs
[
i
],
startIdxs
[
i
]
+
descriptors
[
i
].
rows
);
desc
riptors
[
i
].
copyTo
(
m
);
}
}
}
...
...
@@ -123,7 +135,7 @@ void DescriptorMatcher::DescriptorCollection::set( const vector<Mat>& descCollec
void
DescriptorMatcher
::
DescriptorCollection
::
clear
()
{
startIdxs
.
clear
();
dmatrix
.
release
();
mergedDescriptors
.
release
();
}
const
Mat
DescriptorMatcher
::
DescriptorCollection
::
getDescriptor
(
int
imgIdx
,
int
localDescIdx
)
const
...
...
@@ -135,10 +147,15 @@ const Mat DescriptorMatcher::DescriptorCollection::getDescriptor( int imgIdx, in
return
getDescriptor
(
globalIdx
);
}
const
Mat
&
DescriptorMatcher
::
DescriptorCollection
::
getDescriptors
()
const
{
return
mergedDescriptors
;
}
const
Mat
DescriptorMatcher
::
DescriptorCollection
::
getDescriptor
(
int
globalDescIdx
)
const
{
CV_Assert
(
globalDescIdx
<
size
()
);
return
dmatrix
.
row
(
globalDescIdx
);
return
mergedDescriptors
.
row
(
globalDescIdx
);
}
void
DescriptorMatcher
::
DescriptorCollection
::
getLocalIdx
(
int
globalDescIdx
,
int
&
imgIdx
,
int
&
localDescIdx
)
const
...
...
@@ -157,6 +174,11 @@ void DescriptorMatcher::DescriptorCollection::getLocalIdx( int globalDescIdx, in
localDescIdx
=
globalDescIdx
-
startIdxs
[
imgIdx
];
}
int
DescriptorMatcher
::
DescriptorCollection
::
size
()
const
{
return
mergedDescriptors
.
rows
;
}
/*
* DescriptorMatcher
*/
...
...
@@ -172,9 +194,17 @@ void convertMatches( const vector<vector<DMatch> >& knnMatches, vector<DMatch>&
}
}
void
DescriptorMatcher
::
add
(
const
vector
<
Mat
>&
descCollection
)
DescriptorMatcher
::~
DescriptorMatcher
()
{}
void
DescriptorMatcher
::
add
(
const
vector
<
Mat
>&
descriptors
)
{
trainDescCollection
.
insert
(
trainDescCollection
.
end
(),
descriptors
.
begin
(),
descriptors
.
end
()
);
}
const
vector
<
Mat
>&
DescriptorMatcher
::
getTrainDescriptors
()
const
{
trainDescCollection
.
insert
(
trainDescCollection
.
end
(),
descCollection
.
begin
(),
descCollection
.
end
()
)
;
return
trainDescCollection
;
}
void
DescriptorMatcher
::
clear
()
...
...
@@ -182,67 +212,134 @@ void DescriptorMatcher::clear()
trainDescCollection
.
clear
();
}
void
DescriptorMatcher
::
match
(
const
Mat
&
queryDescs
,
const
Mat
&
trainDescs
,
vector
<
DMatch
>&
matches
,
const
Mat
&
mask
)
const
bool
DescriptorMatcher
::
empty
()
const
{
return
trainDescCollection
.
size
()
==
0
;
}
void
DescriptorMatcher
::
train
()
{}
void
DescriptorMatcher
::
match
(
const
Mat
&
queryDescriptors
,
const
Mat
&
trainDescriptors
,
vector
<
DMatch
>&
matches
,
const
Mat
&
mask
)
const
{
Ptr
<
DescriptorMatcher
>
tempMatcher
=
clone
WithoutData
(
);
tempMatcher
->
add
(
vector
<
Mat
>
(
1
,
trainDescs
)
);
tempMatcher
->
match
(
queryDescs
,
matches
,
vector
<
Mat
>
(
1
,
mask
)
);
Ptr
<
DescriptorMatcher
>
tempMatcher
=
clone
(
true
);
tempMatcher
->
add
(
vector
<
Mat
>
(
1
,
trainDesc
riptor
s
)
);
tempMatcher
->
match
(
queryDesc
riptor
s
,
matches
,
vector
<
Mat
>
(
1
,
mask
)
);
}
void
DescriptorMatcher
::
knnMatch
(
const
Mat
&
queryDesc
s
,
const
Mat
&
trainDesc
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
void
DescriptorMatcher
::
knnMatch
(
const
Mat
&
queryDesc
riptors
,
const
Mat
&
trainDescriptor
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
const
Mat
&
mask
,
bool
compactResult
)
const
{
Ptr
<
DescriptorMatcher
>
tempMatcher
=
clone
WithoutData
(
);
tempMatcher
->
add
(
vector
<
Mat
>
(
1
,
trainDescs
)
);
tempMatcher
->
knnMatch
(
queryDescs
,
matches
,
knn
,
vector
<
Mat
>
(
1
,
mask
),
compactResult
);
Ptr
<
DescriptorMatcher
>
tempMatcher
=
clone
(
true
);
tempMatcher
->
add
(
vector
<
Mat
>
(
1
,
trainDesc
riptor
s
)
);
tempMatcher
->
knnMatch
(
queryDesc
riptor
s
,
matches
,
knn
,
vector
<
Mat
>
(
1
,
mask
),
compactResult
);
}
void
DescriptorMatcher
::
radiusMatch
(
const
Mat
&
queryDesc
s
,
const
Mat
&
trainDesc
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
void
DescriptorMatcher
::
radiusMatch
(
const
Mat
&
queryDesc
riptors
,
const
Mat
&
trainDescriptor
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
Mat
&
mask
,
bool
compactResult
)
const
{
Ptr
<
DescriptorMatcher
>
tempMatcher
=
clone
WithoutData
(
);
tempMatcher
->
add
(
vector
<
Mat
>
(
1
,
trainDescs
)
);
tempMatcher
->
radiusMatch
(
queryDescs
,
matches
,
maxDistance
,
vector
<
Mat
>
(
1
,
mask
),
compactResult
);
Ptr
<
DescriptorMatcher
>
tempMatcher
=
clone
(
true
);
tempMatcher
->
add
(
vector
<
Mat
>
(
1
,
trainDesc
riptor
s
)
);
tempMatcher
->
radiusMatch
(
queryDesc
riptor
s
,
matches
,
maxDistance
,
vector
<
Mat
>
(
1
,
mask
),
compactResult
);
}
void
DescriptorMatcher
::
match
(
const
Mat
&
queryDescs
,
vector
<
DMatch
>&
matches
,
const
vector
<
Mat
>&
masks
)
void
DescriptorMatcher
::
match
(
const
Mat
&
queryDesc
riptor
s
,
vector
<
DMatch
>&
matches
,
const
vector
<
Mat
>&
masks
)
{
vector
<
vector
<
DMatch
>
>
knnMatches
;
knnMatch
(
queryDescs
,
knnMatches
,
1
,
masks
,
true
/*compactResult*/
);
knnMatch
(
queryDesc
riptor
s
,
knnMatches
,
1
,
masks
,
true
/*compactResult*/
);
convertMatches
(
knnMatches
,
matches
);
}
void
DescriptorMatcher
::
knnMatch
(
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
void
DescriptorMatcher
::
checkMasks
(
const
vector
<
Mat
>&
masks
,
int
queryDescriptorsCount
)
const
{
if
(
isMaskSupported
()
&&
!
masks
.
empty
()
)
{
// Check masks
size_t
imageCount
=
trainDescCollection
.
size
();
CV_Assert
(
masks
.
size
()
==
imageCount
);
for
(
size_t
i
=
0
;
i
<
imageCount
;
i
++
)
{
if
(
!
masks
[
i
].
empty
()
&&
!
trainDescCollection
[
i
].
empty
()
)
{
CV_Assert
(
masks
[
i
].
rows
==
queryDescriptorsCount
&&
masks
[
i
].
cols
==
trainDescCollection
[
i
].
rows
&&
masks
[
i
].
type
()
==
CV_8UC1
);
}
}
}
}
void
DescriptorMatcher
::
knnMatch
(
const
Mat
&
queryDescriptors
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
{
matches
.
empty
();
if
(
empty
()
||
queryDescriptors
.
empty
()
)
return
;
CV_Assert
(
knn
>
0
);
checkMasks
(
masks
,
queryDescriptors
.
rows
);
train
();
knnMatchImpl
(
queryDescs
,
matches
,
knn
,
masks
,
compactResult
);
knnMatchImpl
(
queryDesc
riptor
s
,
matches
,
knn
,
masks
,
compactResult
);
}
void
DescriptorMatcher
::
radiusMatch
(
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
void
DescriptorMatcher
::
radiusMatch
(
const
Mat
&
queryDesc
riptor
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
{
matches
.
empty
();
if
(
empty
()
||
queryDescriptors
.
empty
()
)
return
;
CV_Assert
(
maxDistance
>
std
::
numeric_limits
<
float
>::
epsilon
()
);
checkMasks
(
masks
,
queryDescriptors
.
rows
);
train
();
radiusMatchImpl
(
queryDescs
,
matches
,
maxDistance
,
masks
,
compactResult
);
radiusMatchImpl
(
queryDescriptors
,
matches
,
maxDistance
,
masks
,
compactResult
);
}
void
DescriptorMatcher
::
read
(
const
FileNode
&
)
{}
void
DescriptorMatcher
::
write
(
FileStorage
&
)
const
{}
bool
DescriptorMatcher
::
isPossibleMatch
(
const
Mat
&
mask
,
int
queryIdx
,
int
trainIdx
)
{
return
mask
.
empty
()
||
mask
.
at
<
uchar
>
(
queryIdx
,
trainIdx
);
}
bool
DescriptorMatcher
::
isMaskedOut
(
const
vector
<
Mat
>&
masks
,
int
queryIdx
)
{
size_t
outCount
=
0
;
for
(
size_t
i
=
0
;
i
<
masks
.
size
();
i
++
)
{
if
(
!
masks
[
i
].
empty
()
&&
(
countNonZero
(
masks
[
i
].
row
(
queryIdx
))
==
0
)
)
outCount
++
;
}
return
!
masks
.
empty
()
&&
outCount
==
masks
.
size
()
;
}
template
<>
void
BruteForceMatcher
<
L2
<
float
>
>::
knnMatchImpl
(
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
void
BruteForceMatcher
<
L2
<
float
>
>::
knnMatchImpl
(
const
Mat
&
queryDesc
riptor
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
{
#ifndef HAVE_EIGEN2
bfKnnMatchImpl
(
*
this
,
queryDesc
s
,
matches
,
knn
,
masks
,
compactResult
);
commonKnnMatchImpl
(
*
this
,
queryDescriptor
s
,
matches
,
knn
,
masks
,
compactResult
);
#else
CV_Assert
(
queryDesc
s
.
type
()
==
CV_32FC1
||
queryDesc
s
.
empty
()
);
CV_Assert
(
queryDesc
riptors
.
type
()
==
CV_32FC1
||
queryDescriptor
s
.
empty
()
);
CV_Assert
(
masks
.
empty
()
||
masks
.
size
()
==
trainDescCollection
.
size
()
);
matches
.
reserve
(
queryDescs
.
rows
);
matches
.
reserve
(
queryDesc
riptor
s
.
rows
);
size_t
imgCount
=
trainDescCollection
.
size
();
Eigen
::
Matrix
<
float
,
Eigen
::
Dynamic
,
Eigen
::
Dynamic
>
e_query_t
;
vector
<
Eigen
::
Matrix
<
float
,
Eigen
::
Dynamic
,
Eigen
::
Dynamic
>
>
e_trainCollection
(
trainDescCollection
.
size
());
vector
<
Eigen
::
Matrix
<
float
,
Eigen
::
Dynamic
,
Eigen
::
Dynamic
>
>
e_trainNorms2
(
trainDescCollection
.
size
());
cv2eigen
(
queryDescs
.
t
(),
e_query_t
);
cv2eigen
(
queryDesc
riptor
s
.
t
(),
e_query_t
);
for
(
size_t
i
=
0
;
i
<
trainDescCollection
.
size
();
i
++
)
{
cv2eigen
(
trainDescCollection
[
i
],
e_trainCollection
[
i
]
);
...
...
@@ -251,7 +348,7 @@ void BruteForceMatcher<L2<float> >::knnMatchImpl( const Mat& queryDescs, vector<
vector
<
Eigen
::
Matrix
<
float
,
Eigen
::
Dynamic
,
1
>
>
e_allDists
(
imgCount
);
// distances between one query descriptor and all train descriptors
for
(
int
qIdx
=
0
;
qIdx
<
queryDescs
.
rows
;
qIdx
++
)
for
(
int
qIdx
=
0
;
qIdx
<
queryDesc
riptor
s
.
rows
;
qIdx
++
)
{
if
(
maskedOut
(
masks
,
qIdx
)
)
{
...
...
@@ -265,10 +362,10 @@ void BruteForceMatcher<L2<float> >::knnMatchImpl( const Mat& queryDescs, vector<
for
(
size_t
iIdx
=
0
;
iIdx
<
imgCount
;
iIdx
++
)
{
CV_Assert
(
masks
.
empty
()
||
masks
[
iIdx
].
empty
()
||
(
masks
[
iIdx
].
rows
==
queryDescs
.
rows
&&
masks
[
iIdx
].
cols
==
trainDescCollection
[
iIdx
].
rows
&&
(
masks
[
iIdx
].
rows
==
queryDesc
riptor
s
.
rows
&&
masks
[
iIdx
].
cols
==
trainDescCollection
[
iIdx
].
rows
&&
masks
[
iIdx
].
type
()
==
CV_8UC1
)
);
CV_Assert
(
trainDescCollection
[
iIdx
].
type
()
==
CV_32FC1
||
trainDescCollection
[
iIdx
].
empty
()
);
CV_Assert
(
queryDescs
.
cols
==
trainDescCollection
[
iIdx
].
cols
);
CV_Assert
(
queryDesc
riptor
s
.
cols
==
trainDescCollection
[
iIdx
].
cols
);
e_allDists
[
iIdx
]
=
e_trainCollection
[
iIdx
]
*
e_query_t
.
col
(
qIdx
);
e_allDists
[
iIdx
]
-=
e_trainNorms2
[
iIdx
];
...
...
@@ -315,22 +412,22 @@ void BruteForceMatcher<L2<float> >::knnMatchImpl( const Mat& queryDescs, vector<
}
template
<>
void
BruteForceMatcher
<
L2
<
float
>
>::
radiusMatchImpl
(
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
void
BruteForceMatcher
<
L2
<
float
>
>::
radiusMatchImpl
(
const
Mat
&
queryDesc
riptor
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
{
#ifndef HAVE_EIGEN2
bfRadiusMatchImpl
(
*
this
,
queryDesc
s
,
matches
,
maxDistance
,
masks
,
compactResult
);
commonRadiusMatchImpl
(
*
this
,
queryDescriptor
s
,
matches
,
maxDistance
,
masks
,
compactResult
);
#else
CV_Assert
(
queryDesc
s
.
type
()
==
CV_32FC1
||
queryDesc
s
.
empty
()
);
CV_Assert
(
queryDesc
riptors
.
type
()
==
CV_32FC1
||
queryDescriptor
s
.
empty
()
);
CV_Assert
(
masks
.
empty
()
||
masks
.
size
()
==
trainDescCollection
.
size
()
);
matches
.
reserve
(
queryDescs
.
rows
);
matches
.
reserve
(
queryDesc
riptor
s
.
rows
);
size_t
imgCount
=
trainDescCollection
.
size
();
Eigen
::
Matrix
<
float
,
Eigen
::
Dynamic
,
Eigen
::
Dynamic
>
e_query_t
;
vector
<
Eigen
::
Matrix
<
float
,
Eigen
::
Dynamic
,
Eigen
::
Dynamic
>
>
e_trainCollection
(
trainDescCollection
.
size
());
vector
<
Eigen
::
Matrix
<
float
,
Eigen
::
Dynamic
,
Eigen
::
Dynamic
>
>
e_trainNorms2
(
trainDescCollection
.
size
());
cv2eigen
(
queryDescs
.
t
(),
e_query_t
);
cv2eigen
(
queryDesc
riptor
s
.
t
(),
e_query_t
);
for
(
size_t
i
=
0
;
i
<
trainDescCollection
.
size
();
i
++
)
{
cv2eigen
(
trainDescCollection
[
i
],
e_trainCollection
[
i
]
);
...
...
@@ -339,7 +436,7 @@ void BruteForceMatcher<L2<float> >::radiusMatchImpl( const Mat& queryDescs, vect
vector
<
Eigen
::
Matrix
<
float
,
Eigen
::
Dynamic
,
1
>
>
e_allDists
(
imgCount
);
// distances between one query descriptor and all train descriptors
for
(
int
qIdx
=
0
;
qIdx
<
queryDescs
.
rows
;
qIdx
++
)
for
(
int
qIdx
=
0
;
qIdx
<
queryDesc
riptor
s
.
rows
;
qIdx
++
)
{
if
(
maskedOut
(
masks
,
qIdx
)
)
{
...
...
@@ -353,10 +450,10 @@ void BruteForceMatcher<L2<float> >::radiusMatchImpl( const Mat& queryDescs, vect
for
(
size_t
iIdx
=
0
;
iIdx
<
imgCount
;
iIdx
++
)
{
CV_Assert
(
masks
.
empty
()
||
masks
[
iIdx
].
empty
()
||
(
masks
[
iIdx
].
rows
==
queryDescs
.
rows
&&
masks
[
iIdx
].
cols
==
trainDescCollection
[
iIdx
].
rows
&&
(
masks
[
iIdx
].
rows
==
queryDesc
riptor
s
.
rows
&&
masks
[
iIdx
].
cols
==
trainDescCollection
[
iIdx
].
rows
&&
masks
[
iIdx
].
type
()
==
CV_8UC1
)
);
CV_Assert
(
trainDescCollection
[
iIdx
].
type
()
==
CV_32FC1
||
trainDescCollection
[
iIdx
].
empty
()
);
CV_Assert
(
queryDescs
.
cols
==
trainDescCollection
[
iIdx
].
cols
);
CV_Assert
(
queryDesc
riptor
s
.
cols
==
trainDescCollection
[
iIdx
].
cols
);
e_allDists
[
iIdx
]
=
e_trainCollection
[
iIdx
]
*
e_query_t
.
col
(
qIdx
);
e_allDists
[
iIdx
]
-=
e_trainNorms2
[
iIdx
];
...
...
@@ -393,12 +490,12 @@ FlannBasedMatcher::FlannBasedMatcher( const Ptr<flann::IndexParams>& _indexParam
CV_Assert
(
!
_searchParams
.
empty
()
);
}
void
FlannBasedMatcher
::
add
(
const
vector
<
Mat
>&
desc
Collection
)
void
FlannBasedMatcher
::
add
(
const
vector
<
Mat
>&
desc
riptors
)
{
DescriptorMatcher
::
add
(
desc
Collection
);
for
(
size_t
i
=
0
;
i
<
desc
Collection
.
size
();
i
++
)
DescriptorMatcher
::
add
(
desc
riptors
);
for
(
size_t
i
=
0
;
i
<
desc
riptors
.
size
();
i
++
)
{
addedDescCount
+=
desc
Collection
[
i
].
rows
;
addedDescCount
+=
desc
riptors
[
i
].
rows
;
}
}
...
...
@@ -421,6 +518,27 @@ void FlannBasedMatcher::train()
}
}
bool
FlannBasedMatcher
::
isMaskSupported
()
const
{
return
false
;
}
Ptr
<
DescriptorMatcher
>
FlannBasedMatcher
::
clone
(
bool
emptyTrainData
)
const
{
FlannBasedMatcher
*
matcher
=
new
FlannBasedMatcher
(
indexParams
,
searchParams
);
if
(
!
emptyTrainData
)
{
CV_Error
(
CV_StsNotImplemented
,
"deep clone functionality is not implemented, because "
"Flann::Index has not copy constructor or clone method "
);
//matcher->flannIndex;
matcher
->
addedDescCount
=
addedDescCount
;
matcher
->
mergedDescriptors
=
DescriptorCollection
(
mergedDescriptors
);
transform
(
trainDescCollection
.
begin
(),
trainDescCollection
.
end
(),
matcher
->
trainDescCollection
.
begin
(),
clone_op
);
}
return
matcher
;
}
void
FlannBasedMatcher
::
convertToDMatches
(
const
DescriptorCollection
&
collection
,
const
Mat
&
indices
,
const
Mat
&
dists
,
vector
<
vector
<
DMatch
>
>&
matches
)
{
...
...
@@ -440,28 +558,28 @@ void FlannBasedMatcher::convertToDMatches( const DescriptorCollection& collectio
}
}
void
FlannBasedMatcher
::
knnMatchImpl
(
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
void
FlannBasedMatcher
::
knnMatchImpl
(
const
Mat
&
queryDesc
riptor
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
const
vector
<
Mat
>&
/*masks*/
,
bool
/*compactResult*/
)
{
Mat
indices
(
queryDescs
.
rows
,
knn
,
CV_32SC1
);
Mat
dists
(
queryDescs
.
rows
,
knn
,
CV_32FC1
);
flannIndex
->
knnSearch
(
queryDescs
,
indices
,
dists
,
knn
,
*
searchParams
);
Mat
indices
(
queryDesc
riptor
s
.
rows
,
knn
,
CV_32SC1
);
Mat
dists
(
queryDesc
riptor
s
.
rows
,
knn
,
CV_32FC1
);
flannIndex
->
knnSearch
(
queryDesc
riptor
s
,
indices
,
dists
,
knn
,
*
searchParams
);
convertToDMatches
(
mergedDescriptors
,
indices
,
dists
,
matches
);
}
void
FlannBasedMatcher
::
radiusMatchImpl
(
const
Mat
&
queryDescs
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
void
FlannBasedMatcher
::
radiusMatchImpl
(
const
Mat
&
queryDesc
riptor
s
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
/*masks*/
,
bool
/*compactResult*/
)
{
const
int
count
=
mergedDescriptors
.
size
();
// TODO do count as param?
Mat
indices
(
queryDescs
.
rows
,
count
,
CV_32SC1
,
Scalar
::
all
(
-
1
)
);
Mat
dists
(
queryDescs
.
rows
,
count
,
CV_32FC1
,
Scalar
::
all
(
-
1
)
);
for
(
int
qIdx
=
0
;
qIdx
<
queryDescs
.
rows
;
qIdx
++
)
Mat
indices
(
queryDesc
riptor
s
.
rows
,
count
,
CV_32SC1
,
Scalar
::
all
(
-
1
)
);
Mat
dists
(
queryDesc
riptor
s
.
rows
,
count
,
CV_32FC1
,
Scalar
::
all
(
-
1
)
);
for
(
int
qIdx
=
0
;
qIdx
<
queryDesc
riptor
s
.
rows
;
qIdx
++
)
{
Mat
queryDesc
sRow
=
queryDesc
s
.
row
(
qIdx
);
Mat
queryDesc
riptorsRow
=
queryDescriptor
s
.
row
(
qIdx
);
Mat
indicesRow
=
indices
.
row
(
qIdx
);
Mat
distsRow
=
dists
.
row
(
qIdx
);
flannIndex
->
radiusSearch
(
queryDescsRow
,
indicesRow
,
distsRow
,
maxDistance
*
maxDistance
,
*
searchParams
);
flannIndex
->
radiusSearch
(
queryDesc
riptor
sRow
,
indicesRow
,
distsRow
,
maxDistance
*
maxDistance
,
*
searchParams
);
}
convertToDMatches
(
mergedDescriptors
,
indices
,
dists
,
matches
);
...
...
@@ -507,6 +625,22 @@ Ptr<DescriptorMatcher> createDescriptorMatcher( const string& descriptorMatcherT
/*
* KeyPointCollection
*/
GenericDescriptorMatcher
::
KeyPointCollection
::
KeyPointCollection
()
:
pointCount
(
0
)
{}
GenericDescriptorMatcher
::
KeyPointCollection
::
KeyPointCollection
(
const
KeyPointCollection
&
collection
)
{
pointCount
=
collection
.
pointCount
;
transform
(
collection
.
images
.
begin
(),
collection
.
images
.
end
(),
images
.
begin
(),
clone_op
);
keypoints
.
resize
(
collection
.
keypoints
.
size
()
);
for
(
size_t
i
=
0
;
i
<
keypoints
.
size
();
i
++
)
copy
(
collection
.
keypoints
[
i
].
begin
(),
collection
.
keypoints
[
i
].
end
(),
keypoints
[
i
].
begin
()
);
copy
(
collection
.
startIndices
.
begin
(),
collection
.
startIndices
.
end
(),
startIndices
.
begin
()
);
}
void
GenericDescriptorMatcher
::
KeyPointCollection
::
add
(
const
vector
<
Mat
>&
_images
,
const
vector
<
vector
<
KeyPoint
>
>&
_points
)
{
...
...
@@ -514,9 +648,9 @@ void GenericDescriptorMatcher::KeyPointCollection::add( const vector<Mat>& _imag
CV_Assert
(
_images
.
size
()
==
_points
.
size
()
);
images
.
insert
(
images
.
end
(),
_images
.
begin
(),
_images
.
end
()
);
points
.
insert
(
points
.
end
(),
_points
.
begin
(),
_points
.
end
()
);
keypoints
.
insert
(
key
points
.
end
(),
_points
.
begin
(),
_points
.
end
()
);
for
(
size_t
i
=
0
;
i
<
_points
.
size
();
i
++
)
size
+=
_points
[
i
].
size
();
pointCount
+=
_points
[
i
].
size
();
size_t
prevSize
=
startIndices
.
size
(),
addSize
=
_images
.
size
();
startIndices
.
resize
(
prevSize
+
addSize
);
...
...
@@ -524,37 +658,58 @@ void GenericDescriptorMatcher::KeyPointCollection::add( const vector<Mat>& _imag
if
(
prevSize
==
0
)
startIndices
[
prevSize
]
=
0
;
//first
else
startIndices
[
prevSize
]
=
startIndices
[
prevSize
-
1
]
+
points
[
prevSize
-
1
].
size
();
startIndices
[
prevSize
]
=
startIndices
[
prevSize
-
1
]
+
key
points
[
prevSize
-
1
].
size
();
for
(
size_t
i
=
prevSize
+
1
;
i
<
prevSize
+
addSize
;
i
++
)
{
startIndices
[
i
]
=
startIndices
[
i
-
1
]
+
points
[
i
-
1
].
size
();
startIndices
[
i
]
=
startIndices
[
i
-
1
]
+
key
points
[
i
-
1
].
size
();
}
}
void
GenericDescriptorMatcher
::
KeyPointCollection
::
clear
()
{
points
.
clear
();
keypoints
.
clear
();
}
size_t
GenericDescriptorMatcher
::
KeyPointCollection
::
keypointCount
()
const
{
return
pointCount
;
}
size_t
GenericDescriptorMatcher
::
KeyPointCollection
::
imageCount
()
const
{
return
images
.
size
();
}
const
vector
<
vector
<
KeyPoint
>
>&
GenericDescriptorMatcher
::
KeyPointCollection
::
getKeypoints
()
const
{
return
keypoints
;
}
const
vector
<
KeyPoint
>&
GenericDescriptorMatcher
::
KeyPointCollection
::
getKeypoints
(
int
imgIdx
)
const
{
CV_Assert
(
imgIdx
<
(
int
)
imageCount
()
);
return
keypoints
[
imgIdx
];
}
const
KeyPoint
&
GenericDescriptorMatcher
::
KeyPointCollection
::
getKeyPoint
(
int
imgIdx
,
int
localPointIdx
)
const
{
CV_Assert
(
imgIdx
<
(
int
)
images
.
size
()
);
CV_Assert
(
localPointIdx
<
(
int
)
points
[
imgIdx
].
size
()
);
return
points
[
imgIdx
][
localPointIdx
];
CV_Assert
(
localPointIdx
<
(
int
)
key
points
[
imgIdx
].
size
()
);
return
key
points
[
imgIdx
][
localPointIdx
];
}
const
KeyPoint
&
GenericDescriptorMatcher
::
KeyPointCollection
::
getKeyPoint
(
int
globalPointIdx
)
const
{
int
imgIdx
,
localPointIdx
;
getLocalIdx
(
globalPointIdx
,
imgIdx
,
localPointIdx
);
return
points
[
imgIdx
][
localPointIdx
];
return
key
points
[
imgIdx
][
localPointIdx
];
}
void
GenericDescriptorMatcher
::
KeyPointCollection
::
getLocalIdx
(
int
globalPointIdx
,
int
&
imgIdx
,
int
&
localPointIdx
)
const
{
imgIdx
=
-
1
;
CV_Assert
(
globalPointIdx
<
(
int
)
pointCount
()
);
CV_Assert
(
globalPointIdx
<
(
int
)
key
pointCount
()
);
for
(
size_t
i
=
1
;
i
<
startIndices
.
size
();
i
++
)
{
if
(
globalPointIdx
<
startIndices
[
i
]
)
...
...
@@ -567,20 +722,50 @@ void GenericDescriptorMatcher::KeyPointCollection::getLocalIdx( int globalPointI
localPointIdx
=
globalPointIdx
-
startIndices
[
imgIdx
];
}
const
vector
<
Mat
>&
GenericDescriptorMatcher
::
KeyPointCollection
::
getImages
()
const
{
return
images
;
}
const
Mat
&
GenericDescriptorMatcher
::
KeyPointCollection
::
getImage
(
int
imgIdx
)
const
{
CV_Assert
(
imgIdx
<
(
int
)
imageCount
()
);
return
images
[
imgIdx
];
}
/*
* GenericDescriptorMatcher
*/
GenericDescriptorMatcher
::
GenericDescriptorMatcher
()
{}
GenericDescriptorMatcher
::~
GenericDescriptorMatcher
()
{}
void
GenericDescriptorMatcher
::
add
(
const
vector
<
Mat
>&
imgCollection
,
vector
<
vector
<
KeyPoint
>
>&
pointCollection
)
{
trainPointCollection
.
add
(
imgCollection
,
pointCollection
);
}
const
vector
<
Mat
>&
GenericDescriptorMatcher
::
getTrainImages
()
const
{
return
trainPointCollection
.
getImages
();
}
const
vector
<
vector
<
KeyPoint
>
>&
GenericDescriptorMatcher
::
getTrainKeypoints
()
const
{
return
trainPointCollection
.
getKeypoints
();
}
void
GenericDescriptorMatcher
::
clear
()
{
trainPointCollection
.
clear
();
}
void
GenericDescriptorMatcher
::
train
()
{}
void
GenericDescriptorMatcher
::
classify
(
const
Mat
&
queryImage
,
vector
<
KeyPoint
>&
queryPoints
,
const
Mat
&
trainImage
,
vector
<
KeyPoint
>&
trainPoints
)
const
{
...
...
@@ -606,7 +791,7 @@ void GenericDescriptorMatcher::match( const Mat& queryImg, vector<KeyPoint>& que
const
Mat
&
trainImg
,
vector
<
KeyPoint
>&
trainPoints
,
vector
<
DMatch
>&
matches
,
const
Mat
&
mask
)
const
{
Ptr
<
GenericDescriptorMatcher
>
tempMatcher
=
c
reateEmptyMatcherCopy
(
);
Ptr
<
GenericDescriptorMatcher
>
tempMatcher
=
c
lone
(
true
);
vector
<
vector
<
KeyPoint
>
>
vecTrainPoints
(
1
,
trainPoints
);
tempMatcher
->
add
(
vector
<
Mat
>
(
1
,
trainImg
),
vecTrainPoints
);
tempMatcher
->
match
(
queryImg
,
queryPoints
,
matches
,
vector
<
Mat
>
(
1
,
mask
)
);
...
...
@@ -617,7 +802,7 @@ void GenericDescriptorMatcher::knnMatch( const Mat& queryImg, vector<KeyPoint>&
const
Mat
&
trainImg
,
vector
<
KeyPoint
>&
trainPoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
const
Mat
&
mask
,
bool
compactResult
)
const
{
Ptr
<
GenericDescriptorMatcher
>
tempMatcher
=
c
reateEmptyMatcherCopy
(
);
Ptr
<
GenericDescriptorMatcher
>
tempMatcher
=
c
lone
(
true
);
vector
<
vector
<
KeyPoint
>
>
vecTrainPoints
(
1
,
trainPoints
);
tempMatcher
->
add
(
vector
<
Mat
>
(
1
,
trainImg
),
vecTrainPoints
);
tempMatcher
->
knnMatch
(
queryImg
,
queryPoints
,
matches
,
knn
,
vector
<
Mat
>
(
1
,
mask
),
compactResult
);
...
...
@@ -629,7 +814,7 @@ void GenericDescriptorMatcher::radiusMatch( const Mat& queryImg, vector<KeyPoint
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
Mat
&
mask
,
bool
compactResult
)
const
{
Ptr
<
GenericDescriptorMatcher
>
tempMatcher
=
c
reateEmptyMatcherCopy
(
);
Ptr
<
GenericDescriptorMatcher
>
tempMatcher
=
c
lone
(
true
);
vector
<
vector
<
KeyPoint
>
>
vecTrainPoints
(
1
,
trainPoints
);
tempMatcher
->
add
(
vector
<
Mat
>
(
1
,
trainImg
),
vecTrainPoints
);
tempMatcher
->
radiusMatch
(
queryImg
,
queryPoints
,
matches
,
maxDistance
,
vector
<
Mat
>
(
1
,
mask
),
compactResult
);
...
...
@@ -660,9 +845,25 @@ void GenericDescriptorMatcher::radiusMatch( const Mat& queryImg, vector<KeyPoint
radiusMatchImpl
(
queryImg
,
queryPoints
,
matches
,
maxDistance
,
masks
,
compactResult
);
}
void
GenericDescriptorMatcher
::
read
(
const
FileNode
&
)
{}
void
GenericDescriptorMatcher
::
write
(
FileStorage
&
)
const
{}
/****************************************************************************************\
* OneWayDescriptorMatcher *
\****************************************************************************************/
OneWayDescriptorMatcher
::
Params
::
Params
(
int
_poseCount
,
Size
_patchSize
,
string
_pcaFilename
,
string
_trainPath
,
string
_trainImagesList
,
float
_minScale
,
float
_maxScale
,
float
_stepScale
)
:
poseCount
(
_poseCount
),
patchSize
(
_patchSize
),
pcaFilename
(
_pcaFilename
),
trainPath
(
_trainPath
),
trainImagesList
(
_trainImagesList
),
minScale
(
_minScale
),
maxScale
(
_maxScale
),
stepScale
(
_stepScale
)
{}
OneWayDescriptorMatcher
::
OneWayDescriptorMatcher
(
const
Params
&
_params
)
{
initialize
(
_params
);
...
...
@@ -691,13 +892,13 @@ void OneWayDescriptorMatcher::clear()
void
OneWayDescriptorMatcher
::
train
()
{
if
(
base
.
empty
()
||
prevTrainCount
<
(
int
)
trainPointCollection
.
pointCount
()
)
if
(
base
.
empty
()
||
prevTrainCount
<
(
int
)
trainPointCollection
.
key
pointCount
()
)
{
base
=
new
OneWayDescriptorObject
(
params
.
patchSize
,
params
.
poseCount
,
params
.
pcaFilename
,
params
.
trainPath
,
params
.
trainImagesList
,
params
.
minScale
,
params
.
maxScale
,
params
.
stepScale
);
base
->
Allocate
(
trainPointCollection
.
pointCount
()
);
prevTrainCount
=
trainPointCollection
.
pointCount
();
base
->
Allocate
(
trainPointCollection
.
key
pointCount
()
);
prevTrainCount
=
trainPointCollection
.
key
pointCount
();
const
vector
<
vector
<
KeyPoint
>
>&
points
=
trainPointCollection
.
getKeypoints
();
int
count
=
0
;
...
...
@@ -714,6 +915,11 @@ void OneWayDescriptorMatcher::train()
}
}
bool
OneWayDescriptorMatcher
::
isMaskSupported
()
{
return
false
;
}
void
OneWayDescriptorMatcher
::
knnMatchImpl
(
const
Mat
&
queryImg
,
vector
<
KeyPoint
>&
queryPoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
const
vector
<
Mat
>&
/*masks*/
,
bool
/*compactResult*/
)
...
...
@@ -763,6 +969,23 @@ void OneWayDescriptorMatcher::write( FileStorage& fs ) const
base
->
Write
(
fs
);
}
Ptr
<
GenericDescriptorMatcher
>
OneWayDescriptorMatcher
::
clone
(
bool
emptyTrainData
)
const
{
OneWayDescriptorMatcher
*
matcher
=
new
OneWayDescriptorMatcher
(
params
);
if
(
!
emptyTrainData
)
{
CV_Error
(
CV_StsNotImplemented
,
"deep clone dunctionality is not implemented, because "
"OneWayDescriptorBase has not copy constructor or clone method "
);
//matcher->base;
matcher
->
params
=
params
;
matcher
->
prevTrainCount
=
prevTrainCount
;
matcher
->
trainPointCollection
=
trainPointCollection
;
}
return
matcher
;
}
/****************************************************************************************\
* FernDescriptorMatcher *
\****************************************************************************************/
...
...
@@ -805,7 +1028,7 @@ void FernDescriptorMatcher::clear()
void
FernDescriptorMatcher
::
train
()
{
if
(
classifier
.
empty
()
||
prevTrainCount
<
(
int
)
trainPointCollection
.
pointCount
()
)
if
(
classifier
.
empty
()
||
prevTrainCount
<
(
int
)
trainPointCollection
.
key
pointCount
()
)
{
assert
(
params
.
filename
.
empty
()
);
...
...
@@ -819,6 +1042,11 @@ void FernDescriptorMatcher::train()
}
}
bool
FernDescriptorMatcher
::
isMaskSupported
()
{
return
false
;
}
void
FernDescriptorMatcher
::
calcBestProbAndMatchIdx
(
const
Mat
&
image
,
const
Point2f
&
pt
,
float
&
bestProb
,
int
&
bestMatchIdx
,
vector
<
float
>&
signature
)
{
...
...
@@ -921,16 +1149,42 @@ void FernDescriptorMatcher::write( FileStorage& fs ) const
// classifier->write(fs);
}
Ptr
<
GenericDescriptorMatcher
>
FernDescriptorMatcher
::
clone
(
bool
emptyTrainData
)
const
{
FernDescriptorMatcher
*
matcher
=
new
FernDescriptorMatcher
(
params
);
if
(
!
emptyTrainData
)
{
CV_Error
(
CV_StsNotImplemented
,
"deep clone dunctionality is not implemented, because "
"FernClassifier has not copy constructor or clone method "
);
//matcher->classifier;
matcher
->
params
=
params
;
matcher
->
prevTrainCount
=
prevTrainCount
;
matcher
->
trainPointCollection
=
trainPointCollection
;
}
return
matcher
;
}
/****************************************************************************************\
* VectorDescriptorMatcher
*
* VectorDescriptorMatcher *
\****************************************************************************************/
VectorDescriptorMatcher
::
VectorDescriptorMatcher
(
const
Ptr
<
DescriptorExtractor
>&
_extractor
,
const
Ptr
<
DescriptorMatcher
>&
_matcher
)
:
extractor
(
_extractor
),
matcher
(
_matcher
)
{
CV_Assert
(
!
extractor
.
empty
()
&&
!
matcher
.
empty
()
);
}
VectorDescriptorMatcher
::~
VectorDescriptorMatcher
()
{}
void
VectorDescriptorMatcher
::
add
(
const
vector
<
Mat
>&
imgCollection
,
vector
<
vector
<
KeyPoint
>
>&
pointCollection
)
{
vector
<
Mat
>
desc
Collection
;
extractor
->
compute
(
imgCollection
,
pointCollection
,
desc
Collection
);
vector
<
Mat
>
desc
riptors
;
extractor
->
compute
(
imgCollection
,
pointCollection
,
desc
riptors
);
matcher
->
add
(
desc
Collection
);
matcher
->
add
(
desc
riptors
);
trainPointCollection
.
add
(
imgCollection
,
pointCollection
);
}
...
...
@@ -947,28 +1201,33 @@ void VectorDescriptorMatcher::train()
matcher
->
train
();
}
bool
VectorDescriptorMatcher
::
isMaskSupported
()
{
return
matcher
->
isMaskSupported
();
}
void
VectorDescriptorMatcher
::
knnMatchImpl
(
const
Mat
&
queryImg
,
vector
<
KeyPoint
>&
queryPoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
int
knn
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
{
Mat
queryDescs
;
extractor
->
compute
(
queryImg
,
queryPoints
,
queryDescs
);
matcher
->
knnMatch
(
queryDescs
,
matches
,
knn
,
masks
,
compactResult
);
Mat
queryDesc
riptor
s
;
extractor
->
compute
(
queryImg
,
queryPoints
,
queryDesc
riptor
s
);
matcher
->
knnMatch
(
queryDesc
riptor
s
,
matches
,
knn
,
masks
,
compactResult
);
}
void
VectorDescriptorMatcher
::
radiusMatchImpl
(
const
Mat
&
queryImg
,
vector
<
KeyPoint
>&
queryPoints
,
vector
<
vector
<
DMatch
>
>&
matches
,
float
maxDistance
,
const
vector
<
Mat
>&
masks
,
bool
compactResult
)
{
Mat
queryDescs
;
extractor
->
compute
(
queryImg
,
queryPoints
,
queryDescs
);
matcher
->
radiusMatch
(
queryDescs
,
matches
,
maxDistance
,
masks
,
compactResult
);
Mat
queryDesc
riptor
s
;
extractor
->
compute
(
queryImg
,
queryPoints
,
queryDesc
riptor
s
);
matcher
->
radiusMatch
(
queryDesc
riptor
s
,
matches
,
maxDistance
,
masks
,
compactResult
);
}
void
VectorDescriptorMatcher
::
read
(
const
FileNode
&
fn
)
{
GenericDescriptorMatcher
::
read
(
fn
);
extractor
->
read
(
fn
);
extractor
->
read
(
fn
);
}
void
VectorDescriptorMatcher
::
write
(
FileStorage
&
fs
)
const
...
...
@@ -977,6 +1236,12 @@ void VectorDescriptorMatcher::write (FileStorage& fs) const
extractor
->
write
(
fs
);
}
Ptr
<
GenericDescriptorMatcher
>
VectorDescriptorMatcher
::
clone
(
bool
emptyTrainData
)
const
{
// TODO clone extractor
return
new
VectorDescriptorMatcher
(
extractor
,
matcher
->
clone
(
emptyTrainData
)
);
}
/*
* Factory function for GenericDescriptorMatch creating
*/
...
...
samples/cpp/matching_to_many_images.cpp
View file @
e406dfee
...
...
@@ -7,132 +7,228 @@
using
namespace
cv
;
using
namespace
std
;
void
maskMatchesByTrainImgIdx
(
const
vector
<
DMatch
>&
matches
,
int
trainImgIdx
,
vector
<
char
>&
mask
);
void
readTrainFilenames
(
const
string
&
filename
,
string
&
dirName
,
vector
<
string
>&
trainFilenames
);
/*
* This is a sample on matching descriptors detected on one image to descriptors detected in image set.
* So we have one query image and several train images. For each keypoint descriptor of query image
* the one nearest train descriptor is found the entire collection of train images. To visualize the result
* of matching we save images, each of which combines query and train image with matches between them (if they exist).
* Match is drawn as line between corresponding points. Count of all matches is equel to count of
* query keypoints, so we have the same count of lines in all set of result images (but not for each result
* (train) image).
*/
const
string
defaultDetectorType
=
"SURF"
;
const
string
defaultDescriptorType
=
"SURF"
;
const
string
defaultMatcherType
=
"FlannBased"
;
const
string
defaultQueryImageName
=
"../../opencv/samples/cpp/matching_to_many_images/query.png"
;
const
string
defaultFileWithTrainImages
=
"../../opencv/samples/cpp/matching_to_many_images/train/trainImages.txt"
;
const
string
defaultDirToSaveResImages
=
"../../opencv/samples/cpp/matching_to_many_images/results"
;
int
main
(
int
argc
,
char
**
argv
)
void
maskMatchesByTrainImgIdx
(
const
vector
<
DMatch
>&
matches
,
int
trainImgIdx
,
vector
<
char
>&
mask
)
{
mask
.
resize
(
matches
.
size
()
);
fill
(
mask
.
begin
(),
mask
.
end
(),
0
);
for
(
size_t
i
=
0
;
i
<
matches
.
size
();
i
++
)
{
if
(
matches
[
i
].
imgIdx
==
trainImgIdx
)
mask
[
i
]
=
1
;
}
}
void
readTrainFilenames
(
const
string
&
filename
,
string
&
dirName
,
vector
<
string
>&
trainFilenames
)
{
Mat
queryImg
;
vector
<
KeyPoint
>
queryPoints
;
Mat
queryDescs
;
const
char
dlmtr
=
'/'
;
vector
<
Mat
>
trainImgCollection
;
vector
<
vector
<
KeyPoint
>
>
trainPointCollection
;
vector
<
Mat
>
trainDescCollection
;
trainFilenames
.
clear
();
vector
<
DMatch
>
matches
;
ifstream
file
(
filename
.
c_str
()
);
if
(
!
file
.
is_open
()
)
return
;
if
(
argc
!=
7
)
size_t
pos
=
filename
.
rfind
(
dlmtr
);
dirName
=
pos
==
string
::
npos
?
""
:
filename
.
substr
(
0
,
pos
)
+
dlmtr
;
while
(
!
file
.
eof
()
)
{
cout
<<
"Format:"
<<
endl
;
cout
<<
argv
[
0
]
<<
"[detectorType] [descriptorType] [matcherType] [queryImage] [fileWithTrainImages] [dirToSaveResImages]"
<<
endl
;
return
-
1
;
string
str
;
getline
(
file
,
str
)
;
if
(
str
.
empty
()
)
break
;
trainFilenames
.
push_back
(
str
)
;
}
file
.
close
();
}
cout
<<
"< 1.) Creating feature detector, descriptor extractor and descriptor matcher ..."
<<
endl
;
Ptr
<
FeatureDetector
>
detector
=
createFeatureDetector
(
argv
[
1
]
);
Ptr
<
DescriptorExtractor
>
descriptorExtractor
=
createDescriptorExtractor
(
argv
[
2
]
);
Ptr
<
DescriptorMatcher
>
descriptorMatcher
=
createDescriptorMatcher
(
argv
[
3
]
);
bool
createDetectorDescriptorMatcher
(
const
string
&
detectorType
,
const
string
&
descriptorType
,
const
string
&
matcherType
,
Ptr
<
FeatureDetector
>&
featureDetector
,
Ptr
<
DescriptorExtractor
>&
descriptorExtractor
,
Ptr
<
DescriptorMatcher
>&
descriptorMatcher
)
{
cout
<<
"< Creating feature detector, descriptor extractor and descriptor matcher ..."
<<
endl
;
featureDetector
=
createFeatureDetector
(
detectorType
);
descriptorExtractor
=
createDescriptorExtractor
(
descriptorType
);
descriptorMatcher
=
createDescriptorMatcher
(
matcherType
);
cout
<<
">"
<<
endl
;
if
(
detector
.
empty
()
||
descriptorExtractor
.
empty
()
||
descriptorMatcher
.
empty
()
)
{
bool
isCreated
=
!
(
featureDetector
.
empty
()
||
descriptorExtractor
.
empty
()
||
descriptorMatcher
.
empty
()
);
if
(
!
isCreated
)
cout
<<
"Can not create feature detector or descriptor exstractor or descriptor matcher of given types."
<<
endl
<<
">"
<<
endl
;
return
-
1
;
}
cout
<<
"< 2.) Reading the images..."
<<
endl
;
queryImg
=
imread
(
argv
[
4
],
CV_LOAD_IMAGE_GRAYSCALE
);
if
(
queryImg
.
empty
()
)
return
isCreated
;
}
bool
readImages
(
const
string
&
queryImageName
,
const
string
&
trainFilename
,
Mat
&
queryImage
,
vector
<
Mat
>&
trainImages
,
vector
<
string
>&
trainImageNames
)
{
cout
<<
"< Reading the images..."
<<
endl
;
queryImage
=
imread
(
queryImageName
,
CV_LOAD_IMAGE_GRAYSCALE
);
if
(
queryImage
.
empty
()
)
{
cout
<<
"Query image can not be read."
<<
endl
<<
">"
<<
endl
;
return
-
1
;
return
false
;
}
string
trainDirName
;
vector
<
string
>
trainFilenames
;
vector
<
int
>
usedTrainImgIdxs
;
readTrainFilenames
(
argv
[
5
],
trainDirName
,
trainFilenames
);
if
(
trainFilenames
.
empty
()
)
readTrainFilenames
(
trainFilename
,
trainDirName
,
trainImageNames
);
if
(
trainImageNames
.
empty
()
)
{
cout
<<
"Train image filenames can not be read."
<<
endl
<<
">"
<<
endl
;
return
-
1
;
return
false
;
}
for
(
size_t
i
=
0
;
i
<
trainFilenames
.
size
();
i
++
)
int
readImageCount
=
0
;
for
(
size_t
i
=
0
;
i
<
trainImageNames
.
size
();
i
++
)
{
Mat
img
=
imread
(
trainDirName
+
trainFilenames
[
i
],
CV_LOAD_IMAGE_GRAYSCALE
);
if
(
img
.
empty
()
)
cout
<<
"Train image "
<<
trainDirName
+
trainFilenames
[
i
]
<<
" can not be read."
<<
endl
;
trainImgCollection
.
push_back
(
img
);
usedTrainImgIdxs
.
push_back
(
i
);
string
filename
=
trainDirName
+
trainImageNames
[
i
];
Mat
img
=
imread
(
filename
,
CV_LOAD_IMAGE_GRAYSCALE
);
if
(
img
.
empty
()
)
cout
<<
"Train image "
<<
filename
<<
" can not be read."
<<
endl
;
else
readImageCount
++
;
trainImages
.
push_back
(
img
);
}
if
(
trainImgCollection
.
empty
()
)
if
(
!
readImageCount
)
{
cout
<<
"All train images can not be read."
<<
endl
<<
">"
<<
endl
;
return
-
1
;
return
false
;
}
else
cout
<<
trainImgCollection
.
size
()
<<
" train images were read."
<<
endl
;
cout
<<
readImageCount
<<
" train images were read."
<<
endl
;
cout
<<
">"
<<
endl
;
cout
<<
endl
<<
"< 3.) Extracting keypoints from images..."
<<
endl
;
detector
->
detect
(
queryImg
,
queryPoints
);
detector
->
detect
(
trainImgCollection
,
trainPointCollection
);
return
true
;
}
void
detectKeypoints
(
const
Mat
&
queryImage
,
vector
<
KeyPoint
>&
queryKeypoints
,
const
vector
<
Mat
>&
trainImages
,
vector
<
vector
<
KeyPoint
>
>&
trainKeypoints
,
Ptr
<
FeatureDetector
>&
featureDetector
)
{
cout
<<
endl
<<
"< Extracting keypoints from images..."
<<
endl
;
featureDetector
->
detect
(
queryImage
,
queryKeypoints
);
featureDetector
->
detect
(
trainImages
,
trainKeypoints
);
cout
<<
">"
<<
endl
;
}
cout
<<
"< 4.) Computing descriptors for keypoints..."
<<
endl
;
descriptorExtractor
->
compute
(
queryImg
,
queryPoints
,
queryDescs
);
descriptorExtractor
->
compute
(
trainImgCollection
,
trainPointCollection
,
trainDescCollection
);
void
computeDescriptors
(
const
Mat
&
queryImage
,
vector
<
KeyPoint
>&
queryKeypoints
,
Mat
&
queryDescriptors
,
const
vector
<
Mat
>&
trainImages
,
vector
<
vector
<
KeyPoint
>
>&
trainKeypoints
,
vector
<
Mat
>&
trainDescriptors
,
Ptr
<
DescriptorExtractor
>&
descriptorExtractor
)
{
cout
<<
"< Computing descriptors for keypoints..."
<<
endl
;
descriptorExtractor
->
compute
(
queryImage
,
queryKeypoints
,
queryDescriptors
);
descriptorExtractor
->
compute
(
trainImages
,
trainKeypoints
,
trainDescriptors
);
cout
<<
">"
<<
endl
;
}
cout
<<
"< 5.) Set train descriptors collection in the matcher and match query descriptors to them..."
<<
endl
;
descriptorMatcher
->
add
(
trainDescCollection
);
descriptorMatcher
->
match
(
queryDescs
,
matches
);
CV_Assert
(
queryPoints
.
size
()
==
matches
.
size
()
);
void
matchDescriptors
(
const
Mat
&
queryDescriptors
,
const
vector
<
Mat
>&
trainDescriptors
,
vector
<
DMatch
>&
matches
,
Ptr
<
DescriptorMatcher
>&
descriptorMatcher
)
{
cout
<<
"< Set train descriptors collection in the matcher and match query descriptors to them..."
<<
endl
;
descriptorMatcher
->
add
(
trainDescriptors
);
descriptorMatcher
->
match
(
queryDescriptors
,
matches
);
CV_Assert
(
queryDescriptors
.
rows
==
(
int
)
matches
.
size
()
||
matches
.
empty
()
);
cout
<<
">"
<<
endl
;
}
cout
<<
"< 6.) Save results..."
<<
endl
;
void
saveResultImages
(
const
Mat
&
queryImage
,
const
vector
<
KeyPoint
>&
queryKeypoints
,
const
vector
<
Mat
>&
trainImages
,
const
vector
<
vector
<
KeyPoint
>
>&
trainKeypoints
,
const
vector
<
DMatch
>&
matches
,
const
vector
<
string
>&
trainImagesNames
,
const
string
&
resultDir
)
{
cout
<<
"< Save results..."
<<
endl
;
Mat
drawImg
;
vector
<
char
>
mask
;
for
(
size_t
i
=
0
;
i
<
trainIm
gCollection
.
size
();
i
++
)
for
(
size_t
i
=
0
;
i
<
trainIm
ages
.
size
();
i
++
)
{
maskMatchesByTrainImgIdx
(
matches
,
i
,
mask
);
drawMatches
(
queryImg
,
queryPoints
,
trainImgCollection
[
i
],
trainPointCollection
[
i
],
matches
,
drawImg
,
Scalar
::
all
(
-
1
),
Scalar
::
all
(
-
1
),
mask
);
imwrite
(
string
(
argv
[
6
])
+
"/res_"
+
trainFilenames
[
usedTrainImgIdxs
[
i
]]
+
".png"
,
drawImg
);
if
(
!
trainImages
[
i
].
empty
()
)
{
maskMatchesByTrainImgIdx
(
matches
,
i
,
mask
);
drawMatches
(
queryImage
,
queryKeypoints
,
trainImages
[
i
],
trainKeypoints
[
i
],
matches
,
drawImg
,
Scalar
::
all
(
-
1
),
Scalar
::
all
(
-
1
),
mask
);
string
filename
=
resultDir
+
"/res_"
+
trainImagesNames
[
i
];
if
(
!
imwrite
(
filename
,
drawImg
)
)
cout
<<
"Image "
<<
filename
<<
" can not be saved (may be because directory "
<<
resultDir
<<
" does not exist)."
<<
endl
;
}
}
cout
<<
">"
<<
endl
;
return
0
;
}
void
maskMatchesByTrainImgIdx
(
const
vector
<
DMatch
>&
matches
,
int
trainImgIdx
,
vector
<
char
>&
mask
)
void
printPrompt
(
const
string
&
applName
)
{
mask
.
resize
(
matches
.
size
()
);
fill
(
mask
.
begin
(),
mask
.
end
(),
0
);
for
(
size_t
i
=
0
;
i
<
matches
.
size
();
i
++
)
{
if
(
matches
[
i
].
imgIdx
==
trainImgIdx
)
mask
[
i
]
=
1
;
}
cout
<<
endl
<<
"Format:"
<<
endl
;
cout
<<
applName
<<
" [detectorType] [descriptorType] [matcherType] [queryImage] [fileWithTrainImages] [dirToSaveResImages]"
<<
endl
;
cout
<<
endl
<<
"Example:"
<<
endl
<<
defaultDetectorType
<<
" "
<<
defaultDescriptorType
<<
" "
<<
defaultMatcherType
<<
" "
<<
defaultQueryImageName
<<
" "
<<
defaultFileWithTrainImages
<<
" "
<<
defaultDirToSaveResImages
<<
endl
;
}
void
readTrainFilenames
(
const
string
&
filename
,
string
&
dirName
,
vector
<
string
>&
trainFilenames
)
int
main
(
int
argc
,
char
**
argv
)
{
const
char
dlmtr
=
'/'
;
string
detectorType
=
defaultDetectorType
;
string
descriptorType
=
defaultDescriptorType
;
string
matcherType
=
defaultMatcherType
;
string
queryImageName
=
defaultQueryImageName
;
string
fileWithTrainImages
=
defaultFileWithTrainImages
;
string
dirToSaveResImages
=
defaultDirToSaveResImages
;
if
(
argc
!=
7
&&
argc
!=
1
)
{
printPrompt
(
argv
[
0
]
);
return
-
1
;
}
trainFilenames
.
clear
();
if
(
argc
!=
1
)
{
detectorType
=
argv
[
1
];
descriptorType
=
argv
[
2
];
matcherType
=
argv
[
3
];
queryImageName
=
argv
[
4
];
fileWithTrainImages
=
argv
[
5
];
dirToSaveResImages
=
argv
[
6
];
}
ifstream
file
(
filename
.
c_str
()
);
if
(
!
file
.
is_open
()
)
return
;
Ptr
<
FeatureDetector
>
featureDetector
;
Ptr
<
DescriptorExtractor
>
descriptorExtractor
;
Ptr
<
DescriptorMatcher
>
descriptorMatcher
;
if
(
!
createDetectorDescriptorMatcher
(
detectorType
,
descriptorType
,
matcherType
,
featureDetector
,
descriptorExtractor
,
descriptorMatcher
)
)
{
printPrompt
(
argv
[
0
]
);
return
-
1
;
}
size_t
pos
=
filename
.
rfind
(
dlmtr
);
dirName
=
pos
==
string
::
npos
?
""
:
filename
.
substr
(
0
,
pos
)
+
dlmtr
;
while
(
!
file
.
eof
()
)
Mat
queryImage
;
vector
<
Mat
>
trainImages
;
vector
<
string
>
trainImagesNames
;
if
(
!
readImages
(
queryImageName
,
fileWithTrainImages
,
queryImage
,
trainImages
,
trainImagesNames
)
)
{
string
str
;
getline
(
file
,
str
);
if
(
str
.
empty
()
)
break
;
trainFilenames
.
push_back
(
str
);
printPrompt
(
argv
[
0
]
);
return
-
1
;
}
file
.
close
();
vector
<
KeyPoint
>
queryKeypoints
;
vector
<
vector
<
KeyPoint
>
>
trainKeypoints
;
detectKeypoints
(
queryImage
,
queryKeypoints
,
trainImages
,
trainKeypoints
,
featureDetector
);
Mat
queryDescriptors
;
vector
<
Mat
>
trainDescriptors
;
computeDescriptors
(
queryImage
,
queryKeypoints
,
queryDescriptors
,
trainImages
,
trainKeypoints
,
trainDescriptors
,
descriptorExtractor
);
vector
<
DMatch
>
matches
;
matchDescriptors
(
queryDescriptors
,
trainDescriptors
,
matches
,
descriptorMatcher
);
saveResultImages
(
queryImage
,
queryKeypoints
,
trainImages
,
trainKeypoints
,
matches
,
trainImagesNames
,
dirToSaveResImages
);
return
0
;
}
samples/cpp/matching_to_many_images/query.png
0 → 100755
View file @
e406dfee
119 KB
samples/cpp/matching_to_many_images/train/1.png
0 → 100755
View file @
e406dfee
116 KB
samples/cpp/matching_to_many_images/train/2.png
0 → 100755
View file @
e406dfee
112 KB
samples/cpp/matching_to_many_images/train/3.png
0 → 100755
View file @
e406dfee
118 KB
samples/cpp/matching_to_many_images/train/trainImages.txt
0 → 100755
View file @
e406dfee
1.png
2.png
3.png
tests/cv/src/afeatures2d.cpp
View file @
e406dfee
...
...
@@ -60,7 +60,7 @@ public:
CvTest
(
testName
,
"cv::FeatureDetector::detect"
),
fdetector
(
_fdetector
)
{}
protected
:
virtual
void
run
(
int
start_from
)
virtual
void
run
(
int
/*start_from*/
)
{
const
float
maxPtDif
=
1.
f
;
const
float
maxSizeDif
=
1.
f
;
...
...
@@ -112,7 +112,7 @@ protected:
for
(
size_t
c
=
0
;
c
<
calcKeypoints
.
size
();
c
++
)
{
progress
=
update_progress
(
progress
,
v
*
calcKeypoints
.
size
()
+
c
,
progressCount
,
0
);
float
curDist
=
norm
(
calcKeypoints
[
c
].
pt
-
validKeypoints
[
v
].
pt
);
float
curDist
=
(
float
)
norm
(
calcKeypoints
[
c
].
pt
-
validKeypoints
[
v
].
pt
);
if
(
curDist
<
minDist
)
{
minDist
=
curDist
;
...
...
@@ -434,7 +434,7 @@ int CV_DescriptorMatcherTest::testMatch( const Mat& query, const Mat& train )
for
(
size_t
i
=
0
;
i
<
matches
.
size
();
i
++
)
{
DMatch
match
=
matches
[
i
];
int
shift
=
dmatcher
->
supportMask
()
?
1
:
0
;
int
shift
=
dmatcher
->
isMaskSupported
()
?
1
:
0
;
{
if
(
i
<
queryDescCount
/
2
)
{
...
...
@@ -533,7 +533,7 @@ int CV_DescriptorMatcherTest::testKnnMatch( const Mat& query, const Mat& train )
else
{
int
badCount
=
0
;
int
shift
=
dmatcher
->
supportMask
()
?
1
:
0
;
int
shift
=
dmatcher
->
isMaskSupported
()
?
1
:
0
;
for
(
size_t
i
=
0
;
i
<
matches
.
size
();
i
++
)
{
if
(
(
int
)
matches
[
i
].
size
()
!=
knn
)
...
...
@@ -641,8 +641,8 @@ int CV_DescriptorMatcherTest::testRadiusMatch( const Mat& query, const Mat& trai
res
=
curRes
!=
CvTS
::
OK
?
curRes
:
res
;
int
badCount
=
0
;
int
shift
=
dmatcher
->
supportMask
()
?
1
:
0
;
int
needMatchCount
=
dmatcher
->
supportMask
()
?
n
-
1
:
n
;
int
shift
=
dmatcher
->
isMaskSupported
()
?
1
:
0
;
int
needMatchCount
=
dmatcher
->
isMaskSupported
()
?
n
-
1
:
n
;
for
(
size_t
i
=
0
;
i
<
matches
.
size
();
i
++
)
{
if
(
(
int
)
matches
[
i
].
size
()
!=
needMatchCount
)
...
...
@@ -741,6 +741,6 @@ CV_CalonderDescriptorExtractorTest<float> floatCalonderTest( "descriptor-calonde
* Matchers
*/
CV_DescriptorMatcherTest
bruteForceMatcherTest
(
"descriptor-matcher-brute-force"
,
new
BruteForceMatcher
<
L2
<
float
>
>
,
0.01
);
new
BruteForceMatcher
<
L2
<
float
>
>
,
0.01
f
);
CV_DescriptorMatcherTest
flannBasedMatcherTest
(
"descriptor-matcher-flann-based"
,
new
FlannBasedMatcher
,
0.04
);
new
FlannBasedMatcher
,
0.04
f
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment