Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv_contrib
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_contrib
Commits
f9bbe706
Commit
f9bbe706
authored
Dec 17, 2019
by
Alexander Alekhin
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2383 from catree:feat_LOGOS_matching
parents
8a7a625a
a9c1cfcb
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
1050 additions
and
5 deletions
+1050
-5
xfeatures2d.bib
modules/xfeatures2d/doc/xfeatures2d.bib
+9
-0
xfeatures2d.hpp
modules/xfeatures2d/include/opencv2/xfeatures2d.hpp
+21
-5
logos.cpp
modules/xfeatures2d/src/logos.cpp
+69
-0
Logos.cpp
modules/xfeatures2d/src/logos/Logos.cpp
+189
-0
Logos.hpp
modules/xfeatures2d/src/logos/Logos.hpp
+87
-0
Match.cpp
modules/xfeatures2d/src/logos/Match.cpp
+103
-0
Match.hpp
modules/xfeatures2d/src/logos/Match.hpp
+73
-0
Point.cpp
modules/xfeatures2d/src/logos/Point.cpp
+120
-0
Point.hpp
modules/xfeatures2d/src/logos/Point.hpp
+79
-0
PointPair.cpp
modules/xfeatures2d/src/logos/PointPair.cpp
+77
-0
PointPair.hpp
modules/xfeatures2d/src/logos/PointPair.hpp
+71
-0
test_logos_matcher.cpp
modules/xfeatures2d/test/test_logos_matcher.cpp
+152
-0
No files found.
modules/xfeatures2d/doc/xfeatures2d.bib
View file @
f9bbe706
...
...
@@ -71,6 +71,15 @@
publisher = {Kluwer Academic Publishers}
}
@article{Lowry2018LOGOSLG,
title = {LOGOS: Local Geometric Support for High-Outlier Spatial Verification},
author = {Stephanie Lowry and Henrik Andreasson},
journal = {2018 IEEE International Conference on Robotics and Automation (ICRA)},
year = {2018},
pages = {7262-7269},
doi = {10.1109/ICRA.2018.8460988},
}
@article{Mikolajczyk2004,
title = {Scale \& affine invariant interest point detectors},
author = {Mikolajczyk, Krystian and Schmid, Cordelia},
...
...
modules/xfeatures2d/include/opencv2/xfeatures2d.hpp
View file @
f9bbe706
...
...
@@ -55,7 +55,9 @@ known to be patented. You need to set the OPENCV_ENABLE_NONFREE option in cmake
@defgroup xfeatures2d_match Experimental 2D Features Matching Algorithm
This section describes the GMS (Grid-based Motion Statistics) matching strategy.
This section describes the following matching strategies:
- GMS: Grid-based Motion Statistics, @cite Bian2017gms
- LOGOS: Local geometric support for high-outlier spatial verification, @cite Lowry2018LOGOSLG
@}
*/
...
...
@@ -969,7 +971,7 @@ CV_EXPORTS void FASTForPointSet( InputArray image, CV_IN_OUT std::vector<KeyPoin
//! @addtogroup xfeatures2d_match
//! @{
/** @brief GMS
(Grid-based Motion Statistics) feature matching strategy by
@cite Bian2017gms .
/** @brief GMS
(Grid-based Motion Statistics) feature matching strategy described in
@cite Bian2017gms .
@param size1 Input size of image1.
@param size2 Input size of image2.
@param keypoints1 Input keypoints of image1.
...
...
@@ -984,10 +986,24 @@ CV_EXPORTS void FASTForPointSet( InputArray image, CV_IN_OUT std::vector<KeyPoin
If matching results are not satisfying, please add more features. (We use 10000 for images with 640 X 480).
If your images have big rotation and scale changes, please set withRotation or withScale to true.
*/
CV_EXPORTS_W
void
matchGMS
(
const
Size
&
size1
,
const
Size
&
size2
,
const
std
::
vector
<
KeyPoint
>&
keypoints1
,
const
std
::
vector
<
KeyPoint
>&
keypoints2
,
const
std
::
vector
<
DMatch
>&
matches1to2
,
CV_OUT
std
::
vector
<
DMatch
>&
matchesGMS
,
const
bool
withRotation
=
false
,
const
bool
withScale
=
false
,
const
double
thresholdFactor
=
6.0
);
CV_EXPORTS_W
void
matchGMS
(
const
Size
&
size1
,
const
Size
&
size2
,
const
std
::
vector
<
KeyPoint
>&
keypoints1
,
const
std
::
vector
<
KeyPoint
>&
keypoints2
,
const
std
::
vector
<
DMatch
>&
matches1to2
,
CV_OUT
std
::
vector
<
DMatch
>&
matchesGMS
,
const
bool
withRotation
=
false
,
const
bool
withScale
=
false
,
const
double
thresholdFactor
=
6.0
);
/** @brief LOGOS (Local geometric support for high-outlier spatial verification) feature matching strategy described in @cite Lowry2018LOGOSLG .
@param keypoints1 Input keypoints of image1.
@param keypoints2 Input keypoints of image2.
@param nn1 Index to the closest BoW centroid for each descriptors of image1.
@param nn2 Index to the closest BoW centroid for each descriptors of image2.
@param matches1to2 Matches returned by the LOGOS matching strategy.
@note
This matching strategy is suitable for features matching against large scale database.
First step consists in constructing the bag-of-words (BoW) from a representative image database.
Image descriptors are then represented by their closest codevector (nearest BoW centroid).
*/
CV_EXPORTS_W
void
matchLOGOS
(
const
std
::
vector
<
KeyPoint
>&
keypoints1
,
const
std
::
vector
<
KeyPoint
>&
keypoints2
,
const
std
::
vector
<
int
>&
nn1
,
const
std
::
vector
<
int
>&
nn2
,
std
::
vector
<
DMatch
>&
matches1to2
);
//! @}
...
...
modules/xfeatures2d/src/logos.cpp
0 → 100644
View file @
f9bbe706
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
#include "precomp.hpp"
#include "logos/Logos.hpp"
namespace
cv
{
namespace
xfeatures2d
{
void
matchLOGOS
(
const
std
::
vector
<
KeyPoint
>&
keypoints1
,
const
std
::
vector
<
KeyPoint
>&
keypoints2
,
const
std
::
vector
<
int
>&
nn1
,
const
std
::
vector
<
int
>&
nn2
,
std
::
vector
<
DMatch
>&
matches1to2
)
{
CV_CheckEQ
(
keypoints1
.
size
(),
nn1
.
size
(),
"Number of keypoints1 must be equal to the number of nn1."
);
CV_CheckEQ
(
keypoints2
.
size
(),
nn2
.
size
(),
"Number of keypoints2 must be equal to the number of nn2."
);
if
(
keypoints1
.
empty
()
||
keypoints2
.
empty
())
{
return
;
}
std
::
vector
<
logos
::
Point
*>
vP1
,
vP2
;
vP1
.
reserve
(
keypoints1
.
size
());
vP2
.
reserve
(
keypoints2
.
size
());
for
(
size_t
i
=
0
;
i
<
keypoints1
.
size
();
i
++
)
{
logos
::
Point
*
pt1
=
new
logos
::
Point
(
keypoints1
[
i
].
pt
.
x
,
keypoints1
[
i
].
pt
.
y
,
static_cast
<
float
>
(
keypoints1
[
i
].
angle
*
CV_PI
/
180
),
keypoints1
[
i
].
size
,
nn1
[
i
]);
vP1
.
push_back
(
pt1
);
}
for
(
size_t
i
=
0
;
i
<
keypoints2
.
size
();
i
++
)
{
logos
::
Point
*
pt2
=
new
logos
::
Point
(
keypoints2
[
i
].
pt
.
x
,
keypoints2
[
i
].
pt
.
y
,
static_cast
<
float
>
(
keypoints2
[
i
].
angle
*
CV_PI
/
180
),
keypoints2
[
i
].
size
,
nn2
[
i
]);
vP2
.
push_back
(
pt2
);
}
logos
::
Logos
logos
;
std
::
vector
<
logos
::
PointPair
*>
globalMatches
;
logos
.
estimateMatches
(
vP1
,
vP2
,
globalMatches
);
matches1to2
.
clear
();
matches1to2
.
reserve
(
globalMatches
.
size
());
for
(
size_t
i
=
0
;
i
<
globalMatches
.
size
();
i
++
)
{
logos
::
PointPair
*
pp
=
globalMatches
[
i
];
matches1to2
.
push_back
(
DMatch
(
pp
->
getPos1
(),
pp
->
getPos2
(),
0
));
}
for
(
size_t
i
=
0
;
i
<
globalMatches
.
size
();
i
++
)
{
delete
globalMatches
[
i
];
}
for
(
size_t
i
=
0
;
i
<
vP1
.
size
();
i
++
)
{
delete
vP1
[
i
];
}
for
(
size_t
i
=
0
;
i
<
vP2
.
size
();
i
++
)
{
delete
vP2
[
i
];
}
}
}
//namespace xfeatures2d
}
//namespace cv
modules/xfeatures2d/src/logos/Logos.cpp
0 → 100644
View file @
f9bbe706
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
/*
* MIT License
*
* Copyright (c) 2018 Stephanie Lowry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <cmath>
#include "Logos.hpp"
#include <opencv2/core.hpp>
namespace
logos
{
Logos
::
Logos
()
{
LogosParameters
defaultParams
;
init
(
defaultParams
);
}
Logos
::
Logos
(
const
LogosParameters
&
p
)
{
init
(
p
);
}
void
Logos
::
init
(
const
LogosParameters
&
p
)
{
setParams
(
p
);
LB
=
static_cast
<
float
>
(
-
CV_PI
);
BINSIZE
=
logosParams
.
GLOBALORILIMIT
/
3
;
BINNUMBER
=
static_cast
<
unsigned
int
>
(
ceil
(
2
*
CV_PI
/
BINSIZE
));
bins
.
resize
(
BINNUMBER
);
std
::
fill
(
bins
.
begin
(),
bins
.
end
(),
0
);
}
int
Logos
::
estimateMatches
(
std
::
vector
<
Point
*>
vP1
,
std
::
vector
<
Point
*>
vP2
,
std
::
vector
<
PointPair
*>&
globalmatches
)
{
matches
.
clear
();
// for each point
int
count1
=
0
;
for
(
std
::
vector
<
Point
*>::
iterator
pit1
=
vP1
.
begin
();
pit1
!=
vP1
.
end
();
++
pit1
,
count1
++
)
{
(
*
pit1
)
->
nearestNeighbours
(
vP1
,
count1
,
getNum1
());
int
count2
=
0
;
// find possible matches
for
(
std
::
vector
<
Point
*>::
iterator
pit2
=
vP2
.
begin
();
pit2
!=
vP2
.
end
();
++
pit2
,
count2
++
)
{
if
((
*
pit1
)
->
getLabel
()
!=
(
*
pit2
)
->
getLabel
())
{
continue
;
}
// this is a possible match in Image 2
// get nearest neighbours
(
*
pit2
)
->
nearestNeighbours
(
vP2
,
count2
,
getNum2
());
PointPair
*
ptpr
=
new
PointPair
(
*
pit1
,
*
pit2
);
ptpr
->
addPositions
(
count1
,
count2
);
ptpr
->
computeLocalSupport
(
pp
,
getNum2
());
// calc matches
int
support
=
0
;
for
(
std
::
vector
<
PointPair
*>::
const_iterator
it
=
pp
.
begin
();
it
<
pp
.
end
();
++
it
)
{
Match
m
(
ptpr
,
*
it
);
if
(
evaluateMatch
(
m
))
{
support
++
;
}
}
for
(
size_t
i
=
0
;
i
<
pp
.
size
();
i
++
)
{
delete
pp
[
i
];
}
pp
.
clear
();
if
(
support
>
0
)
{
ptpr
->
setSupport
(
support
);
matches
.
push_back
(
ptpr
);
updateBin
(
ptpr
->
getRelOri
());
}
else
{
delete
ptpr
;
ptpr
=
NULL
;
}
}
}
// do global orientation
double
maxang
=
calcGlobalOrientation
();
// find which matches are within global orientation limit
int
numinliers
=
0
;
globalmatches
.
clear
();
for
(
std
::
vector
<
PointPair
*>::
iterator
it
=
matches
.
begin
();
it
!=
matches
.
end
();
++
it
)
{
if
(
std
::
fabs
((
*
it
)
->
getRelOri
()
-
maxang
)
<
logosParams
.
GLOBALORILIMIT
)
{
numinliers
++
;
globalmatches
.
push_back
(
*
it
);
}
else
{
delete
*
it
;
*
it
=
NULL
;
}
}
return
numinliers
;
}
bool
Logos
::
evaluateMatch
(
const
Match
&
m
)
const
{
return
((
m
.
getRelOrientation
()
<
getIntraOriLimit
())
&&
(
m
.
getRelScale
()
<
getIntraScaleLimit
())
&&
(
m
.
getInterOrientation
()
<
getInterOriLimit
())
&&
(
m
.
getInterScale
()
<
getInterScaleLimit
()));
}
void
Logos
::
updateBin
(
float
input
)
{
unsigned
int
binnumber
=
static_cast
<
unsigned
int
>
(
cvFloor
((
input
-
LB
)
/
BINSIZE
));
// compare binnumber to BINNUMBER
if
(
binnumber
<
BINNUMBER
)
{
bins
[
binnumber
]
++
;
}
else
{
bins
[
BINNUMBER
-
1
]
++
;
}
}
float
Logos
::
calcGlobalOrientation
()
{
// find max bin
// check BINNUMBER is big enough
if
(
BINNUMBER
<
3
)
{
return
0
;
}
std
::
vector
<
int
>
bins2
(
BINNUMBER
);
int
maxval
=
0
;
unsigned
int
maxix
=
0
;
bins2
[
0
]
=
bins
[
0
]
+
bins
[
1
]
+
bins
[
BINNUMBER
-
1
];
maxval
=
bins2
[
0
];
for
(
unsigned
int
i
=
1
;
i
<
BINNUMBER
;
i
++
)
{
if
(
i
==
BINNUMBER
-
1
)
{
bins2
[
i
]
=
bins
[
i
]
+
bins
[
i
-
1
]
+
bins
[
0
];
}
else
{
bins2
[
i
]
=
bins
[
i
]
+
bins
[
i
-
1
]
+
bins
[
i
+
1
];
}
if
(
bins2
[
i
]
>
maxval
)
{
maxval
=
bins2
[
i
];
maxix
=
i
;
}
}
// convert to an angle
return
LB
+
maxix
*
BINSIZE
+
BINSIZE
/
2
;
}
}
modules/xfeatures2d/src/logos/Logos.hpp
0 → 100644
View file @
f9bbe706
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
/*
* MIT License
*
* Copyright (c) 2018 Stephanie Lowry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef LOGOS_HPP
#define LOGOS_HPP
#include "Point.hpp"
#include "Match.hpp"
#include "PointPair.hpp"
namespace
logos
{
struct
LogosParameters
{
LogosParameters
()
:
INTRAORILIMIT
(
0.1
f
),
INTRASCALELIMIT
(
0.1
f
),
INTERORILIMIT
(
0.1
f
),
INTERSCALELIMIT
(
0.1
f
),
GLOBALORILIMIT
(
0.1
f
),
NUM1
(
5
),
NUM2
(
5
)
{}
float
INTRAORILIMIT
;
float
INTRASCALELIMIT
;
float
INTERORILIMIT
;
float
INTERSCALELIMIT
;
float
GLOBALORILIMIT
;
int
NUM1
;
int
NUM2
;
};
class
Logos
{
private
:
std
::
vector
<
PointPair
*>
pp
;
std
::
vector
<
PointPair
*>
matches
;
LogosParameters
logosParams
;
float
LB
;
float
BINSIZE
;
unsigned
int
BINNUMBER
;
std
::
vector
<
int
>
bins
;
public
:
Logos
();
Logos
(
const
LogosParameters
&
p
);
void
init
(
const
LogosParameters
&
p
);
int
estimateMatches
(
std
::
vector
<
Point
*>
vP1
,
std
::
vector
<
Point
*>
vP2
,
std
::
vector
<
PointPair
*>&
globalmatches
);
bool
evaluateMatch
(
const
Match
&
m
)
const
;
inline
float
getIntraOriLimit
()
const
{
return
logosParams
.
INTRAORILIMIT
;
}
inline
float
getIntraScaleLimit
()
const
{
return
logosParams
.
INTRASCALELIMIT
;
}
inline
float
getInterOriLimit
()
const
{
return
logosParams
.
INTERORILIMIT
;
}
inline
float
getInterScaleLimit
()
const
{
return
logosParams
.
INTERSCALELIMIT
;
}
inline
float
getGlobalOriLimit
()
const
{
return
logosParams
.
GLOBALORILIMIT
;
}
inline
int
getNum1
()
const
{
return
logosParams
.
NUM1
;
}
inline
int
getNum2
()
const
{
return
logosParams
.
NUM2
;
}
void
updateBin
(
float
input
);
float
calcGlobalOrientation
();
inline
void
setParams
(
const
LogosParameters
&
p
)
{
logosParams
=
p
;
}
};
}
#endif
modules/xfeatures2d/src/logos/Match.cpp
0 → 100644
View file @
f9bbe706
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
/*
* MIT License
*
* Copyright (c) 2018 Stephanie Lowry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <algorithm> // std::min
#include <cmath> // log, acos
#include <iostream>
#include <opencv2/core.hpp>
#include "Match.hpp"
namespace
logos
{
Match
::
Match
(
PointPair
*
r_
,
PointPair
*
s_
)
:
r
(
r_
),
s
(
s_
)
{
calculateInternalVariables
();
setRelOrientation
();
setRelScale
();
interOrientationAndScale
();
}
void
Match
::
calculateInternalVariables
()
{
vijx
=
r
->
getx1
()
-
s
->
getx1
();
vijy
=
r
->
gety1
()
-
s
->
gety1
();
vmnx
=
r
->
getx2
()
-
s
->
getx2
();
vmny
=
r
->
gety2
()
-
s
->
gety2
();
}
void
Match
::
setRelOrientation
()
{
relOrientation
=
angleAbsDiff
(
r
->
getRelOri
(),
s
->
getRelOri
());
}
void
Match
::
setRelScale
()
{
relScale
=
std
::
fabs
(
r
->
getRelScale
()
-
s
->
getRelScale
());
}
float
Match
::
angleAbsDiff
(
float
a1
,
float
a2
)
{
float
ad
=
std
::
fabs
(
a1
-
a2
);
while
(
ad
>
2
*
CV_PI
)
{
ad
=
static_cast
<
float
>
(
ad
-
2
*
CV_PI
);
}
ad
=
std
::
min
(
std
::
fabs
(
ad
),
std
::
fabs
(
static_cast
<
float
>
(
2
*
CV_PI
-
std
::
fabs
(
ad
))));
return
ad
;
}
void
Match
::
interOrientationAndScale
()
{
float
cp
=
vijx
*
vmny
-
vijy
*
vmnx
;
// analogous to 2D cross product
float
nmij
=
std
::
sqrt
(
vijx
*
vijx
+
vijy
*
vijy
);
float
nmnm
=
std
::
sqrt
(
vmnx
*
vmnx
+
vmny
*
vmny
);
float
fr
=
(
vijx
*
vmnx
+
vijy
*
vmny
)
/
(
nmij
*
nmnm
);
// numerator equivalent to dot product
fr
=
std
::
min
(
std
::
max
(
fr
,
-
1.0
f
),
1.0
f
);
ro3
=
std
::
acos
(
fr
)
*
sign
(
cp
);
rs3
=
std
::
log
(
nmij
)
-
std
::
log
(
nmnm
);
interOrientation
=
angleAbsDiff
(
r
->
getRelOri
(),
ro3
);
interScale
=
std
::
fabs
(
r
->
getRelScale
()
-
rs3
);
}
void
Match
::
printMatch
()
const
{
std
::
cout
<<
"Relative Orientation: "
<<
relOrientation
<<
std
::
endl
;
std
::
cout
<<
"Relative Scale: "
<<
relScale
<<
std
::
endl
;
std
::
cout
<<
"Inter Orientation: "
<<
interOrientation
<<
std
::
endl
;
std
::
cout
<<
"Inter Scale: "
<<
interScale
<<
std
::
endl
;
std
::
cout
<<
"Global Relative Orientation: "
<<
r
->
getRelOri
()
<<
std
::
endl
;
}
int
Match
::
sign
(
float
x
)
{
return
(
x
>
0
)
-
(
x
<
0
);
}
}
modules/xfeatures2d/src/logos/Match.hpp
0 → 100644
View file @
f9bbe706
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
/*
* MIT License
*
* Copyright (c) 2018 Stephanie Lowry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef MATCH_HPP
#define MATCH_HPP
#include "PointPair.hpp"
namespace
logos
{
class
Match
{
private
:
PointPair
*
r
;
PointPair
*
s
;
float
relOrientation
;
float
relScale
;
float
interOrientation
;
float
interScale
;
// Internal variables
float
ro3
;
float
rs3
;
float
vijx
;
float
vijy
;
float
vmnx
;
float
vmny
;
// Internal functions
void
calculateInternalVariables
();
void
setRelOrientation
();
void
setRelScale
();
float
angleDiff
(
float
a1
,
float
a2
);
float
angleAbsDiff
(
float
a1
,
float
a2
);
void
interOrientationAndScale
();
int
sign
(
float
x
);
public
:
Match
(
PointPair
*
r
,
PointPair
*
s
);
inline
float
getRelOrientation
()
const
{
return
relOrientation
;
}
inline
float
getRelScale
()
const
{
return
relScale
;
}
inline
float
getInterOrientation
()
const
{
return
interOrientation
;
}
inline
float
getInterScale
()
const
{
return
interScale
;
}
void
printMatch
()
const
;
};
}
#endif
modules/xfeatures2d/src/logos/Point.cpp
0 → 100644
View file @
f9bbe706
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
/*
* MIT License
*
* Copyright (c) 2018 Stephanie Lowry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <iostream>
#include <algorithm> // std::sort
#include "Point.hpp"
namespace
logos
{
static
bool
cMP
(
const
MatchPoint
&
m
,
const
MatchPoint
&
n
)
{
return
(
m
.
sd
<
n
.
sd
);
}
Point
::
Point
()
:
x
(
0
),
y
(
0
),
orientation
(
0
),
scale
(
1
),
nnVector
(),
nnFound
(
false
),
label
(
0
)
{
}
Point
::
Point
(
float
x_
,
float
y_
,
float
orientation_
,
float
scale_
,
int
label_
)
:
x
(
x_
),
y
(
y_
),
orientation
(
orientation_
),
scale
(
scale_
),
nnVector
(),
nnFound
(
false
),
label
(
label_
)
{
}
void
Point
::
nearestNeighbours
(
const
std
::
vector
<
Point
*>&
vP
,
int
index
,
int
N
)
{
nearestNeighboursNaive
(
vP
,
index
,
N
);
}
void
Point
::
nearestNeighboursNaive
(
const
std
::
vector
<
Point
*>&
vP
,
int
index
,
int
N
)
{
// only want to calculate once.
if
(
nnFound
)
{
return
;
}
std
::
vector
<
MatchPoint
>
minMatch
;
minMatch
.
reserve
(
vP
.
size
());
int
i
=
0
;
for
(
std
::
vector
<
Point
*>::
const_iterator
it
=
vP
.
begin
();
it
!=
vP
.
end
();
++
it
,
i
++
)
{
// A point is not it's own neighbour
if
(
i
==
index
)
{
continue
;
}
float
sd
=
squareDist
(
getx
(),
gety
(),
(
*
it
)
->
getx
(),
(
*
it
)
->
gety
());
MatchPoint
mP
(
sd
,
i
);
minMatch
.
push_back
(
mP
);
}
std
::
sort
(
minMatch
.
begin
(),
minMatch
.
end
(),
cMP
);
nnVector
.
resize
(
static_cast
<
size_t
>
(
N
));
int
count
=
0
;
for
(
std
::
vector
<
MatchPoint
>::
const_iterator
mmit
=
minMatch
.
begin
();
count
<
N
;
++
mmit
,
count
++
)
{
nnVector
[
static_cast
<
size_t
>
(
count
)]
=
vP
[
static_cast
<
size_t
>
(
mmit
->
index
)];
}
nnFound
=
true
;
}
void
Point
::
matchLabel
(
int
label_
,
std
::
vector
<
Point
*>&
matchNN
)
{
for
(
std
::
vector
<
Point
*>::
const_iterator
nnIterator
=
nnVector
.
begin
();
nnIterator
!=
nnVector
.
end
();
++
nnIterator
)
{
if
((
*
nnIterator
)
->
label
==
label_
)
{
matchNN
.
push_back
(
*
nnIterator
);
}
}
}
void
Point
::
printPoint
()
const
{
std
::
cout
<<
getx
()
<<
" "
<<
gety
()
<<
" "
<<
getOrientation
()
<<
" "
<<
getScale
()
<<
" "
<<
getLabel
()
<<
std
::
endl
;
}
void
Point
::
printNN
()
const
{
for
(
std
::
vector
<
Point
*>::
const_iterator
nnIterator
=
nnVector
.
begin
();
nnIterator
!=
nnVector
.
end
();
++
nnIterator
)
{
(
*
nnIterator
)
->
printPoint
();
}
}
float
Point
::
squareDist
(
float
x1
,
float
y1
,
float
x2
,
float
y2
)
{
return
(
x1
-
x2
)
*
(
x1
-
x2
)
+
(
y1
-
y2
)
*
(
y1
-
y2
);
}
}
modules/xfeatures2d/src/logos/Point.hpp
0 → 100644
View file @
f9bbe706
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
/*
* MIT License
*
* Copyright (c) 2018 Stephanie Lowry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef POINT_HPP
#define POINT_HPP
#include <vector>
namespace
logos
{
struct
MatchPoint
{
float
sd
;
int
index
;
MatchPoint
(
float
sd_
,
int
idx
)
:
sd
(
sd_
),
index
(
idx
)
{}
};
class
Point
{
private
:
float
x
;
float
y
;
float
orientation
;
float
scale
;
std
::
vector
<
Point
*>
nnVector
;
bool
nnFound
;
int
label
;
public
:
Point
();
Point
(
float
x_
,
float
y_
,
float
orientation_
,
float
scale_
,
int
label_
=
0
);
inline
float
getx
()
const
{
return
x
;
}
inline
float
gety
()
const
{
return
y
;
}
inline
float
getOrientation
()
const
{
return
orientation
;
}
inline
float
getScale
()
const
{
return
scale
;
}
inline
int
getLabel
()
const
{
return
label
;
}
inline
void
setLabel
(
int
label_
)
{
label
=
label_
;
}
inline
void
getNNVector
(
std
::
vector
<
Point
*>&
nnv
)
const
{
nnv
=
nnVector
;
}
void
matchLabel
(
int
label
,
std
::
vector
<
Point
*>&
mNN
);
void
nearestNeighbours
(
const
std
::
vector
<
Point
*>&
vP
,
int
index
,
int
N
);
void
nearestNeighboursNaive
(
const
std
::
vector
<
Point
*>&
vP
,
int
index
,
int
N
);
void
printPoint
()
const
;
void
printNN
()
const
;
float
squareDist
(
float
x1
,
float
y1
,
float
x2
,
float
y2
);
};
}
#endif
modules/xfeatures2d/src/logos/PointPair.cpp
0 → 100644
View file @
f9bbe706
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
/*
* MIT License
*
* Copyright (c) 2018 Stephanie Lowry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <opencv2/core.hpp>
#include "PointPair.hpp"
namespace
logos
{
PointPair
::
PointPair
(
Point
*
p_
,
Point
*
q_
)
:
p
(
p_
),
q
(
q_
),
support
(
0
),
pos1
(
0
),
pos2
(
0
)
{
calculateInternalVariables
();
}
void
PointPair
::
computeLocalSupport
(
std
::
vector
<
PointPair
*>&
pp
,
int
N
)
{
std
::
vector
<
Point
*>
nnVector
;
p
->
getNNVector
(
nnVector
);
// Exposes the nearest neighbours
// for each nearest neighbour
for
(
std
::
vector
<
Point
*>::
iterator
nnIterator
=
nnVector
.
begin
();
nnIterator
!=
nnVector
.
end
();
++
nnIterator
)
{
// is there a matching nearestNeighbour?
std
::
vector
<
Point
*>
matchNN
;
matchNN
.
reserve
(
static_cast
<
size_t
>
(
N
));
q
->
matchLabel
((
*
nnIterator
)
->
getLabel
(),
matchNN
);
for
(
std
::
vector
<
Point
*>::
const_iterator
mit
=
matchNN
.
begin
();
mit
!=
matchNN
.
end
();
++
mit
)
{
PointPair
*
m
=
new
PointPair
(
*
nnIterator
,
*
mit
);
pp
.
push_back
(
m
);
}
}
}
void
PointPair
::
calculateInternalVariables
()
{
relOri
=
angleDiff
(
p
->
getOrientation
(),
q
->
getOrientation
());
relScale
=
std
::
log
(
p
->
getScale
())
-
std
::
log
(
q
->
getScale
());
}
float
PointPair
::
angleDiff
(
float
a1
,
float
a2
)
{
float
ad
=
a1
-
a2
;
while
(
ad
>
CV_PI
)
{
ad
=
static_cast
<
float
>
(
ad
-
2
*
CV_PI
);
}
while
(
ad
<
-
CV_PI
)
{
ad
=
static_cast
<
float
>
(
ad
+
2
*
CV_PI
);
}
return
ad
;
}
}
modules/xfeatures2d/src/logos/PointPair.hpp
0 → 100644
View file @
f9bbe706
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html
/*
* MIT License
*
* Copyright (c) 2018 Stephanie Lowry
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef POINTPAIR_HPP
#define POINTPAIR_HPP
#include "Point.hpp"
namespace
logos
{
class
PointPair
{
private
:
Point
*
p
;
Point
*
q
;
int
support
;
float
relOri
;
float
relScale
;
int
pos1
;
int
pos2
;
float
angleDiff
(
float
a1
,
float
a2
);
public
:
PointPair
(
Point
*
p_
,
Point
*
q_
);
void
computeLocalSupport
(
std
::
vector
<
PointPair
*>&
pp
,
int
N
);
void
calculateInternalVariables
();
float
getRelOri
()
const
{
return
relOri
;
}
float
getRelScale
()
const
{
return
relScale
;
}
float
getx1
()
const
{
return
p
->
getx
();
}
float
getx2
()
const
{
return
q
->
getx
();
}
float
gety1
()
const
{
return
p
->
gety
();
}
float
gety2
()
const
{
return
q
->
gety
();
}
void
addPositions
(
int
pos1_
,
int
pos2_
)
{
pos1
=
pos1_
;
pos2
=
pos2_
;
}
int
getPos1
()
const
{
return
pos1
;
}
int
getPos2
()
const
{
return
pos2
;
}
int
getSupport
()
const
{
return
support
;
}
void
setSupport
(
int
support_
)
{
support
=
support_
;
}
};
}
#endif
modules/xfeatures2d/test/test_logos_matcher.cpp
0 → 100644
View file @
f9bbe706
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "test_precomp.hpp"
namespace
opencv_test
{
namespace
{
static
void
loadKeypoints
(
const
std
::
string
&
vP_path
,
const
std
::
string
&
oP_path
,
const
std
::
string
&
sP_path
,
const
std
::
string
&
w_path
,
std
::
vector
<
cv
::
KeyPoint
>&
keypoints
,
std
::
vector
<
int
>&
nn
)
{
{
std
::
ifstream
file
(
vP_path
.
c_str
());
if
(
file
.
is_open
())
{
float
x
=
0
,
y
=
0
;
while
(
file
>>
x
>>
y
)
{
keypoints
.
push_back
(
cv
::
KeyPoint
(
x
,
y
,
0
));
}
}
}
{
std
::
ifstream
file
(
oP_path
.
c_str
());
if
(
file
.
is_open
())
{
float
orientation
=
0
;
size_t
idx
=
0
;
while
(
file
>>
orientation
)
{
keypoints
[
idx
].
angle
=
static_cast
<
float
>
(
orientation
*
180.0
/
CV_PI
);
idx
++
;
}
}
}
{
std
::
ifstream
file
(
sP_path
.
c_str
());
if
(
file
.
is_open
())
{
float
scale
=
0
;
size_t
idx
=
0
;
while
(
file
>>
scale
)
{
keypoints
[
idx
].
size
=
scale
;
idx
++
;
}
}
}
{
std
::
ifstream
file
(
w_path
.
c_str
());
if
(
file
.
is_open
())
{
int
neighborIdx
=
0
;
while
(
file
>>
neighborIdx
)
{
nn
.
push_back
(
neighborIdx
);
}
}
}
ASSERT_TRUE
(
!
keypoints
.
empty
());
}
static
void
loadGroundTruth
(
const
std
::
string
&
d1_path
,
const
std
::
string
&
b1_path
,
std
::
vector
<
cv
::
DMatch
>&
groundTruth
)
{
std
::
vector
<
int
>
d1_vec
;
{
std
::
ifstream
file
(
d1_path
.
c_str
());
if
(
file
.
is_open
())
{
int
idx
=
0
;
while
(
file
>>
idx
)
{
d1_vec
.
push_back
(
idx
-
1
);
}
}
}
std
::
vector
<
int
>
b1_vec
;
{
std
::
ifstream
file
(
b1_path
.
c_str
());
if
(
file
.
is_open
())
{
int
idx
=
0
;
while
(
file
>>
idx
)
{
b1_vec
.
push_back
(
idx
-
1
);
}
}
}
ASSERT_TRUE
(
!
d1_vec
.
empty
());
ASSERT_EQ
(
d1_vec
.
size
(),
b1_vec
.
size
());
for
(
size_t
i
=
0
;
i
<
d1_vec
.
size
();
i
++
)
{
groundTruth
.
push_back
(
cv
::
DMatch
(
d1_vec
[
i
],
b1_vec
[
i
],
0
));
}
}
TEST
(
XFeatures2d_LogosMatcher
,
logos_matcher_regression
)
{
const
std
::
string
vP1_path
=
cvtest
::
findDataFile
(
"detectors_descriptors_evaluation/matching/LOGOS/vP1.txt"
);
const
std
::
string
oP1_path
=
cvtest
::
findDataFile
(
"detectors_descriptors_evaluation/matching/LOGOS/oP1.txt"
);
const
std
::
string
sP1_path
=
cvtest
::
findDataFile
(
"detectors_descriptors_evaluation/matching/LOGOS/sP1.txt"
);
const
std
::
string
w1_path
=
cvtest
::
findDataFile
(
"detectors_descriptors_evaluation/matching/LOGOS/w1.txt"
);
const
std
::
string
vP2_path
=
cvtest
::
findDataFile
(
"detectors_descriptors_evaluation/matching/LOGOS/vP2.txt"
);
const
std
::
string
oP2_path
=
cvtest
::
findDataFile
(
"detectors_descriptors_evaluation/matching/LOGOS/oP2.txt"
);
const
std
::
string
sP2_path
=
cvtest
::
findDataFile
(
"detectors_descriptors_evaluation/matching/LOGOS/sP2.txt"
);
const
std
::
string
w2_path
=
cvtest
::
findDataFile
(
"detectors_descriptors_evaluation/matching/LOGOS/w2.txt"
);
std
::
vector
<
cv
::
KeyPoint
>
keypoints1
,
keypoints2
;
std
::
vector
<
int
>
nn1
,
nn2
;
loadKeypoints
(
vP1_path
,
oP1_path
,
sP1_path
,
w1_path
,
keypoints1
,
nn1
);
loadKeypoints
(
vP2_path
,
oP2_path
,
sP2_path
,
w2_path
,
keypoints2
,
nn2
);
std
::
vector
<
cv
::
DMatch
>
matchesLogos
;
matchLOGOS
(
keypoints1
,
keypoints2
,
nn1
,
nn2
,
matchesLogos
);
std
::
vector
<
cv
::
DMatch
>
groundTruth
;
const
std
::
string
d1_path
=
cvtest
::
findDataFile
(
"detectors_descriptors_evaluation/matching/LOGOS/d1.txt"
);
const
std
::
string
b1_path
=
cvtest
::
findDataFile
(
"detectors_descriptors_evaluation/matching/LOGOS/b1.txt"
);
loadGroundTruth
(
d1_path
,
b1_path
,
groundTruth
);
int
correctMatches
=
0
;
for
(
size_t
i
=
0
;
i
<
matchesLogos
.
size
();
i
++
)
{
for
(
size_t
j
=
0
;
j
<
groundTruth
.
size
();
j
++
)
{
if
(
groundTruth
[
j
].
queryIdx
==
matchesLogos
[
i
].
queryIdx
&&
groundTruth
[
j
].
trainIdx
==
matchesLogos
[
j
].
trainIdx
)
{
correctMatches
++
;
break
;
}
}
}
ASSERT_EQ
(
static_cast
<
int
>
(
groundTruth
.
size
()),
correctMatches
)
<<
"groundTruth: "
<<
groundTruth
.
size
()
<<
" ; matchesLogos: "
<<
matchesLogos
.
size
()
<<
" ; correctMatches: "
<<
correctMatches
;
}
}}
// namespace
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