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
8ca9b9c5
Commit
8ca9b9c5
authored
Oct 20, 2016
by
Alexander Alekhin
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #486 from cbalint13:vgg
parents
ac62d70f
593e78c5
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
708 additions
and
1 deletion
+708
-1
.gitignore
.gitignore
+2
-0
CMakeLists.txt
modules/xfeatures2d/CMakeLists.txt
+2
-0
download_vgg.cmake
modules/xfeatures2d/cmake/download_vgg.cmake
+23
-0
xfeatures2d.bib
modules/xfeatures2d/doc/xfeatures2d.bib
+7
-0
xfeatures2d.hpp
modules/xfeatures2d/include/opencv2/xfeatures2d.hpp
+39
-1
perf_vgg.cpp
modules/xfeatures2d/perf/perf_vgg.cpp
+35
-0
vgg.cpp
modules/xfeatures2d/src/vgg.cpp
+522
-0
test_features2d.cpp
modules/xfeatures2d/test/test_features2d.cpp
+6
-0
test_rotation_and_scale_invariance.cpp
...s/xfeatures2d/test/test_rotation_and_scale_invariance.cpp
+72
-0
No files found.
.gitignore
View file @
8ca9b9c5
...
...
@@ -8,3 +8,5 @@
Thumbs.db
tags
tegra/
*.i
.download*
modules/xfeatures2d/CMakeLists.txt
View file @
8ca9b9c5
set
(
the_description
"Contributed/Experimental Algorithms for Salient 2D Features Detection"
)
ocv_define_module
(
xfeatures2d opencv_core opencv_imgproc opencv_features2d opencv_calib3d opencv_shape opencv_highgui opencv_videoio opencv_ml
OPTIONAL opencv_cudaarithm WRAP python java
)
include
(
cmake/download_vgg.cmake
)
\ No newline at end of file
modules/xfeatures2d/cmake/download_vgg.cmake
0 → 100644
View file @
8ca9b9c5
set
(
OPENCV_3RDPARTY_COMMIT
"fccf7cd6a4b12079f73bbfb21745f9babcd4eb1d"
)
set
(
FILE_HASH_VGG_48
"e8d0dcd54d1bcfdc29203d011a797179"
)
set
(
FILE_HASH_VGG_64
"7126a5d9a8884ebca5aea5d63d677225"
)
set
(
FILE_HASH_VGG_80
"7cd47228edec52b6d82f46511af325c5"
)
set
(
FILE_HASH_VGG_120
"151805e03568c9f490a5e3a872777b75"
)
set
(
VGG_DOWNLOAD_URL
${
OPENCV_CONTRIB_VGG_URL
}
;$ENV{OPENCV_CONTRIB_VGG_URL};https://raw.githubusercontent.com/Itseez/opencv_3rdparty/
${
OPENCV_3RDPARTY_COMMIT
}
/
)
function
(
vgg_download file id
)
message
(
STATUS
"Check contents of
${
file
}
..."
)
ocv_download
(
PACKAGE
${
file
}
HASH
${
FILE_HASH_
${
id
}}
URL
${
VGG_DOWNLOAD_URL
}
DESTINATION_DIR
${
CMAKE_CURRENT_LIST_DIR
}
/../src
DOWNLOAD_DIR
${
CMAKE_CURRENT_LIST_DIR
}
/.download
)
endfunction
()
vgg_download
(
vgg_generated_48.i VGG_48
)
vgg_download
(
vgg_generated_64.i VGG_64
)
vgg_download
(
vgg_generated_80.i VGG_80
)
vgg_download
(
vgg_generated_120.i VGG_120
)
modules/xfeatures2d/doc/xfeatures2d.bib
View file @
8ca9b9c5
...
...
@@ -71,3 +71,10 @@
booktitle={Asian Conference on Computer Vision -- ACCV 2014},
year={2014}
}
@article{Simonyan14,
author = "Simonyan, K. and Vedaldi, A. and Zisserman, A.",
title = "Learning Local Feature Descriptors Using Convex Optimisation",
journal = "IEEE Transactions on Pattern Analysis and Machine Intelligence",
year = "2014"
}
modules/xfeatures2d/include/opencv2/xfeatures2d.hpp
View file @
8ca9b9c5
...
...
@@ -168,7 +168,7 @@ Note: a complete example can be found under /samples/cpp/tutorial_code/xfeatures
class
CV_EXPORTS_W
LATCH
:
public
Feature2D
{
public
:
CV_WRAP
static
Ptr
<
LATCH
>
create
(
int
bytes
=
32
,
bool
rotationInvariance
=
true
,
int
half_ssd_size
=
3
);
CV_WRAP
static
Ptr
<
LATCH
>
create
(
int
bytes
=
32
,
bool
rotationInvariance
=
true
,
int
half_ssd_size
=
3
);
};
/** @brief Class implementing DAISY descriptor, described in @cite Tola10
...
...
@@ -280,6 +280,44 @@ public:
float
m_scale_factor
=
1.25
f
,
int
m_n_scales
=
-
1
,
bool
m_compute_orientation
=
false
);
};
/** @brief Class implementing VGG (Oxford Visual Geometry Group) descriptor trained end to end
using "Descriptor Learning Using Convex Optimisation" (DLCO) aparatus described in @cite Simonyan14.
@param desc type of descriptor to use, VGG::VGG_120 is default (120 dimensions float)
Available types are VGG::VGG_120, VGG::VGG_80, VGG::VGG_64, VGG::VGG_48
@param isigma gaussian kernel value for image blur (default is 1.4f)
@param img_normalize use image sample intensity normalization (enabled by default)
@param use_orientation sample patterns using keypoints orientation, enabled by default
@param scale_factor adjust the sampling window of detected keypoints to 64.0f (VGG sampling window)
6.25f is default and fits for KAZE, SURF detected keypoints window ratio
6.75f should be the scale for SIFT detected keypoints window ratio
5.00f should be the scale for AKAZE, MSD, AGAST, FAST, BRISK keypoints window ratio
0.75f should be the scale for ORB keypoints ratio
@param dsc_normalize clamp descriptors to 255 and convert to uchar CV_8UC1 (disabled by default)
*/
class
CV_EXPORTS_W
VGG
:
public
Feature2D
{
public
:
CV_WRAP
enum
{
VGG_120
=
100
,
VGG_80
=
101
,
VGG_64
=
102
,
VGG_48
=
103
,
};
CV_WRAP
static
Ptr
<
VGG
>
create
(
int
desc
=
VGG
::
VGG_120
,
float
isigma
=
1.4
f
,
bool
img_normalize
=
true
,
bool
use_scale_orientation
=
true
,
float
scale_factor
=
6.25
f
,
bool
dsc_normalize
=
false
);
/**
* @param image image to extract descriptors
* @param keypoints of interest within image
* @param descriptors resulted descriptors array
*/
CV_WRAP
virtual
void
compute
(
InputArray
image
,
std
::
vector
<
KeyPoint
>&
keypoints
,
OutputArray
descriptors
)
=
0
;
};
//! @}
}
...
...
modules/xfeatures2d/perf/perf_vgg.cpp
0 → 100644
View file @
8ca9b9c5
#include "perf_precomp.hpp"
using
namespace
std
;
using
namespace
cv
;
using
namespace
cv
::
xfeatures2d
;
using
namespace
perf
;
using
std
::
tr1
::
make_tuple
;
using
std
::
tr1
::
get
;
typedef
perf
::
TestBaseWithParam
<
std
::
string
>
vgg
;
#define VGG_IMAGES \
"cv/detectors_descriptors_evaluation/images_datasets/leuven/img1.png",\
"stitching/a3.png"
PERF_TEST_P
(
vgg
,
extract
,
testing
::
Values
(
VGG_IMAGES
))
{
string
filename
=
getDataPath
(
GetParam
());
Mat
frame
=
imread
(
filename
,
IMREAD_GRAYSCALE
);
ASSERT_FALSE
(
frame
.
empty
())
<<
"Unable to load source image "
<<
filename
;
Mat
mask
;
declare
.
in
(
frame
).
time
(
90
);
Ptr
<
KAZE
>
detector
=
KAZE
::
create
();
vector
<
KeyPoint
>
points
;
detector
->
detect
(
frame
,
points
,
mask
);
Ptr
<
VGG
>
descriptor
=
VGG
::
create
();
Mat_
<
float
>
descriptors
;
// compute keypoints descriptor
TEST_CYCLE
()
descriptor
->
compute
(
frame
,
points
,
descriptors
);
SANITY_CHECK_NOTHING
();
}
modules/xfeatures2d/src/vgg.cpp
0 → 100644
View file @
8ca9b9c5
/*********************************************************************
* Software License Agreement (BSD License)
*
* Copyright (c) 2014, 2015
*
* Karen Simonyan <karen at robots dot ox dot ac dot uk>
* Andrea Vedaldi <vedaldi at robots dot ox dot ac dot uk>
* Andrew Zisserman <az at robots dot ox dot ac dot uk>
*
* Visual Geometry Group
* Department of Engineering Science, University of Oxford
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/
/*
"Learning Local Feature Descriptors Using Convex Optimisation",
Simonyan, K. and Vedaldi, A. and Zisserman, A.,
IEEE Transactions on Pattern Analysis and Machine Intelligence, 2014
"Discriminative Learning of Local Image Descriptors",
Matthew A. Brown, Gang Hua, Simon A. J. Winder,
IEEE Transactions on Pattern Analysis and Machine Intelligence, 2011
OpenCV port by: Cristian Balint <cristian dot balint at gmail dot com>
*/
#include "precomp.hpp"
using
namespace
cv
;
using
namespace
std
;
namespace
cv
{
namespace
xfeatures2d
{
/*
!VGG implementation
*/
class
VGG_Impl
:
public
VGG
{
public
:
// constructor
explicit
VGG_Impl
(
int
desc
=
VGG
::
VGG_80
,
float
isigma
=
1.4
f
,
bool
img_normalize
=
true
,
bool
use_scale_orientation
=
true
,
float
scale_factor
=
6.25
f
,
bool
dsc_normalize
=
false
);
// destructor
virtual
~
VGG_Impl
();
// returns the descriptor length in bytes
virtual
int
descriptorSize
()
const
{
return
m_descriptor_size
;
};
// returns the descriptor type
virtual
int
descriptorType
()
const
{
return
CV_32F
;
}
// returns the default norm type
virtual
int
defaultNorm
()
const
{
return
NORM_L2
;
}
// compute descriptors given keypoints
virtual
void
compute
(
InputArray
image
,
vector
<
KeyPoint
>&
keypoints
,
OutputArray
descriptors
);
protected
:
/*
* VGG parameters
*/
int
m_descriptor_size
;
// gauss sigma
float
m_isigma
;
// angle bins
int
m_anglebins
;
// sample window
float
m_scale_factor
;
/*
* VGG switches
*/
// normalize image
bool
m_img_normalize
;
// switch to enable sample by keypoints orientation
bool
m_use_scale_orientation
;
// normalize desc
bool
m_dsc_normalize
;
/*
* VGG arrays
*/
// image
Mat
m_image
;
// pool regions & proj
Mat
m_PRFilters
,
m_Proj
;
private
:
/*
* VGG functions
*/
// initialize parameters
inline
void
ini_params
(
const
int
PRrows
,
const
int
PRcols
,
const
unsigned
int
PRidx
[],
const
unsigned
int
PRidxSize
,
const
unsigned
int
PR
[],
const
int
PJrows
,
const
int
PJcols
,
const
unsigned
int
PJidx
[],
const
unsigned
int
PJidxSize
,
const
unsigned
int
PJ
[]
);
};
// END VGG_Impl CLASS
// -------------------------------------------------
/* VGG internal routines */
// sample 64x64 patch from image given keypoint
static
inline
void
get_patch
(
const
KeyPoint
kp
,
Mat
&
Patch
,
const
Mat
&
image
,
const
bool
use_scale_orientation
,
const
float
scale_factor
)
{
// scale & radians
float
scale
=
kp
.
size
/
64.0
f
*
scale_factor
;
const
float
angle
=
(
kp
.
angle
==
-
1
)
?
0
:
(
(
kp
.
angle
)
*
(
float
)
CV_PI
)
/
180.
f
;
// transforms
const
float
tsin
=
sin
(
angle
)
*
scale
;
const
float
tcos
=
cos
(
angle
)
*
scale
;
const
float
half_cols
=
(
float
)
Patch
.
cols
/
2.0
f
;
const
float
half_rows
=
(
float
)
Patch
.
rows
/
2.0
f
;
// sample form original image
for
(
int
x
=
0
;
x
<
Patch
.
cols
;
x
++
)
{
for
(
int
y
=
0
;
y
<
Patch
.
rows
;
y
++
)
{
if
(
use_scale_orientation
)
{
const
float
xoff
=
x
-
half_cols
;
const
float
yoff
=
y
-
half_rows
;
// the rotation shifts & scale
int
img_x
=
int
(
(
kp
.
pt
.
x
+
0.5
f
)
+
xoff
*
tcos
-
yoff
*
tsin
);
int
img_y
=
int
(
(
kp
.
pt
.
y
+
0.5
f
)
+
xoff
*
tsin
+
yoff
*
tcos
);
// sample only within image
if
(
(
img_x
<
image
.
cols
)
&&
(
img_x
>=
0
)
&&
(
img_y
<
image
.
rows
)
&&
(
img_y
>=
0
)
)
Patch
.
at
<
float
>
(
y
,
x
)
=
image
.
at
<
float
>
(
img_y
,
img_x
);
else
Patch
.
at
<
float
>
(
y
,
x
)
=
0.0
f
;
}
else
{
const
float
xoff
=
x
-
half_cols
;
const
float
yoff
=
y
-
half_rows
;
// the samples from image
int
img_x
=
int
(
kp
.
pt
.
x
+
0.5
f
+
xoff
);
int
img_y
=
int
(
kp
.
pt
.
y
+
0.5
f
+
yoff
);
// sample only within image
if
(
(
img_x
<
image
.
cols
)
&&
(
img_x
>=
0
)
&&
(
img_y
<
image
.
rows
)
&&
(
img_y
>=
0
)
)
Patch
.
at
<
float
>
(
y
,
x
)
=
image
.
at
<
float
>
(
img_y
,
img_x
);
else
Patch
.
at
<
float
>
(
y
,
x
)
=
0.0
f
;
}
}
}
}
// get descriptor given 64x64 image patch
static
void
get_desc
(
const
Mat
Patch
,
Mat
&
PatchTrans
,
int
anglebins
,
bool
img_normalize
)
{
Mat
Ix
,
Iy
;
// % compute gradient
float
kparam
[
3
]
=
{
-
1
,
0
,
1
};
Mat
Kernel
(
1
,
3
,
CV_32F
,
&
kparam
);
filter2D
(
Patch
,
Ix
,
CV_32F
,
Kernel
,
Point
(
-
1
,
-
1
),
0
,
BORDER_REPLICATE
);
filter2D
(
Patch
,
Iy
,
CV_32F
,
Kernel
.
t
(),
Point
(
-
1
,
-
1
),
0
,
BORDER_REPLICATE
);
Mat
GMag
,
GAngle
;
// % gradient magnitude
// % GMag = sqrt(Ix .^ 2 + Iy .^ 2);
magnitude
(
Ix
,
Iy
,
GMag
);
// % gradient orientation: [0; 2 * pi]
// % GAngle = atan2(Iy, Ix) + pi;
//phase( Ix, Iy, GAngle, false ); //<- opencv is buggy
GAngle
=
Mat
(
GMag
.
rows
,
GMag
.
cols
,
CV_32F
);
for
(
int
i
=
0
;
i
<
(
int
)
GAngle
.
total
();
i
++
)
GAngle
.
at
<
float
>
(
i
)
=
atan2
(
Iy
.
at
<
float
>
(
i
),
Ix
.
at
<
float
>
(
i
)
)
+
(
float
)
CV_PI
;
// % soft-assignment of gradients to the orientation histogram
float
AngleStep
=
2.0
f
*
(
float
)
CV_PI
/
(
float
)
anglebins
;
Mat
GAngleRatio
=
GAngle
/
AngleStep
-
0.5
f
;
// % Offset1 = mod(GAngleRatio, 1);
Mat
Offset1
(
GAngleRatio
.
rows
,
GAngleRatio
.
cols
,
CV_32F
);
for
(
int
i
=
0
;
i
<
(
int
)
GAngleRatio
.
total
();
i
++
)
Offset1
.
at
<
float
>
(
i
)
=
GAngleRatio
.
at
<
float
>
(
i
)
-
floor
(
GAngleRatio
.
at
<
float
>
(
i
)
);
Mat
w1
=
1.0
f
-
Offset1
.
t
();
Mat
w2
=
Offset1
.
t
();
Mat
Bin1
(
GAngleRatio
.
rows
,
GAngleRatio
.
cols
,
CV_8U
);
Mat
Bin2
(
GAngleRatio
.
rows
,
GAngleRatio
.
cols
,
CV_8U
);
// % Bin1 = ceil(GAngleRatio);
// % Bin1(Bin1 == 0) = Params.nAngleBins;
for
(
int
i
=
0
;
i
<
(
int
)
GAngleRatio
.
total
();
i
++
)
{
if
(
ceil
(
GAngleRatio
.
at
<
float
>
(
i
)
-
1.0
f
)
==
-
1.0
f
)
Bin1
.
at
<
uchar
>
(
i
)
=
(
uchar
)
anglebins
-
1
;
else
Bin1
.
at
<
uchar
>
(
i
)
=
(
uchar
)
ceil
(
GAngleRatio
.
at
<
float
>
(
i
)
-
1.0
f
);
}
// % Bin2 = Bin1 + 1;
// % Bin2(Bin2 > Params.nAngleBins) = 1;
for
(
int
i
=
0
;
i
<
(
int
)
GAngleRatio
.
total
();
i
++
)
{
if
(
(
Bin1
.
at
<
uchar
>
(
i
)
+
1
)
>
anglebins
-
1
)
Bin2
.
at
<
uchar
>
(
i
)
=
0
;
else
Bin2
.
at
<
uchar
>
(
i
)
=
Bin1
.
at
<
uchar
>
(
i
)
+
1
;
}
// normalize
if
(
img_normalize
)
{
// % Quantile = 0.8;
float
q
=
0.8
f
;
// % T = quantile(GMag(:), Quantile);
Mat
GMagSorted
;
sort
(
GMag
.
reshape
(
0
,
1
),
GMagSorted
,
SORT_ASCENDING
);
int
n
=
GMagSorted
.
cols
;
// scipy/stats/mstats_basic.py#L1718 mquantiles()
// m = alphap + p*(1.-alphap-betap)
// alphap = 0.5 betap = 0.5 => (m = 0.5)
// aleph = (n*p + m)
float
aleph
=
(
n
*
q
+
0.5
f
);
int
k
=
cvFloor
(
aleph
);
if
(
k
>=
n
-
1
)
k
=
n
-
1
;
if
(
k
<=
1
)
k
=
1
;
float
gamma
=
aleph
-
k
;
if
(
gamma
>=
1.0
f
)
gamma
=
1.0
f
;
if
(
gamma
<=
0.0
f
)
gamma
=
0.0
f
;
// quantile out from distribution
float
T
=
(
1.0
f
-
gamma
)
*
GMagSorted
.
at
<
float
>
(
k
-
1
)
+
gamma
*
GMagSorted
.
at
<
float
>
(
k
);
// avoid NaN
if
(
T
!=
0.0
f
)
GMag
/=
(
T
/
anglebins
);
}
Mat
Bin1T
=
Bin1
.
t
();
Mat
Bin2T
=
Bin2
.
t
();
Mat
GMagT
=
GMag
.
t
();
// % feature channels
PatchTrans
=
Mat
(
(
int
)
Patch
.
total
(),
anglebins
,
CV_32F
,
Scalar
::
all
(
0
)
);
for
(
int
i
=
0
;
i
<
anglebins
;
i
++
)
{
for
(
int
p
=
0
;
p
<
(
int
)
Patch
.
total
();
p
++
)
{
if
(
Bin1T
.
at
<
uchar
>
(
p
)
==
i
)
PatchTrans
.
at
<
float
>
(
p
,
i
)
=
w1
.
at
<
float
>
(
p
)
*
GMagT
.
at
<
float
>
(
p
);
if
(
Bin2T
.
at
<
uchar
>
(
p
)
==
i
)
PatchTrans
.
at
<
float
>
(
p
,
i
)
=
w2
.
at
<
float
>
(
p
)
*
GMagT
.
at
<
float
>
(
p
);
}
}
}
// -------------------------------------------------
/* VGG interface implementation */
struct
ComputeDescInvoker
:
ParallelLoopBody
{
ComputeDescInvoker
(
const
Mat
&
_image
,
Mat
*
_descriptors
,
const
vector
<
KeyPoint
>&
_keypoints
,
const
Mat
&
_PRFilters
,
const
Mat
&
_Proj
,
const
int
_anglebins
,
const
bool
_img_normalize
,
const
bool
_use_scale_orientation
,
const
float
_scale_factor
)
{
image
=
_image
;
keypoints
=
_keypoints
;
descriptors
=
_descriptors
;
Proj
=
_Proj
;
PRFilters
=
_PRFilters
;
anglebins
=
_anglebins
;
scale_factor
=
_scale_factor
;
img_normalize
=
_img_normalize
;
use_scale_orientation
=
_use_scale_orientation
;
}
void
operator
()(
const
cv
::
Range
&
range
)
const
{
Mat
Desc
,
PatchTrans
;
Mat
Patch
(
64
,
64
,
CV_32F
);
for
(
int
k
=
range
.
start
;
k
<
range
.
end
;
k
++
)
{
// sample patch from image
get_patch
(
keypoints
[
k
],
Patch
,
image
,
use_scale_orientation
,
scale_factor
);
// compute transform
get_desc
(
Patch
,
PatchTrans
,
anglebins
,
img_normalize
);
// pool features
Desc
=
PRFilters
*
PatchTrans
;
// crop
min
(
Desc
,
1.0
f
,
Desc
);
// reshape
Desc
=
Desc
.
reshape
(
1
,
(
int
)
Desc
.
total
()
);
// project
descriptors
->
row
(
k
)
=
Desc
.
t
()
*
Proj
.
t
();
}
}
Mat
image
;
Mat
*
descriptors
;
vector
<
KeyPoint
>
keypoints
;
Mat
Proj
;
Mat
PRFilters
;
int
anglebins
;
float
scale_factor
;
bool
img_normalize
;
bool
use_scale_orientation
;
};
// descriptor computation using keypoints
void
VGG_Impl
::
compute
(
InputArray
_image
,
vector
<
KeyPoint
>&
keypoints
,
OutputArray
_descriptors
)
{
// do nothing if no image
if
(
_image
.
getMat
().
empty
()
)
return
;
m_image
=
_image
.
getMat
().
clone
();
// Only 8bit images
CV_Assert
(
m_image
.
depth
()
==
CV_8U
);
// convert to gray inplace
if
(
m_image
.
channels
()
>
1
)
cvtColor
(
m_image
,
m_image
,
COLOR_BGR2GRAY
);
//convert
Mat
image
;
m_image
.
convertTo
(
image
,
CV_32F
);
m_image
=
image
;
image
.
release
();
// smooth whole image
GaussianBlur
(
m_image
,
m_image
,
Size
(
0
,
0
),
m_isigma
,
m_isigma
,
BORDER_REPLICATE
);
// allocate array
_descriptors
.
create
(
(
int
)
keypoints
.
size
(),
m_descriptor_size
,
CV_32F
);
// prepare descriptors
Mat
descriptors
=
_descriptors
.
getMat
();
descriptors
.
setTo
(
Scalar
(
0
)
);
parallel_for_
(
Range
(
0
,
(
int
)
keypoints
.
size
()
),
ComputeDescInvoker
(
m_image
,
&
descriptors
,
keypoints
,
m_PRFilters
,
m_Proj
,
m_anglebins
,
m_img_normalize
,
m_use_scale_orientation
,
m_scale_factor
)
);
// normalize desc
if
(
m_dsc_normalize
)
{
normalize
(
descriptors
,
descriptors
,
0.0
f
,
255.0
f
,
NORM_MINMAX
,
CV_32F
);
descriptors
.
convertTo
(
_descriptors
,
CV_8U
);
}
}
void
VGG_Impl
::
ini_params
(
const
int
PRrows
,
const
int
PRcols
,
const
unsigned
int
PRidx
[],
const
unsigned
int
PRidxSize
,
const
unsigned
int
PR
[],
const
int
PJrows
,
const
int
PJcols
,
const
unsigned
int
PJidx
[],
const
unsigned
int
PJidxSize
,
const
unsigned
int
PJ
[]
)
{
int
idx
;
// initialize pool-region matrix
m_PRFilters
=
Mat
::
zeros
(
PRrows
,
PRcols
,
CV_32F
);
// initialize projection matrix
m_Proj
=
Mat
::
zeros
(
PJrows
,
PJcols
,
CV_32F
);
idx
=
0
;
// fill sparse pool-region matrix
for
(
size_t
i
=
0
;
i
<
PRidxSize
;
i
=
i
+
2
)
{
for
(
size_t
k
=
0
;
k
<
PRidx
[
i
+
1
];
k
++
)
{
// expand floats from hex blobs
m_PRFilters
.
at
<
float
>
(
PRidx
[
i
]
+
(
int
)
k
)
=
*
(
float
*
)
&
PR
[
idx
];
idx
++
;
}
}
idx
=
0
;
// fill sparse projection matrix
for
(
size_t
i
=
0
;
i
<
PJidxSize
;
i
=
i
+
2
)
{
for
(
size_t
k
=
0
;
k
<
PJidx
[
i
+
1
];
k
++
)
{
// expand floats from hex blobs
m_Proj
.
at
<
float
>
(
PJidx
[
i
]
+
(
int
)
k
)
=
*
(
float
*
)
&
PJ
[
idx
];
idx
++
;
}
}
}
// constructor
VGG_Impl
::
VGG_Impl
(
int
_desc
,
float
_isigma
,
bool
_img_normalize
,
bool
_use_scale_orientation
,
float
_scale_factor
,
bool
_dsc_normalize
)
:
m_isigma
(
_isigma
),
m_scale_factor
(
_scale_factor
),
m_img_normalize
(
_img_normalize
),
m_use_scale_orientation
(
_use_scale_orientation
),
m_dsc_normalize
(
_dsc_normalize
)
{
// constant
m_anglebins
=
8
;
// desc type
switch
(
_desc
)
{
case
VGG
:
:
VGG_120
:
{
#include "vgg_generated_120.i"
ini_params
(
PRrows
,
PRcols
,
PRidx
,
sizeof
(
PRidx
)
/
sizeof
(
PRidx
[
0
]),
PR
,
PJrows
,
PJcols
,
PJidx
,
sizeof
(
PJidx
)
/
sizeof
(
PJidx
[
0
]),
PJ
);
}
break
;
case
VGG
:
:
VGG_80
:
{
#include "vgg_generated_80.i"
ini_params
(
PRrows
,
PRcols
,
PRidx
,
sizeof
(
PRidx
)
/
sizeof
(
PRidx
[
0
]),
PR
,
PJrows
,
PJcols
,
PJidx
,
sizeof
(
PJidx
)
/
sizeof
(
PJidx
[
0
]),
PJ
);
}
break
;
case
VGG
:
:
VGG_64
:
{
#include "vgg_generated_64.i"
ini_params
(
PRrows
,
PRcols
,
PRidx
,
sizeof
(
PRidx
)
/
sizeof
(
PRidx
[
0
]),
PR
,
PJrows
,
PJcols
,
PJidx
,
sizeof
(
PJidx
)
/
sizeof
(
PJidx
[
0
]),
PJ
);
}
break
;
case
VGG
:
:
VGG_48
:
{
#include "vgg_generated_48.i"
ini_params
(
PRrows
,
PRcols
,
PRidx
,
sizeof
(
PRidx
)
/
sizeof
(
PRidx
[
0
]),
PR
,
PJrows
,
PJcols
,
PJidx
,
sizeof
(
PJidx
)
/
sizeof
(
PJidx
[
0
]),
PJ
);
}
break
;
default
:
CV_Error
(
Error
::
StsInternal
,
"Unknown Descriptor Type."
);
}
// set desc size
m_descriptor_size
=
m_Proj
.
rows
;
}
// destructor
VGG_Impl
::~
VGG_Impl
()
{
}
Ptr
<
VGG
>
VGG
::
create
(
int
desc
,
float
isigma
,
bool
img_normalize
,
bool
use_scale_orientation
,
float
scale_factor
,
bool
dsc_normalize
)
{
return
makePtr
<
VGG_Impl
>
(
desc
,
isigma
,
img_normalize
,
use_scale_orientation
,
scale_factor
,
dsc_normalize
);
}
}
// END NAMESPACE XFEATURES2D
}
// END NAMESPACE CV
modules/xfeatures2d/test/test_features2d.cpp
View file @
8ca9b9c5
...
...
@@ -1050,6 +1050,12 @@ TEST( Features2d_DescriptorExtractor_LATCH, regression )
test
.
safe_run
();
}
TEST
(
Features2d_DescriptorExtractor_VGG
,
regression
)
{
CV_DescriptorExtractorTest
<
L2
<
float
>
>
test
(
"descriptor-vgg"
,
0.03
f
,
VGG
::
create
()
);
test
.
safe_run
();
}
/*#if CV_SSE2
...
...
modules/xfeatures2d/test/test_rotation_and_scale_invariance.cpp
View file @
8ca9b9c5
...
...
@@ -671,6 +671,42 @@ TEST(DISABLED_Features2d_RotationInvariance_Descriptor_DAISY, regression)
test
.
safe_run
();
}
TEST
(
Features2d_RotationInvariance_Descriptor_VGG120
,
regression
)
{
DescriptorRotationInvarianceTest
test
(
KAZE
::
create
(),
VGG
::
create
(
VGG
::
VGG_120
,
1.4
f
,
true
,
true
,
48.0
f
,
false
),
NORM_L1
,
1.00
f
);
test
.
safe_run
();
}
TEST
(
Features2d_RotationInvariance_Descriptor_VGG80
,
regression
)
{
DescriptorRotationInvarianceTest
test
(
KAZE
::
create
(),
VGG
::
create
(
VGG
::
VGG_80
,
1.4
f
,
true
,
true
,
48.0
f
,
false
),
NORM_L1
,
1.00
f
);
test
.
safe_run
();
}
TEST
(
Features2d_RotationInvariance_Descriptor_VGG64
,
regression
)
{
DescriptorRotationInvarianceTest
test
(
KAZE
::
create
(),
VGG
::
create
(
VGG
::
VGG_64
,
1.4
f
,
true
,
true
,
48.0
f
,
false
),
NORM_L1
,
1.00
f
);
test
.
safe_run
();
}
TEST
(
Features2d_RotationInvariance_Descriptor_VGG48
,
regression
)
{
DescriptorRotationInvarianceTest
test
(
KAZE
::
create
(),
VGG
::
create
(
VGG
::
VGG_48
,
1.4
f
,
true
,
true
,
48.0
f
,
false
),
NORM_L1
,
1.00
f
);
test
.
safe_run
();
}
TEST
(
Features2d_RotationInvariance_Descriptor_BRIEF_64
,
regression
)
{
DescriptorRotationInvarianceTest
test
(
SURF
::
create
(),
...
...
@@ -774,3 +810,39 @@ TEST(DISABLED_Features2d_ScaleInvariance_Descriptor_DAISY, regression)
0.075
f
);
test
.
safe_run
();
}
TEST
(
Features2d_ScaleInvariance_Descriptor_VGG120
,
regression
)
{
DescriptorScaleInvarianceTest
test
(
KAZE
::
create
(),
VGG
::
create
(
VGG
::
VGG_120
,
1.4
f
,
true
,
true
,
48.0
f
,
false
),
NORM_L1
,
0.99
f
);
test
.
safe_run
();
}
TEST
(
Features2d_ScaleInvariance_Descriptor_VGG80
,
regression
)
{
DescriptorScaleInvarianceTest
test
(
KAZE
::
create
(),
VGG
::
create
(
VGG
::
VGG_80
,
1.4
f
,
true
,
true
,
48.0
f
,
false
),
NORM_L1
,
0.98
f
);
test
.
safe_run
();
}
TEST
(
Features2d_ScaleInvariance_Descriptor_VGG64
,
regression
)
{
DescriptorScaleInvarianceTest
test
(
KAZE
::
create
(),
VGG
::
create
(
VGG
::
VGG_64
,
1.4
f
,
true
,
true
,
48.0
f
,
false
),
NORM_L1
,
0.97
f
);
test
.
safe_run
();
}
TEST
(
Features2d_ScaleInvariance_Descriptor_VGG48
,
regression
)
{
DescriptorScaleInvarianceTest
test
(
KAZE
::
create
(),
VGG
::
create
(
VGG
::
VGG_48
,
1.4
f
,
true
,
true
,
48.0
f
,
false
),
NORM_L1
,
0.93
f
);
test
.
safe_run
();
}
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