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
6c8ec533
Commit
6c8ec533
authored
Nov 02, 2018
by
Alexander Alekhin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
shape: move to opencv_contrib
parent
687fa6a8
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
0 additions
and
4202 deletions
+0
-4202
CMakeLists.txt
modules/shape/CMakeLists.txt
+0
-2
shape.hpp
modules/shape/include/opencv2/shape.hpp
+0
-57
emdL1.hpp
modules/shape/include/opencv2/shape/emdL1.hpp
+0
-72
hist_cost.hpp
modules/shape/include/opencv2/shape/hist_cost.hpp
+0
-111
shape.hpp
modules/shape/include/opencv2/shape/shape.hpp
+0
-48
shape_distance.hpp
modules/shape/include/opencv2/shape/shape_distance.hpp
+0
-227
shape_transformer.hpp
modules/shape/include/opencv2/shape/shape_transformer.hpp
+0
-132
aff_trans.cpp
modules/shape/src/aff_trans.cpp
+0
-279
emdL1.cpp
modules/shape/src/emdL1.cpp
+0
-797
emdL1_def.hpp
modules/shape/src/emdL1_def.hpp
+0
-148
haus_dis.cpp
modules/shape/src/haus_dis.cpp
+0
-157
hist_cost.cpp
modules/shape/src/hist_cost.cpp
+0
-549
precomp.hpp
modules/shape/src/precomp.hpp
+0
-59
sc_dis.cpp
modules/shape/src/sc_dis.cpp
+0
-793
scd_def.hpp
modules/shape/src/scd_def.hpp
+0
-132
tps_trans.cpp
modules/shape/src/tps_trans.cpp
+0
-295
test_main.cpp
modules/shape/test/test_main.cpp
+0
-10
test_precomp.hpp
modules/shape/test/test_precomp.hpp
+0
-10
test_shape.cpp
modules/shape/test/test_shape.cpp
+0
-324
No files found.
modules/shape/CMakeLists.txt
deleted
100644 → 0
View file @
687fa6a8
set
(
the_description
"Shape descriptors and matchers"
)
ocv_define_module
(
shape opencv_core opencv_imgproc opencv_calib3d WRAP python
)
modules/shape/include/opencv2/shape.hpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009-2012, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef OPENCV_SHAPE_HPP
#define OPENCV_SHAPE_HPP
#include "opencv2/shape/emdL1.hpp"
#include "opencv2/shape/shape_transformer.hpp"
#include "opencv2/shape/hist_cost.hpp"
#include "opencv2/shape/shape_distance.hpp"
/**
@defgroup shape Shape Distance and Matching
*/
#endif
/* End of file. */
modules/shape/include/opencv2/shape/emdL1.hpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009-2012, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef OPENCV_EMD_L1_HPP
#define OPENCV_EMD_L1_HPP
#include "opencv2/core.hpp"
namespace
cv
{
/****************************************************************************************\
* EMDL1 Function *
\****************************************************************************************/
//! @addtogroup shape
//! @{
/** @brief Computes the "minimal work" distance between two weighted point configurations base on the papers
"EMD-L1: An efficient and Robust Algorithm for comparing histogram-based descriptors", by Haibin
Ling and Kazunori Okuda; and "The Earth Mover's Distance is the Mallows Distance: Some Insights from
Statistics", by Elizaveta Levina and Peter Bickel.
@param signature1 First signature, a single column floating-point matrix. Each row is the value of
the histogram in each bin.
@param signature2 Second signature of the same format and size as signature1.
*/
CV_EXPORTS
float
EMDL1
(
InputArray
signature1
,
InputArray
signature2
);
//! @}
}
//namespace cv
#endif
modules/shape/include/opencv2/shape/hist_cost.hpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef OPENCV_HIST_COST_HPP
#define OPENCV_HIST_COST_HPP
#include "opencv2/imgproc.hpp"
namespace
cv
{
//! @addtogroup shape
//! @{
/** @brief Abstract base class for histogram cost algorithms.
*/
class
CV_EXPORTS_W
HistogramCostExtractor
:
public
Algorithm
{
public
:
CV_WRAP
virtual
void
buildCostMatrix
(
InputArray
descriptors1
,
InputArray
descriptors2
,
OutputArray
costMatrix
)
=
0
;
CV_WRAP
virtual
void
setNDummies
(
int
nDummies
)
=
0
;
CV_WRAP
virtual
int
getNDummies
()
const
=
0
;
CV_WRAP
virtual
void
setDefaultCost
(
float
defaultCost
)
=
0
;
CV_WRAP
virtual
float
getDefaultCost
()
const
=
0
;
};
/** @brief A norm based cost extraction. :
*/
class
CV_EXPORTS_W
NormHistogramCostExtractor
:
public
HistogramCostExtractor
{
public
:
CV_WRAP
virtual
void
setNormFlag
(
int
flag
)
=
0
;
CV_WRAP
virtual
int
getNormFlag
()
const
=
0
;
};
CV_EXPORTS_W
Ptr
<
HistogramCostExtractor
>
createNormHistogramCostExtractor
(
int
flag
=
DIST_L2
,
int
nDummies
=
25
,
float
defaultCost
=
0.2
f
);
/** @brief An EMD based cost extraction. :
*/
class
CV_EXPORTS_W
EMDHistogramCostExtractor
:
public
HistogramCostExtractor
{
public
:
CV_WRAP
virtual
void
setNormFlag
(
int
flag
)
=
0
;
CV_WRAP
virtual
int
getNormFlag
()
const
=
0
;
};
CV_EXPORTS_W
Ptr
<
HistogramCostExtractor
>
createEMDHistogramCostExtractor
(
int
flag
=
DIST_L2
,
int
nDummies
=
25
,
float
defaultCost
=
0.2
f
);
/** @brief An Chi based cost extraction. :
*/
class
CV_EXPORTS_W
ChiHistogramCostExtractor
:
public
HistogramCostExtractor
{};
CV_EXPORTS_W
Ptr
<
HistogramCostExtractor
>
createChiHistogramCostExtractor
(
int
nDummies
=
25
,
float
defaultCost
=
0.2
f
);
/** @brief An EMD-L1 based cost extraction. :
*/
class
CV_EXPORTS_W
EMDL1HistogramCostExtractor
:
public
HistogramCostExtractor
{};
CV_EXPORTS_W
Ptr
<
HistogramCostExtractor
>
createEMDL1HistogramCostExtractor
(
int
nDummies
=
25
,
float
defaultCost
=
0.2
f
);
//! @}
}
// cv
#endif
modules/shape/include/opencv2/shape/shape.hpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifdef __OPENCV_BUILD
#error this is a compatibility header which should not be used inside the OpenCV library
#endif
#include "opencv2/shape.hpp"
modules/shape/include/opencv2/shape/shape_distance.hpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef OPENCV_SHAPE_SHAPE_DISTANCE_HPP
#define OPENCV_SHAPE_SHAPE_DISTANCE_HPP
#include "opencv2/core.hpp"
#include "opencv2/shape/hist_cost.hpp"
#include "opencv2/shape/shape_transformer.hpp"
namespace
cv
{
//! @addtogroup shape
//! @{
/** @example samples/cpp/shape_example.cpp
An example using shape distance algorithm
*/
/** @brief Abstract base class for shape distance algorithms.
*/
class
CV_EXPORTS_W
ShapeDistanceExtractor
:
public
Algorithm
{
public
:
/** @brief Compute the shape distance between two shapes defined by its contours.
@param contour1 Contour defining first shape.
@param contour2 Contour defining second shape.
*/
CV_WRAP
virtual
float
computeDistance
(
InputArray
contour1
,
InputArray
contour2
)
=
0
;
};
/***********************************************************************************/
/***********************************************************************************/
/***********************************************************************************/
/** @brief Implementation of the Shape Context descriptor and matching algorithm
proposed by Belongie et al. in "Shape Matching and Object Recognition Using Shape Contexts" (PAMI
2002). This implementation is packaged in a generic scheme, in order to allow you the
implementation of the common variations of the original pipeline.
*/
class
CV_EXPORTS_W
ShapeContextDistanceExtractor
:
public
ShapeDistanceExtractor
{
public
:
/** @brief Establish the number of angular bins for the Shape Context Descriptor used in the shape matching
pipeline.
@param nAngularBins The number of angular bins in the shape context descriptor.
*/
CV_WRAP
virtual
void
setAngularBins
(
int
nAngularBins
)
=
0
;
CV_WRAP
virtual
int
getAngularBins
()
const
=
0
;
/** @brief Establish the number of radial bins for the Shape Context Descriptor used in the shape matching
pipeline.
@param nRadialBins The number of radial bins in the shape context descriptor.
*/
CV_WRAP
virtual
void
setRadialBins
(
int
nRadialBins
)
=
0
;
CV_WRAP
virtual
int
getRadialBins
()
const
=
0
;
/** @brief Set the inner radius of the shape context descriptor.
@param innerRadius The value of the inner radius.
*/
CV_WRAP
virtual
void
setInnerRadius
(
float
innerRadius
)
=
0
;
CV_WRAP
virtual
float
getInnerRadius
()
const
=
0
;
/** @brief Set the outer radius of the shape context descriptor.
@param outerRadius The value of the outer radius.
*/
CV_WRAP
virtual
void
setOuterRadius
(
float
outerRadius
)
=
0
;
CV_WRAP
virtual
float
getOuterRadius
()
const
=
0
;
CV_WRAP
virtual
void
setRotationInvariant
(
bool
rotationInvariant
)
=
0
;
CV_WRAP
virtual
bool
getRotationInvariant
()
const
=
0
;
/** @brief Set the weight of the shape context distance in the final value of the shape distance. The shape
context distance between two shapes is defined as the symmetric sum of shape context matching costs
over best matching points. The final value of the shape distance is a user-defined linear
combination of the shape context distance, an image appearance distance, and a bending energy.
@param shapeContextWeight The weight of the shape context distance in the final distance value.
*/
CV_WRAP
virtual
void
setShapeContextWeight
(
float
shapeContextWeight
)
=
0
;
CV_WRAP
virtual
float
getShapeContextWeight
()
const
=
0
;
/** @brief Set the weight of the Image Appearance cost in the final value of the shape distance. The image
appearance cost is defined as the sum of squared brightness differences in Gaussian windows around
corresponding image points. The final value of the shape distance is a user-defined linear
combination of the shape context distance, an image appearance distance, and a bending energy. If
this value is set to a number different from 0, is mandatory to set the images that correspond to
each shape.
@param imageAppearanceWeight The weight of the appearance cost in the final distance value.
*/
CV_WRAP
virtual
void
setImageAppearanceWeight
(
float
imageAppearanceWeight
)
=
0
;
CV_WRAP
virtual
float
getImageAppearanceWeight
()
const
=
0
;
/** @brief Set the weight of the Bending Energy in the final value of the shape distance. The bending energy
definition depends on what transformation is being used to align the shapes. The final value of the
shape distance is a user-defined linear combination of the shape context distance, an image
appearance distance, and a bending energy.
@param bendingEnergyWeight The weight of the Bending Energy in the final distance value.
*/
CV_WRAP
virtual
void
setBendingEnergyWeight
(
float
bendingEnergyWeight
)
=
0
;
CV_WRAP
virtual
float
getBendingEnergyWeight
()
const
=
0
;
/** @brief Set the images that correspond to each shape. This images are used in the calculation of the Image
Appearance cost.
@param image1 Image corresponding to the shape defined by contours1.
@param image2 Image corresponding to the shape defined by contours2.
*/
CV_WRAP
virtual
void
setImages
(
InputArray
image1
,
InputArray
image2
)
=
0
;
CV_WRAP
virtual
void
getImages
(
OutputArray
image1
,
OutputArray
image2
)
const
=
0
;
CV_WRAP
virtual
void
setIterations
(
int
iterations
)
=
0
;
CV_WRAP
virtual
int
getIterations
()
const
=
0
;
/** @brief Set the algorithm used for building the shape context descriptor cost matrix.
@param comparer Smart pointer to a HistogramCostExtractor, an algorithm that defines the cost
matrix between descriptors.
*/
CV_WRAP
virtual
void
setCostExtractor
(
Ptr
<
HistogramCostExtractor
>
comparer
)
=
0
;
CV_WRAP
virtual
Ptr
<
HistogramCostExtractor
>
getCostExtractor
()
const
=
0
;
/** @brief Set the value of the standard deviation for the Gaussian window for the image appearance cost.
@param sigma Standard Deviation.
*/
CV_WRAP
virtual
void
setStdDev
(
float
sigma
)
=
0
;
CV_WRAP
virtual
float
getStdDev
()
const
=
0
;
/** @brief Set the algorithm used for aligning the shapes.
@param transformer Smart pointer to a ShapeTransformer, an algorithm that defines the aligning
transformation.
*/
CV_WRAP
virtual
void
setTransformAlgorithm
(
Ptr
<
ShapeTransformer
>
transformer
)
=
0
;
CV_WRAP
virtual
Ptr
<
ShapeTransformer
>
getTransformAlgorithm
()
const
=
0
;
};
/* Complete constructor */
CV_EXPORTS_W
Ptr
<
ShapeContextDistanceExtractor
>
createShapeContextDistanceExtractor
(
int
nAngularBins
=
12
,
int
nRadialBins
=
4
,
float
innerRadius
=
0.2
f
,
float
outerRadius
=
2
,
int
iterations
=
3
,
const
Ptr
<
HistogramCostExtractor
>
&
comparer
=
createChiHistogramCostExtractor
(),
const
Ptr
<
ShapeTransformer
>
&
transformer
=
createThinPlateSplineShapeTransformer
());
/***********************************************************************************/
/***********************************************************************************/
/***********************************************************************************/
/** @brief A simple Hausdorff distance measure between shapes defined by contours
according to the paper "Comparing Images using the Hausdorff distance." by D.P. Huttenlocher, G.A.
Klanderman, and W.J. Rucklidge. (PAMI 1993). :
*/
class
CV_EXPORTS_W
HausdorffDistanceExtractor
:
public
ShapeDistanceExtractor
{
public
:
/** @brief Set the norm used to compute the Hausdorff value between two shapes. It can be L1 or L2 norm.
@param distanceFlag Flag indicating which norm is used to compute the Hausdorff distance
(NORM_L1, NORM_L2).
*/
CV_WRAP
virtual
void
setDistanceFlag
(
int
distanceFlag
)
=
0
;
CV_WRAP
virtual
int
getDistanceFlag
()
const
=
0
;
/** @brief This method sets the rank proportion (or fractional value) that establish the Kth ranked value of
the partial Hausdorff distance. Experimentally had been shown that 0.6 is a good value to compare
shapes.
@param rankProportion fractional value (between 0 and 1).
*/
CV_WRAP
virtual
void
setRankProportion
(
float
rankProportion
)
=
0
;
CV_WRAP
virtual
float
getRankProportion
()
const
=
0
;
};
/* Constructor */
CV_EXPORTS_W
Ptr
<
HausdorffDistanceExtractor
>
createHausdorffDistanceExtractor
(
int
distanceFlag
=
cv
::
NORM_L2
,
float
rankProp
=
0.6
f
);
//! @}
}
// cv
#endif
modules/shape/include/opencv2/shape/shape_transformer.hpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef OPENCV_SHAPE_SHAPE_TRANSFORM_HPP
#define OPENCV_SHAPE_SHAPE_TRANSFORM_HPP
#include <vector>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
namespace
cv
{
//! @addtogroup shape
//! @{
/** @brief Abstract base class for shape transformation algorithms.
*/
class
CV_EXPORTS_W
ShapeTransformer
:
public
Algorithm
{
public
:
/** @brief Estimate the transformation parameters of the current transformer algorithm, based on point matches.
@param transformingShape Contour defining first shape.
@param targetShape Contour defining second shape (Target).
@param matches Standard vector of Matches between points.
*/
CV_WRAP
virtual
void
estimateTransformation
(
InputArray
transformingShape
,
InputArray
targetShape
,
std
::
vector
<
DMatch
>&
matches
)
=
0
;
/** @brief Apply a transformation, given a pre-estimated transformation parameters.
@param input Contour (set of points) to apply the transformation.
@param output Output contour.
*/
CV_WRAP
virtual
float
applyTransformation
(
InputArray
input
,
OutputArray
output
=
noArray
())
=
0
;
/** @brief Apply a transformation, given a pre-estimated transformation parameters, to an Image.
@param transformingImage Input image.
@param output Output image.
@param flags Image interpolation method.
@param borderMode border style.
@param borderValue border value.
*/
CV_WRAP
virtual
void
warpImage
(
InputArray
transformingImage
,
OutputArray
output
,
int
flags
=
INTER_LINEAR
,
int
borderMode
=
BORDER_CONSTANT
,
const
Scalar
&
borderValue
=
Scalar
())
const
=
0
;
};
/***********************************************************************************/
/***********************************************************************************/
/** @brief Definition of the transformation
occupied in the paper "Principal Warps: Thin-Plate Splines and Decomposition of Deformations", by
F.L. Bookstein (PAMI 1989). :
*/
class
CV_EXPORTS_W
ThinPlateSplineShapeTransformer
:
public
ShapeTransformer
{
public
:
/** @brief Set the regularization parameter for relaxing the exact interpolation requirements of the TPS
algorithm.
@param beta value of the regularization parameter.
*/
CV_WRAP
virtual
void
setRegularizationParameter
(
double
beta
)
=
0
;
CV_WRAP
virtual
double
getRegularizationParameter
()
const
=
0
;
};
/** Complete constructor */
CV_EXPORTS_W
Ptr
<
ThinPlateSplineShapeTransformer
>
createThinPlateSplineShapeTransformer
(
double
regularizationParameter
=
0
);
/***********************************************************************************/
/***********************************************************************************/
/** @brief Wrapper class for the OpenCV Affine Transformation algorithm. :
*/
class
CV_EXPORTS_W
AffineTransformer
:
public
ShapeTransformer
{
public
:
CV_WRAP
virtual
void
setFullAffine
(
bool
fullAffine
)
=
0
;
CV_WRAP
virtual
bool
getFullAffine
()
const
=
0
;
};
/** Complete constructor */
CV_EXPORTS_W
Ptr
<
AffineTransformer
>
createAffineTransformer
(
bool
fullAffine
);
//! @}
}
// cv
#endif
modules/shape/src/aff_trans.cpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
namespace
cv
{
class
AffineTransformerImpl
:
public
AffineTransformer
{
public
:
/* Constructors */
AffineTransformerImpl
()
{
fullAffine
=
true
;
name_
=
"ShapeTransformer.AFF"
;
transformCost
=
0
;
}
AffineTransformerImpl
(
bool
_fullAffine
)
{
fullAffine
=
_fullAffine
;
name_
=
"ShapeTransformer.AFF"
;
transformCost
=
0
;
}
/* Destructor */
~
AffineTransformerImpl
()
{
}
//! the main operator
virtual
void
estimateTransformation
(
InputArray
transformingShape
,
InputArray
targetShape
,
std
::
vector
<
DMatch
>
&
matches
)
CV_OVERRIDE
;
virtual
float
applyTransformation
(
InputArray
input
,
OutputArray
output
=
noArray
())
CV_OVERRIDE
;
virtual
void
warpImage
(
InputArray
transformingImage
,
OutputArray
output
,
int
flags
,
int
borderMode
,
const
Scalar
&
borderValue
)
const
CV_OVERRIDE
;
//! Setters/Getters
virtual
void
setFullAffine
(
bool
_fullAffine
)
CV_OVERRIDE
{
fullAffine
=
_fullAffine
;}
virtual
bool
getFullAffine
()
const
CV_OVERRIDE
{
return
fullAffine
;}
//! write/read
virtual
void
write
(
FileStorage
&
fs
)
const
CV_OVERRIDE
{
writeFormat
(
fs
);
fs
<<
"name"
<<
name_
<<
"affine_type"
<<
int
(
fullAffine
);
}
virtual
void
read
(
const
FileNode
&
fn
)
CV_OVERRIDE
{
CV_Assert
(
(
String
)
fn
[
"name"
]
==
name_
);
fullAffine
=
int
(
fn
[
"affine_type"
])
?
true
:
false
;
}
private
:
bool
fullAffine
;
Mat
affineMat
;
float
transformCost
;
protected
:
String
name_
;
};
void
AffineTransformerImpl
::
warpImage
(
InputArray
transformingImage
,
OutputArray
output
,
int
flags
,
int
borderMode
,
const
Scalar
&
borderValue
)
const
{
CV_INSTRUMENT_REGION
();
CV_Assert
(
!
affineMat
.
empty
());
warpAffine
(
transformingImage
,
output
,
affineMat
,
transformingImage
.
getMat
().
size
(),
flags
,
borderMode
,
borderValue
);
}
static
Mat
_localAffineEstimate
(
const
std
::
vector
<
Point2f
>&
shape1
,
const
std
::
vector
<
Point2f
>&
shape2
,
bool
fullAfine
)
{
Mat
out
(
2
,
3
,
CV_32F
);
int
siz
=
2
*
(
int
)
shape1
.
size
();
if
(
fullAfine
)
{
Mat
matM
(
siz
,
6
,
CV_32F
);
Mat
matP
(
siz
,
1
,
CV_32F
);
int
contPt
=
0
;
for
(
int
ii
=
0
;
ii
<
siz
;
ii
++
)
{
Mat
therow
=
Mat
::
zeros
(
1
,
6
,
CV_32F
);
if
(
ii
%
2
==
0
)
{
therow
.
at
<
float
>
(
0
,
0
)
=
shape1
[
contPt
].
x
;
therow
.
at
<
float
>
(
0
,
1
)
=
shape1
[
contPt
].
y
;
therow
.
at
<
float
>
(
0
,
2
)
=
1
;
therow
.
row
(
0
).
copyTo
(
matM
.
row
(
ii
));
matP
.
at
<
float
>
(
ii
,
0
)
=
shape2
[
contPt
].
x
;
}
else
{
therow
.
at
<
float
>
(
0
,
3
)
=
shape1
[
contPt
].
x
;
therow
.
at
<
float
>
(
0
,
4
)
=
shape1
[
contPt
].
y
;
therow
.
at
<
float
>
(
0
,
5
)
=
1
;
therow
.
row
(
0
).
copyTo
(
matM
.
row
(
ii
));
matP
.
at
<
float
>
(
ii
,
0
)
=
shape2
[
contPt
].
y
;
contPt
++
;
}
}
Mat
sol
;
solve
(
matM
,
matP
,
sol
,
DECOMP_SVD
);
out
=
sol
.
reshape
(
0
,
2
);
}
else
{
Mat
matM
(
siz
,
4
,
CV_32F
);
Mat
matP
(
siz
,
1
,
CV_32F
);
int
contPt
=
0
;
for
(
int
ii
=
0
;
ii
<
siz
;
ii
++
)
{
Mat
therow
=
Mat
::
zeros
(
1
,
4
,
CV_32F
);
if
(
ii
%
2
==
0
)
{
therow
.
at
<
float
>
(
0
,
0
)
=
shape1
[
contPt
].
x
;
therow
.
at
<
float
>
(
0
,
1
)
=
shape1
[
contPt
].
y
;
therow
.
at
<
float
>
(
0
,
2
)
=
1
;
therow
.
row
(
0
).
copyTo
(
matM
.
row
(
ii
));
matP
.
at
<
float
>
(
ii
,
0
)
=
shape2
[
contPt
].
x
;
}
else
{
therow
.
at
<
float
>
(
0
,
0
)
=
shape1
[
contPt
].
y
;
therow
.
at
<
float
>
(
0
,
1
)
=-
shape1
[
contPt
].
x
;
therow
.
at
<
float
>
(
0
,
3
)
=
1
;
therow
.
row
(
0
).
copyTo
(
matM
.
row
(
ii
));
matP
.
at
<
float
>
(
ii
,
0
)
=
shape2
[
contPt
].
y
;
contPt
++
;
}
}
Mat
sol
;
solve
(
matM
,
matP
,
sol
,
DECOMP_SVD
);
out
.
at
<
float
>
(
0
,
0
)
=
sol
.
at
<
float
>
(
0
,
0
);
out
.
at
<
float
>
(
0
,
1
)
=
sol
.
at
<
float
>
(
1
,
0
);
out
.
at
<
float
>
(
0
,
2
)
=
sol
.
at
<
float
>
(
2
,
0
);
out
.
at
<
float
>
(
1
,
0
)
=-
sol
.
at
<
float
>
(
1
,
0
);
out
.
at
<
float
>
(
1
,
1
)
=
sol
.
at
<
float
>
(
0
,
0
);
out
.
at
<
float
>
(
1
,
2
)
=
sol
.
at
<
float
>
(
3
,
0
);
}
return
out
;
}
void
AffineTransformerImpl
::
estimateTransformation
(
InputArray
_pts1
,
InputArray
_pts2
,
std
::
vector
<
DMatch
>&
_matches
)
{
CV_INSTRUMENT_REGION
();
Mat
pts1
=
_pts1
.
getMat
();
Mat
pts2
=
_pts2
.
getMat
();
CV_Assert
((
pts1
.
channels
()
==
2
)
&&
(
pts1
.
cols
>
0
)
&&
(
pts2
.
channels
()
==
2
)
&&
(
pts2
.
cols
>
0
));
CV_Assert
(
_matches
.
size
()
>
1
);
if
(
pts1
.
type
()
!=
CV_32F
)
pts1
.
convertTo
(
pts1
,
CV_32F
);
if
(
pts2
.
type
()
!=
CV_32F
)
pts2
.
convertTo
(
pts2
,
CV_32F
);
// Use only valid matchings //
std
::
vector
<
DMatch
>
matches
;
for
(
size_t
i
=
0
;
i
<
_matches
.
size
();
i
++
)
{
if
(
_matches
[
i
].
queryIdx
<
pts1
.
cols
&&
_matches
[
i
].
trainIdx
<
pts2
.
cols
)
{
matches
.
push_back
(
_matches
[
i
]);
}
}
// Organizing the correspondent points in vector style //
std
::
vector
<
Point2f
>
shape1
;
// transforming shape
std
::
vector
<
Point2f
>
shape2
;
// target shape
for
(
size_t
i
=
0
;
i
<
matches
.
size
();
i
++
)
{
Point2f
pt1
=
pts1
.
at
<
Point2f
>
(
0
,
matches
[
i
].
queryIdx
);
shape1
.
push_back
(
pt1
);
Point2f
pt2
=
pts2
.
at
<
Point2f
>
(
0
,
matches
[
i
].
trainIdx
);
shape2
.
push_back
(
pt2
);
}
Mat
affine
;
if
(
fullAffine
)
{
estimateAffine2D
(
shape1
,
shape2
).
convertTo
(
affine
,
CV_32F
);
}
else
{
estimateAffinePartial2D
(
shape1
,
shape2
).
convertTo
(
affine
,
CV_32F
);
}
if
(
affine
.
empty
())
//In case there is not good solution, just give a LLS based one
affine
=
_localAffineEstimate
(
shape1
,
shape2
,
fullAffine
);
affineMat
=
affine
;
}
float
AffineTransformerImpl
::
applyTransformation
(
InputArray
inPts
,
OutputArray
outPts
)
{
CV_INSTRUMENT_REGION
();
Mat
pts1
=
inPts
.
getMat
();
CV_Assert
((
pts1
.
channels
()
==
2
)
&&
(
pts1
.
cols
>
0
));
//Apply transformation in the complete set of points
Mat
fAffine
;
transform
(
pts1
,
fAffine
,
affineMat
);
// Ensambling output //
if
(
outPts
.
needed
())
{
outPts
.
create
(
1
,
fAffine
.
cols
,
CV_32FC2
);
Mat
outMat
=
outPts
.
getMat
();
for
(
int
i
=
0
;
i
<
fAffine
.
cols
;
i
++
)
outMat
.
at
<
Point2f
>
(
0
,
i
)
=
fAffine
.
at
<
Point2f
>
(
0
,
i
);
}
// Updating Transform Cost //
Mat
Af
(
2
,
2
,
CV_32F
);
Af
.
at
<
float
>
(
0
,
0
)
=
affineMat
.
at
<
float
>
(
0
,
0
);
Af
.
at
<
float
>
(
0
,
1
)
=
affineMat
.
at
<
float
>
(
1
,
0
);
Af
.
at
<
float
>
(
1
,
0
)
=
affineMat
.
at
<
float
>
(
0
,
1
);
Af
.
at
<
float
>
(
1
,
1
)
=
affineMat
.
at
<
float
>
(
1
,
1
);
SVD
mysvd
(
Af
,
SVD
::
NO_UV
);
Mat
singVals
=
mysvd
.
w
;
transformCost
=
std
::
log
((
singVals
.
at
<
float
>
(
0
,
0
)
+
FLT_MIN
)
/
(
singVals
.
at
<
float
>
(
1
,
0
)
+
FLT_MIN
));
return
transformCost
;
}
Ptr
<
AffineTransformer
>
createAffineTransformer
(
bool
fullAffine
)
{
return
Ptr
<
AffineTransformer
>
(
new
AffineTransformerImpl
(
fullAffine
)
);
}
}
// cv
modules/shape/src/emdL1.cpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
/*
* Implementation of an optimized EMD for histograms based in
* the papers "EMD-L1: An efficient and Robust Algorithm
* for comparing histogram-based descriptors", by Haibin Ling and
* Kazunori Okuda; and "The Earth Mover's Distance is the Mallows
* Distance: Some Insights from Statistics", by Elizaveta Levina and
* Peter Bickel, based on HAIBIN LING AND KAZUNORI OKADA implementation.
*/
#include "precomp.hpp"
#include "emdL1_def.hpp"
#include <limits>
/****************************************************************************************\
* EMDL1 Class *
\****************************************************************************************/
float
EmdL1
::
getEMDL1
(
cv
::
Mat
&
sig1
,
cv
::
Mat
&
sig2
)
{
// Initialization
CV_Assert
((
sig1
.
rows
==
sig2
.
rows
)
&&
(
sig1
.
cols
==
sig2
.
cols
)
&&
(
!
sig1
.
empty
())
&&
(
!
sig2
.
empty
()));
if
(
!
initBaseTrees
(
sig1
.
rows
,
1
))
return
-
1
;
float
*
H1
=
new
float
[
sig1
.
rows
],
*
H2
=
new
float
[
sig2
.
rows
];
for
(
int
ii
=
0
;
ii
<
sig1
.
rows
;
ii
++
)
{
H1
[
ii
]
=
sig1
.
at
<
float
>
(
ii
,
0
);
H2
[
ii
]
=
sig2
.
at
<
float
>
(
ii
,
0
);
}
fillBaseTrees
(
H1
,
H2
);
// Initialize histograms
greedySolution
();
// Construct an initial Basic Feasible solution
initBVTree
();
// Initialize BVTree
// Iteration
bool
bOptimal
=
false
;
m_nItr
=
0
;
while
(
!
bOptimal
&&
m_nItr
<
nMaxIt
)
{
// Derive U=(u_ij) for row i and column j
if
(
m_nItr
==
0
)
updateSubtree
(
m_pRoot
);
else
updateSubtree
(
m_pEnter
->
pChild
);
// Optimality test
bOptimal
=
isOptimal
();
// Find new solution
if
(
!
bOptimal
)
findNewSolution
();
++
m_nItr
;
}
delete
[]
H1
;
delete
[]
H2
;
// Output the total flow
return
compuTotalFlow
();
}
void
EmdL1
::
setMaxIteration
(
int
_nMaxIt
)
{
nMaxIt
=
_nMaxIt
;
}
//-- SubFunctions called in the EMD algorithm
bool
EmdL1
::
initBaseTrees
(
int
n1
,
int
n2
,
int
n3
)
{
if
(
binsDim1
==
n1
&&
binsDim2
==
n2
&&
binsDim3
==
n3
)
return
true
;
binsDim1
=
n1
;
binsDim2
=
n2
;
binsDim3
=
n3
;
if
(
binsDim1
==
0
||
binsDim2
==
0
)
dimension
=
0
;
else
dimension
=
(
binsDim3
==
0
)
?
2
:
3
;
if
(
dimension
==
2
)
{
m_Nodes
.
resize
(
binsDim1
);
m_EdgesUp
.
resize
(
binsDim1
);
m_EdgesRight
.
resize
(
binsDim1
);
for
(
int
i1
=
0
;
i1
<
binsDim1
;
i1
++
)
{
m_Nodes
[
i1
].
resize
(
binsDim2
);
m_EdgesUp
[
i1
].
resize
(
binsDim2
);
m_EdgesRight
[
i1
].
resize
(
binsDim2
);
}
m_NBVEdges
.
resize
(
binsDim1
*
binsDim2
*
4
+
2
);
m_auxQueue
.
resize
(
binsDim1
*
binsDim2
+
2
);
m_fromLoop
.
resize
(
binsDim1
*
binsDim2
+
2
);
m_toLoop
.
resize
(
binsDim1
*
binsDim2
+
2
);
}
else
if
(
dimension
==
3
)
{
m_3dNodes
.
resize
(
binsDim1
);
m_3dEdgesUp
.
resize
(
binsDim1
);
m_3dEdgesRight
.
resize
(
binsDim1
);
m_3dEdgesDeep
.
resize
(
binsDim1
);
for
(
int
i1
=
0
;
i1
<
binsDim1
;
i1
++
)
{
m_3dNodes
[
i1
].
resize
(
binsDim2
);
m_3dEdgesUp
[
i1
].
resize
(
binsDim2
);
m_3dEdgesRight
[
i1
].
resize
(
binsDim2
);
m_3dEdgesDeep
[
i1
].
resize
(
binsDim2
);
for
(
int
i2
=
0
;
i2
<
binsDim2
;
i2
++
)
{
m_3dNodes
[
i1
][
i2
].
resize
(
binsDim3
);
m_3dEdgesUp
[
i1
][
i2
].
resize
(
binsDim3
);
m_3dEdgesRight
[
i1
][
i2
].
resize
(
binsDim3
);
m_3dEdgesDeep
[
i1
][
i2
].
resize
(
binsDim3
);
}
}
m_NBVEdges
.
resize
(
binsDim1
*
binsDim2
*
binsDim3
*
6
+
4
);
m_auxQueue
.
resize
(
binsDim1
*
binsDim2
*
binsDim3
+
4
);
m_fromLoop
.
resize
(
binsDim1
*
binsDim2
*
binsDim3
+
4
);
m_toLoop
.
resize
(
binsDim1
*
binsDim2
*
binsDim3
+
2
);
}
else
return
false
;
return
true
;
}
bool
EmdL1
::
fillBaseTrees
(
float
*
H1
,
float
*
H2
)
{
//- Set global counters
m_pRoot
=
NULL
;
// Graph initialization
float
*
p1
=
H1
;
float
*
p2
=
H2
;
if
(
dimension
==
2
)
{
for
(
int
c
=
0
;
c
<
binsDim2
;
c
++
)
{
for
(
int
r
=
0
;
r
<
binsDim1
;
r
++
)
{
//- initialize nodes and links
m_Nodes
[
r
][
c
].
pos
[
0
]
=
r
;
m_Nodes
[
r
][
c
].
pos
[
1
]
=
c
;
m_Nodes
[
r
][
c
].
d
=
*
(
p1
++
)
-*
(
p2
++
);
m_Nodes
[
r
][
c
].
pParent
=
NULL
;
m_Nodes
[
r
][
c
].
pChild
=
NULL
;
m_Nodes
[
r
][
c
].
iLevel
=
-
1
;
//- initialize edges
// to the right
m_EdgesRight
[
r
][
c
].
pParent
=
&
(
m_Nodes
[
r
][
c
]);
m_EdgesRight
[
r
][
c
].
pChild
=
&
(
m_Nodes
[
r
][(
c
+
1
)
%
binsDim2
]);
m_EdgesRight
[
r
][
c
].
flow
=
0
;
m_EdgesRight
[
r
][
c
].
iDir
=
1
;
m_EdgesRight
[
r
][
c
].
pNxt
=
NULL
;
// to the upward
m_EdgesUp
[
r
][
c
].
pParent
=
&
(
m_Nodes
[
r
][
c
]);
m_EdgesUp
[
r
][
c
].
pChild
=
&
(
m_Nodes
[(
r
+
1
)
%
binsDim1
][
c
]);
m_EdgesUp
[
r
][
c
].
flow
=
0
;
m_EdgesUp
[
r
][
c
].
iDir
=
1
;
m_EdgesUp
[
r
][
c
].
pNxt
=
NULL
;
}
}
}
else
if
(
dimension
==
3
)
{
for
(
int
z
=
0
;
z
<
binsDim3
;
z
++
)
{
for
(
int
c
=
0
;
c
<
binsDim2
;
c
++
)
{
for
(
int
r
=
0
;
r
<
binsDim1
;
r
++
)
{
//- initialize nodes and edges
m_3dNodes
[
r
][
c
][
z
].
pos
[
0
]
=
r
;
m_3dNodes
[
r
][
c
][
z
].
pos
[
1
]
=
c
;
m_3dNodes
[
r
][
c
][
z
].
pos
[
2
]
=
z
;
m_3dNodes
[
r
][
c
][
z
].
d
=
*
(
p1
++
)
-*
(
p2
++
);
m_3dNodes
[
r
][
c
][
z
].
pParent
=
NULL
;
m_3dNodes
[
r
][
c
][
z
].
pChild
=
NULL
;
m_3dNodes
[
r
][
c
][
z
].
iLevel
=
-
1
;
//- initialize edges
// to the upward
m_3dEdgesUp
[
r
][
c
][
z
].
pParent
=
&
(
m_3dNodes
[
r
][
c
][
z
]);
m_3dEdgesUp
[
r
][
c
][
z
].
pChild
=
&
(
m_3dNodes
[(
r
+
1
)
%
binsDim1
][
c
][
z
]);
m_3dEdgesUp
[
r
][
c
][
z
].
flow
=
0
;
m_3dEdgesUp
[
r
][
c
][
z
].
iDir
=
1
;
m_3dEdgesUp
[
r
][
c
][
z
].
pNxt
=
NULL
;
// to the right
m_3dEdgesRight
[
r
][
c
][
z
].
pParent
=
&
(
m_3dNodes
[
r
][
c
][
z
]);
m_3dEdgesRight
[
r
][
c
][
z
].
pChild
=
&
(
m_3dNodes
[
r
][(
c
+
1
)
%
binsDim2
][
z
]);
m_3dEdgesRight
[
r
][
c
][
z
].
flow
=
0
;
m_3dEdgesRight
[
r
][
c
][
z
].
iDir
=
1
;
m_3dEdgesRight
[
r
][
c
][
z
].
pNxt
=
NULL
;
// to the deep
m_3dEdgesDeep
[
r
][
c
][
z
].
pParent
=
&
(
m_3dNodes
[
r
][
c
][
z
]);
m_3dEdgesDeep
[
r
][
c
][
z
].
pChild
=
&
(
m_3dNodes
[
r
][
c
])[(
z
+
1
)
%
binsDim3
];
m_3dEdgesDeep
[
r
][
c
][
z
].
flow
=
0
;
m_3dEdgesDeep
[
r
][
c
][
z
].
iDir
=
1
;
m_3dEdgesDeep
[
r
][
c
][
z
].
pNxt
=
NULL
;
}
}
}
}
return
true
;
}
bool
EmdL1
::
greedySolution
()
{
return
dimension
==
2
?
greedySolution2
()
:
greedySolution3
();
}
bool
EmdL1
::
greedySolution2
()
{
//- Prepare auxiliary array, D=H1-H2
int
c
,
r
;
floatArray2D
D
(
binsDim1
);
for
(
r
=
0
;
r
<
binsDim1
;
r
++
)
{
D
[
r
].
resize
(
binsDim2
);
for
(
c
=
0
;
c
<
binsDim2
;
c
++
)
D
[
r
][
c
]
=
m_Nodes
[
r
][
c
].
d
;
}
// compute integrated values along each dimension
std
::
vector
<
float
>
d2s
(
binsDim2
);
d2s
[
0
]
=
0
;
for
(
c
=
0
;
c
<
binsDim2
-
1
;
c
++
)
{
d2s
[
c
+
1
]
=
d2s
[
c
];
for
(
r
=
0
;
r
<
binsDim1
;
r
++
)
d2s
[
c
+
1
]
-=
D
[
r
][
c
];
}
std
::
vector
<
float
>
d1s
(
binsDim1
);
d1s
[
0
]
=
0
;
for
(
r
=
0
;
r
<
binsDim1
-
1
;
r
++
)
{
d1s
[
r
+
1
]
=
d1s
[
r
];
for
(
c
=
0
;
c
<
binsDim2
;
c
++
)
d1s
[
r
+
1
]
-=
D
[
r
][
c
];
}
//- Greedy algorithm for initial solution
cvPEmdEdge
pBV
;
float
dFlow
;
bool
bUpward
=
false
;
nNBV
=
0
;
// number of NON-BV edges
for
(
c
=
0
;
c
<
binsDim2
-
1
;
c
++
)
for
(
r
=
0
;
r
<
binsDim1
;
r
++
)
{
dFlow
=
D
[
r
][
c
];
bUpward
=
(
r
<
binsDim1
-
1
)
&&
(
fabs
(
dFlow
+
d2s
[
c
+
1
])
>
fabs
(
dFlow
+
d1s
[
r
+
1
]));
// Move upward or right
// modify basic variables, record BV and related values
if
(
bUpward
)
{
// move to up
pBV
=
&
(
m_EdgesUp
[
r
][
c
]);
m_NBVEdges
[
nNBV
++
]
=
&
(
m_EdgesRight
[
r
][
c
]);
D
[
r
+
1
][
c
]
+=
dFlow
;
// auxiliary matrix maintenance
d1s
[
r
+
1
]
+=
dFlow
;
// auxiliary matrix maintenance
}
else
{
// move to right, no other choice
pBV
=
&
(
m_EdgesRight
[
r
][
c
]);
if
(
r
<
binsDim1
-
1
)
m_NBVEdges
[
nNBV
++
]
=
&
(
m_EdgesUp
[
r
][
c
]);
D
[
r
][
c
+
1
]
+=
dFlow
;
// auxiliary matrix maintenance
d2s
[
c
+
1
]
+=
dFlow
;
// auxiliary matrix maintenance
}
pBV
->
pParent
->
pChild
=
pBV
;
pBV
->
flow
=
fabs
(
dFlow
);
pBV
->
iDir
=
dFlow
>
0
;
// 1:outward, 0:inward
}
//- rightmost column, no choice but move upward
c
=
binsDim2
-
1
;
for
(
r
=
0
;
r
<
binsDim1
-
1
;
r
++
)
{
dFlow
=
D
[
r
][
c
];
pBV
=
&
(
m_EdgesUp
[
r
][
c
]);
D
[
r
+
1
][
c
]
+=
dFlow
;
// auxiliary matrix maintenance
pBV
->
pParent
->
pChild
=
pBV
;
pBV
->
flow
=
fabs
(
dFlow
);
pBV
->
iDir
=
dFlow
>
0
;
// 1:outward, 0:inward
}
return
true
;
}
bool
EmdL1
::
greedySolution3
()
{
//- Prepare auxiliary array, D=H1-H2
int
i1
,
i2
,
i3
;
std
::
vector
<
floatArray2D
>
D
(
binsDim1
);
for
(
i1
=
0
;
i1
<
binsDim1
;
i1
++
)
{
D
[
i1
].
resize
(
binsDim2
);
for
(
i2
=
0
;
i2
<
binsDim2
;
i2
++
)
{
D
[
i1
][
i2
].
resize
(
binsDim3
);
for
(
i3
=
0
;
i3
<
binsDim3
;
i3
++
)
D
[
i1
][
i2
][
i3
]
=
m_3dNodes
[
i1
][
i2
][
i3
].
d
;
}
}
// compute integrated values along each dimension
std
::
vector
<
float
>
d1s
(
binsDim1
);
d1s
[
0
]
=
0
;
for
(
i1
=
0
;
i1
<
binsDim1
-
1
;
i1
++
)
{
d1s
[
i1
+
1
]
=
d1s
[
i1
];
for
(
i2
=
0
;
i2
<
binsDim2
;
i2
++
)
{
for
(
i3
=
0
;
i3
<
binsDim3
;
i3
++
)
d1s
[
i1
+
1
]
-=
D
[
i1
][
i2
][
i3
];
}
}
std
::
vector
<
float
>
d2s
(
binsDim2
);
d2s
[
0
]
=
0
;
for
(
i2
=
0
;
i2
<
binsDim2
-
1
;
i2
++
)
{
d2s
[
i2
+
1
]
=
d2s
[
i2
];
for
(
i1
=
0
;
i1
<
binsDim1
;
i1
++
)
{
for
(
i3
=
0
;
i3
<
binsDim3
;
i3
++
)
d2s
[
i2
+
1
]
-=
D
[
i1
][
i2
][
i3
];
}
}
std
::
vector
<
float
>
d3s
(
binsDim3
);
d3s
[
0
]
=
0
;
for
(
i3
=
0
;
i3
<
binsDim3
-
1
;
i3
++
)
{
d3s
[
i3
+
1
]
=
d3s
[
i3
];
for
(
i1
=
0
;
i1
<
binsDim1
;
i1
++
)
{
for
(
i2
=
0
;
i2
<
binsDim2
;
i2
++
)
d3s
[
i3
+
1
]
-=
D
[
i1
][
i2
][
i3
];
}
}
//- Greedy algorithm for initial solution
cvPEmdEdge
pBV
;
float
dFlow
,
f1
,
f2
,
f3
;
nNBV
=
0
;
// number of NON-BV edges
for
(
i3
=
0
;
i3
<
binsDim3
;
i3
++
)
{
for
(
i2
=
0
;
i2
<
binsDim2
;
i2
++
)
{
for
(
i1
=
0
;
i1
<
binsDim1
;
i1
++
)
{
if
(
i3
==
binsDim3
-
1
&&
i2
==
binsDim2
-
1
&&
i1
==
binsDim1
-
1
)
break
;
//- determine which direction to move, either right or upward
dFlow
=
D
[
i1
][
i2
][
i3
];
f1
=
(
i1
<
(
binsDim1
-
1
))
?
fabs
(
dFlow
+
d1s
[
i1
+
1
])
:
std
::
numeric_limits
<
float
>::
max
();
f2
=
(
i2
<
(
binsDim2
-
1
))
?
fabs
(
dFlow
+
d2s
[
i2
+
1
])
:
std
::
numeric_limits
<
float
>::
max
();
f3
=
(
i3
<
(
binsDim3
-
1
))
?
fabs
(
dFlow
+
d3s
[
i3
+
1
])
:
std
::
numeric_limits
<
float
>::
max
();
if
(
f1
<
f2
&&
f1
<
f3
)
{
pBV
=
&
(
m_3dEdgesUp
[
i1
][
i2
][
i3
]);
// up
if
(
i2
<
binsDim2
-
1
)
m_NBVEdges
[
nNBV
++
]
=
&
(
m_3dEdgesRight
[
i1
][
i2
][
i3
]);
// right
if
(
i3
<
binsDim3
-
1
)
m_NBVEdges
[
nNBV
++
]
=
&
(
m_3dEdgesDeep
[
i1
][
i2
][
i3
]);
// deep
D
[
i1
+
1
][
i2
][
i3
]
+=
dFlow
;
// maintain auxiliary matrix
d1s
[
i1
+
1
]
+=
dFlow
;
}
else
if
(
f2
<
f3
)
{
pBV
=
&
(
m_3dEdgesRight
[
i1
][
i2
][
i3
]);
// right
if
(
i1
<
binsDim1
-
1
)
m_NBVEdges
[
nNBV
++
]
=
&
(
m_3dEdgesUp
[
i1
][
i2
][
i3
]);
// up
if
(
i3
<
binsDim3
-
1
)
m_NBVEdges
[
nNBV
++
]
=
&
(
m_3dEdgesDeep
[
i1
][
i2
][
i3
]);
// deep
D
[
i1
][
i2
+
1
][
i3
]
+=
dFlow
;
// maintain auxiliary matrix
d2s
[
i2
+
1
]
+=
dFlow
;
}
else
{
pBV
=
&
(
m_3dEdgesDeep
[
i1
][
i2
][
i3
]);
// deep
if
(
i2
<
binsDim2
-
1
)
m_NBVEdges
[
nNBV
++
]
=
&
(
m_3dEdgesRight
[
i1
][
i2
][
i3
]);
// right
if
(
i1
<
binsDim1
-
1
)
m_NBVEdges
[
nNBV
++
]
=
&
(
m_3dEdgesUp
[
i1
][
i2
][
i3
]);
// up
D
[
i1
][
i2
][
i3
+
1
]
+=
dFlow
;
// maintain auxiliary matrix
d3s
[
i3
+
1
]
+=
dFlow
;
}
pBV
->
flow
=
fabs
(
dFlow
);
pBV
->
iDir
=
dFlow
>
0
;
// 1:outward, 0:inward
pBV
->
pParent
->
pChild
=
pBV
;
}
}
}
return
true
;
}
void
EmdL1
::
initBVTree
()
{
// initialize BVTree from the initial BF solution
//- Using the center of the graph as the root
int
r
=
(
int
)(
0.5
*
binsDim1
-
.5
);
int
c
=
(
int
)(
0.5
*
binsDim2
-
.5
);
int
z
=
(
int
)(
0.5
*
binsDim3
-
.5
);
m_pRoot
=
dimension
==
2
?
&
(
m_Nodes
[
r
][
c
])
:
&
(
m_3dNodes
[
r
][
c
][
z
]);
m_pRoot
->
u
=
0
;
m_pRoot
->
iLevel
=
0
;
m_pRoot
->
pParent
=
NULL
;
m_pRoot
->
pPEdge
=
NULL
;
//- Prepare a queue
m_auxQueue
[
0
]
=
m_pRoot
;
int
nQueue
=
1
;
// length of queue
int
iQHead
=
0
;
// head of queue
//- Recursively build subtrees
cvPEmdEdge
pCurE
=
NULL
,
pNxtE
=
NULL
;
cvPEmdNode
pCurN
=
NULL
,
pNxtN
=
NULL
;
int
nBin
=
binsDim1
*
binsDim2
*
std
::
max
(
binsDim3
,
1
);
while
(
iQHead
<
nQueue
&&
nQueue
<
nBin
)
{
pCurN
=
m_auxQueue
[
iQHead
++
];
// pop out from queue
r
=
pCurN
->
pos
[
0
];
c
=
pCurN
->
pos
[
1
];
z
=
pCurN
->
pos
[
2
];
// check connection from itself
pCurE
=
pCurN
->
pChild
;
// the initial child from initial solution
if
(
pCurE
)
{
pNxtN
=
pCurE
->
pChild
;
pNxtN
->
pParent
=
pCurN
;
pNxtN
->
pPEdge
=
pCurE
;
m_auxQueue
[
nQueue
++
]
=
pNxtN
;
}
// check four neighbor nodes
int
nNB
=
dimension
==
2
?
4
:
6
;
for
(
int
k
=
0
;
k
<
nNB
;
k
++
)
{
if
(
dimension
==
2
)
{
if
(
k
==
0
&&
c
>
0
)
pNxtN
=
&
(
m_Nodes
[
r
][
c
-
1
]);
// left
else
if
(
k
==
1
&&
r
>
0
)
pNxtN
=
&
(
m_Nodes
[
r
-
1
][
c
]);
// down
else
if
(
k
==
2
&&
c
<
binsDim2
-
1
)
pNxtN
=
&
(
m_Nodes
[
r
][
c
+
1
]);
// right
else
if
(
k
==
3
&&
r
<
binsDim1
-
1
)
pNxtN
=
&
(
m_Nodes
[
r
+
1
][
c
]);
// up
else
continue
;
}
else
if
(
dimension
==
3
)
{
if
(
k
==
0
&&
c
>
0
)
pNxtN
=
&
(
m_3dNodes
[
r
][
c
-
1
][
z
]);
// left
else
if
(
k
==
1
&&
c
<
binsDim2
-
1
)
pNxtN
=
&
(
m_3dNodes
[
r
][
c
+
1
][
z
]);
// right
else
if
(
k
==
2
&&
r
>
0
)
pNxtN
=
&
(
m_3dNodes
[
r
-
1
][
c
][
z
]);
// down
else
if
(
k
==
3
&&
r
<
binsDim1
-
1
)
pNxtN
=
&
(
m_3dNodes
[
r
+
1
][
c
][
z
]);
// up
else
if
(
k
==
4
&&
z
>
0
)
pNxtN
=
&
(
m_3dNodes
[
r
][
c
][
z
-
1
]);
// shallow
else
if
(
k
==
5
&&
z
<
binsDim3
-
1
)
pNxtN
=
&
(
m_3dNodes
[
r
][
c
][
z
+
1
]);
// deep
else
continue
;
}
if
(
pNxtN
!=
pCurN
->
pParent
)
{
CV_Assert
(
pNxtN
!=
NULL
);
pNxtE
=
pNxtN
->
pChild
;
if
(
pNxtE
&&
pNxtE
->
pChild
==
pCurN
)
// has connection
{
pNxtN
->
pParent
=
pCurN
;
pNxtN
->
pPEdge
=
pNxtE
;
pNxtN
->
pChild
=
NULL
;
m_auxQueue
[
nQueue
++
]
=
pNxtN
;
pNxtE
->
pParent
=
pCurN
;
// reverse direction
pNxtE
->
pChild
=
pNxtN
;
pNxtE
->
iDir
=
!
pNxtE
->
iDir
;
if
(
pCurE
)
pCurE
->
pNxt
=
pNxtE
;
// add to edge list
else
pCurN
->
pChild
=
pNxtE
;
pCurE
=
pNxtE
;
}
}
}
}
}
void
EmdL1
::
updateSubtree
(
cvPEmdNode
pRoot
)
{
// Initialize auxiliary queue
m_auxQueue
[
0
]
=
pRoot
;
int
nQueue
=
1
;
// queue length
int
iQHead
=
0
;
// head of queue
// BFS browing
cvPEmdNode
pCurN
=
NULL
,
pNxtN
=
NULL
;
cvPEmdEdge
pCurE
=
NULL
;
while
(
iQHead
<
nQueue
)
{
pCurN
=
m_auxQueue
[
iQHead
++
];
// pop out from queue
pCurE
=
pCurN
->
pChild
;
// browsing all children
while
(
pCurE
)
{
pNxtN
=
pCurE
->
pChild
;
pNxtN
->
iLevel
=
pCurN
->
iLevel
+
1
;
pNxtN
->
u
=
pCurE
->
iDir
?
(
pCurN
->
u
-
1
)
:
(
pCurN
->
u
+
1
);
pCurE
=
pCurE
->
pNxt
;
m_auxQueue
[
nQueue
++
]
=
pNxtN
;
}
}
}
bool
EmdL1
::
isOptimal
()
{
int
iC
,
iMinC
=
0
;
cvPEmdEdge
pE
;
m_pEnter
=
NULL
;
m_iEnter
=
-
1
;
// test each NON-BV edges
for
(
int
k
=
0
;
k
<
nNBV
;
++
k
)
{
pE
=
m_NBVEdges
[
k
];
iC
=
1
-
pE
->
pParent
->
u
+
pE
->
pChild
->
u
;
if
(
iC
<
iMinC
)
{
iMinC
=
iC
;
m_iEnter
=
k
;
}
else
{
// Try reversing the direction
iC
=
1
+
pE
->
pParent
->
u
-
pE
->
pChild
->
u
;
if
(
iC
<
iMinC
)
{
iMinC
=
iC
;
m_iEnter
=
k
;
}
}
}
if
(
m_iEnter
>=
0
)
{
m_pEnter
=
m_NBVEdges
[
m_iEnter
];
if
(
iMinC
==
(
1
-
m_pEnter
->
pChild
->
u
+
m_pEnter
->
pParent
->
u
))
{
// reverse direction
cvPEmdNode
pN
=
m_pEnter
->
pParent
;
m_pEnter
->
pParent
=
m_pEnter
->
pChild
;
m_pEnter
->
pChild
=
pN
;
}
m_pEnter
->
iDir
=
1
;
}
return
m_iEnter
==-
1
;
}
void
EmdL1
::
findNewSolution
()
{
// Find loop formed by adding the Enter BV edge.
findLoopFromEnterBV
();
// Modify flow values along the loop
cvPEmdEdge
pE
=
NULL
;
CV_Assert
(
m_pLeave
!=
NULL
);
float
minFlow
=
m_pLeave
->
flow
;
int
k
;
for
(
k
=
0
;
k
<
m_iFrom
;
k
++
)
{
pE
=
m_fromLoop
[
k
];
if
(
pE
->
iDir
)
pE
->
flow
+=
minFlow
;
// outward
else
pE
->
flow
-=
minFlow
;
// inward
}
for
(
k
=
0
;
k
<
m_iTo
;
k
++
)
{
pE
=
m_toLoop
[
k
];
if
(
pE
->
iDir
)
pE
->
flow
-=
minFlow
;
// outward
else
pE
->
flow
+=
minFlow
;
// inward
}
// Update BV Tree, removing the Leaving-BV edge
cvPEmdNode
pLParentN
=
m_pLeave
->
pParent
;
cvPEmdNode
pLChildN
=
m_pLeave
->
pChild
;
cvPEmdEdge
pPreE
=
pLParentN
->
pChild
;
if
(
pPreE
==
m_pLeave
)
{
pLParentN
->
pChild
=
m_pLeave
->
pNxt
;
// Leaving-BV is the first child
}
else
{
while
(
pPreE
->
pNxt
!=
m_pLeave
)
pPreE
=
pPreE
->
pNxt
;
pPreE
->
pNxt
=
m_pLeave
->
pNxt
;
// remove Leaving-BV from child list
}
pLChildN
->
pParent
=
NULL
;
pLChildN
->
pPEdge
=
NULL
;
m_NBVEdges
[
m_iEnter
]
=
m_pLeave
;
// put the leaving-BV into the NBV array
// Add the Enter BV edge
cvPEmdNode
pEParentN
=
m_pEnter
->
pParent
;
cvPEmdNode
pEChildN
=
m_pEnter
->
pChild
;
m_pEnter
->
flow
=
minFlow
;
m_pEnter
->
pNxt
=
pEParentN
->
pChild
;
// insert the Enter BV as the first child
pEParentN
->
pChild
=
m_pEnter
;
// of its parent
// Recursively update the tree start from pEChildN
cvPEmdNode
pPreN
=
pEParentN
;
cvPEmdNode
pCurN
=
pEChildN
;
cvPEmdNode
pNxtN
;
cvPEmdEdge
pNxtE
,
pPreE0
;
pPreE
=
m_pEnter
;
while
(
pCurN
)
{
pNxtN
=
pCurN
->
pParent
;
pNxtE
=
pCurN
->
pPEdge
;
pCurN
->
pParent
=
pPreN
;
pCurN
->
pPEdge
=
pPreE
;
if
(
pNxtN
)
{
// remove the edge from pNxtN's child list
if
(
pNxtN
->
pChild
==
pNxtE
)
{
pNxtN
->
pChild
=
pNxtE
->
pNxt
;
// first child
}
else
{
pPreE0
=
pNxtN
->
pChild
;
while
(
pPreE0
->
pNxt
!=
pNxtE
)
pPreE0
=
pPreE0
->
pNxt
;
pPreE0
->
pNxt
=
pNxtE
->
pNxt
;
// remove Leaving-BV from child list
}
// reverse the parent-child direction
pNxtE
->
pParent
=
pCurN
;
pNxtE
->
pChild
=
pNxtN
;
pNxtE
->
iDir
=
!
pNxtE
->
iDir
;
pNxtE
->
pNxt
=
pCurN
->
pChild
;
pCurN
->
pChild
=
pNxtE
;
pPreE
=
pNxtE
;
pPreN
=
pCurN
;
}
pCurN
=
pNxtN
;
}
// Update U at the child of the Enter BV
pEChildN
->
u
=
m_pEnter
->
iDir
?
(
pEParentN
->
u
-
1
)
:
(
pEParentN
->
u
+
1
);
pEChildN
->
iLevel
=
pEParentN
->
iLevel
+
1
;
}
void
EmdL1
::
findLoopFromEnterBV
()
{
// Initialize Leaving-BV edge
float
minFlow
=
std
::
numeric_limits
<
float
>::
max
();
cvPEmdEdge
pE
=
NULL
;
int
iLFlag
=
0
;
// 0: in the FROM list, 1: in the TO list
// Using two loop list to store the loop nodes
cvPEmdNode
pFrom
=
m_pEnter
->
pParent
;
cvPEmdNode
pTo
=
m_pEnter
->
pChild
;
m_iFrom
=
0
;
m_iTo
=
0
;
m_pLeave
=
NULL
;
// Trace back to make pFrom and pTo at the same level
while
(
pFrom
->
iLevel
>
pTo
->
iLevel
)
{
pE
=
pFrom
->
pPEdge
;
m_fromLoop
[
m_iFrom
++
]
=
pE
;
if
(
!
pE
->
iDir
&&
pE
->
flow
<
minFlow
)
{
minFlow
=
pE
->
flow
;
m_pLeave
=
pE
;
iLFlag
=
0
;
// 0: in the FROM list
}
pFrom
=
pFrom
->
pParent
;
}
while
(
pTo
->
iLevel
>
pFrom
->
iLevel
)
{
pE
=
pTo
->
pPEdge
;
m_toLoop
[
m_iTo
++
]
=
pE
;
if
(
pE
->
iDir
&&
pE
->
flow
<
minFlow
)
{
minFlow
=
pE
->
flow
;
m_pLeave
=
pE
;
iLFlag
=
1
;
// 1: in the TO list
}
pTo
=
pTo
->
pParent
;
}
// Trace pTo and pFrom simultaneously till find their common ancester
while
(
pTo
!=
pFrom
)
{
pE
=
pFrom
->
pPEdge
;
m_fromLoop
[
m_iFrom
++
]
=
pE
;
if
(
!
pE
->
iDir
&&
pE
->
flow
<
minFlow
)
{
minFlow
=
pE
->
flow
;
m_pLeave
=
pE
;
iLFlag
=
0
;
// 0: in the FROM list, 1: in the TO list
}
pFrom
=
pFrom
->
pParent
;
pE
=
pTo
->
pPEdge
;
m_toLoop
[
m_iTo
++
]
=
pE
;
if
(
pE
->
iDir
&&
pE
->
flow
<
minFlow
)
{
minFlow
=
pE
->
flow
;
m_pLeave
=
pE
;
iLFlag
=
1
;
// 0: in the FROM list, 1: in the TO list
}
pTo
=
pTo
->
pParent
;
}
// Reverse the direction of the Enter BV edge if necessary
if
(
iLFlag
==
0
)
{
cvPEmdNode
pN
=
m_pEnter
->
pParent
;
m_pEnter
->
pParent
=
m_pEnter
->
pChild
;
m_pEnter
->
pChild
=
pN
;
m_pEnter
->
iDir
=
!
m_pEnter
->
iDir
;
}
}
float
EmdL1
::
compuTotalFlow
()
{
// Computing the total flow as the final distance
float
f
=
0
;
// Initialize auxiliary queue
m_auxQueue
[
0
]
=
m_pRoot
;
int
nQueue
=
1
;
// length of queue
int
iQHead
=
0
;
// head of queue
// BFS browing the tree
cvPEmdNode
pCurN
=
NULL
,
pNxtN
=
NULL
;
cvPEmdEdge
pCurE
=
NULL
;
while
(
iQHead
<
nQueue
)
{
pCurN
=
m_auxQueue
[
iQHead
++
];
// pop out from queue
pCurE
=
pCurN
->
pChild
;
// browsing all children
while
(
pCurE
)
{
f
+=
pCurE
->
flow
;
pNxtN
=
pCurE
->
pChild
;
pCurE
=
pCurE
->
pNxt
;
m_auxQueue
[
nQueue
++
]
=
pNxtN
;
}
}
return
f
;
}
/****************************************************************************************\
* EMDL1 Function *
\****************************************************************************************/
float
cv
::
EMDL1
(
InputArray
_signature1
,
InputArray
_signature2
)
{
CV_INSTRUMENT_REGION
();
Mat
signature1
=
_signature1
.
getMat
(),
signature2
=
_signature2
.
getMat
();
EmdL1
emdl1
;
return
emdl1
.
getEMDL1
(
signature1
,
signature2
);
}
modules/shape/src/emdL1_def.hpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include <stdlib.h>
#include <math.h>
#include <vector>
/****************************************************************************************\
* For EMDL1 Framework *
\****************************************************************************************/
typedef
struct
cvEMDEdge
*
cvPEmdEdge
;
typedef
struct
cvEMDNode
*
cvPEmdNode
;
struct
cvEMDNode
{
int
pos
[
3
];
// grid position
float
d
;
// initial value
int
u
;
// tree maintenance
int
iLevel
;
// level in the tree, 0 means root
cvPEmdNode
pParent
;
// pointer to its parent
cvPEmdEdge
pChild
;
cvPEmdEdge
pPEdge
;
// point to the edge coming out from its parent
};
struct
cvEMDEdge
{
float
flow
;
// initial value
int
iDir
;
// 1:outward, 0:inward
// tree maintenance
cvPEmdNode
pParent
;
// point to its parent
cvPEmdNode
pChild
;
// the child node
cvPEmdEdge
pNxt
;
// next child/edge
};
typedef
std
::
vector
<
cvEMDNode
>
cvEMDNodeArray
;
typedef
std
::
vector
<
cvEMDEdge
>
cvEMDEdgeArray
;
typedef
std
::
vector
<
cvEMDNodeArray
>
cvEMDNodeArray2D
;
typedef
std
::
vector
<
cvEMDEdgeArray
>
cvEMDEdgeArray2D
;
typedef
std
::
vector
<
float
>
floatArray
;
typedef
std
::
vector
<
floatArray
>
floatArray2D
;
/****************************************************************************************\
* EMDL1 Class *
\****************************************************************************************/
class
EmdL1
{
public
:
EmdL1
()
{
m_pRoot
=
NULL
;
binsDim1
=
0
;
binsDim2
=
0
;
binsDim3
=
0
;
dimension
=
0
;
nMaxIt
=
500
;
m_pLeave
=
0
;
m_iEnter
=
0
;
nNBV
=
0
;
m_nItr
=
0
;
m_iTo
=
0
;
m_iFrom
=
0
;
m_pEnter
=
0
;
}
~
EmdL1
()
{
}
float
getEMDL1
(
cv
::
Mat
&
sig1
,
cv
::
Mat
&
sig2
);
void
setMaxIteration
(
int
_nMaxIt
);
private
:
//-- SubFunctions called in the EMD algorithm
bool
initBaseTrees
(
int
n1
=
0
,
int
n2
=
0
,
int
n3
=
0
);
bool
fillBaseTrees
(
float
*
H1
,
float
*
H2
);
bool
greedySolution
();
bool
greedySolution2
();
bool
greedySolution3
();
void
initBVTree
();
void
updateSubtree
(
cvPEmdNode
pRoot
);
bool
isOptimal
();
void
findNewSolution
();
void
findLoopFromEnterBV
();
float
compuTotalFlow
();
private
:
int
dimension
;
int
binsDim1
,
binsDim2
,
binsDim3
;
// the histogram contains m_n1 rows and m_n2 columns
int
nNBV
;
// number of Non-Basic Variables (NBV)
int
nMaxIt
;
cvEMDNodeArray2D
m_Nodes
;
// all nodes
cvEMDEdgeArray2D
m_EdgesRight
;
// all edges to right
cvEMDEdgeArray2D
m_EdgesUp
;
// all edges to upward
std
::
vector
<
cvEMDNodeArray2D
>
m_3dNodes
;
// all nodes for 3D
std
::
vector
<
cvEMDEdgeArray2D
>
m_3dEdgesRight
;
// all edges to right, 3D
std
::
vector
<
cvEMDEdgeArray2D
>
m_3dEdgesUp
;
// all edges to upward, 3D
std
::
vector
<
cvEMDEdgeArray2D
>
m_3dEdgesDeep
;
// all edges to deep, 3D
std
::
vector
<
cvPEmdEdge
>
m_NBVEdges
;
// pointers to all NON-BV edges
std
::
vector
<
cvPEmdNode
>
m_auxQueue
;
// auxiliary node queue
cvPEmdNode
m_pRoot
;
// root of the BV Tree
cvPEmdEdge
m_pEnter
;
// Enter BV edge
int
m_iEnter
;
// Enter BV edge, index in m_NBVEdges
cvPEmdEdge
m_pLeave
;
// Leave BV edge
int
m_nItr
;
// number of iteration
// auxiliary variables for searching a new loop
std
::
vector
<
cvPEmdEdge
>
m_fromLoop
;
std
::
vector
<
cvPEmdEdge
>
m_toLoop
;
int
m_iFrom
;
int
m_iTo
;
};
modules/shape/src/haus_dis.cpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
namespace
cv
{
class
HausdorffDistanceExtractorImpl
CV_FINAL
:
public
HausdorffDistanceExtractor
{
public
:
/* Constructor */
HausdorffDistanceExtractorImpl
(
int
_distanceFlag
=
NORM_L1
,
float
_rankProportion
=
0.6
)
{
distanceFlag
=
_distanceFlag
;
rankProportion
=
_rankProportion
;
name_
=
"ShapeDistanceExtractor.HAU"
;
}
/* Destructor */
~
HausdorffDistanceExtractorImpl
()
{
}
//! the main operator
virtual
float
computeDistance
(
InputArray
contour1
,
InputArray
contour2
)
CV_OVERRIDE
;
//! Setters/Getters
virtual
void
setDistanceFlag
(
int
_distanceFlag
)
CV_OVERRIDE
{
distanceFlag
=
_distanceFlag
;}
virtual
int
getDistanceFlag
()
const
CV_OVERRIDE
{
return
distanceFlag
;}
virtual
void
setRankProportion
(
float
_rankProportion
)
CV_OVERRIDE
{
CV_Assert
((
_rankProportion
>
0
)
&&
(
_rankProportion
<=
1
));
rankProportion
=
_rankProportion
;
}
virtual
float
getRankProportion
()
const
CV_OVERRIDE
{
return
rankProportion
;}
//! write/read
virtual
void
write
(
FileStorage
&
fs
)
const
CV_OVERRIDE
{
writeFormat
(
fs
);
fs
<<
"name"
<<
name_
<<
"distance"
<<
distanceFlag
<<
"rank"
<<
rankProportion
;
}
virtual
void
read
(
const
FileNode
&
fn
)
CV_OVERRIDE
{
CV_Assert
(
(
String
)
fn
[
"name"
]
==
name_
);
distanceFlag
=
(
int
)
fn
[
"distance"
];
rankProportion
=
(
float
)
fn
[
"rank"
];
}
private
:
int
distanceFlag
;
float
rankProportion
;
protected
:
String
name_
;
};
//! Hausdorff distance for a pair of set of points
static
float
_apply
(
const
Mat
&
set1
,
const
Mat
&
set2
,
int
distType
,
double
propRank
)
{
// Building distance matrix //
Mat
disMat
(
set1
.
cols
,
set2
.
cols
,
CV_32F
);
int
K
=
int
(
propRank
*
(
disMat
.
rows
-
1
));
for
(
int
r
=
0
;
r
<
disMat
.
rows
;
r
++
)
{
for
(
int
c
=
0
;
c
<
disMat
.
cols
;
c
++
)
{
Point2f
diff
=
set1
.
at
<
Point2f
>
(
0
,
r
)
-
set2
.
at
<
Point2f
>
(
0
,
c
);
disMat
.
at
<
float
>
(
r
,
c
)
=
(
float
)
norm
(
Mat
(
diff
),
distType
);
}
}
Mat
shortest
(
disMat
.
rows
,
1
,
CV_32F
);
for
(
int
ii
=
0
;
ii
<
disMat
.
rows
;
ii
++
)
{
Mat
therow
=
disMat
.
row
(
ii
);
double
mindis
;
minMaxIdx
(
therow
,
&
mindis
);
shortest
.
at
<
float
>
(
ii
,
0
)
=
float
(
mindis
);
}
Mat
sorted
;
cv
::
sort
(
shortest
,
sorted
,
SORT_EVERY_ROW
|
SORT_DESCENDING
);
return
sorted
.
at
<
float
>
(
K
,
0
);
}
float
HausdorffDistanceExtractorImpl
::
computeDistance
(
InputArray
contour1
,
InputArray
contour2
)
{
CV_INSTRUMENT_REGION
();
Mat
set1
=
contour1
.
getMat
(),
set2
=
contour2
.
getMat
();
if
(
set1
.
type
()
!=
CV_32F
)
set1
.
convertTo
(
set1
,
CV_32F
);
if
(
set2
.
type
()
!=
CV_32F
)
set2
.
convertTo
(
set2
,
CV_32F
);
CV_Assert
((
set1
.
channels
()
==
2
)
&&
(
set1
.
cols
>
0
));
CV_Assert
((
set2
.
channels
()
==
2
)
&&
(
set2
.
cols
>
0
));
// Force vectors column-based
if
(
set1
.
dims
>
1
)
set1
=
set1
.
reshape
(
2
,
1
);
if
(
set2
.
dims
>
1
)
set2
=
set2
.
reshape
(
2
,
1
);
return
std
::
max
(
_apply
(
set1
,
set2
,
distanceFlag
,
rankProportion
),
_apply
(
set2
,
set1
,
distanceFlag
,
rankProportion
)
);
}
Ptr
<
HausdorffDistanceExtractor
>
createHausdorffDistanceExtractor
(
int
distanceFlag
,
float
rankProp
)
{
return
Ptr
<
HausdorffDistanceExtractor
>
(
new
HausdorffDistanceExtractorImpl
(
distanceFlag
,
rankProp
));
}
}
// cv
modules/shape/src/hist_cost.cpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
namespace
cv
{
/*! */
class
NormHistogramCostExtractorImpl
CV_FINAL
:
public
NormHistogramCostExtractor
{
public
:
/* Constructors */
NormHistogramCostExtractorImpl
(
int
_flag
,
int
_nDummies
,
float
_defaultCost
)
{
flag
=
_flag
;
nDummies
=
_nDummies
;
defaultCost
=
_defaultCost
;
name_
=
"HistogramCostExtractor.NOR"
;
}
/* Destructor */
~
NormHistogramCostExtractorImpl
()
CV_OVERRIDE
{
}
//! the main operator
virtual
void
buildCostMatrix
(
InputArray
descriptors1
,
InputArray
descriptors2
,
OutputArray
costMatrix
)
CV_OVERRIDE
;
//! Setters/Getters
void
setNDummies
(
int
_nDummies
)
CV_OVERRIDE
{
nDummies
=
_nDummies
;
}
int
getNDummies
()
const
CV_OVERRIDE
{
return
nDummies
;
}
void
setDefaultCost
(
float
_defaultCost
)
CV_OVERRIDE
{
defaultCost
=
_defaultCost
;
}
float
getDefaultCost
()
const
CV_OVERRIDE
{
return
defaultCost
;
}
virtual
void
setNormFlag
(
int
_flag
)
CV_OVERRIDE
{
flag
=
_flag
;
}
virtual
int
getNormFlag
()
const
CV_OVERRIDE
{
return
flag
;
}
//! write/read
virtual
void
write
(
FileStorage
&
fs
)
const
CV_OVERRIDE
{
writeFormat
(
fs
);
fs
<<
"name"
<<
name_
<<
"flag"
<<
flag
<<
"dummies"
<<
nDummies
<<
"default"
<<
defaultCost
;
}
virtual
void
read
(
const
FileNode
&
fn
)
CV_OVERRIDE
{
CV_Assert
(
(
String
)
fn
[
"name"
]
==
name_
);
flag
=
(
int
)
fn
[
"flag"
];
nDummies
=
(
int
)
fn
[
"dummies"
];
defaultCost
=
(
float
)
fn
[
"default"
];
}
private
:
int
flag
;
int
nDummies
;
float
defaultCost
;
protected
:
String
name_
;
};
void
NormHistogramCostExtractorImpl
::
buildCostMatrix
(
InputArray
_descriptors1
,
InputArray
_descriptors2
,
OutputArray
_costMatrix
)
{
CV_INSTRUMENT_REGION
();
// size of the costMatrix with dummies //
Mat
descriptors1
=
_descriptors1
.
getMat
();
Mat
descriptors2
=
_descriptors2
.
getMat
();
int
costrows
=
std
::
max
(
descriptors1
.
rows
,
descriptors2
.
rows
)
+
nDummies
;
_costMatrix
.
create
(
costrows
,
costrows
,
CV_32F
);
Mat
costMatrix
=
_costMatrix
.
getMat
();
// Obtain copies of the descriptors //
cv
::
Mat
scd1
=
descriptors1
.
clone
();
cv
::
Mat
scd2
=
descriptors2
.
clone
();
// row normalization //
for
(
int
i
=
0
;
i
<
scd1
.
rows
;
i
++
)
{
scd1
.
row
(
i
)
/=
(
sum
(
scd1
.
row
(
i
))[
0
]
+
FLT_EPSILON
);
}
for
(
int
i
=
0
;
i
<
scd2
.
rows
;
i
++
)
{
scd2
.
row
(
i
)
/=
(
sum
(
scd2
.
row
(
i
))[
0
]
+
FLT_EPSILON
);
}
// Compute the Cost Matrix //
for
(
int
i
=
0
;
i
<
costrows
;
i
++
)
{
for
(
int
j
=
0
;
j
<
costrows
;
j
++
)
{
if
(
i
<
scd1
.
rows
&&
j
<
scd2
.
rows
)
{
Mat
columnDiff
=
scd1
.
row
(
i
)
-
scd2
.
row
(
j
);
costMatrix
.
at
<
float
>
(
i
,
j
)
=
(
float
)
norm
(
columnDiff
,
flag
);
}
else
{
costMatrix
.
at
<
float
>
(
i
,
j
)
=
defaultCost
;
}
}
}
}
Ptr
<
HistogramCostExtractor
>
createNormHistogramCostExtractor
(
int
flag
,
int
nDummies
,
float
defaultCost
)
{
return
Ptr
<
HistogramCostExtractor
>
(
new
NormHistogramCostExtractorImpl
(
flag
,
nDummies
,
defaultCost
)
);
}
/*! */
class
EMDHistogramCostExtractorImpl
CV_FINAL
:
public
EMDHistogramCostExtractor
{
public
:
/* Constructors */
EMDHistogramCostExtractorImpl
(
int
_flag
,
int
_nDummies
,
float
_defaultCost
)
{
flag
=
_flag
;
nDummies
=
_nDummies
;
defaultCost
=
_defaultCost
;
name_
=
"HistogramCostExtractor.EMD"
;
}
/* Destructor */
~
EMDHistogramCostExtractorImpl
()
CV_OVERRIDE
{
}
//! the main operator
virtual
void
buildCostMatrix
(
InputArray
descriptors1
,
InputArray
descriptors2
,
OutputArray
costMatrix
)
CV_OVERRIDE
;
//! Setters/Getters
void
setNDummies
(
int
_nDummies
)
CV_OVERRIDE
{
nDummies
=
_nDummies
;
}
int
getNDummies
()
const
CV_OVERRIDE
{
return
nDummies
;
}
void
setDefaultCost
(
float
_defaultCost
)
CV_OVERRIDE
{
defaultCost
=
_defaultCost
;
}
float
getDefaultCost
()
const
CV_OVERRIDE
{
return
defaultCost
;
}
virtual
void
setNormFlag
(
int
_flag
)
CV_OVERRIDE
{
flag
=
_flag
;
}
virtual
int
getNormFlag
()
const
CV_OVERRIDE
{
return
flag
;
}
//! write/read
virtual
void
write
(
FileStorage
&
fs
)
const
CV_OVERRIDE
{
writeFormat
(
fs
);
fs
<<
"name"
<<
name_
<<
"flag"
<<
flag
<<
"dummies"
<<
nDummies
<<
"default"
<<
defaultCost
;
}
virtual
void
read
(
const
FileNode
&
fn
)
CV_OVERRIDE
{
CV_Assert
(
(
String
)
fn
[
"name"
]
==
name_
);
flag
=
(
int
)
fn
[
"flag"
];
nDummies
=
(
int
)
fn
[
"dummies"
];
defaultCost
=
(
float
)
fn
[
"default"
];
}
private
:
int
flag
;
int
nDummies
;
float
defaultCost
;
protected
:
String
name_
;
};
void
EMDHistogramCostExtractorImpl
::
buildCostMatrix
(
InputArray
_descriptors1
,
InputArray
_descriptors2
,
OutputArray
_costMatrix
)
{
CV_INSTRUMENT_REGION
();
// size of the costMatrix with dummies //
Mat
descriptors1
=
_descriptors1
.
getMat
();
Mat
descriptors2
=
_descriptors2
.
getMat
();
int
costrows
=
std
::
max
(
descriptors1
.
rows
,
descriptors2
.
rows
)
+
nDummies
;
_costMatrix
.
create
(
costrows
,
costrows
,
CV_32F
);
Mat
costMatrix
=
_costMatrix
.
getMat
();
// Obtain copies of the descriptors //
cv
::
Mat
scd1
=
descriptors1
.
clone
();
cv
::
Mat
scd2
=
descriptors2
.
clone
();
// row normalization //
for
(
int
i
=
0
;
i
<
scd1
.
rows
;
i
++
)
{
cv
::
Mat
row
=
scd1
.
row
(
i
);
scd1
.
row
(
i
)
/=
(
sum
(
row
)[
0
]
+
FLT_EPSILON
);
}
for
(
int
i
=
0
;
i
<
scd2
.
rows
;
i
++
)
{
cv
::
Mat
row
=
scd2
.
row
(
i
);
scd2
.
row
(
i
)
/=
(
sum
(
row
)[
0
]
+
FLT_EPSILON
);
}
// Compute the Cost Matrix //
for
(
int
i
=
0
;
i
<
costrows
;
i
++
)
{
for
(
int
j
=
0
;
j
<
costrows
;
j
++
)
{
if
(
i
<
scd1
.
rows
&&
j
<
scd2
.
rows
)
{
cv
::
Mat
sig1
(
scd1
.
cols
,
2
,
CV_32F
),
sig2
(
scd2
.
cols
,
2
,
CV_32F
);
sig1
.
col
(
0
)
=
scd1
.
row
(
i
).
t
();
sig2
.
col
(
0
)
=
scd2
.
row
(
j
).
t
();
for
(
int
k
=
0
;
k
<
sig1
.
rows
;
k
++
)
{
sig1
.
at
<
float
>
(
k
,
1
)
=
float
(
k
);
}
for
(
int
k
=
0
;
k
<
sig2
.
rows
;
k
++
)
{
sig2
.
at
<
float
>
(
k
,
1
)
=
float
(
k
);
}
costMatrix
.
at
<
float
>
(
i
,
j
)
=
cv
::
EMD
(
sig1
,
sig2
,
flag
);
}
else
{
costMatrix
.
at
<
float
>
(
i
,
j
)
=
defaultCost
;
}
}
}
}
Ptr
<
HistogramCostExtractor
>
createEMDHistogramCostExtractor
(
int
flag
,
int
nDummies
,
float
defaultCost
)
{
return
Ptr
<
HistogramCostExtractor
>
(
new
EMDHistogramCostExtractorImpl
(
flag
,
nDummies
,
defaultCost
)
);
}
/*! */
class
ChiHistogramCostExtractorImpl
CV_FINAL
:
public
ChiHistogramCostExtractor
{
public
:
/* Constructors */
ChiHistogramCostExtractorImpl
(
int
_nDummies
,
float
_defaultCost
)
{
name_
=
"HistogramCostExtractor.CHI"
;
nDummies
=
_nDummies
;
defaultCost
=
_defaultCost
;
}
/* Destructor */
~
ChiHistogramCostExtractorImpl
()
CV_OVERRIDE
{
}
//! the main operator
virtual
void
buildCostMatrix
(
InputArray
descriptors1
,
InputArray
descriptors2
,
OutputArray
costMatrix
)
CV_OVERRIDE
;
//! setters / getters
void
setNDummies
(
int
_nDummies
)
CV_OVERRIDE
{
nDummies
=
_nDummies
;
}
int
getNDummies
()
const
CV_OVERRIDE
{
return
nDummies
;
}
void
setDefaultCost
(
float
_defaultCost
)
CV_OVERRIDE
{
defaultCost
=
_defaultCost
;
}
float
getDefaultCost
()
const
CV_OVERRIDE
{
return
defaultCost
;
}
//! write/read
virtual
void
write
(
FileStorage
&
fs
)
const
CV_OVERRIDE
{
writeFormat
(
fs
);
fs
<<
"name"
<<
name_
<<
"dummies"
<<
nDummies
<<
"default"
<<
defaultCost
;
}
virtual
void
read
(
const
FileNode
&
fn
)
CV_OVERRIDE
{
CV_Assert
(
(
String
)
fn
[
"name"
]
==
name_
);
nDummies
=
(
int
)
fn
[
"dummies"
];
defaultCost
=
(
float
)
fn
[
"default"
];
}
protected
:
String
name_
;
int
nDummies
;
float
defaultCost
;
};
void
ChiHistogramCostExtractorImpl
::
buildCostMatrix
(
InputArray
_descriptors1
,
InputArray
_descriptors2
,
OutputArray
_costMatrix
)
{
CV_INSTRUMENT_REGION
();
// size of the costMatrix with dummies //
Mat
descriptors1
=
_descriptors1
.
getMat
();
Mat
descriptors2
=
_descriptors2
.
getMat
();
int
costrows
=
std
::
max
(
descriptors1
.
rows
,
descriptors2
.
rows
)
+
nDummies
;
_costMatrix
.
create
(
costrows
,
costrows
,
CV_32FC1
);
Mat
costMatrix
=
_costMatrix
.
getMat
();
// Obtain copies of the descriptors //
cv
::
Mat
scd1
=
descriptors1
.
clone
();
cv
::
Mat
scd2
=
descriptors2
.
clone
();
// row normalization //
for
(
int
i
=
0
;
i
<
scd1
.
rows
;
i
++
)
{
cv
::
Mat
row
=
scd1
.
row
(
i
);
scd1
.
row
(
i
)
/=
(
sum
(
row
)[
0
]
+
FLT_EPSILON
);
}
for
(
int
i
=
0
;
i
<
scd2
.
rows
;
i
++
)
{
cv
::
Mat
row
=
scd2
.
row
(
i
);
scd2
.
row
(
i
)
/=
(
sum
(
row
)[
0
]
+
FLT_EPSILON
);
}
// Compute the Cost Matrix //
for
(
int
i
=
0
;
i
<
costrows
;
i
++
)
{
for
(
int
j
=
0
;
j
<
costrows
;
j
++
)
{
if
(
i
<
scd1
.
rows
&&
j
<
scd2
.
rows
)
{
float
csum
=
0
;
for
(
int
k
=
0
;
k
<
scd2
.
cols
;
k
++
)
{
float
resta
=
scd1
.
at
<
float
>
(
i
,
k
)
-
scd2
.
at
<
float
>
(
j
,
k
);
float
suma
=
scd1
.
at
<
float
>
(
i
,
k
)
+
scd2
.
at
<
float
>
(
j
,
k
);
csum
+=
resta
*
resta
/
(
FLT_EPSILON
+
suma
);
}
costMatrix
.
at
<
float
>
(
i
,
j
)
=
csum
/
2
;
}
else
{
costMatrix
.
at
<
float
>
(
i
,
j
)
=
defaultCost
;
}
}
}
}
Ptr
<
HistogramCostExtractor
>
createChiHistogramCostExtractor
(
int
nDummies
,
float
defaultCost
)
{
return
Ptr
<
HistogramCostExtractor
>
(
new
ChiHistogramCostExtractorImpl
(
nDummies
,
defaultCost
)
);
}
/*! */
class
EMDL1HistogramCostExtractorImpl
CV_FINAL
:
public
EMDL1HistogramCostExtractor
{
public
:
/* Constructors */
EMDL1HistogramCostExtractorImpl
(
int
_nDummies
,
float
_defaultCost
)
{
name_
=
"HistogramCostExtractor.CHI"
;
nDummies
=
_nDummies
;
defaultCost
=
_defaultCost
;
}
/* Destructor */
~
EMDL1HistogramCostExtractorImpl
()
CV_OVERRIDE
{
}
//! the main operator
virtual
void
buildCostMatrix
(
InputArray
descriptors1
,
InputArray
descriptors2
,
OutputArray
costMatrix
)
CV_OVERRIDE
;
//! setters / getters
void
setNDummies
(
int
_nDummies
)
CV_OVERRIDE
{
nDummies
=
_nDummies
;
}
int
getNDummies
()
const
CV_OVERRIDE
{
return
nDummies
;
}
void
setDefaultCost
(
float
_defaultCost
)
CV_OVERRIDE
{
defaultCost
=
_defaultCost
;
}
float
getDefaultCost
()
const
CV_OVERRIDE
{
return
defaultCost
;
}
//! write/read
virtual
void
write
(
FileStorage
&
fs
)
const
CV_OVERRIDE
{
writeFormat
(
fs
);
fs
<<
"name"
<<
name_
<<
"dummies"
<<
nDummies
<<
"default"
<<
defaultCost
;
}
virtual
void
read
(
const
FileNode
&
fn
)
CV_OVERRIDE
{
CV_Assert
(
(
String
)
fn
[
"name"
]
==
name_
);
nDummies
=
(
int
)
fn
[
"dummies"
];
defaultCost
=
(
float
)
fn
[
"default"
];
}
protected
:
String
name_
;
int
nDummies
;
float
defaultCost
;
};
void
EMDL1HistogramCostExtractorImpl
::
buildCostMatrix
(
InputArray
_descriptors1
,
InputArray
_descriptors2
,
OutputArray
_costMatrix
)
{
CV_INSTRUMENT_REGION
();
// size of the costMatrix with dummies //
Mat
descriptors1
=
_descriptors1
.
getMat
();
Mat
descriptors2
=
_descriptors2
.
getMat
();
int
costrows
=
std
::
max
(
descriptors1
.
rows
,
descriptors2
.
rows
)
+
nDummies
;
_costMatrix
.
create
(
costrows
,
costrows
,
CV_32F
);
Mat
costMatrix
=
_costMatrix
.
getMat
();
// Obtain copies of the descriptors //
cv
::
Mat
scd1
=
descriptors1
.
clone
();
cv
::
Mat
scd2
=
descriptors2
.
clone
();
// row normalization //
for
(
int
i
=
0
;
i
<
scd1
.
rows
;
i
++
)
{
cv
::
Mat
row
=
scd1
.
row
(
i
);
scd1
.
row
(
i
)
/=
(
sum
(
row
)[
0
]
+
FLT_EPSILON
);
}
for
(
int
i
=
0
;
i
<
scd2
.
rows
;
i
++
)
{
cv
::
Mat
row
=
scd2
.
row
(
i
);
scd2
.
row
(
i
)
/=
(
sum
(
row
)[
0
]
+
FLT_EPSILON
);
}
// Compute the Cost Matrix //
for
(
int
i
=
0
;
i
<
costrows
;
i
++
)
{
for
(
int
j
=
0
;
j
<
costrows
;
j
++
)
{
if
(
i
<
scd1
.
rows
&&
j
<
scd2
.
rows
)
{
cv
::
Mat
sig1
(
scd1
.
cols
,
1
,
CV_32F
),
sig2
(
scd2
.
cols
,
1
,
CV_32F
);
sig1
.
col
(
0
)
=
scd1
.
row
(
i
).
t
();
sig2
.
col
(
0
)
=
scd2
.
row
(
j
).
t
();
costMatrix
.
at
<
float
>
(
i
,
j
)
=
cv
::
EMDL1
(
sig1
,
sig2
);
}
else
{
costMatrix
.
at
<
float
>
(
i
,
j
)
=
defaultCost
;
}
}
}
}
Ptr
<
HistogramCostExtractor
>
createEMDL1HistogramCostExtractor
(
int
nDummies
,
float
defaultCost
)
{
return
Ptr
<
HistogramCostExtractor
>
(
new
EMDL1HistogramCostExtractorImpl
(
nDummies
,
defaultCost
)
);
}
}
// cv
modules/shape/src/precomp.hpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __OPENCV_PRECOMP_H__
#define __OPENCV_PRECOMP_H__
#include <vector>
#include <cmath>
#include <iostream>
#include "opencv2/calib3d.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/shape.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/core/private.hpp"
#include "opencv2/opencv_modules.hpp"
#endif
modules/shape/src/sc_dis.cpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
/*
* Implementation of the paper Shape Matching and Object Recognition Using Shape Contexts
* Belongie et al., 2002 by Juan Manuel Perez for GSoC 2013.
*/
#include "precomp.hpp"
#include "opencv2/core.hpp"
#include "scd_def.hpp"
#include <limits>
namespace
cv
{
class
ShapeContextDistanceExtractorImpl
:
public
ShapeContextDistanceExtractor
{
public
:
/* Constructors */
ShapeContextDistanceExtractorImpl
(
int
_nAngularBins
,
int
_nRadialBins
,
float
_innerRadius
,
float
_outerRadius
,
int
_iterations
,
const
Ptr
<
HistogramCostExtractor
>
&
_comparer
,
const
Ptr
<
ShapeTransformer
>
&
_transformer
)
{
nAngularBins
=
_nAngularBins
;
nRadialBins
=
_nRadialBins
;
innerRadius
=
_innerRadius
;
outerRadius
=
_outerRadius
;
rotationInvariant
=
false
;
comparer
=
_comparer
;
iterations
=
_iterations
;
transformer
=
_transformer
;
bendingEnergyWeight
=
0.3
f
;
imageAppearanceWeight
=
0.0
f
;
shapeContextWeight
=
1.0
f
;
sigma
=
10.0
f
;
name_
=
"ShapeDistanceExtractor.SCD"
;
costFlag
=
0
;
}
/* Destructor */
~
ShapeContextDistanceExtractorImpl
()
CV_OVERRIDE
{
}
//! the main operator
virtual
float
computeDistance
(
InputArray
contour1
,
InputArray
contour2
)
CV_OVERRIDE
;
//! Setters/Getters
virtual
void
setAngularBins
(
int
_nAngularBins
)
CV_OVERRIDE
{
CV_Assert
(
_nAngularBins
>
0
);
nAngularBins
=
_nAngularBins
;
}
virtual
int
getAngularBins
()
const
CV_OVERRIDE
{
return
nAngularBins
;
}
virtual
void
setRadialBins
(
int
_nRadialBins
)
CV_OVERRIDE
{
CV_Assert
(
_nRadialBins
>
0
);
nRadialBins
=
_nRadialBins
;
}
virtual
int
getRadialBins
()
const
CV_OVERRIDE
{
return
nRadialBins
;
}
virtual
void
setInnerRadius
(
float
_innerRadius
)
CV_OVERRIDE
{
CV_Assert
(
_innerRadius
>
0
);
innerRadius
=
_innerRadius
;
}
virtual
float
getInnerRadius
()
const
CV_OVERRIDE
{
return
innerRadius
;
}
virtual
void
setOuterRadius
(
float
_outerRadius
)
CV_OVERRIDE
{
CV_Assert
(
_outerRadius
>
0
);
outerRadius
=
_outerRadius
;
}
virtual
float
getOuterRadius
()
const
CV_OVERRIDE
{
return
outerRadius
;
}
virtual
void
setRotationInvariant
(
bool
_rotationInvariant
)
CV_OVERRIDE
{
rotationInvariant
=
_rotationInvariant
;
}
virtual
bool
getRotationInvariant
()
const
CV_OVERRIDE
{
return
rotationInvariant
;
}
virtual
void
setCostExtractor
(
Ptr
<
HistogramCostExtractor
>
_comparer
)
CV_OVERRIDE
{
comparer
=
_comparer
;
}
virtual
Ptr
<
HistogramCostExtractor
>
getCostExtractor
()
const
CV_OVERRIDE
{
return
comparer
;
}
virtual
void
setShapeContextWeight
(
float
_shapeContextWeight
)
CV_OVERRIDE
{
shapeContextWeight
=
_shapeContextWeight
;
}
virtual
float
getShapeContextWeight
()
const
CV_OVERRIDE
{
return
shapeContextWeight
;
}
virtual
void
setImageAppearanceWeight
(
float
_imageAppearanceWeight
)
CV_OVERRIDE
{
imageAppearanceWeight
=
_imageAppearanceWeight
;
}
virtual
float
getImageAppearanceWeight
()
const
CV_OVERRIDE
{
return
imageAppearanceWeight
;
}
virtual
void
setBendingEnergyWeight
(
float
_bendingEnergyWeight
)
CV_OVERRIDE
{
bendingEnergyWeight
=
_bendingEnergyWeight
;
}
virtual
float
getBendingEnergyWeight
()
const
CV_OVERRIDE
{
return
bendingEnergyWeight
;
}
virtual
void
setStdDev
(
float
_sigma
)
CV_OVERRIDE
{
sigma
=
_sigma
;
}
virtual
float
getStdDev
()
const
CV_OVERRIDE
{
return
sigma
;
}
virtual
void
setImages
(
InputArray
_image1
,
InputArray
_image2
)
CV_OVERRIDE
{
Mat
image1_
=
_image1
.
getMat
(),
image2_
=
_image2
.
getMat
();
CV_Assert
((
image1_
.
depth
()
==
0
)
&&
(
image2_
.
depth
()
==
0
));
image1
=
image1_
;
image2
=
image2_
;
}
virtual
void
getImages
(
OutputArray
_image1
,
OutputArray
_image2
)
const
CV_OVERRIDE
{
CV_Assert
((
!
image1
.
empty
())
&&
(
!
image2
.
empty
()));
image1
.
copyTo
(
_image1
);
image2
.
copyTo
(
_image2
);
}
virtual
void
setIterations
(
int
_iterations
)
CV_OVERRIDE
{
CV_Assert
(
_iterations
>
0
);
iterations
=
_iterations
;}
virtual
int
getIterations
()
const
CV_OVERRIDE
{
return
iterations
;}
virtual
void
setTransformAlgorithm
(
Ptr
<
ShapeTransformer
>
_transformer
)
CV_OVERRIDE
{
transformer
=
_transformer
;}
virtual
Ptr
<
ShapeTransformer
>
getTransformAlgorithm
()
const
CV_OVERRIDE
{
return
transformer
;}
//! write/read
virtual
void
write
(
FileStorage
&
fs
)
const
CV_OVERRIDE
{
writeFormat
(
fs
);
fs
<<
"name"
<<
name_
<<
"nRads"
<<
nRadialBins
<<
"nAngs"
<<
nAngularBins
<<
"iters"
<<
iterations
<<
"img_1"
<<
image1
<<
"img_2"
<<
image2
<<
"beWei"
<<
bendingEnergyWeight
<<
"scWei"
<<
shapeContextWeight
<<
"iaWei"
<<
imageAppearanceWeight
<<
"costF"
<<
costFlag
<<
"rotIn"
<<
rotationInvariant
<<
"sigma"
<<
sigma
;
}
virtual
void
read
(
const
FileNode
&
fn
)
CV_OVERRIDE
{
CV_Assert
(
(
String
)
fn
[
"name"
]
==
name_
);
nRadialBins
=
(
int
)
fn
[
"nRads"
];
nAngularBins
=
(
int
)
fn
[
"nAngs"
];
iterations
=
(
int
)
fn
[
"iters"
];
bendingEnergyWeight
=
(
float
)
fn
[
"beWei"
];
shapeContextWeight
=
(
float
)
fn
[
"scWei"
];
imageAppearanceWeight
=
(
float
)
fn
[
"iaWei"
];
costFlag
=
(
int
)
fn
[
"costF"
];
sigma
=
(
float
)
fn
[
"sigma"
];
}
protected
:
int
nAngularBins
;
int
nRadialBins
;
float
innerRadius
;
float
outerRadius
;
bool
rotationInvariant
;
int
costFlag
;
int
iterations
;
Ptr
<
ShapeTransformer
>
transformer
;
Ptr
<
HistogramCostExtractor
>
comparer
;
Mat
image1
;
Mat
image2
;
float
bendingEnergyWeight
;
float
imageAppearanceWeight
;
float
shapeContextWeight
;
float
sigma
;
String
name_
;
};
float
ShapeContextDistanceExtractorImpl
::
computeDistance
(
InputArray
contour1
,
InputArray
contour2
)
{
CV_INSTRUMENT_REGION
();
// Checking //
Mat
sset1
=
contour1
.
getMat
(),
sset2
=
contour2
.
getMat
(),
set1
,
set2
;
if
(
set1
.
type
()
!=
CV_32F
)
sset1
.
convertTo
(
set1
,
CV_32F
);
else
sset1
.
copyTo
(
set1
);
if
(
set2
.
type
()
!=
CV_32F
)
sset2
.
convertTo
(
set2
,
CV_32F
);
else
sset2
.
copyTo
(
set2
);
CV_Assert
((
set1
.
channels
()
==
2
)
&&
(
set1
.
cols
>
0
));
CV_Assert
((
set2
.
channels
()
==
2
)
&&
(
set2
.
cols
>
0
));
// Force vectors column-based
if
(
set1
.
dims
>
1
)
set1
=
set1
.
reshape
(
2
,
1
);
if
(
set2
.
dims
>
1
)
set2
=
set2
.
reshape
(
2
,
1
);
if
(
imageAppearanceWeight
!=
0
)
{
CV_Assert
((
!
image1
.
empty
())
&&
(
!
image2
.
empty
()));
}
// Initializing Extractor, Descriptor structures and Matcher //
SCD
set1SCE
(
nAngularBins
,
nRadialBins
,
innerRadius
,
outerRadius
,
rotationInvariant
);
Mat
set1SCD
;
SCD
set2SCE
(
nAngularBins
,
nRadialBins
,
innerRadius
,
outerRadius
,
rotationInvariant
);
Mat
set2SCD
;
SCDMatcher
matcher
;
std
::
vector
<
DMatch
>
matches
;
// Distance components (The output is a linear combination of these 3) //
float
sDistance
=
0
,
bEnergy
=
0
,
iAppearance
=
0
;
float
beta
;
// Initializing some variables //
std
::
vector
<
int
>
inliers1
,
inliers2
;
Ptr
<
ThinPlateSplineShapeTransformer
>
transDown
=
transformer
.
dynamicCast
<
ThinPlateSplineShapeTransformer
>
();
Mat
warpedImage
;
int
ii
,
jj
,
pt
;
for
(
ii
=
0
;
ii
<
iterations
;
ii
++
)
{
// Extract SCD descriptor in the set1 //
set1SCE
.
extractSCD
(
set1
,
set1SCD
,
inliers1
);
// Extract SCD descriptor of the set2 (TARGET) //
set2SCE
.
extractSCD
(
set2
,
set2SCD
,
inliers2
,
set1SCE
.
getMeanDistance
());
// regularization parameter with annealing rate annRate //
beta
=
set1SCE
.
getMeanDistance
();
beta
*=
beta
;
// match //
matcher
.
matchDescriptors
(
set1SCD
,
set2SCD
,
matches
,
comparer
,
inliers1
,
inliers2
);
// apply TPS transform //
if
(
!
transDown
.
empty
()
)
transDown
->
setRegularizationParameter
(
beta
);
transformer
->
estimateTransformation
(
set1
,
set2
,
matches
);
bEnergy
+=
transformer
->
applyTransformation
(
set1
,
set1
);
// Image appearance //
if
(
imageAppearanceWeight
!=
0
)
{
// Have to accumulate the transformation along all the iterations
if
(
ii
==
0
)
{
if
(
!
transDown
.
empty
()
)
{
image2
.
copyTo
(
warpedImage
);
}
else
{
image1
.
copyTo
(
warpedImage
);
}
}
transformer
->
warpImage
(
warpedImage
,
warpedImage
);
}
}
Mat
gaussWindow
,
diffIm
;
if
(
imageAppearanceWeight
!=
0
)
{
// compute appearance cost
if
(
!
transDown
.
empty
()
)
{
resize
(
warpedImage
,
warpedImage
,
image1
.
size
(),
0
,
0
,
INTER_LINEAR_EXACT
);
Mat
temp
=
(
warpedImage
-
image1
);
multiply
(
temp
,
temp
,
diffIm
);
}
else
{
resize
(
warpedImage
,
warpedImage
,
image2
.
size
(),
0
,
0
,
INTER_LINEAR_EXACT
);
Mat
temp
=
(
warpedImage
-
image2
);
multiply
(
temp
,
temp
,
diffIm
);
}
gaussWindow
=
Mat
::
zeros
(
warpedImage
.
rows
,
warpedImage
.
cols
,
CV_32F
);
for
(
pt
=
0
;
pt
<
sset1
.
cols
;
pt
++
)
{
Point2f
p
=
sset1
.
at
<
Point2f
>
(
0
,
pt
);
for
(
ii
=
0
;
ii
<
diffIm
.
rows
;
ii
++
)
{
for
(
jj
=
0
;
jj
<
diffIm
.
cols
;
jj
++
)
{
float
val
=
float
(
std
::
exp
(
-
float
(
(
p
.
x
-
jj
)
*
(
p
.
x
-
jj
)
+
(
p
.
y
-
ii
)
*
(
p
.
y
-
ii
)
)
/
(
2
*
sigma
*
sigma
)
)
/
(
sigma
*
sigma
*
2
*
CV_PI
));
gaussWindow
.
at
<
float
>
(
ii
,
jj
)
+=
val
;
}
}
}
Mat
appIm
(
diffIm
.
rows
,
diffIm
.
cols
,
CV_32F
);
for
(
ii
=
0
;
ii
<
diffIm
.
rows
;
ii
++
)
{
for
(
jj
=
0
;
jj
<
diffIm
.
cols
;
jj
++
)
{
float
elema
=
float
(
diffIm
.
at
<
uchar
>
(
ii
,
jj
)
)
/
255
;
float
elemb
=
gaussWindow
.
at
<
float
>
(
ii
,
jj
);
appIm
.
at
<
float
>
(
ii
,
jj
)
=
elema
*
elemb
;
}
}
iAppearance
=
float
(
cv
::
sum
(
appIm
)[
0
]
/
sset1
.
cols
);
}
sDistance
=
matcher
.
getMatchingCost
();
return
(
sDistance
*
shapeContextWeight
+
bEnergy
*
bendingEnergyWeight
+
iAppearance
*
imageAppearanceWeight
);
}
Ptr
<
ShapeContextDistanceExtractor
>
createShapeContextDistanceExtractor
(
int
nAngularBins
,
int
nRadialBins
,
float
innerRadius
,
float
outerRadius
,
int
iterations
,
const
Ptr
<
HistogramCostExtractor
>
&
comparer
,
const
Ptr
<
ShapeTransformer
>
&
transformer
)
{
return
Ptr
<
ShapeContextDistanceExtractor
>
(
new
ShapeContextDistanceExtractorImpl
(
nAngularBins
,
nRadialBins
,
innerRadius
,
outerRadius
,
iterations
,
comparer
,
transformer
)
);
}
//! SCD
void
SCD
::
extractSCD
(
cv
::
Mat
&
contour
,
cv
::
Mat
&
descriptors
,
const
std
::
vector
<
int
>
&
queryInliers
,
const
float
_meanDistance
)
{
cv
::
Mat
contourMat
=
contour
;
cv
::
Mat
disMatrix
=
cv
::
Mat
::
zeros
(
contourMat
.
cols
,
contourMat
.
cols
,
CV_32F
);
cv
::
Mat
angleMatrix
=
cv
::
Mat
::
zeros
(
contourMat
.
cols
,
contourMat
.
cols
,
CV_32F
);
std
::
vector
<
double
>
logspaces
,
angspaces
;
logarithmicSpaces
(
logspaces
);
angularSpaces
(
angspaces
);
buildNormalizedDistanceMatrix
(
contourMat
,
disMatrix
,
queryInliers
,
_meanDistance
);
buildAngleMatrix
(
contourMat
,
angleMatrix
);
// Now, build the descriptor matrix (each row is a point) //
descriptors
=
cv
::
Mat
::
zeros
(
contourMat
.
cols
,
descriptorSize
(),
CV_32F
);
for
(
int
ptidx
=
0
;
ptidx
<
contourMat
.
cols
;
ptidx
++
)
{
for
(
int
cmp
=
0
;
cmp
<
contourMat
.
cols
;
cmp
++
)
{
if
(
ptidx
==
cmp
)
continue
;
if
((
int
)
queryInliers
.
size
()
>
0
)
{
if
(
queryInliers
[
ptidx
]
==
0
||
queryInliers
[
cmp
]
==
0
)
continue
;
//avoid outliers
}
int
angidx
=-
1
,
radidx
=-
1
;
for
(
int
i
=
0
;
i
<
nRadialBins
;
i
++
)
{
if
(
disMatrix
.
at
<
float
>
(
ptidx
,
cmp
)
<
logspaces
[
i
])
{
radidx
=
i
;
break
;
}
}
for
(
int
i
=
0
;
i
<
nAngularBins
;
i
++
)
{
if
(
angleMatrix
.
at
<
float
>
(
ptidx
,
cmp
)
<
angspaces
[
i
])
{
angidx
=
i
;
break
;
}
}
if
(
angidx
!=-
1
&&
radidx
!=-
1
)
{
int
idx
=
angidx
+
radidx
*
nAngularBins
;
descriptors
.
at
<
float
>
(
ptidx
,
idx
)
++
;
}
}
}
}
void
SCD
::
logarithmicSpaces
(
std
::
vector
<
double
>
&
vecSpaces
)
const
{
double
logmin
=
log10
(
innerRadius
);
double
logmax
=
log10
(
outerRadius
);
double
delta
=
(
logmax
-
logmin
)
/
(
nRadialBins
-
1
);
double
accdelta
=
0
;
for
(
int
i
=
0
;
i
<
nRadialBins
;
i
++
)
{
double
val
=
std
::
pow
(
10
,
logmin
+
accdelta
);
vecSpaces
.
push_back
(
val
);
accdelta
+=
delta
;
}
}
void
SCD
::
angularSpaces
(
std
::
vector
<
double
>
&
vecSpaces
)
const
{
double
delta
=
2
*
CV_PI
/
nAngularBins
;
double
val
=
0
;
for
(
int
i
=
0
;
i
<
nAngularBins
;
i
++
)
{
val
+=
delta
;
vecSpaces
.
push_back
(
val
);
}
}
void
SCD
::
buildNormalizedDistanceMatrix
(
cv
::
Mat
&
contour
,
cv
::
Mat
&
disMatrix
,
const
std
::
vector
<
int
>
&
queryInliers
,
const
float
_meanDistance
)
{
cv
::
Mat
contourMat
=
contour
;
cv
::
Mat
mask
(
disMatrix
.
rows
,
disMatrix
.
cols
,
CV_8U
);
for
(
int
i
=
0
;
i
<
contourMat
.
cols
;
i
++
)
{
for
(
int
j
=
0
;
j
<
contourMat
.
cols
;
j
++
)
{
disMatrix
.
at
<
float
>
(
i
,
j
)
=
(
float
)
norm
(
cv
::
Mat
(
contourMat
.
at
<
cv
::
Point2f
>
(
0
,
i
)
-
contourMat
.
at
<
cv
::
Point2f
>
(
0
,
j
)),
cv
::
NORM_L2
);
if
(
_meanDistance
<
0
)
{
if
(
queryInliers
.
size
()
>
0
)
{
mask
.
at
<
char
>
(
i
,
j
)
=
char
(
queryInliers
[
j
]
&&
queryInliers
[
i
]);
}
else
{
mask
.
at
<
char
>
(
i
,
j
)
=
1
;
}
}
}
}
if
(
_meanDistance
<
0
)
{
meanDistance
=
(
float
)
mean
(
disMatrix
,
mask
)[
0
];
}
else
{
meanDistance
=
_meanDistance
;
}
disMatrix
/=
meanDistance
+
FLT_EPSILON
;
}
void
SCD
::
buildAngleMatrix
(
cv
::
Mat
&
contour
,
cv
::
Mat
&
angleMatrix
)
const
{
cv
::
Mat
contourMat
=
contour
;
// if descriptor is rotationInvariant compute massCenter //
cv
::
Point2f
massCenter
(
0
,
0
);
if
(
rotationInvariant
)
{
for
(
int
i
=
0
;
i
<
contourMat
.
cols
;
i
++
)
{
massCenter
+=
contourMat
.
at
<
cv
::
Point2f
>
(
0
,
i
);
}
massCenter
.
x
=
massCenter
.
x
/
(
float
)
contourMat
.
cols
;
massCenter
.
y
=
massCenter
.
y
/
(
float
)
contourMat
.
cols
;
}
for
(
int
i
=
0
;
i
<
contourMat
.
cols
;
i
++
)
{
for
(
int
j
=
0
;
j
<
contourMat
.
cols
;
j
++
)
{
if
(
i
==
j
)
{
angleMatrix
.
at
<
float
>
(
i
,
j
)
=
0.0
;
}
else
{
cv
::
Point2f
dif
=
contourMat
.
at
<
cv
::
Point2f
>
(
0
,
i
)
-
contourMat
.
at
<
cv
::
Point2f
>
(
0
,
j
);
angleMatrix
.
at
<
float
>
(
i
,
j
)
=
std
::
atan2
(
dif
.
y
,
dif
.
x
);
if
(
rotationInvariant
)
{
cv
::
Point2f
refPt
=
contourMat
.
at
<
cv
::
Point2f
>
(
0
,
i
)
-
massCenter
;
float
refAngle
=
atan2
(
refPt
.
y
,
refPt
.
x
);
angleMatrix
.
at
<
float
>
(
i
,
j
)
-=
refAngle
;
}
angleMatrix
.
at
<
float
>
(
i
,
j
)
=
float
(
fmod
(
double
(
angleMatrix
.
at
<
float
>
(
i
,
j
)
+
(
double
)
FLT_EPSILON
),
2
*
CV_PI
)
+
CV_PI
);
}
}
}
}
//! SCDMatcher
void
SCDMatcher
::
matchDescriptors
(
cv
::
Mat
&
descriptors1
,
cv
::
Mat
&
descriptors2
,
std
::
vector
<
cv
::
DMatch
>
&
matches
,
cv
::
Ptr
<
cv
::
HistogramCostExtractor
>
&
comparer
,
std
::
vector
<
int
>
&
inliers1
,
std
::
vector
<
int
>
&
inliers2
)
{
matches
.
clear
();
// Build the cost Matrix between descriptors //
cv
::
Mat
costMat
;
buildCostMatrix
(
descriptors1
,
descriptors2
,
costMat
,
comparer
);
// Solve the matching problem using the hungarian method //
hungarian
(
costMat
,
matches
,
inliers1
,
inliers2
,
descriptors1
.
rows
,
descriptors2
.
rows
);
}
void
SCDMatcher
::
buildCostMatrix
(
const
cv
::
Mat
&
descriptors1
,
const
cv
::
Mat
&
descriptors2
,
cv
::
Mat
&
costMatrix
,
cv
::
Ptr
<
cv
::
HistogramCostExtractor
>
&
comparer
)
const
{
CV_INSTRUMENT_REGION
();
comparer
->
buildCostMatrix
(
descriptors1
,
descriptors2
,
costMatrix
);
}
void
SCDMatcher
::
hungarian
(
cv
::
Mat
&
costMatrix
,
std
::
vector
<
cv
::
DMatch
>
&
outMatches
,
std
::
vector
<
int
>
&
inliers1
,
std
::
vector
<
int
>
&
inliers2
,
int
sizeScd1
,
int
sizeScd2
)
{
std
::
vector
<
int
>
free
(
costMatrix
.
rows
,
0
),
collist
(
costMatrix
.
rows
,
0
);
std
::
vector
<
int
>
matches
(
costMatrix
.
rows
,
0
),
colsol
(
costMatrix
.
rows
),
rowsol
(
costMatrix
.
rows
);
std
::
vector
<
float
>
d
(
costMatrix
.
rows
),
pred
(
costMatrix
.
rows
),
v
(
costMatrix
.
rows
);
const
float
LOWV
=
1e-10
f
;
bool
unassignedfound
;
int
i
=
0
,
imin
=
0
,
numfree
=
0
,
prvnumfree
=
0
,
f
=
0
,
i0
=
0
,
k
=
0
,
freerow
=
0
;
int
j
=
0
,
j1
=
0
,
j2
=
0
,
endofpath
=
0
,
last
=
0
,
low
=
0
,
up
=
0
;
float
min
=
0
,
h
=
0
,
umin
=
0
,
usubmin
=
0
,
v2
=
0
;
// COLUMN REDUCTION //
for
(
j
=
costMatrix
.
rows
-
1
;
j
>=
0
;
j
--
)
{
// find minimum cost over rows.
min
=
costMatrix
.
at
<
float
>
(
0
,
j
);
imin
=
0
;
for
(
i
=
1
;
i
<
costMatrix
.
rows
;
i
++
)
if
(
costMatrix
.
at
<
float
>
(
i
,
j
)
<
min
)
{
min
=
costMatrix
.
at
<
float
>
(
i
,
j
);
imin
=
i
;
}
v
[
j
]
=
min
;
if
(
++
matches
[
imin
]
==
1
)
{
rowsol
[
imin
]
=
j
;
colsol
[
j
]
=
imin
;
}
else
{
colsol
[
j
]
=-
1
;
}
}
// REDUCTION TRANSFER //
for
(
i
=
0
;
i
<
costMatrix
.
rows
;
i
++
)
{
if
(
matches
[
i
]
==
0
)
{
free
[
numfree
++
]
=
i
;
}
else
{
if
(
matches
[
i
]
==
1
)
{
j1
=
rowsol
[
i
];
min
=
std
::
numeric_limits
<
float
>::
max
();
for
(
j
=
0
;
j
<
costMatrix
.
rows
;
j
++
)
{
if
(
j
!=
j1
)
{
if
(
costMatrix
.
at
<
float
>
(
i
,
j
)
-
v
[
j
]
<
min
)
{
min
=
costMatrix
.
at
<
float
>
(
i
,
j
)
-
v
[
j
];
}
}
}
v
[
j1
]
=
v
[
j1
]
-
min
;
}
}
}
// AUGMENTING ROW REDUCTION //
int
loopcnt
=
0
;
do
{
loopcnt
++
;
k
=
0
;
prvnumfree
=
numfree
;
numfree
=
0
;
while
(
k
<
prvnumfree
)
{
i
=
free
[
k
];
k
++
;
umin
=
costMatrix
.
at
<
float
>
(
i
,
0
)
-
v
[
0
];
j1
=
0
;
usubmin
=
std
::
numeric_limits
<
float
>::
max
();
for
(
j
=
1
;
j
<
costMatrix
.
rows
;
j
++
)
{
h
=
costMatrix
.
at
<
float
>
(
i
,
j
)
-
v
[
j
];
if
(
h
<
usubmin
)
{
if
(
h
>=
umin
)
{
usubmin
=
h
;
j2
=
j
;
}
else
{
usubmin
=
umin
;
umin
=
h
;
j2
=
j1
;
j1
=
j
;
}
}
}
i0
=
colsol
[
j1
];
if
(
fabs
(
umin
-
usubmin
)
>
LOWV
)
//if( umin < usubmin )
{
v
[
j1
]
=
v
[
j1
]
-
(
usubmin
-
umin
);
}
else
// minimum and subminimum equal.
{
if
(
i0
>=
0
)
// minimum column j1 is assigned.
{
j1
=
j2
;
i0
=
colsol
[
j2
];
}
}
// (re-)assign i to j1, possibly de-assigning an i0.
rowsol
[
i
]
=
j1
;
colsol
[
j1
]
=
i
;
if
(
i0
>=
0
)
{
//if( umin < usubmin )
if
(
fabs
(
umin
-
usubmin
)
>
LOWV
)
{
free
[
--
k
]
=
i0
;
}
else
{
free
[
numfree
++
]
=
i0
;
}
}
}
}
while
(
loopcnt
<
2
);
// repeat once.
// AUGMENT SOLUTION for each free row //
for
(
f
=
0
;
f
<
numfree
;
f
++
)
{
freerow
=
free
[
f
];
// start row of augmenting path.
// Dijkstra shortest path algorithm.
// runs until unassigned column added to shortest path tree.
for
(
j
=
0
;
j
<
costMatrix
.
rows
;
j
++
)
{
d
[
j
]
=
costMatrix
.
at
<
float
>
(
freerow
,
j
)
-
v
[
j
];
pred
[
j
]
=
float
(
freerow
);
collist
[
j
]
=
j
;
// init column list.
}
low
=
0
;
// columns in 0..low-1 are ready, now none.
up
=
0
;
// columns in low..up-1 are to be scanned for current minimum, now none.
unassignedfound
=
false
;
do
{
if
(
up
==
low
)
{
last
=
low
-
1
;
min
=
d
[
collist
[
up
++
]];
for
(
k
=
up
;
k
<
costMatrix
.
rows
;
k
++
)
{
j
=
collist
[
k
];
h
=
d
[
j
];
if
(
h
<=
min
)
{
if
(
h
<
min
)
// new minimum.
{
up
=
low
;
// restart list at index low.
min
=
h
;
}
collist
[
k
]
=
collist
[
up
];
collist
[
up
++
]
=
j
;
}
}
for
(
k
=
low
;
k
<
up
;
k
++
)
{
if
(
colsol
[
collist
[
k
]]
<
0
)
{
endofpath
=
collist
[
k
];
unassignedfound
=
true
;
break
;
}
}
}
if
(
!
unassignedfound
)
{
// update 'distances' between freerow and all unscanned columns, via next scanned column.
j1
=
collist
[
low
];
low
++
;
i
=
colsol
[
j1
];
h
=
costMatrix
.
at
<
float
>
(
i
,
j1
)
-
v
[
j1
]
-
min
;
for
(
k
=
up
;
k
<
costMatrix
.
rows
;
k
++
)
{
j
=
collist
[
k
];
v2
=
costMatrix
.
at
<
float
>
(
i
,
j
)
-
v
[
j
]
-
h
;
if
(
v2
<
d
[
j
])
{
pred
[
j
]
=
float
(
i
);
if
(
v2
==
min
)
{
if
(
colsol
[
j
]
<
0
)
{
// if unassigned, shortest augmenting path is complete.
endofpath
=
j
;
unassignedfound
=
true
;
break
;
}
else
{
collist
[
k
]
=
collist
[
up
];
collist
[
up
++
]
=
j
;
}
}
d
[
j
]
=
v2
;
}
}
}
}
while
(
!
unassignedfound
);
// update column prices.
for
(
k
=
0
;
k
<=
last
;
k
++
)
{
j1
=
collist
[
k
];
v
[
j1
]
=
v
[
j1
]
+
d
[
j1
]
-
min
;
}
// reset row and column assignments along the alternating path.
do
{
i
=
int
(
pred
[
endofpath
]);
colsol
[
endofpath
]
=
i
;
j1
=
endofpath
;
endofpath
=
rowsol
[
i
];
rowsol
[
i
]
=
j1
;
}
while
(
i
!=
freerow
);
}
// calculate symmetric shape context cost
cv
::
Mat
trueCostMatrix
(
costMatrix
,
cv
::
Rect
(
0
,
0
,
sizeScd1
,
sizeScd2
));
CV_Assert
(
!
trueCostMatrix
.
empty
());
float
leftcost
=
0
;
for
(
int
nrow
=
0
;
nrow
<
trueCostMatrix
.
rows
;
nrow
++
)
{
double
minval
;
minMaxIdx
(
trueCostMatrix
.
row
(
nrow
),
&
minval
);
leftcost
+=
float
(
minval
);
}
leftcost
/=
trueCostMatrix
.
rows
;
float
rightcost
=
0
;
for
(
int
ncol
=
0
;
ncol
<
trueCostMatrix
.
cols
;
ncol
++
)
{
double
minval
;
minMaxIdx
(
trueCostMatrix
.
col
(
ncol
),
&
minval
);
rightcost
+=
float
(
minval
);
}
rightcost
/=
trueCostMatrix
.
cols
;
minMatchCost
=
std
::
max
(
leftcost
,
rightcost
);
// Save in a DMatch vector
for
(
i
=
0
;
i
<
costMatrix
.
cols
;
i
++
)
{
cv
::
DMatch
singleMatch
(
colsol
[
i
],
i
,
costMatrix
.
at
<
float
>
(
colsol
[
i
],
i
));
//queryIdx,trainIdx,distance
outMatches
.
push_back
(
singleMatch
);
}
// Update inliers
inliers1
.
reserve
(
sizeScd1
);
for
(
size_t
kc
=
0
;
kc
<
inliers1
.
size
();
kc
++
)
{
if
(
rowsol
[
kc
]
<
sizeScd2
)
// if a real match
inliers1
[
kc
]
=
1
;
else
inliers1
[
kc
]
=
0
;
}
inliers2
.
reserve
(
sizeScd2
);
for
(
size_t
kc
=
0
;
kc
<
inliers2
.
size
();
kc
++
)
{
if
(
colsol
[
kc
]
<
sizeScd1
)
// if a real match
inliers2
[
kc
]
=
1
;
else
inliers2
[
kc
]
=
0
;
}
}
}
modules/shape/src/scd_def.hpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include <stdlib.h>
#include <math.h>
#include <vector>
namespace
cv
{
/*
* ShapeContextDescriptor class
*/
class
SCD
{
public
:
//! the full constructor taking all the necessary parameters
explicit
SCD
(
int
_nAngularBins
=
12
,
int
_nRadialBins
=
5
,
double
_innerRadius
=
0.1
,
double
_outerRadius
=
1
,
bool
_rotationInvariant
=
false
)
{
setAngularBins
(
_nAngularBins
);
setRadialBins
(
_nRadialBins
);
setInnerRadius
(
_innerRadius
);
setOuterRadius
(
_outerRadius
);
setRotationInvariant
(
_rotationInvariant
);
meanDistance
=
0
;
}
void
extractSCD
(
cv
::
Mat
&
contour
,
cv
::
Mat
&
descriptors
,
const
std
::
vector
<
int
>&
queryInliers
=
std
::
vector
<
int
>
(),
const
float
_meanDistance
=-
1
);
int
descriptorSize
()
{
return
nAngularBins
*
nRadialBins
;}
void
setAngularBins
(
int
angularBins
)
{
nAngularBins
=
angularBins
;
}
void
setRadialBins
(
int
radialBins
)
{
nRadialBins
=
radialBins
;
}
void
setInnerRadius
(
double
_innerRadius
)
{
innerRadius
=
_innerRadius
;
}
void
setOuterRadius
(
double
_outerRadius
)
{
outerRadius
=
_outerRadius
;
}
void
setRotationInvariant
(
bool
_rotationInvariant
)
{
rotationInvariant
=
_rotationInvariant
;
}
int
getAngularBins
()
const
{
return
nAngularBins
;
}
int
getRadialBins
()
const
{
return
nRadialBins
;
}
double
getInnerRadius
()
const
{
return
innerRadius
;
}
double
getOuterRadius
()
const
{
return
outerRadius
;
}
bool
getRotationInvariant
()
const
{
return
rotationInvariant
;
}
float
getMeanDistance
()
const
{
return
meanDistance
;
}
private
:
int
nAngularBins
;
int
nRadialBins
;
double
innerRadius
;
double
outerRadius
;
bool
rotationInvariant
;
float
meanDistance
;
protected
:
void
logarithmicSpaces
(
std
::
vector
<
double
>&
vecSpaces
)
const
;
void
angularSpaces
(
std
::
vector
<
double
>&
vecSpaces
)
const
;
void
buildNormalizedDistanceMatrix
(
cv
::
Mat
&
contour
,
cv
::
Mat
&
disMatrix
,
const
std
::
vector
<
int
>
&
queryInliers
,
const
float
_meanDistance
=-
1
);
void
buildAngleMatrix
(
cv
::
Mat
&
contour
,
cv
::
Mat
&
angleMatrix
)
const
;
};
/*
* Matcher
*/
class
SCDMatcher
{
public
:
// the full constructor
SCDMatcher
()
:
minMatchCost
(
0
)
{
}
// the matcher function using Hungarian method
void
matchDescriptors
(
cv
::
Mat
&
descriptors1
,
cv
::
Mat
&
descriptors2
,
std
::
vector
<
cv
::
DMatch
>&
matches
,
cv
::
Ptr
<
cv
::
HistogramCostExtractor
>&
comparer
,
std
::
vector
<
int
>&
inliers1
,
std
::
vector
<
int
>
&
inliers2
);
// matching cost
float
getMatchingCost
()
const
{
return
minMatchCost
;}
private
:
float
minMatchCost
;
protected
:
void
buildCostMatrix
(
const
cv
::
Mat
&
descriptors1
,
const
cv
::
Mat
&
descriptors2
,
cv
::
Mat
&
costMatrix
,
cv
::
Ptr
<
cv
::
HistogramCostExtractor
>&
comparer
)
const
;
void
hungarian
(
cv
::
Mat
&
costMatrix
,
std
::
vector
<
cv
::
DMatch
>&
outMatches
,
std
::
vector
<
int
>
&
inliers1
,
std
::
vector
<
int
>
&
inliers2
,
int
sizeScd1
=
0
,
int
sizeScd2
=
0
);
};
}
modules/shape/src/tps_trans.cpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
namespace
cv
{
class
ThinPlateSplineShapeTransformerImpl
CV_FINAL
:
public
ThinPlateSplineShapeTransformer
{
public
:
/* Constructors */
ThinPlateSplineShapeTransformerImpl
()
{
regularizationParameter
=
0
;
name_
=
"ShapeTransformer.TPS"
;
tpsComputed
=
false
;
transformCost
=
0
;
}
ThinPlateSplineShapeTransformerImpl
(
double
_regularizationParameter
)
{
regularizationParameter
=
_regularizationParameter
;
name_
=
"ShapeTransformer.TPS"
;
tpsComputed
=
false
;
transformCost
=
0
;
}
/* Destructor */
~
ThinPlateSplineShapeTransformerImpl
()
CV_OVERRIDE
{
}
//! the main operators
virtual
void
estimateTransformation
(
InputArray
transformingShape
,
InputArray
targetShape
,
std
::
vector
<
DMatch
>
&
matches
)
CV_OVERRIDE
;
virtual
float
applyTransformation
(
InputArray
inPts
,
OutputArray
output
=
noArray
())
CV_OVERRIDE
;
virtual
void
warpImage
(
InputArray
transformingImage
,
OutputArray
output
,
int
flags
,
int
borderMode
,
const
Scalar
&
borderValue
)
const
CV_OVERRIDE
;
//! Setters/Getters
virtual
void
setRegularizationParameter
(
double
_regularizationParameter
)
CV_OVERRIDE
{
regularizationParameter
=
_regularizationParameter
;
}
virtual
double
getRegularizationParameter
()
const
CV_OVERRIDE
{
return
regularizationParameter
;
}
//! write/read
virtual
void
write
(
FileStorage
&
fs
)
const
CV_OVERRIDE
{
writeFormat
(
fs
);
fs
<<
"name"
<<
name_
<<
"regularization"
<<
regularizationParameter
;
}
virtual
void
read
(
const
FileNode
&
fn
)
CV_OVERRIDE
{
CV_Assert
(
(
String
)
fn
[
"name"
]
==
name_
);
regularizationParameter
=
(
int
)
fn
[
"regularization"
];
}
private
:
bool
tpsComputed
;
double
regularizationParameter
;
float
transformCost
;
Mat
tpsParameters
;
Mat
shapeReference
;
protected
:
String
name_
;
};
static
float
distance
(
Point2f
p
,
Point2f
q
)
{
Point2f
diff
=
p
-
q
;
float
norma
=
diff
.
x
*
diff
.
x
+
diff
.
y
*
diff
.
y
;
// - 2*diff.x*diff.y;
if
(
norma
<
0
)
norma
=
0
;
//else norma = std::sqrt(norma);
norma
=
norma
*
std
::
log
(
norma
+
FLT_EPSILON
);
return
norma
;
}
static
Point2f
_applyTransformation
(
const
Mat
&
shapeRef
,
const
Point2f
point
,
const
Mat
&
tpsParameters
)
{
Point2f
out
;
for
(
int
i
=
0
;
i
<
2
;
i
++
)
{
float
a1
=
tpsParameters
.
at
<
float
>
(
tpsParameters
.
rows
-
3
,
i
);
float
ax
=
tpsParameters
.
at
<
float
>
(
tpsParameters
.
rows
-
2
,
i
);
float
ay
=
tpsParameters
.
at
<
float
>
(
tpsParameters
.
rows
-
1
,
i
);
float
affine
=
a1
+
ax
*
point
.
x
+
ay
*
point
.
y
;
float
nonrigid
=
0
;
for
(
int
j
=
0
;
j
<
shapeRef
.
rows
;
j
++
)
{
nonrigid
+=
tpsParameters
.
at
<
float
>
(
j
,
i
)
*
distance
(
Point2f
(
shapeRef
.
at
<
float
>
(
j
,
0
),
shapeRef
.
at
<
float
>
(
j
,
1
)),
point
);
}
if
(
i
==
0
)
{
out
.
x
=
affine
+
nonrigid
;
}
if
(
i
==
1
)
{
out
.
y
=
affine
+
nonrigid
;
}
}
return
out
;
}
/* public methods */
void
ThinPlateSplineShapeTransformerImpl
::
warpImage
(
InputArray
transformingImage
,
OutputArray
output
,
int
flags
,
int
borderMode
,
const
Scalar
&
borderValue
)
const
{
CV_INSTRUMENT_REGION
();
CV_Assert
(
tpsComputed
==
true
);
Mat
theinput
=
transformingImage
.
getMat
();
Mat
mapX
(
theinput
.
rows
,
theinput
.
cols
,
CV_32FC1
);
Mat
mapY
(
theinput
.
rows
,
theinput
.
cols
,
CV_32FC1
);
for
(
int
row
=
0
;
row
<
theinput
.
rows
;
row
++
)
{
for
(
int
col
=
0
;
col
<
theinput
.
cols
;
col
++
)
{
Point2f
pt
=
_applyTransformation
(
shapeReference
,
Point2f
(
float
(
col
),
float
(
row
)),
tpsParameters
);
mapX
.
at
<
float
>
(
row
,
col
)
=
pt
.
x
;
mapY
.
at
<
float
>
(
row
,
col
)
=
pt
.
y
;
}
}
remap
(
transformingImage
,
output
,
mapX
,
mapY
,
flags
,
borderMode
,
borderValue
);
}
float
ThinPlateSplineShapeTransformerImpl
::
applyTransformation
(
InputArray
inPts
,
OutputArray
outPts
)
{
CV_INSTRUMENT_REGION
();
CV_Assert
(
tpsComputed
);
Mat
pts1
=
inPts
.
getMat
();
CV_Assert
((
pts1
.
channels
()
==
2
)
&&
(
pts1
.
cols
>
0
));
//Apply transformation in the complete set of points
// Ensambling output //
if
(
outPts
.
needed
())
{
outPts
.
create
(
1
,
pts1
.
cols
,
CV_32FC2
);
Mat
outMat
=
outPts
.
getMat
();
for
(
int
i
=
0
;
i
<
pts1
.
cols
;
i
++
)
{
Point2f
pt
=
pts1
.
at
<
Point2f
>
(
0
,
i
);
outMat
.
at
<
Point2f
>
(
0
,
i
)
=
_applyTransformation
(
shapeReference
,
pt
,
tpsParameters
);
}
}
return
transformCost
;
}
void
ThinPlateSplineShapeTransformerImpl
::
estimateTransformation
(
InputArray
_pts1
,
InputArray
_pts2
,
std
::
vector
<
DMatch
>&
_matches
)
{
CV_INSTRUMENT_REGION
();
Mat
pts1
=
_pts1
.
getMat
();
Mat
pts2
=
_pts2
.
getMat
();
CV_Assert
((
pts1
.
channels
()
==
2
)
&&
(
pts1
.
cols
>
0
)
&&
(
pts2
.
channels
()
==
2
)
&&
(
pts2
.
cols
>
0
));
CV_Assert
(
_matches
.
size
()
>
1
);
if
(
pts1
.
type
()
!=
CV_32F
)
pts1
.
convertTo
(
pts1
,
CV_32F
);
if
(
pts2
.
type
()
!=
CV_32F
)
pts2
.
convertTo
(
pts2
,
CV_32F
);
// Use only valid matchings //
std
::
vector
<
DMatch
>
matches
;
for
(
size_t
i
=
0
;
i
<
_matches
.
size
();
i
++
)
{
if
(
_matches
[
i
].
queryIdx
<
pts1
.
cols
&&
_matches
[
i
].
trainIdx
<
pts2
.
cols
)
{
matches
.
push_back
(
_matches
[
i
]);
}
}
// Organizing the correspondent points in matrix style //
Mat
shape1
((
int
)
matches
.
size
(),
2
,
CV_32F
);
// transforming shape
Mat
shape2
((
int
)
matches
.
size
(),
2
,
CV_32F
);
// target shape
for
(
int
i
=
0
,
end
=
(
int
)
matches
.
size
();
i
<
end
;
i
++
)
{
Point2f
pt1
=
pts1
.
at
<
Point2f
>
(
0
,
matches
[
i
].
queryIdx
);
shape1
.
at
<
float
>
(
i
,
0
)
=
pt1
.
x
;
shape1
.
at
<
float
>
(
i
,
1
)
=
pt1
.
y
;
Point2f
pt2
=
pts2
.
at
<
Point2f
>
(
0
,
matches
[
i
].
trainIdx
);
shape2
.
at
<
float
>
(
i
,
0
)
=
pt2
.
x
;
shape2
.
at
<
float
>
(
i
,
1
)
=
pt2
.
y
;
}
shape1
.
copyTo
(
shapeReference
);
// Building the matrices for solving the L*(w|a)=(v|0) problem with L={[K|P];[P'|0]}
//Building K and P (Needed to build L)
Mat
matK
((
int
)
matches
.
size
(),(
int
)
matches
.
size
(),
CV_32F
);
Mat
matP
((
int
)
matches
.
size
(),
3
,
CV_32F
);
for
(
int
i
=
0
,
end
=
(
int
)
matches
.
size
();
i
<
end
;
i
++
)
{
for
(
int
j
=
0
;
j
<
end
;
j
++
)
{
if
(
i
==
j
)
{
matK
.
at
<
float
>
(
i
,
j
)
=
float
(
regularizationParameter
);
}
else
{
matK
.
at
<
float
>
(
i
,
j
)
=
distance
(
Point2f
(
shape1
.
at
<
float
>
(
i
,
0
),
shape1
.
at
<
float
>
(
i
,
1
)),
Point2f
(
shape1
.
at
<
float
>
(
j
,
0
),
shape1
.
at
<
float
>
(
j
,
1
)));
}
}
matP
.
at
<
float
>
(
i
,
0
)
=
1
;
matP
.
at
<
float
>
(
i
,
1
)
=
shape1
.
at
<
float
>
(
i
,
0
);
matP
.
at
<
float
>
(
i
,
2
)
=
shape1
.
at
<
float
>
(
i
,
1
);
}
//Building L
Mat
matL
=
Mat
::
zeros
((
int
)
matches
.
size
()
+
3
,(
int
)
matches
.
size
()
+
3
,
CV_32F
);
Mat
matLroi
(
matL
,
Rect
(
0
,
0
,(
int
)
matches
.
size
(),(
int
)
matches
.
size
()));
//roi for K
matK
.
copyTo
(
matLroi
);
matLroi
=
Mat
(
matL
,
Rect
((
int
)
matches
.
size
(),
0
,
3
,(
int
)
matches
.
size
()));
//roi for P
matP
.
copyTo
(
matLroi
);
Mat
matPt
;
transpose
(
matP
,
matPt
);
matLroi
=
Mat
(
matL
,
Rect
(
0
,(
int
)
matches
.
size
(),(
int
)
matches
.
size
(),
3
));
//roi for P'
matPt
.
copyTo
(
matLroi
);
//Building B (v|0)
Mat
matB
=
Mat
::
zeros
((
int
)
matches
.
size
()
+
3
,
2
,
CV_32F
);
for
(
int
i
=
0
,
end
=
(
int
)
matches
.
size
();
i
<
end
;
i
++
)
{
matB
.
at
<
float
>
(
i
,
0
)
=
shape2
.
at
<
float
>
(
i
,
0
);
//x's
matB
.
at
<
float
>
(
i
,
1
)
=
shape2
.
at
<
float
>
(
i
,
1
);
//y's
}
//Obtaining transformation params (w|a)
solve
(
matL
,
matB
,
tpsParameters
,
DECOMP_LU
);
//tpsParameters = matL.inv()*matB;
//Setting transform Cost and Shape reference
Mat
w
(
tpsParameters
,
Rect
(
0
,
0
,
2
,
tpsParameters
.
rows
-
3
));
Mat
Q
=
w
.
t
()
*
matK
*
w
;
transformCost
=
fabs
(
Q
.
at
<
float
>
(
0
,
0
)
*
Q
.
at
<
float
>
(
1
,
1
));
//fabs(mean(Q.diag(0))[0]);//std::max(Q.at<float>(0,0),Q.at<float>(1,1));
tpsComputed
=
true
;
}
Ptr
<
ThinPlateSplineShapeTransformer
>
createThinPlateSplineShapeTransformer
(
double
regularizationParameter
)
{
return
Ptr
<
ThinPlateSplineShapeTransformer
>
(
new
ThinPlateSplineShapeTransformerImpl
(
regularizationParameter
)
);
}
}
// cv
modules/shape/test/test_main.cpp
deleted
100644 → 0
View file @
687fa6a8
// 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"
#if defined(HAVE_HPX)
#include <hpx/hpx_main.hpp>
#endif
CV_TEST_MAIN
(
"cv"
)
modules/shape/test/test_precomp.hpp
deleted
100644 → 0
View file @
687fa6a8
// 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.
#ifndef __OPENCV_TEST_PRECOMP_HPP__
#define __OPENCV_TEST_PRECOMP_HPP__
#include "opencv2/ts.hpp"
#include "opencv2/shape.hpp"
#endif
modules/shape/test/test_shape.cpp
deleted
100644 → 0
View file @
687fa6a8
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "test_precomp.hpp"
namespace
opencv_test
{
namespace
{
template
<
typename
T
,
typename
compute
>
class
ShapeBaseTest
:
public
cvtest
::
BaseTest
{
public
:
typedef
Point_
<
T
>
PointType
;
ShapeBaseTest
(
int
_NSN
,
int
_NP
,
float
_CURRENT_MAX_ACCUR
)
:
NSN
(
_NSN
),
NP
(
_NP
),
CURRENT_MAX_ACCUR
(
_CURRENT_MAX_ACCUR
)
{
// generate file list
vector
<
string
>
shapeNames
;
shapeNames
.
push_back
(
"apple"
);
//ok
shapeNames
.
push_back
(
"children"
);
// ok
shapeNames
.
push_back
(
"device7"
);
// ok
shapeNames
.
push_back
(
"Heart"
);
// ok
shapeNames
.
push_back
(
"teddy"
);
// ok
for
(
vector
<
string
>::
const_iterator
i
=
shapeNames
.
begin
();
i
!=
shapeNames
.
end
();
++
i
)
{
for
(
int
j
=
0
;
j
<
NSN
;
++
j
)
{
std
::
stringstream
filename
;
filename
<<
cvtest
::
TS
::
ptr
()
->
get_data_path
()
<<
"shape/mpeg_test/"
<<
*
i
<<
"-"
<<
j
+
1
<<
".png"
;
filenames
.
push_back
(
filename
.
str
());
}
}
// distance matrix
const
int
totalCount
=
(
int
)
filenames
.
size
();
distanceMat
=
Mat
::
zeros
(
totalCount
,
totalCount
,
CV_32F
);
}
protected
:
void
run
(
int
)
{
mpegTest
();
displayMPEGResults
();
}
vector
<
PointType
>
convertContourType
(
const
Mat
&
currentQuery
)
const
{
if
(
currentQuery
.
empty
())
{
return
vector
<
PointType
>
();
}
vector
<
vector
<
Point
>
>
_contoursQuery
;
findContours
(
currentQuery
,
_contoursQuery
,
RETR_LIST
,
CHAIN_APPROX_NONE
);
vector
<
PointType
>
contoursQuery
;
for
(
size_t
border
=
0
;
border
<
_contoursQuery
.
size
();
border
++
)
{
for
(
size_t
p
=
0
;
p
<
_contoursQuery
[
border
].
size
();
p
++
)
{
contoursQuery
.
push_back
(
PointType
((
T
)
_contoursQuery
[
border
][
p
].
x
,
(
T
)
_contoursQuery
[
border
][
p
].
y
));
}
}
// In case actual number of points is less than n
for
(
int
add
=
(
int
)
contoursQuery
.
size
()
-
1
;
add
<
NP
;
add
++
)
{
contoursQuery
.
push_back
(
contoursQuery
[
contoursQuery
.
size
()
-
add
+
1
]);
//adding dummy values
}
// Uniformly sampling
cv
::
randShuffle
(
contoursQuery
);
int
nStart
=
NP
;
vector
<
PointType
>
cont
;
for
(
int
i
=
0
;
i
<
nStart
;
i
++
)
{
cont
.
push_back
(
contoursQuery
[
i
]);
}
return
cont
;
}
void
mpegTest
()
{
// query contours (normal v flipped, h flipped) and testing contour
vector
<
PointType
>
contoursQuery1
,
contoursQuery2
,
contoursQuery3
,
contoursTesting
;
// reading query and computing its properties
for
(
vector
<
string
>::
const_iterator
a
=
filenames
.
begin
();
a
!=
filenames
.
end
();
++
a
)
{
// read current image
int
aIndex
=
(
int
)(
a
-
filenames
.
begin
());
Mat
currentQuery
=
imread
(
*
a
,
IMREAD_GRAYSCALE
);
Mat
flippedHQuery
,
flippedVQuery
;
flip
(
currentQuery
,
flippedHQuery
,
0
);
flip
(
currentQuery
,
flippedVQuery
,
1
);
// compute border of the query and its flipped versions
contoursQuery1
=
convertContourType
(
currentQuery
);
contoursQuery2
=
convertContourType
(
flippedHQuery
);
contoursQuery3
=
convertContourType
(
flippedVQuery
);
// compare with all the rest of the images: testing
for
(
vector
<
string
>::
const_iterator
b
=
filenames
.
begin
();
b
!=
filenames
.
end
();
++
b
)
{
int
bIndex
=
(
int
)(
b
-
filenames
.
begin
());
float
distance
=
0
;
// skip self-comparisson
if
(
a
!=
b
)
{
// read testing image
Mat
currentTest
=
imread
(
*
b
,
IMREAD_GRAYSCALE
);
// compute border of the testing
contoursTesting
=
convertContourType
(
currentTest
);
// compute shape distance
distance
=
cmp
(
contoursQuery1
,
contoursQuery2
,
contoursQuery3
,
contoursTesting
);
}
distanceMat
.
at
<
float
>
(
aIndex
,
bIndex
)
=
distance
;
}
}
}
void
displayMPEGResults
()
{
const
int
FIRST_MANY
=
2
*
NSN
;
int
corrects
=
0
;
int
divi
=
0
;
for
(
int
row
=
0
;
row
<
distanceMat
.
rows
;
row
++
)
{
if
(
row
%
NSN
==
0
)
//another group
{
divi
+=
NSN
;
}
for
(
int
col
=
divi
-
NSN
;
col
<
divi
;
col
++
)
{
int
nsmall
=
0
;
for
(
int
i
=
0
;
i
<
distanceMat
.
cols
;
i
++
)
{
if
(
distanceMat
.
at
<
float
>
(
row
,
col
)
>
distanceMat
.
at
<
float
>
(
row
,
i
))
{
nsmall
++
;
}
}
if
(
nsmall
<=
FIRST_MANY
)
{
corrects
++
;
}
}
}
float
porc
=
100
*
float
(
corrects
)
/
(
NSN
*
distanceMat
.
rows
);
std
::
cout
<<
"Test result: "
<<
porc
<<
"%"
<<
std
::
endl
;
if
(
porc
>=
CURRENT_MAX_ACCUR
)
ts
->
set_failed_test_info
(
cvtest
::
TS
::
OK
);
else
ts
->
set_failed_test_info
(
cvtest
::
TS
::
FAIL_BAD_ACCURACY
);
}
protected
:
int
NSN
;
int
NP
;
float
CURRENT_MAX_ACCUR
;
vector
<
string
>
filenames
;
Mat
distanceMat
;
compute
cmp
;
};
//------------------------------------------------------------------------
// Test Shape_SCD.regression
//------------------------------------------------------------------------
class
computeShapeDistance_Chi
{
Ptr
<
ShapeContextDistanceExtractor
>
mysc
;
public
:
computeShapeDistance_Chi
()
{
const
int
angularBins
=
12
;
const
int
radialBins
=
4
;
const
float
minRad
=
0.2
f
;
const
float
maxRad
=
2
;
mysc
=
createShapeContextDistanceExtractor
(
angularBins
,
radialBins
,
minRad
,
maxRad
);
mysc
->
setIterations
(
1
);
mysc
->
setCostExtractor
(
createChiHistogramCostExtractor
(
30
,
0.15
f
));
mysc
->
setTransformAlgorithm
(
createThinPlateSplineShapeTransformer
()
);
}
float
operator
()(
vector
<
Point2f
>&
query1
,
vector
<
Point2f
>&
query2
,
vector
<
Point2f
>&
query3
,
vector
<
Point2f
>&
testq
)
{
return
std
::
min
(
mysc
->
computeDistance
(
query1
,
testq
),
std
::
min
(
mysc
->
computeDistance
(
query2
,
testq
),
mysc
->
computeDistance
(
query3
,
testq
)));
}
};
TEST
(
Shape_SCD
,
regression
)
{
const
int
NSN_val
=
5
;
//10;//20; //number of shapes per class
const
int
NP_val
=
120
;
//number of points simplifying the contour
const
float
CURRENT_MAX_ACCUR_val
=
95
;
//99% and 100% reached in several tests, 95 is fixed as minimum boundary
ShapeBaseTest
<
float
,
computeShapeDistance_Chi
>
test
(
NSN_val
,
NP_val
,
CURRENT_MAX_ACCUR_val
);
test
.
safe_run
();
}
//------------------------------------------------------------------------
// Test ShapeEMD_SCD.regression
//------------------------------------------------------------------------
class
computeShapeDistance_EMD
{
Ptr
<
ShapeContextDistanceExtractor
>
mysc
;
public
:
computeShapeDistance_EMD
()
{
const
int
angularBins
=
12
;
const
int
radialBins
=
4
;
const
float
minRad
=
0.2
f
;
const
float
maxRad
=
2
;
mysc
=
createShapeContextDistanceExtractor
(
angularBins
,
radialBins
,
minRad
,
maxRad
);
mysc
->
setIterations
(
1
);
mysc
->
setCostExtractor
(
createEMDL1HistogramCostExtractor
()
);
mysc
->
setTransformAlgorithm
(
createThinPlateSplineShapeTransformer
()
);
}
float
operator
()(
vector
<
Point2f
>&
query1
,
vector
<
Point2f
>&
query2
,
vector
<
Point2f
>&
query3
,
vector
<
Point2f
>&
testq
)
{
return
std
::
min
(
mysc
->
computeDistance
(
query1
,
testq
),
std
::
min
(
mysc
->
computeDistance
(
query2
,
testq
),
mysc
->
computeDistance
(
query3
,
testq
)));
}
};
TEST
(
ShapeEMD_SCD
,
regression
)
{
const
int
NSN_val
=
5
;
//10;//20; //number of shapes per class
const
int
NP_val
=
100
;
//number of points simplifying the contour
const
float
CURRENT_MAX_ACCUR_val
=
95
;
//98% and 99% reached in several tests, 95 is fixed as minimum boundary
ShapeBaseTest
<
float
,
computeShapeDistance_EMD
>
test
(
NSN_val
,
NP_val
,
CURRENT_MAX_ACCUR_val
);
test
.
safe_run
();
}
//------------------------------------------------------------------------
// Test Hauss.regression
//------------------------------------------------------------------------
class
computeShapeDistance_Haussdorf
{
Ptr
<
HausdorffDistanceExtractor
>
haus
;
public
:
computeShapeDistance_Haussdorf
()
{
haus
=
createHausdorffDistanceExtractor
();
}
float
operator
()(
vector
<
Point
>
&
query1
,
vector
<
Point
>
&
query2
,
vector
<
Point
>
&
query3
,
vector
<
Point
>
&
testq
)
{
return
std
::
min
(
haus
->
computeDistance
(
query1
,
testq
),
std
::
min
(
haus
->
computeDistance
(
query2
,
testq
),
haus
->
computeDistance
(
query3
,
testq
)));
}
};
TEST
(
Hauss
,
regression
)
{
const
int
NSN_val
=
5
;
//10;//20; //number of shapes per class
const
int
NP_val
=
180
;
//number of points simplifying the contour
const
float
CURRENT_MAX_ACCUR_val
=
85
;
//90% and 91% reached in several tests, 85 is fixed as minimum boundary
ShapeBaseTest
<
int
,
computeShapeDistance_Haussdorf
>
test
(
NSN_val
,
NP_val
,
CURRENT_MAX_ACCUR_val
);
test
.
safe_run
();
}
TEST
(
computeDistance
,
regression_4976
)
{
Mat
a
=
imread
(
cvtest
::
findDataFile
(
"shape/samples/1.png"
),
0
);
Mat
b
=
imread
(
cvtest
::
findDataFile
(
"shape/samples/2.png"
),
0
);
vector
<
vector
<
Point
>
>
ca
,
cb
;
findContours
(
a
,
ca
,
cv
::
RETR_CCOMP
,
cv
::
CHAIN_APPROX_TC89_KCOS
);
findContours
(
b
,
cb
,
cv
::
RETR_CCOMP
,
cv
::
CHAIN_APPROX_TC89_KCOS
);
Ptr
<
HausdorffDistanceExtractor
>
hd
=
createHausdorffDistanceExtractor
();
Ptr
<
ShapeContextDistanceExtractor
>
sd
=
createShapeContextDistanceExtractor
();
double
d1
=
hd
->
computeDistance
(
ca
[
0
],
cb
[
0
]);
double
d2
=
sd
->
computeDistance
(
ca
[
0
],
cb
[
0
]);
EXPECT_NEAR
(
d1
,
26.4196891785
,
1e-3
)
<<
"HausdorffDistanceExtractor"
;
EXPECT_NEAR
(
d2
,
0.25804194808
,
1e-3
)
<<
"ShapeContextDistanceExtractor"
;
}
}}
// 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