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
6569a585
Commit
6569a585
authored
Mar 05, 2013
by
Andrey Kamaev
Committed by
OpenCV Buildbot
Mar 05, 2013
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #592 from vpisarev:c2cpp_calib3d_ptsetreg
parents
816adcfd
f303de12
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1877 additions
and
1649 deletions
+1877
-1649
calib3d_init.cpp
modules/calib3d/src/calib3d_init.cpp
+20
-36
calibration.cpp
modules/calib3d/src/calibration.cpp
+0
-241
circlesgrid.cpp
modules/calib3d/src/circlesgrid.cpp
+8
-6
compat_ptsetreg.cpp
modules/calib3d/src/compat_ptsetreg.cpp
+430
-0
five-point.cpp
modules/calib3d/src/five-point.cpp
+0
-0
fundam.cpp
modules/calib3d/src/fundam.cpp
+598
-863
levmarq.cpp
modules/calib3d/src/levmarq.cpp
+226
-0
modelest.cpp
modules/calib3d/src/modelest.cpp
+0
-502
precomp.hpp
modules/calib3d/src/precomp.hpp
+47
-0
ptsetreg.cpp
modules/calib3d/src/ptsetreg.cpp
+540
-0
test_affine3d_estimator.cpp
modules/calib3d/test/test_affine3d_estimator.cpp
+2
-0
test_fundam.cpp
modules/calib3d/test/test_fundam.cpp
+1
-1
test_modelest.cpp
modules/calib3d/test/test_modelest.cpp
+5
-0
No files found.
modules/calib3d/src/
_modelest.h
→
modules/calib3d/src/
calib3d_init.cpp
View file @
6569a585
...
@@ -7,10 +7,11 @@
...
@@ -7,10 +7,11 @@
// copy or use the software.
// copy or use the software.
//
//
//
//
//
Intel
License Agreement
//
License Agreement
// For Open Source Computer Vision Library
// For Open Source Computer Vision Library
//
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// 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.
// Third party copyrights are property of their respective owners.
//
//
// Redistribution and use in source and binary forms, with or without modification,
// Redistribution and use in source and binary forms, with or without modification,
...
@@ -23,7 +24,7 @@
...
@@ -23,7 +24,7 @@
// this list of conditions and the following disclaimer in the documentation
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// and/or other materials provided with the distribution.
//
//
// * The name of
Intel Corporation
may not be used to endorse or promote products
// * The name of
the copyright holders
may not be used to endorse or promote products
// derived from this software without specific prior written permission.
// derived from this software without specific prior written permission.
//
//
// This software is provided by the copyright holders and contributors "as is" and
// This software is provided by the copyright holders and contributors "as is" and
...
@@ -39,44 +40,27 @@
...
@@ -39,44 +40,27 @@
//
//
//M*/
//M*/
#include "precomp.hpp"
#ifndef _CV_MODEL_EST_H_
using
namespace
cv
;
#define _CV_MODEL_EST_H_
#include "opencv2/calib3d/calib3d.hpp"
//////////////////////////////////////////////////////////////////////////////////////////////////////////
class
CV_EXPORTS
CvModelEstimator2
{
public
:
CvModelEstimator2
(
int
_modelPoints
,
CvSize
_modelSize
,
int
_maxBasicSolutions
);
virtual
~
CvModelEstimator2
();
virtual
int
runKernel
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
model
)
=
0
;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual
bool
runLMeDS
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
model
,
CvMat
*
mask
,
double
confidence
=
0
.
99
,
int
maxIters
=
2000
);
virtual
bool
runRANSAC
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
model
,
CvMat
*
mask
,
double
threshold
,
double
confidence
=
0
.
99
,
int
maxIters
=
2000
);
virtual
bool
refine
(
const
CvMat
*
,
const
CvMat
*
,
CvMat
*
,
int
)
{
return
true
;
}
virtual
void
setSeed
(
int64
seed
);
protected
:
virtual
void
computeReprojError
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
const
CvMat
*
model
,
CvMat
*
error
)
=
0
;
virtual
int
findInliers
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
const
CvMat
*
model
,
CvMat
*
error
,
CvMat
*
mask
,
double
threshold
);
virtual
bool
getSubset
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
ms1
,
CvMat
*
ms2
,
int
maxAttempts
=
1000
);
virtual
bool
checkSubset
(
const
CvMat
*
ms1
,
int
count
);
virtual
bool
isMinimalSetConsistent
(
const
CvMat
*
/*m1*/
,
const
CvMat
*
/*m2*/
)
{
return
true
;
};
CvRNG
rng
;
///////////////////////////////////////////////////////////////////////////////////////////////////////////
int
modelPoints
;
CvSize
modelSize
;
int
maxBasicSolutions
;
bool
checkPartialSubsets
;
};
#endif // _CV_MODEL_EST_H_
#if 0
bool cv::initModule_calib3d(void)
{
bool all = true;
all &= !RANSACPointSetRegistrator_info_auto.name().empty();
all &= !LMeDSPointSetRegistrator_info_auto.name().empty();
all &= !LMSolverImpl_info_auto.name().empty();
return all;
}
#endif
modules/calib3d/src/calibration.cpp
View file @
6569a585
...
@@ -55,247 +55,6 @@
...
@@ -55,247 +55,6 @@
using
namespace
cv
;
using
namespace
cv
;
CvLevMarq
::
CvLevMarq
()
{
mask
=
prevParam
=
param
=
J
=
err
=
JtJ
=
JtJN
=
JtErr
=
JtJV
=
JtJW
=
Ptr
<
CvMat
>
();
lambdaLg10
=
0
;
state
=
DONE
;
criteria
=
cvTermCriteria
(
0
,
0
,
0
);
iters
=
0
;
completeSymmFlag
=
false
;
}
CvLevMarq
::
CvLevMarq
(
int
nparams
,
int
nerrs
,
CvTermCriteria
criteria0
,
bool
_completeSymmFlag
)
{
mask
=
prevParam
=
param
=
J
=
err
=
JtJ
=
JtJN
=
JtErr
=
JtJV
=
JtJW
=
Ptr
<
CvMat
>
();
init
(
nparams
,
nerrs
,
criteria0
,
_completeSymmFlag
);
}
void
CvLevMarq
::
clear
()
{
mask
.
release
();
prevParam
.
release
();
param
.
release
();
J
.
release
();
err
.
release
();
JtJ
.
release
();
JtJN
.
release
();
JtErr
.
release
();
JtJV
.
release
();
JtJW
.
release
();
}
CvLevMarq
::~
CvLevMarq
()
{
clear
();
}
void
CvLevMarq
::
init
(
int
nparams
,
int
nerrs
,
CvTermCriteria
criteria0
,
bool
_completeSymmFlag
)
{
if
(
!
param
||
param
->
rows
!=
nparams
||
nerrs
!=
(
err
?
err
->
rows
:
0
)
)
clear
();
mask
=
cvCreateMat
(
nparams
,
1
,
CV_8U
);
cvSet
(
mask
,
cvScalarAll
(
1
));
prevParam
=
cvCreateMat
(
nparams
,
1
,
CV_64F
);
param
=
cvCreateMat
(
nparams
,
1
,
CV_64F
);
JtJ
=
cvCreateMat
(
nparams
,
nparams
,
CV_64F
);
JtJN
=
cvCreateMat
(
nparams
,
nparams
,
CV_64F
);
JtJV
=
cvCreateMat
(
nparams
,
nparams
,
CV_64F
);
JtJW
=
cvCreateMat
(
nparams
,
1
,
CV_64F
);
JtErr
=
cvCreateMat
(
nparams
,
1
,
CV_64F
);
if
(
nerrs
>
0
)
{
J
=
cvCreateMat
(
nerrs
,
nparams
,
CV_64F
);
err
=
cvCreateMat
(
nerrs
,
1
,
CV_64F
);
}
prevErrNorm
=
DBL_MAX
;
lambdaLg10
=
-
3
;
criteria
=
criteria0
;
if
(
criteria
.
type
&
CV_TERMCRIT_ITER
)
criteria
.
max_iter
=
MIN
(
MAX
(
criteria
.
max_iter
,
1
),
1000
);
else
criteria
.
max_iter
=
30
;
if
(
criteria
.
type
&
CV_TERMCRIT_EPS
)
criteria
.
epsilon
=
MAX
(
criteria
.
epsilon
,
0
);
else
criteria
.
epsilon
=
DBL_EPSILON
;
state
=
STARTED
;
iters
=
0
;
completeSymmFlag
=
_completeSymmFlag
;
}
bool
CvLevMarq
::
update
(
const
CvMat
*&
_param
,
CvMat
*&
matJ
,
CvMat
*&
_err
)
{
double
change
;
matJ
=
_err
=
0
;
assert
(
!
err
.
empty
()
);
if
(
state
==
DONE
)
{
_param
=
param
;
return
false
;
}
if
(
state
==
STARTED
)
{
_param
=
param
;
cvZero
(
J
);
cvZero
(
err
);
matJ
=
J
;
_err
=
err
;
state
=
CALC_J
;
return
true
;
}
if
(
state
==
CALC_J
)
{
cvMulTransposed
(
J
,
JtJ
,
1
);
cvGEMM
(
J
,
err
,
1
,
0
,
0
,
JtErr
,
CV_GEMM_A_T
);
cvCopy
(
param
,
prevParam
);
step
();
if
(
iters
==
0
)
prevErrNorm
=
cvNorm
(
err
,
0
,
CV_L2
);
_param
=
param
;
cvZero
(
err
);
_err
=
err
;
state
=
CHECK_ERR
;
return
true
;
}
assert
(
state
==
CHECK_ERR
);
errNorm
=
cvNorm
(
err
,
0
,
CV_L2
);
if
(
errNorm
>
prevErrNorm
)
{
if
(
++
lambdaLg10
<=
16
)
{
step
();
_param
=
param
;
cvZero
(
err
);
_err
=
err
;
state
=
CHECK_ERR
;
return
true
;
}
}
lambdaLg10
=
MAX
(
lambdaLg10
-
1
,
-
16
);
if
(
++
iters
>=
criteria
.
max_iter
||
(
change
=
cvNorm
(
param
,
prevParam
,
CV_RELATIVE_L2
))
<
criteria
.
epsilon
)
{
_param
=
param
;
state
=
DONE
;
return
true
;
}
prevErrNorm
=
errNorm
;
_param
=
param
;
cvZero
(
J
);
matJ
=
J
;
_err
=
err
;
state
=
CALC_J
;
return
true
;
}
bool
CvLevMarq
::
updateAlt
(
const
CvMat
*&
_param
,
CvMat
*&
_JtJ
,
CvMat
*&
_JtErr
,
double
*&
_errNorm
)
{
double
change
;
CV_Assert
(
err
.
empty
()
);
if
(
state
==
DONE
)
{
_param
=
param
;
return
false
;
}
if
(
state
==
STARTED
)
{
_param
=
param
;
cvZero
(
JtJ
);
cvZero
(
JtErr
);
errNorm
=
0
;
_JtJ
=
JtJ
;
_JtErr
=
JtErr
;
_errNorm
=
&
errNorm
;
state
=
CALC_J
;
return
true
;
}
if
(
state
==
CALC_J
)
{
cvCopy
(
param
,
prevParam
);
step
();
_param
=
param
;
prevErrNorm
=
errNorm
;
errNorm
=
0
;
_errNorm
=
&
errNorm
;
state
=
CHECK_ERR
;
return
true
;
}
assert
(
state
==
CHECK_ERR
);
if
(
errNorm
>
prevErrNorm
)
{
if
(
++
lambdaLg10
<=
16
)
{
step
();
_param
=
param
;
errNorm
=
0
;
_errNorm
=
&
errNorm
;
state
=
CHECK_ERR
;
return
true
;
}
}
lambdaLg10
=
MAX
(
lambdaLg10
-
1
,
-
16
);
if
(
++
iters
>=
criteria
.
max_iter
||
(
change
=
cvNorm
(
param
,
prevParam
,
CV_RELATIVE_L2
))
<
criteria
.
epsilon
)
{
_param
=
param
;
state
=
DONE
;
return
false
;
}
prevErrNorm
=
errNorm
;
cvZero
(
JtJ
);
cvZero
(
JtErr
);
_param
=
param
;
_JtJ
=
JtJ
;
_JtErr
=
JtErr
;
state
=
CALC_J
;
return
true
;
}
void
CvLevMarq
::
step
()
{
const
double
LOG10
=
log
(
10.
);
double
lambda
=
exp
(
lambdaLg10
*
LOG10
);
int
i
,
j
,
nparams
=
param
->
rows
;
for
(
i
=
0
;
i
<
nparams
;
i
++
)
if
(
mask
->
data
.
ptr
[
i
]
==
0
)
{
double
*
row
=
JtJ
->
data
.
db
+
i
*
nparams
,
*
col
=
JtJ
->
data
.
db
+
i
;
for
(
j
=
0
;
j
<
nparams
;
j
++
)
row
[
j
]
=
col
[
j
*
nparams
]
=
0
;
JtErr
->
data
.
db
[
i
]
=
0
;
}
if
(
!
err
)
cvCompleteSymm
(
JtJ
,
completeSymmFlag
);
#if 1
cvCopy
(
JtJ
,
JtJN
);
for
(
i
=
0
;
i
<
nparams
;
i
++
)
JtJN
->
data
.
db
[(
nparams
+
1
)
*
i
]
*=
1.
+
lambda
;
#else
cvSetIdentity
(
JtJN
,
cvRealScalar
(
lambda
));
cvAdd
(
JtJ
,
JtJN
,
JtJN
);
#endif
cvSVD
(
JtJN
,
JtJW
,
0
,
JtJV
,
CV_SVD_MODIFY_A
+
CV_SVD_U_T
+
CV_SVD_V_T
);
cvSVBkSb
(
JtJW
,
JtJV
,
JtJV
,
JtErr
,
param
,
CV_SVD_U_T
+
CV_SVD_V_T
);
for
(
i
=
0
;
i
<
nparams
;
i
++
)
param
->
data
.
db
[
i
]
=
prevParam
->
data
.
db
[
i
]
-
(
mask
->
data
.
ptr
[
i
]
?
param
->
data
.
db
[
i
]
:
0
);
}
// reimplementation of dAB.m
// reimplementation of dAB.m
CV_IMPL
void
cvCalcMatMulDeriv
(
const
CvMat
*
A
,
const
CvMat
*
B
,
CvMat
*
dABdA
,
CvMat
*
dABdB
)
CV_IMPL
void
cvCalcMatMulDeriv
(
const
CvMat
*
A
,
const
CvMat
*
B
,
CvMat
*
dABdA
,
CvMat
*
dABdB
)
{
{
...
...
modules/calib3d/src/circlesgrid.cpp
View file @
6569a585
...
@@ -402,14 +402,16 @@ void CirclesGridClusterFinder::parsePatternPoints(const std::vector<cv::Point2f>
...
@@ -402,14 +402,16 @@ void CirclesGridClusterFinder::parsePatternPoints(const std::vector<cv::Point2f>
else
else
idealPt
=
Point2f
(
j
*
squareSize
,
i
*
squareSize
);
idealPt
=
Point2f
(
j
*
squareSize
,
i
*
squareSize
);
std
::
vector
<
float
>
query
=
Mat
(
idealPt
);
Mat
query
(
1
,
2
,
CV_32F
,
&
idealPt
);
int
knn
=
1
;
const
int
knn
=
1
;
std
::
vector
<
int
>
indices
(
knn
);
int
indicesbuf
[
knn
]
=
{
0
};
std
::
vector
<
float
>
dists
(
knn
);
float
distsbuf
[
knn
]
=
{
0.
f
};
Mat
indices
(
1
,
knn
,
CV_32S
,
&
indicesbuf
);
Mat
dists
(
1
,
knn
,
CV_32F
,
&
distsbuf
);
flannIndex
.
knnSearch
(
query
,
indices
,
dists
,
knn
,
flann
::
SearchParams
());
flannIndex
.
knnSearch
(
query
,
indices
,
dists
,
knn
,
flann
::
SearchParams
());
centers
.
push_back
(
patternPoints
.
at
(
indices
[
0
]));
centers
.
push_back
(
patternPoints
.
at
(
indices
buf
[
0
]));
if
(
dists
[
0
]
>
maxRectifiedDistance
)
if
(
dists
buf
[
0
]
>
maxRectifiedDistance
)
{
{
#ifdef DEBUG_CIRCLES
#ifdef DEBUG_CIRCLES
cout
<<
"Pattern not detected: too large rectified distance"
<<
endl
;
cout
<<
"Pattern not detected: too large rectified distance"
<<
endl
;
...
...
modules/calib3d/src/compat_ptsetreg.cpp
0 → 100644
View file @
6569a585
/*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, Intel Corporation, 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*/
#include "precomp.hpp"
/************************************************************************************\
Some backward compatibility stuff, to be moved to legacy or compat module
\************************************************************************************/
using
cv
::
Ptr
;
////////////////// Levenberg-Marquardt engine (the old variant) ////////////////////////
CvLevMarq
::
CvLevMarq
()
{
mask
=
prevParam
=
param
=
J
=
err
=
JtJ
=
JtJN
=
JtErr
=
JtJV
=
JtJW
=
Ptr
<
CvMat
>
();
lambdaLg10
=
0
;
state
=
DONE
;
criteria
=
cvTermCriteria
(
0
,
0
,
0
);
iters
=
0
;
completeSymmFlag
=
false
;
}
CvLevMarq
::
CvLevMarq
(
int
nparams
,
int
nerrs
,
CvTermCriteria
criteria0
,
bool
_completeSymmFlag
)
{
mask
=
prevParam
=
param
=
J
=
err
=
JtJ
=
JtJN
=
JtErr
=
JtJV
=
JtJW
=
Ptr
<
CvMat
>
();
init
(
nparams
,
nerrs
,
criteria0
,
_completeSymmFlag
);
}
void
CvLevMarq
::
clear
()
{
mask
.
release
();
prevParam
.
release
();
param
.
release
();
J
.
release
();
err
.
release
();
JtJ
.
release
();
JtJN
.
release
();
JtErr
.
release
();
JtJV
.
release
();
JtJW
.
release
();
}
CvLevMarq
::~
CvLevMarq
()
{
clear
();
}
void
CvLevMarq
::
init
(
int
nparams
,
int
nerrs
,
CvTermCriteria
criteria0
,
bool
_completeSymmFlag
)
{
if
(
!
param
||
param
->
rows
!=
nparams
||
nerrs
!=
(
err
?
err
->
rows
:
0
)
)
clear
();
mask
=
cvCreateMat
(
nparams
,
1
,
CV_8U
);
cvSet
(
mask
,
cvScalarAll
(
1
));
prevParam
=
cvCreateMat
(
nparams
,
1
,
CV_64F
);
param
=
cvCreateMat
(
nparams
,
1
,
CV_64F
);
JtJ
=
cvCreateMat
(
nparams
,
nparams
,
CV_64F
);
JtJN
=
cvCreateMat
(
nparams
,
nparams
,
CV_64F
);
JtJV
=
cvCreateMat
(
nparams
,
nparams
,
CV_64F
);
JtJW
=
cvCreateMat
(
nparams
,
1
,
CV_64F
);
JtErr
=
cvCreateMat
(
nparams
,
1
,
CV_64F
);
if
(
nerrs
>
0
)
{
J
=
cvCreateMat
(
nerrs
,
nparams
,
CV_64F
);
err
=
cvCreateMat
(
nerrs
,
1
,
CV_64F
);
}
prevErrNorm
=
DBL_MAX
;
lambdaLg10
=
-
3
;
criteria
=
criteria0
;
if
(
criteria
.
type
&
CV_TERMCRIT_ITER
)
criteria
.
max_iter
=
MIN
(
MAX
(
criteria
.
max_iter
,
1
),
1000
);
else
criteria
.
max_iter
=
30
;
if
(
criteria
.
type
&
CV_TERMCRIT_EPS
)
criteria
.
epsilon
=
MAX
(
criteria
.
epsilon
,
0
);
else
criteria
.
epsilon
=
DBL_EPSILON
;
state
=
STARTED
;
iters
=
0
;
completeSymmFlag
=
_completeSymmFlag
;
}
bool
CvLevMarq
::
update
(
const
CvMat
*&
_param
,
CvMat
*&
matJ
,
CvMat
*&
_err
)
{
double
change
;
matJ
=
_err
=
0
;
assert
(
!
err
.
empty
()
);
if
(
state
==
DONE
)
{
_param
=
param
;
return
false
;
}
if
(
state
==
STARTED
)
{
_param
=
param
;
cvZero
(
J
);
cvZero
(
err
);
matJ
=
J
;
_err
=
err
;
state
=
CALC_J
;
return
true
;
}
if
(
state
==
CALC_J
)
{
cvMulTransposed
(
J
,
JtJ
,
1
);
cvGEMM
(
J
,
err
,
1
,
0
,
0
,
JtErr
,
CV_GEMM_A_T
);
cvCopy
(
param
,
prevParam
);
step
();
if
(
iters
==
0
)
prevErrNorm
=
cvNorm
(
err
,
0
,
CV_L2
);
_param
=
param
;
cvZero
(
err
);
_err
=
err
;
state
=
CHECK_ERR
;
return
true
;
}
assert
(
state
==
CHECK_ERR
);
errNorm
=
cvNorm
(
err
,
0
,
CV_L2
);
if
(
errNorm
>
prevErrNorm
)
{
if
(
++
lambdaLg10
<=
16
)
{
step
();
_param
=
param
;
cvZero
(
err
);
_err
=
err
;
state
=
CHECK_ERR
;
return
true
;
}
}
lambdaLg10
=
MAX
(
lambdaLg10
-
1
,
-
16
);
if
(
++
iters
>=
criteria
.
max_iter
||
(
change
=
cvNorm
(
param
,
prevParam
,
CV_RELATIVE_L2
))
<
criteria
.
epsilon
)
{
_param
=
param
;
state
=
DONE
;
return
true
;
}
prevErrNorm
=
errNorm
;
_param
=
param
;
cvZero
(
J
);
matJ
=
J
;
_err
=
err
;
state
=
CALC_J
;
return
true
;
}
bool
CvLevMarq
::
updateAlt
(
const
CvMat
*&
_param
,
CvMat
*&
_JtJ
,
CvMat
*&
_JtErr
,
double
*&
_errNorm
)
{
double
change
;
CV_Assert
(
err
.
empty
()
);
if
(
state
==
DONE
)
{
_param
=
param
;
return
false
;
}
if
(
state
==
STARTED
)
{
_param
=
param
;
cvZero
(
JtJ
);
cvZero
(
JtErr
);
errNorm
=
0
;
_JtJ
=
JtJ
;
_JtErr
=
JtErr
;
_errNorm
=
&
errNorm
;
state
=
CALC_J
;
return
true
;
}
if
(
state
==
CALC_J
)
{
cvCopy
(
param
,
prevParam
);
step
();
_param
=
param
;
prevErrNorm
=
errNorm
;
errNorm
=
0
;
_errNorm
=
&
errNorm
;
state
=
CHECK_ERR
;
return
true
;
}
assert
(
state
==
CHECK_ERR
);
if
(
errNorm
>
prevErrNorm
)
{
if
(
++
lambdaLg10
<=
16
)
{
step
();
_param
=
param
;
errNorm
=
0
;
_errNorm
=
&
errNorm
;
state
=
CHECK_ERR
;
return
true
;
}
}
lambdaLg10
=
MAX
(
lambdaLg10
-
1
,
-
16
);
if
(
++
iters
>=
criteria
.
max_iter
||
(
change
=
cvNorm
(
param
,
prevParam
,
CV_RELATIVE_L2
))
<
criteria
.
epsilon
)
{
_param
=
param
;
state
=
DONE
;
return
false
;
}
prevErrNorm
=
errNorm
;
cvZero
(
JtJ
);
cvZero
(
JtErr
);
_param
=
param
;
_JtJ
=
JtJ
;
_JtErr
=
JtErr
;
state
=
CALC_J
;
return
true
;
}
void
CvLevMarq
::
step
()
{
const
double
LOG10
=
log
(
10.
);
double
lambda
=
exp
(
lambdaLg10
*
LOG10
);
int
i
,
j
,
nparams
=
param
->
rows
;
for
(
i
=
0
;
i
<
nparams
;
i
++
)
if
(
mask
->
data
.
ptr
[
i
]
==
0
)
{
double
*
row
=
JtJ
->
data
.
db
+
i
*
nparams
,
*
col
=
JtJ
->
data
.
db
+
i
;
for
(
j
=
0
;
j
<
nparams
;
j
++
)
row
[
j
]
=
col
[
j
*
nparams
]
=
0
;
JtErr
->
data
.
db
[
i
]
=
0
;
}
if
(
!
err
)
cvCompleteSymm
(
JtJ
,
completeSymmFlag
);
#if 1
cvCopy
(
JtJ
,
JtJN
);
for
(
i
=
0
;
i
<
nparams
;
i
++
)
JtJN
->
data
.
db
[(
nparams
+
1
)
*
i
]
*=
1.
+
lambda
;
#else
cvSetIdentity
(
JtJN
,
cvRealScalar
(
lambda
));
cvAdd
(
JtJ
,
JtJN
,
JtJN
);
#endif
cvSVD
(
JtJN
,
JtJW
,
0
,
JtJV
,
CV_SVD_MODIFY_A
+
CV_SVD_U_T
+
CV_SVD_V_T
);
cvSVBkSb
(
JtJW
,
JtJV
,
JtJV
,
JtErr
,
param
,
CV_SVD_U_T
+
CV_SVD_V_T
);
for
(
i
=
0
;
i
<
nparams
;
i
++
)
param
->
data
.
db
[
i
]
=
prevParam
->
data
.
db
[
i
]
-
(
mask
->
data
.
ptr
[
i
]
?
param
->
data
.
db
[
i
]
:
0
);
}
CV_IMPL
int
cvRANSACUpdateNumIters
(
double
p
,
double
ep
,
int
modelPoints
,
int
maxIters
)
{
return
cv
::
RANSACUpdateNumIters
(
p
,
ep
,
modelPoints
,
maxIters
);
}
CV_IMPL
int
cvFindHomography
(
const
CvMat
*
_src
,
const
CvMat
*
_dst
,
CvMat
*
__H
,
int
method
,
double
ransacReprojThreshold
,
CvMat
*
_mask
)
{
cv
::
Mat
src
=
cv
::
cvarrToMat
(
_src
),
dst
=
cv
::
cvarrToMat
(
_dst
);
if
(
src
.
channels
()
==
1
&&
(
src
.
rows
==
2
||
src
.
rows
==
3
)
&&
src
.
cols
>
3
)
cv
::
transpose
(
src
,
src
);
if
(
dst
.
channels
()
==
1
&&
(
dst
.
rows
==
2
||
dst
.
rows
==
3
)
&&
dst
.
cols
>
3
)
cv
::
transpose
(
dst
,
dst
);
const
cv
::
Mat
H
=
cv
::
cvarrToMat
(
__H
),
mask
=
cv
::
cvarrToMat
(
_mask
);
cv
::
Mat
H0
=
cv
::
findHomography
(
src
,
dst
,
method
,
ransacReprojThreshold
,
_mask
?
cv
::
_OutputArray
(
mask
)
:
cv
::
_OutputArray
());
if
(
H0
.
empty
()
)
{
cv
::
Mat
Hz
=
cv
::
cvarrToMat
(
__H
);
Hz
.
setTo
(
cv
::
Scalar
::
all
(
0
));
return
0
;
}
H0
.
convertTo
(
H
,
H
.
type
());
return
1
;
}
CV_IMPL
int
cvFindFundamentalMat
(
const
CvMat
*
points1
,
const
CvMat
*
points2
,
CvMat
*
fmatrix
,
int
method
,
double
param1
,
double
param2
,
CvMat
*
_mask
)
{
cv
::
Mat
m1
=
cv
::
cvarrToMat
(
points1
),
m2
=
cv
::
cvarrToMat
(
points2
);
if
(
m1
.
channels
()
==
1
&&
(
m1
.
rows
==
2
||
m1
.
rows
==
3
)
&&
m1
.
cols
>
3
)
cv
::
transpose
(
m1
,
m1
);
if
(
m2
.
channels
()
==
1
&&
(
m2
.
rows
==
2
||
m2
.
rows
==
3
)
&&
m2
.
cols
>
3
)
cv
::
transpose
(
m2
,
m2
);
const
cv
::
Mat
FM
=
cv
::
cvarrToMat
(
fmatrix
),
mask
=
cv
::
cvarrToMat
(
_mask
);
cv
::
Mat
FM0
=
cv
::
findFundamentalMat
(
m1
,
m2
,
method
,
param1
,
param2
,
_mask
?
cv
::
_OutputArray
(
mask
)
:
cv
::
_OutputArray
());
if
(
FM0
.
empty
()
)
{
cv
::
Mat
FM0z
=
cv
::
cvarrToMat
(
fmatrix
);
FM0z
.
setTo
(
cv
::
Scalar
::
all
(
0
));
return
0
;
}
CV_Assert
(
FM0
.
cols
==
3
&&
FM0
.
rows
%
3
==
0
&&
FM
.
cols
==
3
&&
FM
.
rows
%
3
==
0
&&
FM
.
channels
()
==
1
);
cv
::
Mat
FM1
=
FM
.
rowRange
(
0
,
MIN
(
FM0
.
rows
,
FM
.
rows
));
FM0
.
rowRange
(
0
,
FM1
.
rows
).
convertTo
(
FM1
,
FM1
.
type
());
return
FM1
.
rows
/
3
;
}
CV_IMPL
void
cvComputeCorrespondEpilines
(
const
CvMat
*
points
,
int
pointImageID
,
const
CvMat
*
fmatrix
,
CvMat
*
_lines
)
{
cv
::
Mat
pt
=
cv
::
cvarrToMat
(
points
),
fm
=
cv
::
cvarrToMat
(
fmatrix
);
cv
::
Mat
lines
=
cv
::
cvarrToMat
(
_lines
);
const
cv
::
Mat
lines0
=
lines
;
if
(
pt
.
channels
()
==
1
&&
(
pt
.
rows
==
2
||
pt
.
rows
==
3
)
&&
pt
.
cols
>
3
)
cv
::
transpose
(
pt
,
pt
);
cv
::
computeCorrespondEpilines
(
pt
,
pointImageID
,
fm
,
lines
);
bool
tflag
=
lines0
.
channels
()
==
1
&&
lines0
.
rows
==
3
&&
lines0
.
cols
>
3
;
lines
=
lines
.
reshape
(
lines0
.
channels
(),
(
tflag
?
lines0
.
cols
:
lines0
.
rows
));
if
(
tflag
)
{
CV_Assert
(
lines
.
rows
==
lines0
.
cols
&&
lines
.
cols
==
lines0
.
rows
);
if
(
lines0
.
type
()
==
lines
.
type
()
)
transpose
(
lines
,
lines0
);
else
{
transpose
(
lines
,
lines
);
lines
.
convertTo
(
lines0
,
lines0
.
type
()
);
}
}
else
{
CV_Assert
(
lines
.
size
()
==
lines0
.
size
()
);
if
(
lines
.
data
!=
lines0
.
data
)
lines
.
convertTo
(
lines0
,
lines0
.
type
());
}
}
CV_IMPL
void
cvConvertPointsHomogeneous
(
const
CvMat
*
_src
,
CvMat
*
_dst
)
{
cv
::
Mat
src
=
cv
::
cvarrToMat
(
_src
),
dst
=
cv
::
cvarrToMat
(
_dst
);
const
cv
::
Mat
dst0
=
dst
;
int
d0
=
src
.
channels
()
>
1
?
src
.
channels
()
:
MIN
(
src
.
cols
,
src
.
rows
);
if
(
src
.
channels
()
==
1
&&
src
.
cols
>
d0
)
cv
::
transpose
(
src
,
src
);
int
d1
=
dst
.
channels
()
>
1
?
dst
.
channels
()
:
MIN
(
dst
.
cols
,
dst
.
rows
);
if
(
d0
==
d1
)
src
.
copyTo
(
dst
);
else
if
(
d0
<
d1
)
cv
::
convertPointsToHomogeneous
(
src
,
dst
);
else
cv
::
convertPointsFromHomogeneous
(
src
,
dst
);
bool
tflag
=
dst0
.
channels
()
==
1
&&
dst0
.
cols
>
d1
;
dst
=
dst
.
reshape
(
dst0
.
channels
(),
(
tflag
?
dst0
.
cols
:
dst0
.
rows
));
if
(
tflag
)
{
CV_Assert
(
dst
.
rows
==
dst0
.
cols
&&
dst
.
cols
==
dst0
.
rows
);
if
(
dst0
.
type
()
==
dst
.
type
()
)
transpose
(
dst
,
dst0
);
else
{
transpose
(
dst
,
dst
);
dst
.
convertTo
(
dst0
,
dst0
.
type
()
);
}
}
else
{
CV_Assert
(
dst
.
size
()
==
dst0
.
size
()
);
if
(
dst
.
data
!=
dst0
.
data
)
dst
.
convertTo
(
dst0
,
dst0
.
type
());
}
}
modules/calib3d/src/five-point.cpp
View file @
6569a585
This source diff could not be displayed because it is too large. You can
view the blob
instead.
modules/calib3d/src/fundam.cpp
View file @
6569a585
...
@@ -7,10 +7,11 @@
...
@@ -7,10 +7,11 @@
// copy or use the software.
// copy or use the software.
//
//
//
//
//
Intel
License Agreement
//
License Agreement
// For Open Source Computer Vision Library
// For Open Source Computer Vision Library
//
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
// Third party copyrights are property of their respective owners.
//
//
// Redistribution and use in source and binary forms, with or without modification,
// Redistribution and use in source and binary forms, with or without modification,
...
@@ -23,7 +24,7 @@
...
@@ -23,7 +24,7 @@
// this list of conditions and the following disclaimer in the documentation
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// and/or other materials provided with the distribution.
//
//
// * The name of
Intel Corporation
may not be used to endorse or promote products
// * The name of
the copyright holders
may not be used to endorse or promote products
// derived from this software without specific prior written permission.
// derived from this software without specific prior written permission.
//
//
// This software is provided by the copyright holders and contributors "as is" and
// This software is provided by the copyright holders and contributors "as is" and
...
@@ -40,11 +41,35 @@
...
@@ -40,11 +41,35 @@
//M*/
//M*/
#include "precomp.hpp"
#include "precomp.hpp"
#include
"_modelest.h"
#include
<iostream>
using
namespace
cv
;
namespace
cv
{
template
<
typename
T
>
int
icvCompressPoints
(
T
*
ptr
,
const
uchar
*
mask
,
int
mstep
,
int
count
)
static
bool
haveCollinearPoints
(
const
Mat
&
m
,
int
count
)
{
int
j
,
k
,
i
=
count
-
1
;
const
Point2f
*
ptr
=
m
.
ptr
<
Point2f
>
();
// check that the i-th selected point does not belong
// to a line connecting some previously selected points
for
(
j
=
0
;
j
<
i
;
j
++
)
{
double
dx1
=
ptr
[
j
].
x
-
ptr
[
i
].
x
;
double
dy1
=
ptr
[
j
].
y
-
ptr
[
i
].
y
;
for
(
k
=
0
;
k
<
j
;
k
++
)
{
double
dx2
=
ptr
[
k
].
x
-
ptr
[
i
].
x
;
double
dy2
=
ptr
[
k
].
y
-
ptr
[
i
].
y
;
if
(
fabs
(
dx2
*
dy1
-
dy2
*
dx1
)
<=
FLT_EPSILON
*
(
fabs
(
dx1
)
+
fabs
(
dy1
)
+
fabs
(
dx2
)
+
fabs
(
dy2
)))
return
true
;
}
}
return
false
;
}
template
<
typename
T
>
int
compressPoints
(
T
*
ptr
,
const
uchar
*
mask
,
int
mstep
,
int
count
)
{
{
int
i
,
j
;
int
i
,
j
;
for
(
i
=
j
=
0
;
i
<
count
;
i
++
)
for
(
i
=
j
=
0
;
i
<
count
;
i
++
)
...
@@ -57,308 +82,280 @@ template<typename T> int icvCompressPoints( T* ptr, const uchar* mask, int mstep
...
@@ -57,308 +82,280 @@ template<typename T> int icvCompressPoints( T* ptr, const uchar* mask, int mstep
return
j
;
return
j
;
}
}
class
CvHomographyEstimator
:
public
CvModelEstimator2
class
HomographyEstimatorCallback
:
public
PointSetRegistrator
::
Callback
{
{
public
:
public
:
CvHomographyEstimator
(
int
modelPoints
);
bool
checkSubset
(
InputArray
_ms1
,
InputArray
_ms2
,
int
count
)
const
{
virtual
int
runKernel
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
model
);
Mat
ms1
=
_ms1
.
getMat
(),
ms2
=
_ms2
.
getMat
();
virtual
bool
refine
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
if
(
haveCollinearPoints
(
ms1
,
count
)
||
haveCollinearPoints
(
ms2
,
count
)
)
CvMat
*
model
,
int
maxIters
);
return
false
;
protected
:
virtual
void
computeReprojError
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
// We check whether the minimal set of points for the homography estimation
const
CvMat
*
model
,
CvMat
*
error
);
// are geometrically consistent. We check if every 3 correspondences sets
virtual
bool
isMinimalSetConsistent
(
const
CvMat
*
m1
,
const
CvMat
*
m2
);
// fulfills the constraint.
virtual
bool
weakConstraint
(
const
CvMat
*
srcPoints
,
const
CvMat
*
dstPoints
,
int
t1
,
int
t2
,
int
t3
);
//
};
// The usefullness of this constraint is explained in the paper:
//
// "Speeding-up homography estimation in mobile devices"
// Journal of Real-Time Image Processing. 2013. DOI: 10.1007/s11554-012-0314-1
// Pablo Marquez-Neila, Javier Lopez-Alberca, Jose M. Buenaposada, Luis Baumela
if
(
count
==
4
)
{
static
const
int
tt
[][
3
]
=
{{
0
,
1
,
2
},
{
1
,
2
,
3
},
{
0
,
2
,
3
},
{
0
,
1
,
3
}};
const
Point2f
*
src
=
ms1
.
ptr
<
Point2f
>
();
const
Point2f
*
dst
=
ms2
.
ptr
<
Point2f
>
();
int
negative
=
0
;
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
const
int
*
t
=
tt
[
i
];
Matx33d
A
(
src
[
t
[
0
]].
x
,
src
[
t
[
0
]].
y
,
1.
,
src
[
t
[
1
]].
x
,
src
[
t
[
1
]].
y
,
1.
,
src
[
t
[
2
]].
x
,
src
[
t
[
2
]].
y
,
1.
);
Matx33d
B
(
dst
[
t
[
0
]].
x
,
dst
[
t
[
0
]].
y
,
1.
,
dst
[
t
[
1
]].
x
,
dst
[
t
[
1
]].
y
,
1.
,
dst
[
t
[
2
]].
x
,
dst
[
t
[
2
]].
y
,
1.
);
CvHomographyEstimator
::
CvHomographyEstimator
(
int
_modelPoints
)
negative
+=
determinant
(
A
)
*
determinant
(
B
)
<
0
;
:
CvModelEstimator2
(
_modelPoints
,
cvSize
(
3
,
3
),
1
)
}
{
if
(
negative
!=
0
&&
negative
!=
4
)
assert
(
_modelPoints
==
4
||
_modelPoints
==
5
);
return
false
;
checkPartialSubsets
=
false
;
}
}
int
CvHomographyEstimator
::
runKernel
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
H
)
return
true
;
{
}
int
i
,
count
=
m1
->
rows
*
m1
->
cols
;
const
CvPoint2D64f
*
M
=
(
const
CvPoint2D64f
*
)
m1
->
data
.
ptr
;
const
CvPoint2D64f
*
m
=
(
const
CvPoint2D64f
*
)
m2
->
data
.
ptr
;
double
LtL
[
9
][
9
],
W
[
9
][
1
],
V
[
9
][
9
];
CvMat
_LtL
=
cvMat
(
9
,
9
,
CV_64F
,
LtL
);
CvMat
matW
=
cvMat
(
9
,
1
,
CV_64F
,
W
);
CvMat
matV
=
cvMat
(
9
,
9
,
CV_64F
,
V
);
CvMat
_H0
=
cvMat
(
3
,
3
,
CV_64F
,
V
[
8
]
);
CvMat
_Htemp
=
cvMat
(
3
,
3
,
CV_64F
,
V
[
7
]
);
CvPoint2D64f
cM
=
{
0
,
0
},
cm
=
{
0
,
0
},
sM
=
{
0
,
0
},
sm
=
{
0
,
0
};
for
(
i
=
0
;
i
<
count
;
i
++
)
int
runKernel
(
InputArray
_m1
,
InputArray
_m2
,
OutputArray
_model
)
const
{
{
cm
.
x
+=
m
[
i
].
x
;
cm
.
y
+=
m
[
i
].
y
;
Mat
m1
=
_m1
.
getMat
(),
m2
=
_m2
.
getMat
();
cM
.
x
+=
M
[
i
].
x
;
cM
.
y
+=
M
[
i
].
y
;
int
i
,
count
=
m1
.
checkVector
(
2
);
}
const
Point2f
*
M
=
m1
.
ptr
<
Point2f
>
();
const
Point2f
*
m
=
m2
.
ptr
<
Point2f
>
();
cm
.
x
/=
count
;
cm
.
y
/=
count
;
double
LtL
[
9
][
9
],
W
[
9
][
1
],
V
[
9
][
9
];
cM
.
x
/=
count
;
cM
.
y
/=
count
;
Mat
_LtL
(
9
,
9
,
CV_64F
,
&
LtL
[
0
][
0
]
);
Mat
matW
(
9
,
1
,
CV_64F
,
W
);
Mat
matV
(
9
,
9
,
CV_64F
,
V
);
Mat
_H0
(
3
,
3
,
CV_64F
,
V
[
8
]
);
Mat
_Htemp
(
3
,
3
,
CV_64F
,
V
[
7
]
);
Point2d
cM
(
0
,
0
),
cm
(
0
,
0
),
sM
(
0
,
0
),
sm
(
0
,
0
);
for
(
i
=
0
;
i
<
count
;
i
++
)
for
(
i
=
0
;
i
<
count
;
i
++
)
{
{
sm
.
x
+=
fabs
(
m
[
i
].
x
-
cm
.
x
);
cm
.
x
+=
m
[
i
].
x
;
cm
.
y
+=
m
[
i
].
y
;
sm
.
y
+=
fabs
(
m
[
i
].
y
-
cm
.
y
);
cM
.
x
+=
M
[
i
].
x
;
cM
.
y
+=
M
[
i
].
y
;
sM
.
x
+=
fabs
(
M
[
i
].
x
-
cM
.
x
);
}
sM
.
y
+=
fabs
(
M
[
i
].
y
-
cM
.
y
);
}
if
(
fabs
(
sm
.
x
)
<
DBL_EPSILON
||
fabs
(
sm
.
y
)
<
DBL_EPSILON
||
cm
.
x
/=
count
;
fabs
(
sM
.
x
)
<
DBL_EPSILON
||
fabs
(
sM
.
y
)
<
DBL_EPSILON
)
cm
.
y
/=
count
;
return
0
;
cM
.
x
/=
count
;
sm
.
x
=
count
/
sm
.
x
;
sm
.
y
=
count
/
sm
.
y
;
cM
.
y
/=
count
;
sM
.
x
=
count
/
sM
.
x
;
sM
.
y
=
count
/
sM
.
y
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
sm
.
x
+=
fabs
(
m
[
i
].
x
-
cm
.
x
);
sm
.
y
+=
fabs
(
m
[
i
].
y
-
cm
.
y
);
sM
.
x
+=
fabs
(
M
[
i
].
x
-
cM
.
x
);
sM
.
y
+=
fabs
(
M
[
i
].
y
-
cM
.
y
);
}
double
invHnorm
[
9
]
=
{
1.
/
sm
.
x
,
0
,
cm
.
x
,
0
,
1.
/
sm
.
y
,
cm
.
y
,
0
,
0
,
1
};
if
(
fabs
(
sm
.
x
)
<
DBL_EPSILON
||
fabs
(
sm
.
y
)
<
DBL_EPSILON
||
double
Hnorm2
[
9
]
=
{
sM
.
x
,
0
,
-
cM
.
x
*
sM
.
x
,
0
,
sM
.
y
,
-
cM
.
y
*
sM
.
y
,
0
,
0
,
1
};
fabs
(
sM
.
x
)
<
DBL_EPSILON
||
fabs
(
sM
.
y
)
<
DBL_EPSILON
)
CvMat
_invHnorm
=
cvMat
(
3
,
3
,
CV_64FC1
,
invHnorm
);
return
0
;
CvMat
_Hnorm2
=
cvMat
(
3
,
3
,
CV_64FC1
,
Hnorm2
);
sm
.
x
=
count
/
sm
.
x
;
sm
.
y
=
count
/
sm
.
y
;
sM
.
x
=
count
/
sM
.
x
;
sM
.
y
=
count
/
sM
.
y
;
cvZero
(
&
_LtL
);
double
invHnorm
[
9
]
=
{
1.
/
sm
.
x
,
0
,
cm
.
x
,
0
,
1.
/
sm
.
y
,
cm
.
y
,
0
,
0
,
1
};
for
(
i
=
0
;
i
<
count
;
i
++
)
double
Hnorm2
[
9
]
=
{
sM
.
x
,
0
,
-
cM
.
x
*
sM
.
x
,
0
,
sM
.
y
,
-
cM
.
y
*
sM
.
y
,
0
,
0
,
1
};
{
Mat
_invHnorm
(
3
,
3
,
CV_64FC1
,
invHnorm
);
double
x
=
(
m
[
i
].
x
-
cm
.
x
)
*
sm
.
x
,
y
=
(
m
[
i
].
y
-
cm
.
y
)
*
sm
.
y
;
Mat
_Hnorm2
(
3
,
3
,
CV_64FC1
,
Hnorm2
);
double
X
=
(
M
[
i
].
x
-
cM
.
x
)
*
sM
.
x
,
Y
=
(
M
[
i
].
y
-
cM
.
y
)
*
sM
.
y
;
double
Lx
[]
=
{
X
,
Y
,
1
,
0
,
0
,
0
,
-
x
*
X
,
-
x
*
Y
,
-
x
};
_LtL
.
setTo
(
Scalar
::
all
(
0
));
double
Ly
[]
=
{
0
,
0
,
0
,
X
,
Y
,
1
,
-
y
*
X
,
-
y
*
Y
,
-
y
};
for
(
i
=
0
;
i
<
count
;
i
++
)
int
j
,
k
;
{
for
(
j
=
0
;
j
<
9
;
j
++
)
double
x
=
(
m
[
i
].
x
-
cm
.
x
)
*
sm
.
x
,
y
=
(
m
[
i
].
y
-
cm
.
y
)
*
sm
.
y
;
for
(
k
=
j
;
k
<
9
;
k
++
)
double
X
=
(
M
[
i
].
x
-
cM
.
x
)
*
sM
.
x
,
Y
=
(
M
[
i
].
y
-
cM
.
y
)
*
sM
.
y
;
LtL
[
j
][
k
]
+=
Lx
[
j
]
*
Lx
[
k
]
+
Ly
[
j
]
*
Ly
[
k
];
double
Lx
[]
=
{
X
,
Y
,
1
,
0
,
0
,
0
,
-
x
*
X
,
-
x
*
Y
,
-
x
};
double
Ly
[]
=
{
0
,
0
,
0
,
X
,
Y
,
1
,
-
y
*
X
,
-
y
*
Y
,
-
y
};
int
j
,
k
;
for
(
j
=
0
;
j
<
9
;
j
++
)
for
(
k
=
j
;
k
<
9
;
k
++
)
LtL
[
j
][
k
]
+=
Lx
[
j
]
*
Lx
[
k
]
+
Ly
[
j
]
*
Ly
[
k
];
}
completeSymm
(
_LtL
);
eigen
(
_LtL
,
matW
,
matV
);
_Htemp
=
_invHnorm
*
_H0
;
_H0
=
_Htemp
*
_Hnorm2
;
_H0
.
convertTo
(
_model
,
_H0
.
type
(),
1.
/
_H0
.
at
<
double
>
(
2
,
2
)
);
return
1
;
}
}
cvCompleteSymm
(
&
_LtL
);
//cvSVD( &_LtL, &matW, 0, &matV, CV_SVD_MODIFY_A + CV_SVD_V_T );
void
computeError
(
InputArray
_m1
,
InputArray
_m2
,
InputArray
_model
,
OutputArray
_err
)
const
cvEigenVV
(
&
_LtL
,
&
matV
,
&
matW
);
{
cvMatMul
(
&
_invHnorm
,
&
_H0
,
&
_Htemp
);
Mat
m1
=
_m1
.
getMat
(),
m2
=
_m2
.
getMat
(),
model
=
_model
.
getMat
();
cvMatMul
(
&
_Htemp
,
&
_Hnorm2
,
&
_H0
);
int
i
,
count
=
m1
.
checkVector
(
2
);
cvConvertScale
(
&
_H0
,
H
,
1.
/
_H0
.
data
.
db
[
8
]
);
const
Point2f
*
M
=
m1
.
ptr
<
Point2f
>
();
const
Point2f
*
m
=
m2
.
ptr
<
Point2f
>
();
const
double
*
H
=
model
.
ptr
<
double
>
();
float
Hf
[]
=
{
(
float
)
H
[
0
],
(
float
)
H
[
1
],
(
float
)
H
[
2
],
(
float
)
H
[
3
],
(
float
)
H
[
4
],
(
float
)
H
[
5
],
(
float
)
H
[
6
],
(
float
)
H
[
7
]
};
return
1
;
_err
.
create
(
count
,
1
,
CV_32F
)
;
}
float
*
err
=
_err
.
getMat
().
ptr
<
float
>
();
for
(
i
=
0
;
i
<
count
;
i
++
)
{
float
ww
=
1.
f
/
(
Hf
[
6
]
*
M
[
i
].
x
+
Hf
[
7
]
*
M
[
i
].
y
+
1.
f
);
float
dx
=
(
Hf
[
0
]
*
M
[
i
].
x
+
Hf
[
1
]
*
M
[
i
].
y
+
Hf
[
2
])
*
ww
-
m
[
i
].
x
;
float
dy
=
(
Hf
[
3
]
*
M
[
i
].
x
+
Hf
[
4
]
*
M
[
i
].
y
+
Hf
[
5
])
*
ww
-
m
[
i
].
y
;
err
[
i
]
=
(
float
)(
dx
*
dx
+
dy
*
dy
);
}
}
};
void
CvHomographyEstimator
::
computeReprojError
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
const
CvMat
*
model
,
CvMat
*
_err
)
{
int
i
,
count
=
m1
->
rows
*
m1
->
cols
;
const
CvPoint2D64f
*
M
=
(
const
CvPoint2D64f
*
)
m1
->
data
.
ptr
;
const
CvPoint2D64f
*
m
=
(
const
CvPoint2D64f
*
)
m2
->
data
.
ptr
;
const
double
*
H
=
model
->
data
.
db
;
float
*
err
=
_err
->
data
.
fl
;
for
(
i
=
0
;
i
<
count
;
i
++
)
class
HomographyRefineCallback
:
public
LMSolver
::
Callback
{
public
:
HomographyRefineCallback
(
InputArray
_src
,
InputArray
_dst
)
{
{
double
ww
=
1.
/
(
H
[
6
]
*
M
[
i
].
x
+
H
[
7
]
*
M
[
i
].
y
+
1.
);
src
=
_src
.
getMat
();
double
dx
=
(
H
[
0
]
*
M
[
i
].
x
+
H
[
1
]
*
M
[
i
].
y
+
H
[
2
])
*
ww
-
m
[
i
].
x
;
dst
=
_dst
.
getMat
();
double
dy
=
(
H
[
3
]
*
M
[
i
].
x
+
H
[
4
]
*
M
[
i
].
y
+
H
[
5
])
*
ww
-
m
[
i
].
y
;
err
[
i
]
=
(
float
)(
dx
*
dx
+
dy
*
dy
);
}
}
}
bool
CvHomographyEstimator
::
refine
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
model
,
int
maxIters
)
bool
compute
(
InputArray
_param
,
OutputArray
_err
,
OutputArray
_Jac
)
const
{
CvLevMarq
solver
(
8
,
0
,
cvTermCriteria
(
CV_TERMCRIT_ITER
+
CV_TERMCRIT_EPS
,
maxIters
,
DBL_EPSILON
));
int
i
,
j
,
k
,
count
=
m1
->
rows
*
m1
->
cols
;
const
CvPoint2D64f
*
M
=
(
const
CvPoint2D64f
*
)
m1
->
data
.
ptr
;
const
CvPoint2D64f
*
m
=
(
const
CvPoint2D64f
*
)
m2
->
data
.
ptr
;
CvMat
modelPart
=
cvMat
(
solver
.
param
->
rows
,
solver
.
param
->
cols
,
model
->
type
,
model
->
data
.
ptr
);
cvCopy
(
&
modelPart
,
solver
.
param
);
for
(;;)
{
{
const
CvMat
*
_param
=
0
;
int
i
,
count
=
src
.
checkVector
(
2
);
CvMat
*
_JtJ
=
0
,
*
_JtErr
=
0
;
Mat
param
=
_param
.
getMat
();
double
*
_errNorm
=
0
;
_err
.
create
(
count
*
2
,
1
,
CV_64F
);
Mat
err
=
_err
.
getMat
(),
J
;
if
(
_Jac
.
needed
())
{
_Jac
.
create
(
count
*
2
,
param
.
rows
,
CV_64F
);
J
=
_Jac
.
getMat
();
CV_Assert
(
J
.
isContinuous
()
&&
J
.
cols
==
8
);
}
if
(
!
solver
.
updateAlt
(
_param
,
_JtJ
,
_JtErr
,
_errNorm
))
const
Point2f
*
M
=
src
.
ptr
<
Point2f
>
();
break
;
const
Point2f
*
m
=
dst
.
ptr
<
Point2f
>
();
const
double
*
h
=
param
.
ptr
<
double
>
();
double
*
errptr
=
err
.
ptr
<
double
>
();
double
*
Jptr
=
J
.
data
?
J
.
ptr
<
double
>
()
:
0
;
for
(
i
=
0
;
i
<
count
;
i
++
)
for
(
i
=
0
;
i
<
count
;
i
++
)
{
{
const
double
*
h
=
_param
->
data
.
db
;
double
Mx
=
M
[
i
].
x
,
My
=
M
[
i
].
y
;
double
Mx
=
M
[
i
].
x
,
My
=
M
[
i
].
y
;
double
ww
=
h
[
6
]
*
Mx
+
h
[
7
]
*
My
+
1.
;
double
ww
=
h
[
6
]
*
Mx
+
h
[
7
]
*
My
+
1.
;
ww
=
fabs
(
ww
)
>
DBL_EPSILON
?
1.
/
ww
:
0
;
ww
=
fabs
(
ww
)
>
DBL_EPSILON
?
1.
/
ww
:
0
;
double
_xi
=
(
h
[
0
]
*
Mx
+
h
[
1
]
*
My
+
h
[
2
])
*
ww
;
double
xi
=
(
h
[
0
]
*
Mx
+
h
[
1
]
*
My
+
h
[
2
])
*
ww
;
double
_yi
=
(
h
[
3
]
*
Mx
+
h
[
4
]
*
My
+
h
[
5
])
*
ww
;
double
yi
=
(
h
[
3
]
*
Mx
+
h
[
4
]
*
My
+
h
[
5
])
*
ww
;
double
err
[]
=
{
_xi
-
m
[
i
].
x
,
_yi
-
m
[
i
].
y
};
errptr
[
i
*
2
]
=
xi
-
m
[
i
].
x
;
if
(
_JtJ
||
_JtErr
)
errptr
[
i
*
2
+
1
]
=
yi
-
m
[
i
].
y
;
if
(
Jptr
)
{
{
double
J
[][
8
]
=
Jptr
[
0
]
=
Mx
*
ww
;
Jptr
[
1
]
=
My
*
ww
;
Jptr
[
2
]
=
ww
;
{
Jptr
[
3
]
=
Jptr
[
4
]
=
Jptr
[
5
]
=
0.
;
{
Mx
*
ww
,
My
*
ww
,
ww
,
0
,
0
,
0
,
-
Mx
*
ww
*
_xi
,
-
My
*
ww
*
_xi
},
Jptr
[
6
]
=
-
Mx
*
ww
*
xi
;
Jptr
[
7
]
=
-
My
*
ww
*
xi
;
{
0
,
0
,
0
,
Mx
*
ww
,
My
*
ww
,
ww
,
-
Mx
*
ww
*
_yi
,
-
My
*
ww
*
_yi
}
Jptr
[
8
]
=
Jptr
[
9
]
=
Jptr
[
10
]
=
0.
;
};
Jptr
[
11
]
=
Mx
*
ww
;
Jptr
[
12
]
=
My
*
ww
;
Jptr
[
13
]
=
ww
;
Jptr
[
14
]
=
-
Mx
*
ww
*
yi
;
Jptr
[
15
]
=
-
My
*
ww
*
yi
;
for
(
j
=
0
;
j
<
8
;
j
++
)
{
for
(
k
=
j
;
k
<
8
;
k
++
)
_JtJ
->
data
.
db
[
j
*
8
+
k
]
+=
J
[
0
][
j
]
*
J
[
0
][
k
]
+
J
[
1
][
j
]
*
J
[
1
][
k
];
_JtErr
->
data
.
db
[
j
]
+=
J
[
0
][
j
]
*
err
[
0
]
+
J
[
1
][
j
]
*
err
[
1
];
}
}
}
if
(
_errNorm
)
*
_errNorm
+=
err
[
0
]
*
err
[
0
]
+
err
[
1
]
*
err
[
1
];
}
}
return
true
;
}
}
cvCopy
(
solver
.
param
,
&
modelPart
);
Mat
src
,
dst
;
return
true
;
};
}
}
CV_IMPL
int
cv
::
Mat
cv
::
findHomography
(
InputArray
_points1
,
InputArray
_points2
,
cvFindHomography
(
const
CvMat
*
objectPoints
,
const
CvMat
*
imagePoints
,
int
method
,
double
ransacReprojThreshold
,
OutputArray
_mask
)
CvMat
*
__H
,
int
method
,
double
ransacReprojThreshold
,
CvMat
*
mask
)
{
{
const
double
confidence
=
0.995
;
const
double
confidence
=
0.995
;
const
int
maxIters
=
2000
;
const
int
maxIters
=
2000
;
const
double
defaultRANSACReprojThreshold
=
3
;
const
double
defaultRANSACReprojThreshold
=
3
;
bool
result
=
false
;
bool
result
=
false
;
Ptr
<
CvMat
>
m
,
M
,
tempMask
;
double
H
[
9
];
Mat
points1
=
_points1
.
getMat
(),
points2
=
_points2
.
getMat
();
CvMat
matH
=
cvMat
(
3
,
3
,
CV_64FC1
,
H
);
Mat
src
,
dst
,
H
,
tempMask
;
int
count
;
int
npoints
=
-
1
;
for
(
int
i
=
1
;
i
<=
2
;
i
++
)
{
Mat
&
p
=
i
==
1
?
points1
:
points2
;
Mat
&
m
=
i
==
1
?
src
:
dst
;
npoints
=
p
.
checkVector
(
2
,
-
1
,
false
);
if
(
npoints
<
0
)
{
npoints
=
p
.
checkVector
(
3
,
-
1
,
false
);
if
(
npoints
<
0
)
CV_Error
(
CV_StsBadArg
,
"The input arrays should be 2D or 3D point sets"
);
if
(
npoints
==
0
)
return
Mat
();
convertPointsFromHomogeneous
(
p
,
p
);
}
p
.
reshape
(
2
,
npoints
).
convertTo
(
m
,
CV_32F
);
}
CV_Assert
(
CV_IS_MAT
(
imagePoints
)
&&
CV_IS_MAT
(
objectPoints
)
);
CV_Assert
(
src
.
checkVector
(
2
)
==
dst
.
checkVector
(
2
)
);
count
=
MAX
(
imagePoints
->
cols
,
imagePoints
->
rows
);
CV_Assert
(
count
>=
4
);
if
(
ransacReprojThreshold
<=
0
)
if
(
ransacReprojThreshold
<=
0
)
ransacReprojThreshold
=
defaultRANSACReprojThreshold
;
ransacReprojThreshold
=
defaultRANSACReprojThreshold
;
m
=
cvCreateMat
(
1
,
count
,
CV_64FC2
);
Ptr
<
PointSetRegistrator
::
Callback
>
cb
=
new
HomographyEstimatorCallback
;
cvConvertPointsHomogeneous
(
imagePoints
,
m
);
M
=
cvCreateMat
(
1
,
count
,
CV_64FC2
);
cvConvertPointsHomogeneous
(
objectPoints
,
M
);
if
(
m
ask
)
if
(
m
ethod
==
0
||
npoints
==
4
)
{
{
CV_Assert
(
CV_IS_MASK_ARR
(
mask
)
&&
CV_IS_MAT_CONT
(
mask
->
type
)
&&
tempMask
=
Mat
::
ones
(
npoints
,
1
,
CV_8U
);
(
mask
->
rows
==
1
||
mask
->
cols
==
1
)
&&
result
=
cb
->
runKernel
(
src
,
dst
,
H
)
>
0
;
mask
->
rows
*
mask
->
cols
==
count
);
}
}
if
(
mask
||
count
>
4
)
else
if
(
method
==
RANSAC
)
tempMask
=
cvCreateMat
(
1
,
count
,
CV_8U
);
result
=
createRANSACPointSetRegistrator
(
cb
,
4
,
ransacReprojThreshold
,
confidence
,
maxIters
)
->
run
(
src
,
dst
,
H
,
tempMask
);
if
(
!
tempMask
.
empty
()
)
else
if
(
method
==
LMEDS
)
cvSet
(
tempMask
,
cvScalarAll
(
1.
)
);
result
=
createLMeDSPointSetRegistrator
(
cb
,
4
,
confidence
,
maxIters
)
->
run
(
src
,
dst
,
H
,
tempMask
);
CvHomographyEstimator
estimator
(
4
);
if
(
count
==
4
)
method
=
0
;
if
(
method
==
CV_LMEDS
)
result
=
estimator
.
runLMeDS
(
M
,
m
,
&
matH
,
tempMask
,
confidence
,
maxIters
);
else
if
(
method
==
CV_RANSAC
)
result
=
estimator
.
runRANSAC
(
M
,
m
,
&
matH
,
tempMask
,
ransacReprojThreshold
,
confidence
,
maxIters
);
else
else
result
=
estimator
.
runKernel
(
M
,
m
,
&
matH
)
>
0
;
CV_Error
(
CV_StsBadArg
,
"Unknown estimation method"
)
;
if
(
result
&&
count
>
4
)
if
(
result
&&
npoints
>
4
)
{
{
icvCompressPoints
(
(
CvPoint2D64f
*
)
M
->
data
.
ptr
,
tempMask
->
data
.
ptr
,
1
,
count
);
compressPoints
(
src
.
ptr
<
Point2f
>
(),
tempMask
.
ptr
<
uchar
>
(),
1
,
npoints
);
count
=
icvCompressPoints
(
(
CvPoint2D64f
*
)
m
->
data
.
ptr
,
tempMask
->
data
.
ptr
,
1
,
count
);
npoints
=
compressPoints
(
dst
.
ptr
<
Point2f
>
(),
tempMask
.
ptr
<
uchar
>
(),
1
,
npoints
);
M
->
cols
=
m
->
cols
=
count
;
if
(
npoints
>
0
)
if
(
method
==
CV_RANSAC
)
{
estimator
.
runKernel
(
M
,
m
,
&
matH
);
Mat
src1
=
src
.
rowRange
(
0
,
npoints
);
estimator
.
refine
(
M
,
m
,
&
matH
,
10
);
Mat
dst1
=
dst
.
rowRange
(
0
,
npoints
);
src
=
src1
;
dst
=
dst1
;
if
(
method
==
RANSAC
||
method
==
LMEDS
)
cb
->
runKernel
(
src
,
dst
,
H
);
Mat
H8
(
8
,
1
,
CV_64F
,
H
.
ptr
<
double
>
());
createLMSolver
(
new
HomographyRefineCallback
(
src
,
dst
),
10
)
->
run
(
H8
);
}
}
}
if
(
result
)
if
(
result
)
cvConvert
(
&
matH
,
__H
);
if
(
mask
&&
tempMask
)
{
{
if
(
CV_ARE_SIZES_EQ
(
mask
,
tempMask
)
)
if
(
_mask
.
needed
()
)
cvCopy
(
tempMask
,
mask
);
tempMask
.
copyTo
(
_mask
);
else
cvTranspose
(
tempMask
,
mask
);
}
}
else
H
.
release
();
return
(
int
)
result
;
return
H
;
}
}
// We check whether three correspondences for the homography estimation
cv
::
Mat
cv
::
findHomography
(
InputArray
_points1
,
InputArray
_points2
,
// are geometrically consistent (the points in the source image should
OutputArray
_mask
,
int
method
,
double
ransacReprojThreshold
)
// maintain the same circular order than in the destination image).
//
// The usefullness of this constraint is explained in the paper:
//
// "Speeding-up homography estimation in mobile devices"
// Journal of Real-Time Image Processing. 2013. DOI: 10.1007/s11554-012-0314-1
// Pablo Marquez-Neila, Javier Lopez-Alberca, Jose M. Buenaposada, Luis Baumela
bool
CvHomographyEstimator
::
weakConstraint
(
const
CvMat
*
srcPoints
,
const
CvMat
*
dstPoints
,
int
t1
,
int
t2
,
int
t3
)
{
const
CvPoint2D64f
*
src
=
(
const
CvPoint2D64f
*
)
srcPoints
->
data
.
ptr
;
const
CvPoint2D64f
*
dst
=
(
const
CvPoint2D64f
*
)
dstPoints
->
data
.
ptr
;
CvMat
*
A
=
cvCreateMat
(
3
,
3
,
CV_64F
);
CvMat
*
B
=
cvCreateMat
(
3
,
3
,
CV_64F
);
double
detA
;
double
detB
;
cvmSet
(
A
,
0
,
0
,
src
[
t1
].
x
);
cvmSet
(
A
,
0
,
1
,
src
[
t1
].
y
);
cvmSet
(
A
,
0
,
2
,
1
);
cvmSet
(
A
,
1
,
0
,
src
[
t2
].
x
);
cvmSet
(
A
,
1
,
1
,
src
[
t2
].
y
);
cvmSet
(
A
,
1
,
2
,
1
);
cvmSet
(
A
,
2
,
0
,
src
[
t3
].
x
);
cvmSet
(
A
,
2
,
1
,
src
[
t3
].
y
);
cvmSet
(
A
,
2
,
2
,
1
);
cvmSet
(
B
,
0
,
0
,
dst
[
t1
].
x
);
cvmSet
(
B
,
0
,
1
,
dst
[
t1
].
y
);
cvmSet
(
B
,
0
,
2
,
1
);
cvmSet
(
B
,
1
,
0
,
dst
[
t2
].
x
);
cvmSet
(
B
,
1
,
1
,
dst
[
t2
].
y
);
cvmSet
(
B
,
1
,
2
,
1
);
cvmSet
(
B
,
2
,
0
,
dst
[
t3
].
x
);
cvmSet
(
B
,
2
,
1
,
dst
[
t3
].
y
);
cvmSet
(
B
,
2
,
2
,
1
);
detA
=
cvDet
(
A
);
detB
=
cvDet
(
B
);
cvReleaseMat
(
&
A
);
cvReleaseMat
(
&
B
);
return
(
detA
*
detB
>=
0
);
};
// We check whether the minimal set of points for the homography estimation
// are geometrically consistent. We check if every 3 correspondences sets
// fulfills the constraint.
//
// The usefullness of this constraint is explained in the paper:
//
// "Speeding-up homography estimation in mobile devices"
// Journal of Real-Time Image Processing. 2013. DOI: 10.1007/s11554-012-0314-1
// Pablo Marquez-Neila, Javier Lopez-Alberca, Jose M. Buenaposada, Luis Baumela
bool
CvHomographyEstimator
::
isMinimalSetConsistent
(
const
CvMat
*
srcPoints
,
const
CvMat
*
dstPoints
)
{
{
return
weakConstraint
(
srcPoints
,
dstPoints
,
0
,
1
,
2
)
&&
return
cv
::
findHomography
(
_points1
,
_points2
,
method
,
ransacReprojThreshold
,
_mask
);
weakConstraint
(
srcPoints
,
dstPoints
,
1
,
2
,
3
)
&&
weakConstraint
(
srcPoints
,
dstPoints
,
0
,
2
,
3
)
&&
weakConstraint
(
srcPoints
,
dstPoints
,
0
,
1
,
3
);
}
}
/* Evaluation of Fundamental Matrix from point correspondences.
/* Estimation of Fundamental Matrix from point correspondences.
The original code has been written by Valery Mosyagin */
The original code has been written by Valery Mosyagin */
/* The algorithms (except for RANSAC) and the notation have been taken from
/* The algorithms (except for RANSAC) and the notation have been taken from
...
@@ -367,44 +364,23 @@ CvHomographyEstimator::isMinimalSetConsistent ( const CvMat* srcPoints, const Cv
...
@@ -367,44 +364,23 @@ CvHomographyEstimator::isMinimalSetConsistent ( const CvMat* srcPoints, const Cv
that can be found at http://www-sop.inria.fr/robotvis/personnel/zzhang/zzhang-eng.html */
that can be found at http://www-sop.inria.fr/robotvis/personnel/zzhang/zzhang-eng.html */
/************************************** 7-point algorithm *******************************/
/************************************** 7-point algorithm *******************************/
class
CvFMEstimator
:
public
CvModelEstimator2
namespace
cv
{
{
public
:
CvFMEstimator
(
int
_modelPoints
);
virtual
int
runKernel
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
model
);
virtual
int
run7Point
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
model
);
virtual
int
run8Point
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
model
);
protected
:
virtual
void
computeReprojError
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
const
CvMat
*
model
,
CvMat
*
error
);
};
CvFMEstimator
::
CvFMEstimator
(
int
_modelPoints
)
static
int
run7Point
(
const
Mat
&
_m1
,
const
Mat
&
_m2
,
Mat
&
_fmatrix
)
:
CvModelEstimator2
(
_modelPoints
,
cvSize
(
3
,
3
),
_modelPoints
==
7
?
3
:
1
)
{
{
assert
(
_modelPoints
==
7
||
_modelPoints
==
8
);
double
a
[
7
*
9
],
w
[
7
],
u
[
9
*
9
],
v
[
9
*
9
],
c
[
4
],
r
[
3
];
}
int
CvFMEstimator
::
runKernel
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
model
)
{
return
modelPoints
==
7
?
run7Point
(
m1
,
m2
,
model
)
:
run8Point
(
m1
,
m2
,
model
);
}
int
CvFMEstimator
::
run7Point
(
const
CvMat
*
_m1
,
const
CvMat
*
_m2
,
CvMat
*
_fmatrix
)
{
double
a
[
7
*
9
],
w
[
7
],
v
[
9
*
9
],
c
[
4
],
r
[
3
];
double
*
f1
,
*
f2
;
double
*
f1
,
*
f2
;
double
t0
,
t1
,
t2
;
double
t0
,
t1
,
t2
;
CvMat
A
=
cvMat
(
7
,
9
,
CV_64F
,
a
);
Mat
A
(
7
,
9
,
CV_64F
,
a
);
CvMat
V
=
cvMat
(
9
,
9
,
CV_64F
,
v
);
Mat
U
(
7
,
9
,
CV_64F
,
u
);
CvMat
W
=
cvMat
(
7
,
1
,
CV_64F
,
w
);
Mat
Vt
(
9
,
9
,
CV_64F
,
v
);
CvMat
coeffs
=
cvMat
(
1
,
4
,
CV_64F
,
c
);
Mat
W
(
7
,
1
,
CV_64F
,
w
);
CvMat
roots
=
cvMat
(
1
,
3
,
CV_64F
,
r
);
Mat
coeffs
(
1
,
4
,
CV_64F
,
c
);
const
CvPoint2D64f
*
m1
=
(
const
CvPoint2D64f
*
)
_m1
->
data
.
ptr
;
Mat
roots
(
1
,
3
,
CV_64F
,
r
);
const
CvPoint2D64f
*
m2
=
(
const
CvPoint2D64f
*
)
_m2
->
data
.
ptr
;
const
Point2f
*
m1
=
_m1
.
ptr
<
Point2f
>
();
double
*
fmatrix
=
_fmatrix
->
data
.
db
;
const
Point2f
*
m2
=
_m2
.
ptr
<
Point2f
>
();
double
*
fmatrix
=
_fmatrix
.
ptr
<
double
>
();
int
i
,
k
,
n
;
int
i
,
k
,
n
;
// form a linear system: i-th row of A(=a) represents
// form a linear system: i-th row of A(=a) represents
...
@@ -429,7 +405,7 @@ int CvFMEstimator::run7Point( const CvMat* _m1, const CvMat* _m2, CvMat* _fmatri
...
@@ -429,7 +405,7 @@ int CvFMEstimator::run7Point( const CvMat* _m1, const CvMat* _m2, CvMat* _fmatri
// the solution is linear subspace of dimensionality 2.
// the solution is linear subspace of dimensionality 2.
// => use the last two singular vectors as a basis of the space
// => use the last two singular vectors as a basis of the space
// (according to SVD properties)
// (according to SVD properties)
cvSVD
(
&
A
,
&
W
,
0
,
&
V
,
CV_SVD_MODIFY_A
+
CV_SVD_V_T
);
SVDecomp
(
A
,
W
,
U
,
Vt
,
SVD
::
MODIFY_A
+
SVD
::
FULL_UV
);
f1
=
v
+
7
*
9
;
f1
=
v
+
7
*
9
;
f2
=
v
+
8
*
9
;
f2
=
v
+
8
*
9
;
...
@@ -449,29 +425,29 @@ int CvFMEstimator::run7Point( const CvMat* _m1, const CvMat* _m2, CvMat* _fmatri
...
@@ -449,29 +425,29 @@ int CvFMEstimator::run7Point( const CvMat* _m1, const CvMat* _m2, CvMat* _fmatri
c
[
3
]
=
f2
[
0
]
*
t0
-
f2
[
1
]
*
t1
+
f2
[
2
]
*
t2
;
c
[
3
]
=
f2
[
0
]
*
t0
-
f2
[
1
]
*
t1
+
f2
[
2
]
*
t2
;
c
[
2
]
=
f1
[
0
]
*
t0
-
f1
[
1
]
*
t1
+
f1
[
2
]
*
t2
-
c
[
2
]
=
f1
[
0
]
*
t0
-
f1
[
1
]
*
t1
+
f1
[
2
]
*
t2
-
f1
[
3
]
*
(
f2
[
1
]
*
f2
[
8
]
-
f2
[
2
]
*
f2
[
7
])
+
f1
[
3
]
*
(
f2
[
1
]
*
f2
[
8
]
-
f2
[
2
]
*
f2
[
7
])
+
f1
[
4
]
*
(
f2
[
0
]
*
f2
[
8
]
-
f2
[
2
]
*
f2
[
6
])
-
f1
[
4
]
*
(
f2
[
0
]
*
f2
[
8
]
-
f2
[
2
]
*
f2
[
6
])
-
f1
[
5
]
*
(
f2
[
0
]
*
f2
[
7
]
-
f2
[
1
]
*
f2
[
6
])
+
f1
[
5
]
*
(
f2
[
0
]
*
f2
[
7
]
-
f2
[
1
]
*
f2
[
6
])
+
f1
[
6
]
*
(
f2
[
1
]
*
f2
[
5
]
-
f2
[
2
]
*
f2
[
4
])
-
f1
[
6
]
*
(
f2
[
1
]
*
f2
[
5
]
-
f2
[
2
]
*
f2
[
4
])
-
f1
[
7
]
*
(
f2
[
0
]
*
f2
[
5
]
-
f2
[
2
]
*
f2
[
3
])
+
f1
[
7
]
*
(
f2
[
0
]
*
f2
[
5
]
-
f2
[
2
]
*
f2
[
3
])
+
f1
[
8
]
*
(
f2
[
0
]
*
f2
[
4
]
-
f2
[
1
]
*
f2
[
3
]);
f1
[
8
]
*
(
f2
[
0
]
*
f2
[
4
]
-
f2
[
1
]
*
f2
[
3
]);
t0
=
f1
[
4
]
*
f1
[
8
]
-
f1
[
5
]
*
f1
[
7
];
t0
=
f1
[
4
]
*
f1
[
8
]
-
f1
[
5
]
*
f1
[
7
];
t1
=
f1
[
3
]
*
f1
[
8
]
-
f1
[
5
]
*
f1
[
6
];
t1
=
f1
[
3
]
*
f1
[
8
]
-
f1
[
5
]
*
f1
[
6
];
t2
=
f1
[
3
]
*
f1
[
7
]
-
f1
[
4
]
*
f1
[
6
];
t2
=
f1
[
3
]
*
f1
[
7
]
-
f1
[
4
]
*
f1
[
6
];
c
[
1
]
=
f2
[
0
]
*
t0
-
f2
[
1
]
*
t1
+
f2
[
2
]
*
t2
-
c
[
1
]
=
f2
[
0
]
*
t0
-
f2
[
1
]
*
t1
+
f2
[
2
]
*
t2
-
f2
[
3
]
*
(
f1
[
1
]
*
f1
[
8
]
-
f1
[
2
]
*
f1
[
7
])
+
f2
[
3
]
*
(
f1
[
1
]
*
f1
[
8
]
-
f1
[
2
]
*
f1
[
7
])
+
f2
[
4
]
*
(
f1
[
0
]
*
f1
[
8
]
-
f1
[
2
]
*
f1
[
6
])
-
f2
[
4
]
*
(
f1
[
0
]
*
f1
[
8
]
-
f1
[
2
]
*
f1
[
6
])
-
f2
[
5
]
*
(
f1
[
0
]
*
f1
[
7
]
-
f1
[
1
]
*
f1
[
6
])
+
f2
[
5
]
*
(
f1
[
0
]
*
f1
[
7
]
-
f1
[
1
]
*
f1
[
6
])
+
f2
[
6
]
*
(
f1
[
1
]
*
f1
[
5
]
-
f1
[
2
]
*
f1
[
4
])
-
f2
[
6
]
*
(
f1
[
1
]
*
f1
[
5
]
-
f1
[
2
]
*
f1
[
4
])
-
f2
[
7
]
*
(
f1
[
0
]
*
f1
[
5
]
-
f1
[
2
]
*
f1
[
3
])
+
f2
[
7
]
*
(
f1
[
0
]
*
f1
[
5
]
-
f1
[
2
]
*
f1
[
3
])
+
f2
[
8
]
*
(
f1
[
0
]
*
f1
[
4
]
-
f1
[
1
]
*
f1
[
3
]);
f2
[
8
]
*
(
f1
[
0
]
*
f1
[
4
]
-
f1
[
1
]
*
f1
[
3
]);
c
[
0
]
=
f1
[
0
]
*
t0
-
f1
[
1
]
*
t1
+
f1
[
2
]
*
t2
;
c
[
0
]
=
f1
[
0
]
*
t0
-
f1
[
1
]
*
t1
+
f1
[
2
]
*
t2
;
// solve the cubic equation; there can be 1 to 3 roots ...
// solve the cubic equation; there can be 1 to 3 roots ...
n
=
cvSolveCubic
(
&
coeffs
,
&
roots
);
n
=
solveCubic
(
coeffs
,
roots
);
if
(
n
<
1
||
n
>
3
)
if
(
n
<
1
||
n
>
3
)
return
n
;
return
n
;
...
@@ -499,77 +475,77 @@ int CvFMEstimator::run7Point( const CvMat* _m1, const CvMat* _m2, CvMat* _fmatri
...
@@ -499,77 +475,77 @@ int CvFMEstimator::run7Point( const CvMat* _m1, const CvMat* _m2, CvMat* _fmatri
return
n
;
return
n
;
}
}
int
CvFMEstimator
::
run8Point
(
const
CvMat
*
_m1
,
const
CvMat
*
_m2
,
CvMat
*
_fmatrix
)
static
int
run8Point
(
const
Mat
&
_m1
,
const
Mat
&
_m2
,
Mat
&
_fmatrix
)
{
{
double
a
[
9
*
9
],
w
[
9
],
v
[
9
*
9
];
double
a
[
9
*
9
],
w
[
9
],
v
[
9
*
9
];
CvMat
W
=
cvMat
(
1
,
9
,
CV_64F
,
w
);
Mat
W
(
9
,
1
,
CV_64F
,
w
);
CvMat
V
=
cvMat
(
9
,
9
,
CV_64F
,
v
);
Mat
V
(
9
,
9
,
CV_64F
,
v
);
CvMat
A
=
cvMat
(
9
,
9
,
CV_64F
,
a
);
Mat
A
(
9
,
9
,
CV_64F
,
a
);
Cv
Mat
U
,
F0
,
TF
;
Mat
U
,
F0
,
TF
;
CvPoint2D64f
m0c
=
{
0
,
0
},
m1c
=
{
0
,
0
}
;
Point2d
m1c
(
0
,
0
),
m2c
(
0
,
0
)
;
double
t
,
scale
0
=
0
,
scale1
=
0
;
double
t
,
scale
1
=
0
,
scale2
=
0
;
const
CvPoint2D64f
*
m1
=
(
const
CvPoint2D64f
*
)
_m1
->
data
.
ptr
;
const
Point2f
*
m1
=
_m1
.
ptr
<
Point2f
>
()
;
const
CvPoint2D64f
*
m2
=
(
const
CvPoint2D64f
*
)
_m2
->
data
.
ptr
;
const
Point2f
*
m2
=
_m2
.
ptr
<
Point2f
>
()
;
double
*
fmatrix
=
_fmatrix
->
data
.
db
;
double
*
fmatrix
=
_fmatrix
.
ptr
<
double
>
()
;
CV_Assert
(
(
_m1
->
cols
==
1
||
_m1
->
rows
==
1
)
&&
CV_ARE_SIZES_EQ
(
_m1
,
_m2
));
CV_Assert
(
(
_m1
.
cols
==
1
||
_m1
.
rows
==
1
)
&&
_m1
.
size
()
==
_m2
.
size
(
));
int
i
,
j
,
k
,
count
=
_m1
->
cols
*
_m1
->
rows
;
int
i
,
j
,
k
,
count
=
_m1
.
checkVector
(
2
)
;
// compute centers and average distances for each of the two point sets
// compute centers and average distances for each of the two point sets
for
(
i
=
0
;
i
<
count
;
i
++
)
for
(
i
=
0
;
i
<
count
;
i
++
)
{
{
double
x
=
m1
[
i
].
x
,
y
=
m1
[
i
].
y
;
double
x
=
m1
[
i
].
x
,
y
=
m1
[
i
].
y
;
m
0c
.
x
+=
x
;
m0
c
.
y
+=
y
;
m
1c
.
x
+=
x
;
m1
c
.
y
+=
y
;
x
=
m2
[
i
].
x
,
y
=
m2
[
i
].
y
;
x
=
m2
[
i
].
x
,
y
=
m2
[
i
].
y
;
m
1c
.
x
+=
x
;
m1
c
.
y
+=
y
;
m
2c
.
x
+=
x
;
m2
c
.
y
+=
y
;
}
}
// calculate the normalizing transformations for each of the point sets:
// calculate the normalizing transformations for each of the point sets:
// after the transformation each set will have the mass center at the coordinate origin
// after the transformation each set will have the mass center at the coordinate origin
// and the average distance from the origin will be ~sqrt(2).
// and the average distance from the origin will be ~sqrt(2).
t
=
1.
/
count
;
t
=
1.
/
count
;
m0c
.
x
*=
t
;
m0c
.
y
*=
t
;
m1c
.
x
*=
t
;
m1c
.
y
*=
t
;
m1c
.
x
*=
t
;
m1c
.
y
*=
t
;
m2c
.
x
*=
t
;
m2c
.
y
*=
t
;
for
(
i
=
0
;
i
<
count
;
i
++
)
for
(
i
=
0
;
i
<
count
;
i
++
)
{
{
double
x
=
m1
[
i
].
x
-
m
0c
.
x
,
y
=
m1
[
i
].
y
-
m0
c
.
y
;
double
x
=
m1
[
i
].
x
-
m
1c
.
x
,
y
=
m1
[
i
].
y
-
m1
c
.
y
;
scale
0
+=
sqrt
(
x
*
x
+
y
*
y
);
scale
1
+=
std
::
sqrt
(
x
*
x
+
y
*
y
);
x
=
m2
[
i
].
x
-
m
1c
.
x
,
y
=
m2
[
i
].
y
-
m1
c
.
y
;
x
=
m2
[
i
].
x
-
m
2c
.
x
,
y
=
m2
[
i
].
y
-
m2
c
.
y
;
scale
1
+=
sqrt
(
x
*
x
+
y
*
y
);
scale
2
+=
std
::
sqrt
(
x
*
x
+
y
*
y
);
}
}
scale0
*=
t
;
scale1
*=
t
;
scale1
*=
t
;
scale2
*=
t
;
if
(
scale
0
<
FLT_EPSILON
||
scale1
<
FLT_EPSILON
)
if
(
scale
1
<
FLT_EPSILON
||
scale2
<
FLT_EPSILON
)
return
0
;
return
0
;
scale
0
=
sqrt
(
2.
)
/
scale0
;
scale
1
=
std
::
sqrt
(
2.
)
/
scale1
;
scale
1
=
sqrt
(
2.
)
/
scale1
;
scale
2
=
std
::
sqrt
(
2.
)
/
scale2
;
cvZero
(
&
A
);
A
.
setTo
(
Scalar
::
all
(
0
)
);
// form a linear system Ax=0: for each selected pair of points m1 & m2,
// form a linear system Ax=0: for each selected pair of points m1 & m2,
// the row of A(=a) represents the coefficients of equation: (m2, 1)'*F*(m1, 1) = 0
// the row of A(=a) represents the coefficients of equation: (m2, 1)'*F*(m1, 1) = 0
// to save computation time, we compute (At*A) instead of A and then solve (At*A)x=0.
// to save computation time, we compute (At*A) instead of A and then solve (At*A)x=0.
for
(
i
=
0
;
i
<
count
;
i
++
)
for
(
i
=
0
;
i
<
count
;
i
++
)
{
{
double
x
0
=
(
m1
[
i
].
x
-
m0c
.
x
)
*
scale0
;
double
x
1
=
(
m1
[
i
].
x
-
m1c
.
x
)
*
scale1
;
double
y
0
=
(
m1
[
i
].
y
-
m0c
.
y
)
*
scale0
;
double
y
1
=
(
m1
[
i
].
y
-
m1c
.
y
)
*
scale1
;
double
x
1
=
(
m2
[
i
].
x
-
m1c
.
x
)
*
scale1
;
double
x
2
=
(
m2
[
i
].
x
-
m2c
.
x
)
*
scale2
;
double
y
1
=
(
m2
[
i
].
y
-
m1c
.
y
)
*
scale1
;
double
y
2
=
(
m2
[
i
].
y
-
m2c
.
y
)
*
scale2
;
double
r
[
9
]
=
{
x
1
*
x0
,
x1
*
y0
,
x1
,
y1
*
x0
,
y1
*
y0
,
y1
,
x0
,
y0
,
1
};
double
r
[
9
]
=
{
x
2
*
x1
,
x2
*
y1
,
x2
,
y2
*
x1
,
y2
*
y1
,
y2
,
x1
,
y1
,
1
};
for
(
j
=
0
;
j
<
9
;
j
++
)
for
(
j
=
0
;
j
<
9
;
j
++
)
for
(
k
=
0
;
k
<
9
;
k
++
)
for
(
k
=
0
;
k
<
9
;
k
++
)
a
[
j
*
9
+
k
]
+=
r
[
j
]
*
r
[
k
];
a
[
j
*
9
+
k
]
+=
r
[
j
]
*
r
[
k
];
}
}
cvEigenVV
(
&
A
,
&
V
,
&
W
);
eigen
(
A
,
W
,
V
);
for
(
i
=
0
;
i
<
9
;
i
++
)
for
(
i
=
0
;
i
<
9
;
i
++
)
{
{
...
@@ -580,122 +556,148 @@ int CvFMEstimator::run8Point( const CvMat* _m1, const CvMat* _m2, CvMat* _fmatri
...
@@ -580,122 +556,148 @@ int CvFMEstimator::run8Point( const CvMat* _m1, const CvMat* _m2, CvMat* _fmatri
if
(
i
<
8
)
if
(
i
<
8
)
return
0
;
return
0
;
F0
=
cv
Mat
(
3
,
3
,
CV_64F
,
v
+
9
*
8
);
// take the last column of v as a solution of Af = 0
F0
=
Mat
(
3
,
3
,
CV_64F
,
v
+
9
*
8
);
// take the last column of v as a solution of Af = 0
// make F0 singular (of rank 2) by decomposing it with SVD,
// make F0 singular (of rank 2) by decomposing it with SVD,
// zeroing the last diagonal element of W and then composing the matrices back.
// zeroing the last diagonal element of W and then composing the matrices back.
// use v as a temporary storage for different 3x3 matrices
// use v as a temporary storage for different 3x3 matrices
W
=
U
=
V
=
TF
=
F0
;
W
=
U
=
V
=
TF
=
F0
;
W
.
data
.
db
=
v
;
W
=
Mat
(
3
,
1
,
CV_64F
,
v
)
;
U
.
data
.
db
=
v
+
9
;
U
=
Mat
(
3
,
3
,
CV_64F
,
v
+
9
)
;
V
.
data
.
db
=
v
+
18
;
V
=
Mat
(
3
,
3
,
CV_64F
,
v
+
18
)
;
TF
.
data
.
db
=
v
+
27
;
TF
=
Mat
(
3
,
3
,
CV_64F
,
v
+
27
)
;
cvSVD
(
&
F0
,
&
W
,
&
U
,
&
V
,
CV_SVD_MODIFY_A
+
CV_SVD_U_T
+
CV_SVD_V_T
);
SVDecomp
(
F0
,
W
,
U
,
V
,
SVD
::
MODIFY_A
);
W
.
data
.
db
[
8
]
=
0.
;
W
.
at
<
double
>
(
2
)
=
0.
;
// F0 <- U*diag([W(1), W(2), 0])*V'
// F0 <- U*diag([W(1), W(2), 0])*V'
cvGEMM
(
&
U
,
&
W
,
1.
,
0
,
0.
,
&
TF
,
CV_GEMM_A
_T
);
gemm
(
U
,
Mat
::
diag
(
W
),
1.
,
0
,
0.
,
TF
,
GEMM_1
_T
);
cvGEMM
(
&
TF
,
&
V
,
1.
,
0
,
0.
,
&
F0
,
0
/*CV_GEMM_B_T*/
);
gemm
(
TF
,
V
,
1.
,
0
,
0.
,
F0
,
0
/*CV_GEMM_B_T*/
);
// apply the transformation that is inverse
// apply the transformation that is inverse
// to what we used to normalize the point coordinates
// to what we used to normalize the point coordinates
{
double
tt1
[]
=
{
scale1
,
0
,
-
scale1
*
m1c
.
x
,
0
,
scale1
,
-
scale1
*
m1c
.
y
,
0
,
0
,
1
};
double
tt0
[]
=
{
scale0
,
0
,
-
scale0
*
m0c
.
x
,
0
,
scale0
,
-
scale0
*
m0c
.
y
,
0
,
0
,
1
};
double
tt2
[]
=
{
scale2
,
0
,
-
scale2
*
m2c
.
x
,
0
,
scale2
,
-
scale2
*
m2c
.
y
,
0
,
0
,
1
};
double
tt1
[]
=
{
scale1
,
0
,
-
scale1
*
m1c
.
x
,
0
,
scale1
,
-
scale1
*
m1c
.
y
,
0
,
0
,
1
};
Mat
T1
(
3
,
3
,
CV_64F
,
tt1
),
T2
(
3
,
3
,
CV_64F
,
tt2
);
CvMat
T0
,
T1
;
T0
=
T1
=
F0
;
// F0 <- T2'*F0*T1
T0
.
data
.
db
=
tt0
;
gemm
(
T2
,
F0
,
1.
,
0
,
0.
,
TF
,
GEMM_1_T
);
T1
.
data
.
db
=
tt1
;
F0
=
Mat
(
3
,
3
,
CV_64F
,
fmatrix
);
gemm
(
TF
,
T1
,
1.
,
0
,
0.
,
F0
,
0
);
// F0 <- T1'*F0*T0
cvGEMM
(
&
T1
,
&
F0
,
1.
,
0
,
0.
,
&
TF
,
CV_GEMM_A_T
);
// make F(3,3) = 1
F0
.
data
.
db
=
fmatrix
;
if
(
fabs
(
F0
.
at
<
double
>
(
2
,
2
))
>
FLT_EPSILON
)
cvGEMM
(
&
TF
,
&
T0
,
1.
,
0
,
0.
,
&
F0
,
0
);
F0
*=
1.
/
F0
.
at
<
double
>
(
2
,
2
);
// make F(3,3) = 1
if
(
fabs
(
F0
.
data
.
db
[
8
])
>
FLT_EPSILON
)
cvScale
(
&
F0
,
&
F0
,
1.
/
F0
.
data
.
db
[
8
]
);
}
return
1
;
return
1
;
}
}
void
CvFMEstimator
::
computeReprojError
(
const
CvMat
*
_m1
,
const
CvMat
*
_m2
,
class
FMEstimatorCallback
:
public
PointSetRegistrator
::
Callback
const
CvMat
*
model
,
CvMat
*
_err
)
{
{
int
i
,
count
=
_m1
->
rows
*
_m1
->
cols
;
public
:
const
CvPoint2D64f
*
m1
=
(
const
CvPoint2D64f
*
)
_m1
->
data
.
ptr
;
bool
checkSubset
(
InputArray
_ms1
,
InputArray
_ms2
,
int
count
)
const
const
CvPoint2D64f
*
m2
=
(
const
CvPoint2D64f
*
)
_m2
->
data
.
ptr
;
{
const
double
*
F
=
model
->
data
.
db
;
Mat
ms1
=
_ms1
.
getMat
(),
ms2
=
_ms2
.
getMat
();
float
*
err
=
_err
->
data
.
fl
;
return
!
haveCollinearPoints
(
ms1
,
count
)
&&
!
haveCollinearPoints
(
ms2
,
count
);
}
for
(
i
=
0
;
i
<
count
;
i
++
)
int
runKernel
(
InputArray
_m1
,
InputArray
_m2
,
OutputArray
_model
)
const
{
double
f
[
9
*
3
];
Mat
m1
=
_m1
.
getMat
(),
m2
=
_m2
.
getMat
();
int
count
=
m1
.
checkVector
(
2
);
Mat
F
(
count
==
7
?
9
:
3
,
3
,
CV_64F
,
f
);
int
n
=
count
==
7
?
run7Point
(
m1
,
m2
,
F
)
:
run8Point
(
m1
,
m2
,
F
);
if
(
n
==
0
)
_model
.
release
();
else
F
.
rowRange
(
0
,
n
*
3
).
copyTo
(
_model
);
return
n
;
}
void
computeError
(
InputArray
_m1
,
InputArray
_m2
,
InputArray
_model
,
OutputArray
_err
)
const
{
{
double
a
,
b
,
c
,
d1
,
d2
,
s1
,
s2
;
Mat
__m1
=
_m1
.
getMat
(),
__m2
=
_m2
.
getMat
(),
__model
=
_model
.
getMat
();
int
i
,
count
=
__m1
.
checkVector
(
2
);
const
Point2f
*
m1
=
__m1
.
ptr
<
Point2f
>
();
const
Point2f
*
m2
=
__m2
.
ptr
<
Point2f
>
();
const
double
*
F
=
__model
.
ptr
<
double
>
();
_err
.
create
(
count
,
1
,
CV_32F
);
float
*
err
=
_err
.
getMat
().
ptr
<
float
>
();
a
=
F
[
0
]
*
m1
[
i
].
x
+
F
[
1
]
*
m1
[
i
].
y
+
F
[
2
];
for
(
i
=
0
;
i
<
count
;
i
++
)
b
=
F
[
3
]
*
m1
[
i
].
x
+
F
[
4
]
*
m1
[
i
].
y
+
F
[
5
];
{
c
=
F
[
6
]
*
m1
[
i
].
x
+
F
[
7
]
*
m1
[
i
].
y
+
F
[
8
]
;
double
a
,
b
,
c
,
d1
,
d2
,
s1
,
s2
;
s2
=
1.
/
(
a
*
a
+
b
*
b
);
a
=
F
[
0
]
*
m1
[
i
].
x
+
F
[
1
]
*
m1
[
i
].
y
+
F
[
2
];
d2
=
m2
[
i
].
x
*
a
+
m2
[
i
].
y
*
b
+
c
;
b
=
F
[
3
]
*
m1
[
i
].
x
+
F
[
4
]
*
m1
[
i
].
y
+
F
[
5
];
c
=
F
[
6
]
*
m1
[
i
].
x
+
F
[
7
]
*
m1
[
i
].
y
+
F
[
8
];
a
=
F
[
0
]
*
m2
[
i
].
x
+
F
[
3
]
*
m2
[
i
].
y
+
F
[
6
];
s2
=
1.
/
(
a
*
a
+
b
*
b
);
b
=
F
[
1
]
*
m2
[
i
].
x
+
F
[
4
]
*
m2
[
i
].
y
+
F
[
7
];
d2
=
m2
[
i
].
x
*
a
+
m2
[
i
].
y
*
b
+
c
;
c
=
F
[
2
]
*
m2
[
i
].
x
+
F
[
5
]
*
m2
[
i
].
y
+
F
[
8
];
s1
=
1.
/
(
a
*
a
+
b
*
b
);
a
=
F
[
0
]
*
m2
[
i
].
x
+
F
[
3
]
*
m2
[
i
].
y
+
F
[
6
];
d1
=
m1
[
i
].
x
*
a
+
m1
[
i
].
y
*
b
+
c
;
b
=
F
[
1
]
*
m2
[
i
].
x
+
F
[
4
]
*
m2
[
i
].
y
+
F
[
7
];
c
=
F
[
2
]
*
m2
[
i
].
x
+
F
[
5
]
*
m2
[
i
].
y
+
F
[
8
];
err
[
i
]
=
(
float
)
std
::
max
(
d1
*
d1
*
s1
,
d2
*
d2
*
s2
);
s1
=
1.
/
(
a
*
a
+
b
*
b
);
d1
=
m1
[
i
].
x
*
a
+
m1
[
i
].
y
*
b
+
c
;
err
[
i
]
=
(
float
)
std
::
max
(
d1
*
d1
*
s1
,
d2
*
d2
*
s2
);
}
}
}
}
}
;
}
CV_IMPL
int
cvFindFundamentalMat
(
const
CvMat
*
points1
,
const
CvMat
*
points2
,
cv
::
Mat
cv
::
findFundamentalMat
(
InputArray
_points1
,
InputArray
_
points2
,
CvMat
*
fmatrix
,
int
method
,
int
method
,
double
param1
,
double
param2
,
double
param1
,
double
param2
,
CvMat
*
mask
)
OutputArray
_
mask
)
{
{
int
result
=
0
;
Mat
points1
=
_points1
.
getMat
(),
points2
=
_points2
.
getMat
();
Ptr
<
CvMat
>
m1
,
m2
,
tempMask
;
Mat
m1
,
m2
,
F
;
int
npoints
=
-
1
;
double
F
[
3
*
9
];
CvMat
_F3x3
=
cvMat
(
3
,
3
,
CV_64FC1
,
F
),
_F9x3
=
cvMat
(
9
,
3
,
CV_64FC1
,
F
);
int
count
;
CV_Assert
(
CV_IS_MAT
(
points1
)
&&
CV_IS_MAT
(
points2
)
&&
CV_ARE_SIZES_EQ
(
points1
,
points2
)
);
for
(
int
i
=
1
;
i
<=
2
;
i
++
)
CV_Assert
(
CV_IS_MAT
(
fmatrix
)
&&
fmatrix
->
cols
==
3
&&
{
(
fmatrix
->
rows
==
3
||
(
fmatrix
->
rows
==
9
&&
method
==
CV_FM_7POINT
))
);
Mat
&
p
=
i
==
1
?
points1
:
points2
;
Mat
&
m
=
i
==
1
?
m1
:
m2
;
npoints
=
p
.
checkVector
(
2
,
-
1
,
false
);
if
(
npoints
<
0
)
{
npoints
=
p
.
checkVector
(
3
,
-
1
,
false
);
if
(
npoints
<
0
)
CV_Error
(
CV_StsBadArg
,
"The input arrays should be 2D or 3D point sets"
);
if
(
npoints
==
0
)
return
Mat
();
convertPointsFromHomogeneous
(
p
,
p
);
}
p
.
reshape
(
2
,
npoints
).
convertTo
(
m
,
CV_32F
);
}
count
=
MAX
(
points1
->
cols
,
points1
->
rows
);
CV_Assert
(
m1
.
checkVector
(
2
)
==
m2
.
checkVector
(
2
)
);
if
(
count
<
7
)
return
0
;
m1
=
cvCreateMat
(
1
,
count
,
CV_64FC2
);
if
(
npoints
<
7
)
cvConvertPointsHomogeneous
(
points1
,
m1
);
return
Mat
(
);
m2
=
cvCreateMat
(
1
,
count
,
CV_64FC2
)
;
Ptr
<
PointSetRegistrator
::
Callback
>
cb
=
new
FMEstimatorCallback
;
cvConvertPointsHomogeneous
(
points2
,
m2
)
;
int
result
;
if
(
mask
)
if
(
npoints
==
7
||
method
==
FM_8POINT
)
{
{
CV_Assert
(
CV_IS_MASK_ARR
(
mask
)
&&
CV_IS_MAT_CONT
(
mask
->
type
)
&&
result
=
cb
->
runKernel
(
m1
,
m2
,
F
);
(
mask
->
rows
==
1
||
mask
->
cols
==
1
)
&&
if
(
_mask
.
needed
()
)
mask
->
rows
*
mask
->
cols
==
count
);
{
_mask
.
create
(
npoints
,
1
,
CV_8U
,
-
1
,
true
);
Mat
mask
=
_mask
.
getMat
();
CV_Assert
(
(
mask
.
cols
==
1
||
mask
.
rows
==
1
)
&&
(
int
)
mask
.
total
()
==
npoints
);
mask
.
setTo
(
Scalar
::
all
(
1
));
}
}
}
if
(
mask
||
count
>=
8
)
tempMask
=
cvCreateMat
(
1
,
count
,
CV_8U
);
if
(
!
tempMask
.
empty
()
)
cvSet
(
tempMask
,
cvScalarAll
(
1.
)
);
CvFMEstimator
estimator
(
7
);
if
(
count
==
7
)
result
=
estimator
.
run7Point
(
m1
,
m2
,
&
_F9x3
);
else
if
(
method
==
CV_FM_8POINT
)
result
=
estimator
.
run8Point
(
m1
,
m2
,
&
_F3x3
);
else
else
{
{
if
(
param1
<=
0
)
if
(
param1
<=
0
)
...
@@ -703,546 +705,279 @@ CV_IMPL int cvFindFundamentalMat( const CvMat* points1, const CvMat* points2,
...
@@ -703,546 +705,279 @@ CV_IMPL int cvFindFundamentalMat( const CvMat* points1, const CvMat* points2,
if
(
param2
<
DBL_EPSILON
||
param2
>
1
-
DBL_EPSILON
)
if
(
param2
<
DBL_EPSILON
||
param2
>
1
-
DBL_EPSILON
)
param2
=
0.99
;
param2
=
0.99
;
if
(
(
method
&
~
3
)
==
CV_RANSAC
&&
count
>=
15
)
if
(
(
method
&
~
3
)
==
FM_RANSAC
&&
npoints
>=
15
)
result
=
estimator
.
runRANSAC
(
m1
,
m2
,
&
_F3x3
,
tempMask
,
param1
,
param2
);
result
=
createRANSACPointSetRegistrator
(
cb
,
7
,
param1
,
param2
)
->
run
(
m1
,
m2
,
F
,
_mask
);
else
else
result
=
estimator
.
runLMeDS
(
m1
,
m2
,
&
_F3x3
,
tempMask
,
param2
);
result
=
createLMeDSPointSetRegistrator
(
cb
,
7
,
param2
)
->
run
(
m1
,
m2
,
F
,
_mask
);
if
(
result
<=
0
)
return
0
;
/*icvCompressPoints( (CvPoint2D64f*)m1->data.ptr, tempMask->data.ptr, 1, count );
count = icvCompressPoints( (CvPoint2D64f*)m2->data.ptr, tempMask->data.ptr, 1, count );
assert( count >= 8 );
m1->cols = m2->cols = count;
estimator.run8Point(m1, m2, &_F3x3);*/
}
}
if
(
result
)
if
(
result
<=
0
)
cvConvert
(
fmatrix
->
rows
==
3
?
&
_F3x3
:
&
_F9x3
,
fmatrix
);
return
Mat
(
);
if
(
mask
&&
tempMask
)
return
F
;
{
}
if
(
CV_ARE_SIZES_EQ
(
mask
,
tempMask
)
)
cvCopy
(
tempMask
,
mask
);
else
cvTranspose
(
tempMask
,
mask
);
}
return
result
;
cv
::
Mat
cv
::
findFundamentalMat
(
InputArray
_points1
,
InputArray
_points2
,
OutputArray
_mask
,
int
method
,
double
param1
,
double
param2
)
{
return
cv
::
findFundamentalMat
(
_points1
,
_points2
,
method
,
param1
,
param2
,
_mask
);
}
}
CV_IMPL
void
cvComputeCorrespondEpilines
(
const
CvMat
*
points
,
int
pointImageID
,
void
cv
::
computeCorrespondEpilines
(
InputArray
_points
,
int
whichImage
,
const
CvMat
*
fmatrix
,
CvMat
*
lines
)
InputArray
_Fmat
,
OutputArray
_
lines
)
{
{
int
abc_stride
,
abc_plane_stride
,
abc_elem_size
;
int
plane_stride
,
stride
,
elem_size
;
int
i
,
dims
,
count
,
depth
,
cn
,
abc_dims
,
abc_count
,
abc_depth
,
abc_cn
;
uchar
*
ap
,
*
bp
,
*
cp
;
const
uchar
*
xp
,
*
yp
,
*
zp
;
double
f
[
9
];
double
f
[
9
];
CvMat
F
=
cvMat
(
3
,
3
,
CV_64F
,
f
);
Mat
tempF
(
3
,
3
,
CV_64F
,
f
);
Mat
points
=
_points
.
getMat
(),
F
=
_Fmat
.
getMat
();
if
(
!
CV_IS_MAT
(
points
)
)
CV_Error
(
!
points
?
CV_StsNullPtr
:
CV_StsBadArg
,
"points parameter is not a valid matrix"
);
depth
=
CV_MAT_DEPTH
(
points
->
type
);
cn
=
CV_MAT_CN
(
points
->
type
);
if
(
(
depth
!=
CV_32F
&&
depth
!=
CV_64F
)
||
(
cn
!=
1
&&
cn
!=
2
&&
cn
!=
3
)
)
CV_Error
(
CV_StsUnsupportedFormat
,
"The format of point matrix is unsupported"
);
if
(
cn
>
1
)
{
dims
=
cn
;
CV_Assert
(
points
->
rows
==
1
||
points
->
cols
==
1
);
count
=
points
->
rows
*
points
->
cols
;
}
else
if
(
points
->
rows
>
points
->
cols
)
{
dims
=
cn
*
points
->
cols
;
count
=
points
->
rows
;
}
else
{
if
(
(
points
->
rows
>
1
&&
cn
>
1
)
||
(
points
->
rows
==
1
&&
cn
==
1
)
)
CV_Error
(
CV_StsBadSize
,
"The point matrix does not have a proper layout (2xn, 3xn, nx2 or nx3)"
);
dims
=
points
->
rows
;
count
=
points
->
cols
;
}
if
(
dims
!=
2
&&
dims
!=
3
)
CV_Error
(
CV_StsOutOfRange
,
"The dimensionality of points must be 2 or 3"
);
if
(
!
CV_IS_MAT
(
fmatrix
)
)
CV_Error
(
!
fmatrix
?
CV_StsNullPtr
:
CV_StsBadArg
,
"fmatrix is not a valid matrix"
);
if
(
CV_MAT_TYPE
(
fmatrix
->
type
)
!=
CV_32FC1
&&
CV_MAT_TYPE
(
fmatrix
->
type
)
!=
CV_64FC1
)
CV_Error
(
CV_StsUnsupportedFormat
,
"fundamental matrix must have 32fC1 or 64fC1 type"
);
if
(
fmatrix
->
cols
!=
3
||
fmatrix
->
rows
!=
3
)
CV_Error
(
CV_StsBadSize
,
"fundamental matrix must be 3x3"
);
if
(
!
CV_IS_MAT
(
lines
)
)
CV_Error
(
!
lines
?
CV_StsNullPtr
:
CV_StsBadArg
,
"lines parameter is not a valid matrix"
);
abc_depth
=
CV_MAT_DEPTH
(
lines
->
type
);
if
(
!
points
.
isContinuous
()
)
abc_cn
=
CV_MAT_CN
(
lines
->
type
);
points
=
points
.
clone
();
if
(
(
abc_depth
!=
CV_32F
&&
abc_depth
!=
CV_64F
)
||
(
abc_cn
!=
1
&&
abc_cn
!=
3
)
)
CV_Error
(
CV_StsUnsupportedFormat
,
"The format of the matrix of lines is unsupported"
);
if
(
abc_cn
>
1
)
int
npoints
=
points
.
checkVector
(
2
);
{
if
(
npoints
<
0
)
abc_dims
=
abc_cn
;
CV_Assert
(
lines
->
rows
==
1
||
lines
->
cols
==
1
);
abc_count
=
lines
->
rows
*
lines
->
cols
;
}
else
if
(
lines
->
rows
>
lines
->
cols
)
{
abc_dims
=
abc_cn
*
lines
->
cols
;
abc_count
=
lines
->
rows
;
}
else
{
{
if
(
(
lines
->
rows
>
1
&&
abc_cn
>
1
)
||
(
lines
->
rows
==
1
&&
abc_cn
==
1
)
)
npoints
=
points
.
checkVector
(
3
);
CV_Error
(
CV_StsBadSize
,
"The lines matrix does not have a proper layout (3xn or nx3)"
);
if
(
npoints
<
0
)
abc_dims
=
lines
->
rows
;
CV_Error
(
CV_StsBadArg
,
"The input should be a 2D or 3D point set"
);
abc_count
=
lines
->
cols
;
Mat
temp
;
convertPointsFromHomogeneous
(
points
,
temp
);
points
=
temp
;
}
}
int
depth
=
points
.
depth
();
CV_Assert
(
depth
==
CV_32F
||
depth
==
CV_32S
||
depth
==
CV_64F
);
if
(
abc_dims
!=
3
)
CV_Assert
(
F
.
size
()
==
Size
(
3
,
3
));
CV_Error
(
CV_StsOutOfRange
,
"The lines matrix does not have a proper layout (3xn or nx3)"
);
F
.
convertTo
(
tempF
,
CV_64F
);
if
(
whichImage
==
2
)
if
(
abc_count
!=
count
)
transpose
(
tempF
,
tempF
);
CV_Error
(
CV_StsUnmatchedSizes
,
"The numbers of points and lines are different"
);
elem_size
=
CV_ELEM_SIZE
(
depth
);
abc_elem_size
=
CV_ELEM_SIZE
(
abc_depth
);
if
(
cn
==
1
&&
points
->
rows
==
dims
)
int
ltype
=
CV_MAKETYPE
(
MAX
(
depth
,
CV_32F
),
3
);
_lines
.
create
(
npoints
,
1
,
ltype
);
Mat
lines
=
_lines
.
getMat
();
if
(
!
lines
.
isContinuous
()
)
{
{
plane_stride
=
points
->
step
;
_lines
.
release
();
stride
=
elem_size
;
_lines
.
create
(
npoints
,
1
,
ltype
);
}
lines
=
_lines
.
getMat
();
else
{
plane_stride
=
elem_size
;
stride
=
points
->
rows
==
1
?
dims
*
elem_size
:
points
->
step
;
}
}
CV_Assert
(
lines
.
isContinuous
());
if
(
abc_cn
==
1
&&
lines
->
rows
==
3
)
if
(
depth
==
CV_32S
||
depth
==
CV_32F
)
{
{
abc_plane_stride
=
lines
->
step
;
const
Point
*
ptsi
=
(
const
Point
*
)
points
.
data
;
abc_stride
=
abc_elem_size
;
const
Point2f
*
ptsf
=
(
const
Point2f
*
)
points
.
data
;
Point3f
*
dstf
=
lines
.
ptr
<
Point3f
>
();
for
(
int
i
=
0
;
i
<
npoints
;
i
++
)
{
Point2f
pt
=
depth
==
CV_32F
?
ptsf
[
i
]
:
Point2f
((
float
)
ptsi
[
i
].
x
,
(
float
)
ptsi
[
i
].
y
);
double
a
=
f
[
0
]
*
pt
.
x
+
f
[
1
]
*
pt
.
y
+
f
[
2
];
double
b
=
f
[
3
]
*
pt
.
x
+
f
[
4
]
*
pt
.
y
+
f
[
5
];
double
c
=
f
[
6
]
*
pt
.
x
+
f
[
7
]
*
pt
.
y
+
f
[
8
];
double
nu
=
a
*
a
+
b
*
b
;
nu
=
nu
?
1.
/
std
::
sqrt
(
nu
)
:
1.
;
a
*=
nu
;
b
*=
nu
;
c
*=
nu
;
dstf
[
i
]
=
Point3f
((
float
)
a
,
(
float
)
b
,
(
float
)
c
);
}
}
}
else
else
{
{
abc_plane_stride
=
abc_elem_size
;
const
Point2d
*
ptsd
=
(
const
Point2d
*
)
points
.
data
;
abc_stride
=
lines
->
rows
==
1
?
3
*
abc_elem_size
:
lines
->
step
;
Point3d
*
dstd
=
lines
.
ptr
<
Point3d
>
();
}
for
(
int
i
=
0
;
i
<
npoints
;
i
++
)
cvConvert
(
fmatrix
,
&
F
);
if
(
pointImageID
==
2
)
cvTranspose
(
&
F
,
&
F
);
xp
=
points
->
data
.
ptr
;
yp
=
xp
+
plane_stride
;
zp
=
dims
==
3
?
yp
+
plane_stride
:
0
;
ap
=
lines
->
data
.
ptr
;
bp
=
ap
+
abc_plane_stride
;
cp
=
bp
+
abc_plane_stride
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
double
x
,
y
,
z
=
1.
;
double
a
,
b
,
c
,
nu
;
if
(
depth
==
CV_32F
)
{
{
x
=
*
(
float
*
)
xp
;
y
=
*
(
float
*
)
yp
;
Point2d
pt
=
ptsd
[
i
];
if
(
zp
)
double
a
=
f
[
0
]
*
pt
.
x
+
f
[
1
]
*
pt
.
y
+
f
[
2
];
z
=
*
(
float
*
)
zp
,
zp
+=
stride
;
double
b
=
f
[
3
]
*
pt
.
x
+
f
[
4
]
*
pt
.
y
+
f
[
5
];
double
c
=
f
[
6
]
*
pt
.
x
+
f
[
7
]
*
pt
.
y
+
f
[
8
];
double
nu
=
a
*
a
+
b
*
b
;
nu
=
nu
?
1.
/
std
::
sqrt
(
nu
)
:
1.
;
a
*=
nu
;
b
*=
nu
;
c
*=
nu
;
dstd
[
i
]
=
Point3d
(
a
,
b
,
c
);
}
}
else
{
x
=
*
(
double
*
)
xp
;
y
=
*
(
double
*
)
yp
;
if
(
zp
)
z
=
*
(
double
*
)
zp
,
zp
+=
stride
;
}
xp
+=
stride
;
yp
+=
stride
;
a
=
f
[
0
]
*
x
+
f
[
1
]
*
y
+
f
[
2
]
*
z
;
b
=
f
[
3
]
*
x
+
f
[
4
]
*
y
+
f
[
5
]
*
z
;
c
=
f
[
6
]
*
x
+
f
[
7
]
*
y
+
f
[
8
]
*
z
;
nu
=
a
*
a
+
b
*
b
;
nu
=
nu
?
1.
/
sqrt
(
nu
)
:
1.
;
a
*=
nu
;
b
*=
nu
;
c
*=
nu
;
if
(
abc_depth
==
CV_32F
)
{
*
(
float
*
)
ap
=
(
float
)
a
;
*
(
float
*
)
bp
=
(
float
)
b
;
*
(
float
*
)
cp
=
(
float
)
c
;
}
else
{
*
(
double
*
)
ap
=
a
;
*
(
double
*
)
bp
=
b
;
*
(
double
*
)
cp
=
c
;
}
ap
+=
abc_stride
;
bp
+=
abc_stride
;
cp
+=
abc_stride
;
}
}
}
}
void
cv
::
convertPointsFromHomogeneous
(
InputArray
_src
,
OutputArray
_dst
)
CV_IMPL
void
cvConvertPointsHomogeneous
(
const
CvMat
*
src
,
CvMat
*
dst
)
{
{
Ptr
<
CvMat
>
temp
,
denom
;
Mat
src
=
_src
.
getMat
();
if
(
!
src
.
isContinuous
()
)
int
i
,
s_count
,
s_dims
,
d_count
,
d_dims
;
src
=
src
.
clone
();
CvMat
_src
,
_dst
,
_ones
;
int
i
,
npoints
=
src
.
checkVector
(
3
),
depth
=
src
.
depth
(),
cn
=
3
;
CvMat
*
ones
=
0
;
if
(
npoints
<
0
)
if
(
!
CV_IS_MAT
(
src
)
)
CV_Error
(
!
src
?
CV_StsNullPtr
:
CV_StsBadArg
,
"The input parameter is not a valid matrix"
);
if
(
!
CV_IS_MAT
(
dst
)
)
CV_Error
(
!
dst
?
CV_StsNullPtr
:
CV_StsBadArg
,
"The output parameter is not a valid matrix"
);
if
(
src
==
dst
||
src
->
data
.
ptr
==
dst
->
data
.
ptr
)
{
if
(
src
!=
dst
&&
(
!
CV_ARE_TYPES_EQ
(
src
,
dst
)
||
!
CV_ARE_SIZES_EQ
(
src
,
dst
))
)
CV_Error
(
CV_StsBadArg
,
"Invalid inplace operation"
);
return
;
}
if
(
src
->
rows
>
src
->
cols
)
{
if
(
!
((
src
->
cols
>
1
)
^
(
CV_MAT_CN
(
src
->
type
)
>
1
))
)
CV_Error
(
CV_StsBadSize
,
"Either the number of channels or columns or rows must be =1"
);
s_dims
=
CV_MAT_CN
(
src
->
type
)
*
src
->
cols
;
s_count
=
src
->
rows
;
}
else
{
{
if
(
!
((
src
->
rows
>
1
)
^
(
CV_MAT_CN
(
src
->
type
)
>
1
))
)
npoints
=
src
.
checkVector
(
4
);
CV_Error
(
CV_StsBadSize
,
"Either the number of channels or columns or rows must be =1"
);
CV_Assert
(
npoints
>=
0
);
cn
=
4
;
s_dims
=
CV_MAT_CN
(
src
->
type
)
*
src
->
rows
;
s_count
=
src
->
cols
;
}
}
CV_Assert
(
npoints
>=
0
&&
(
depth
==
CV_32S
||
depth
==
CV_32F
||
depth
==
CV_64F
));
if
(
src
->
rows
==
1
||
src
->
cols
==
1
)
int
dtype
=
CV_MAKETYPE
(
depth
<=
CV_32F
?
CV_32F
:
CV_64F
,
cn
-
1
);
src
=
cvReshape
(
src
,
&
_src
,
1
,
s_count
);
_dst
.
create
(
npoints
,
1
,
dtype
);
Mat
dst
=
_dst
.
getMat
();
if
(
dst
->
rows
>
dst
->
cols
)
if
(
!
dst
.
isContinuous
()
)
{
if
(
!
((
dst
->
cols
>
1
)
^
(
CV_MAT_CN
(
dst
->
type
)
>
1
))
)
CV_Error
(
CV_StsBadSize
,
"Either the number of channels or columns or rows in the input matrix must be =1"
);
d_dims
=
CV_MAT_CN
(
dst
->
type
)
*
dst
->
cols
;
d_count
=
dst
->
rows
;
}
else
{
{
if
(
!
((
dst
->
rows
>
1
)
^
(
CV_MAT_CN
(
dst
->
type
)
>
1
))
)
_dst
.
release
();
CV_Error
(
CV_StsBadSize
,
_dst
.
create
(
npoints
,
1
,
dtype
);
"Either the number of channels or columns or rows in the output matrix must be =1"
);
dst
=
_dst
.
getMat
();
d_dims
=
CV_MAT_CN
(
dst
->
type
)
*
dst
->
rows
;
d_count
=
dst
->
cols
;
}
}
CV_Assert
(
dst
.
isContinuous
()
);
if
(
dst
->
rows
==
1
||
dst
->
cols
==
1
)
if
(
depth
==
CV_32S
)
dst
=
cvReshape
(
dst
,
&
_dst
,
1
,
d_count
);
if
(
s_count
!=
d_count
)
CV_Error
(
CV_StsUnmatchedSizes
,
"Both matrices must have the same number of points"
);
if
(
CV_MAT_DEPTH
(
src
->
type
)
<
CV_32F
||
CV_MAT_DEPTH
(
dst
->
type
)
<
CV_32F
)
CV_Error
(
CV_StsUnsupportedFormat
,
"Both matrices must be floating-point (single or double precision)"
);
if
(
s_dims
<
2
||
s_dims
>
4
||
d_dims
<
2
||
d_dims
>
4
)
CV_Error
(
CV_StsOutOfRange
,
"Both input and output point dimensionality must be 2, 3 or 4"
);
if
(
s_dims
<
d_dims
-
1
||
s_dims
>
d_dims
+
1
)
CV_Error
(
CV_StsUnmatchedSizes
,
"The dimensionalities of input and output point sets differ too much"
);
if
(
s_dims
==
d_dims
-
1
)
{
{
if
(
d_count
==
dst
->
rows
)
if
(
cn
==
3
)
{
{
ones
=
cvGetSubRect
(
dst
,
&
_ones
,
cvRect
(
s_dims
,
0
,
1
,
d_count
));
const
Point3i
*
sptr
=
(
const
Point3i
*
)
src
.
data
;
dst
=
cvGetSubRect
(
dst
,
&
_dst
,
cvRect
(
0
,
0
,
s_dims
,
d_count
));
Point2f
*
dptr
=
(
Point2f
*
)
dst
.
data
;
for
(
i
=
0
;
i
<
npoints
;
i
++
)
{
float
scale
=
sptr
[
i
].
z
!=
0
?
1.
f
/
sptr
[
i
].
z
:
1.
f
;
dptr
[
i
]
=
Point2f
(
sptr
[
i
].
x
*
scale
,
sptr
[
i
].
y
*
scale
);
}
}
}
else
else
{
{
ones
=
cvGetSubRect
(
dst
,
&
_ones
,
cvRect
(
0
,
s_dims
,
d_count
,
1
));
const
Vec4i
*
sptr
=
(
const
Vec4i
*
)
src
.
data
;
dst
=
cvGetSubRect
(
dst
,
&
_dst
,
cvRect
(
0
,
0
,
d_count
,
s_dims
));
Point3f
*
dptr
=
(
Point3f
*
)
dst
.
data
;
for
(
i
=
0
;
i
<
npoints
;
i
++
)
{
float
scale
=
sptr
[
i
][
3
]
!=
0
?
1.
f
/
sptr
[
i
][
3
]
:
1.
f
;
dptr
[
i
]
=
Point3f
(
sptr
[
i
][
0
]
*
scale
,
sptr
[
i
][
1
]
*
scale
,
sptr
[
i
][
2
]
*
scale
);
}
}
}
}
}
else
if
(
depth
==
CV_32F
)
if
(
s_dims
<=
d_dims
)
{
{
if
(
src
->
rows
==
dst
->
rows
&&
src
->
cols
==
dst
->
cols
)
if
(
cn
==
3
)
{
{
if
(
CV_ARE_TYPES_EQ
(
src
,
dst
)
)
const
Point3f
*
sptr
=
(
const
Point3f
*
)
src
.
data
;
cvCopy
(
src
,
dst
);
Point2f
*
dptr
=
(
Point2f
*
)
dst
.
data
;
else
for
(
i
=
0
;
i
<
npoints
;
i
++
)
cvConvert
(
src
,
dst
);
{
float
scale
=
sptr
[
i
].
z
!=
0.
f
?
1.
f
/
sptr
[
i
].
z
:
1.
f
;
dptr
[
i
]
=
Point2f
(
sptr
[
i
].
x
*
scale
,
sptr
[
i
].
y
*
scale
);
}
}
}
else
else
{
{
if
(
!
CV_ARE_TYPES_EQ
(
src
,
dst
))
const
Vec4f
*
sptr
=
(
const
Vec4f
*
)
src
.
data
;
Point3f
*
dptr
=
(
Point3f
*
)
dst
.
data
;
for
(
i
=
0
;
i
<
npoints
;
i
++
)
{
{
temp
=
cvCreateMat
(
src
->
rows
,
src
->
cols
,
dst
->
type
);
float
scale
=
sptr
[
i
][
3
]
!=
0.
f
?
1.
f
/
sptr
[
i
][
3
]
:
1.
f
;
cvConvert
(
src
,
temp
);
dptr
[
i
]
=
Point3f
(
sptr
[
i
][
0
]
*
scale
,
sptr
[
i
][
1
]
*
scale
,
sptr
[
i
][
2
]
*
scale
);
src
=
temp
;
}
}
cvTranspose
(
src
,
dst
);
}
}
if
(
ones
)
cvSet
(
ones
,
cvRealScalar
(
1.
)
);
}
}
else
else
if
(
depth
==
CV_64F
)
{
{
int
s_plane_stride
,
s_stride
,
d_plane_stride
,
d_stride
,
elem_size
;
if
(
cn
==
3
)
if
(
!
CV_ARE_TYPES_EQ
(
src
,
dst
))
{
temp
=
cvCreateMat
(
src
->
rows
,
src
->
cols
,
dst
->
type
);
cvConvert
(
src
,
temp
);
src
=
temp
;
}
elem_size
=
CV_ELEM_SIZE
(
src
->
type
);
if
(
s_count
==
src
->
cols
)
s_plane_stride
=
src
->
step
/
elem_size
,
s_stride
=
1
;
else
s_stride
=
src
->
step
/
elem_size
,
s_plane_stride
=
1
;
if
(
d_count
==
dst
->
cols
)
d_plane_stride
=
dst
->
step
/
elem_size
,
d_stride
=
1
;
else
d_stride
=
dst
->
step
/
elem_size
,
d_plane_stride
=
1
;
denom
=
cvCreateMat
(
1
,
d_count
,
dst
->
type
);
if
(
CV_MAT_DEPTH
(
dst
->
type
)
==
CV_32F
)
{
{
const
float
*
xs
=
src
->
data
.
fl
;
const
Point3d
*
sptr
=
(
const
Point3d
*
)
src
.
data
;
const
float
*
ys
=
xs
+
s_plane_stride
;
Point2d
*
dptr
=
(
Point2d
*
)
dst
.
data
;
const
float
*
zs
=
0
;
for
(
i
=
0
;
i
<
npoints
;
i
++
)
const
float
*
ws
=
xs
+
(
s_dims
-
1
)
*
s_plane_stride
;
float
*
iw
=
denom
->
data
.
fl
;
float
*
xd
=
dst
->
data
.
fl
;
float
*
yd
=
xd
+
d_plane_stride
;
float
*
zd
=
0
;
if
(
d_dims
==
3
)
{
{
zs
=
ys
+
s_plane_stride
;
double
scale
=
sptr
[
i
].
z
!=
0.
?
1.
/
sptr
[
i
].
z
:
1.
;
zd
=
yd
+
d_plane_stride
;
dptr
[
i
]
=
Point2d
(
sptr
[
i
].
x
*
scale
,
sptr
[
i
].
y
*
scale
)
;
}
}
for
(
i
=
0
;
i
<
d_count
;
i
++
,
ws
+=
s_stride
)
{
float
t
=
*
ws
;
iw
[
i
]
=
fabs
((
double
)
t
)
>
FLT_EPSILON
?
t
:
1.
f
;
}
cvDiv
(
0
,
denom
,
denom
);
if
(
d_dims
==
3
)
for
(
i
=
0
;
i
<
d_count
;
i
++
)
{
float
w
=
iw
[
i
];
float
x
=
*
xs
*
w
,
y
=
*
ys
*
w
,
z
=
*
zs
*
w
;
xs
+=
s_stride
;
ys
+=
s_stride
;
zs
+=
s_stride
;
*
xd
=
x
;
*
yd
=
y
;
*
zd
=
z
;
xd
+=
d_stride
;
yd
+=
d_stride
;
zd
+=
d_stride
;
}
else
for
(
i
=
0
;
i
<
d_count
;
i
++
)
{
float
w
=
iw
[
i
];
float
x
=
*
xs
*
w
,
y
=
*
ys
*
w
;
xs
+=
s_stride
;
ys
+=
s_stride
;
*
xd
=
x
;
*
yd
=
y
;
xd
+=
d_stride
;
yd
+=
d_stride
;
}
}
}
else
else
{
{
const
double
*
xs
=
src
->
data
.
db
;
const
Vec4d
*
sptr
=
(
const
Vec4d
*
)
src
.
data
;
const
double
*
ys
=
xs
+
s_plane_stride
;
Point3d
*
dptr
=
(
Point3d
*
)
dst
.
data
;
const
double
*
zs
=
0
;
for
(
i
=
0
;
i
<
npoints
;
i
++
)
const
double
*
ws
=
xs
+
(
s_dims
-
1
)
*
s_plane_stride
;
double
*
iw
=
denom
->
data
.
db
;
double
*
xd
=
dst
->
data
.
db
;
double
*
yd
=
xd
+
d_plane_stride
;
double
*
zd
=
0
;
if
(
d_dims
==
3
)
{
{
zs
=
ys
+
s_plane_stride
;
double
scale
=
sptr
[
i
][
3
]
!=
0.
f
?
1.
/
sptr
[
i
][
3
]
:
1.
;
zd
=
yd
+
d_plane_stride
;
dptr
[
i
]
=
Point3d
(
sptr
[
i
][
0
]
*
scale
,
sptr
[
i
][
1
]
*
scale
,
sptr
[
i
][
2
]
*
scale
)
;
}
}
for
(
i
=
0
;
i
<
d_count
;
i
++
,
ws
+=
s_stride
)
{
double
t
=
*
ws
;
iw
[
i
]
=
fabs
(
t
)
>
DBL_EPSILON
?
t
:
1.
;
}
cvDiv
(
0
,
denom
,
denom
);
if
(
d_dims
==
3
)
for
(
i
=
0
;
i
<
d_count
;
i
++
)
{
double
w
=
iw
[
i
];
double
x
=
*
xs
*
w
,
y
=
*
ys
*
w
,
z
=
*
zs
*
w
;
xs
+=
s_stride
;
ys
+=
s_stride
;
zs
+=
s_stride
;
*
xd
=
x
;
*
yd
=
y
;
*
zd
=
z
;
xd
+=
d_stride
;
yd
+=
d_stride
;
zd
+=
d_stride
;
}
else
for
(
i
=
0
;
i
<
d_count
;
i
++
)
{
double
w
=
iw
[
i
];
double
x
=
*
xs
*
w
,
y
=
*
ys
*
w
;
xs
+=
s_stride
;
ys
+=
s_stride
;
*
xd
=
x
;
*
yd
=
y
;
xd
+=
d_stride
;
yd
+=
d_stride
;
}
}
}
}
}
else
CV_Error
(
CV_StsUnsupportedFormat
,
""
);
}
}
cv
::
Mat
cv
::
findHomography
(
InputArray
_points1
,
InputArray
_points2
,
int
method
,
double
ransacReprojThreshold
,
OutputArray
_mask
)
void
cv
::
convertPointsToHomogeneous
(
InputArray
_src
,
OutputArray
_dst
)
{
{
Mat
points1
=
_points1
.
getMat
(),
points2
=
_points2
.
getMat
();
Mat
src
=
_src
.
getMat
();
int
npoints
=
points1
.
checkVector
(
2
);
if
(
!
src
.
isContinuous
()
)
CV_Assert
(
npoints
>=
0
&&
points2
.
checkVector
(
2
)
==
npoints
&&
src
=
src
.
clone
();
points1
.
type
()
==
points2
.
type
());
int
i
,
npoints
=
src
.
checkVector
(
2
),
depth
=
src
.
depth
(),
cn
=
2
;
if
(
npoints
<
0
)
Mat
H
(
3
,
3
,
CV_64F
);
CvMat
_pt1
=
points1
,
_pt2
=
points2
;
CvMat
matH
=
H
,
c_mask
,
*
p_mask
=
0
;
if
(
_mask
.
needed
()
)
{
{
_mask
.
create
(
npoints
,
1
,
CV_8U
,
-
1
,
true
);
npoints
=
src
.
checkVector
(
3
);
p_mask
=
&
(
c_mask
=
_mask
.
getMat
());
CV_Assert
(
npoints
>=
0
);
cn
=
3
;
}
}
bool
ok
=
cvFindHomography
(
&
_pt1
,
&
_pt2
,
&
matH
,
method
,
ransacReprojThreshold
,
p_mask
)
>
0
;
CV_Assert
(
npoints
>=
0
&&
(
depth
==
CV_32S
||
depth
==
CV_32F
||
depth
==
CV_64F
));
if
(
!
ok
)
H
=
Scalar
(
0
);
return
H
;
}
cv
::
Mat
cv
::
findHomography
(
InputArray
_points1
,
InputArray
_points2
,
OutputArray
_mask
,
int
method
,
double
ransacReprojThreshold
)
{
return
cv
::
findHomography
(
_points1
,
_points2
,
method
,
ransacReprojThreshold
,
_mask
);
}
cv
::
Mat
cv
::
findFundamentalMat
(
InputArray
_points1
,
InputArray
_points2
,
int
dtype
=
CV_MAKETYPE
(
depth
<=
CV_32F
?
CV_32F
:
CV_64F
,
cn
+
1
);
int
method
,
double
param1
,
double
param2
,
_dst
.
create
(
npoints
,
1
,
dtype
);
OutputArray
_mask
)
Mat
dst
=
_dst
.
getMat
();
{
if
(
!
dst
.
isContinuous
()
)
Mat
points1
=
_points1
.
getMat
(),
points2
=
_points2
.
getMat
();
int
npoints
=
points1
.
checkVector
(
2
);
CV_Assert
(
npoints
>=
0
&&
points2
.
checkVector
(
2
)
==
npoints
&&
points1
.
type
()
==
points2
.
type
());
Mat
F
(
method
==
CV_FM_7POINT
?
9
:
3
,
3
,
CV_64F
);
CvMat
_pt1
=
points1
,
_pt2
=
points2
;
CvMat
matF
=
F
,
c_mask
,
*
p_mask
=
0
;
if
(
_mask
.
needed
()
)
{
{
_mask
.
create
(
npoints
,
1
,
CV_8U
,
-
1
,
true
);
_dst
.
release
();
p_mask
=
&
(
c_mask
=
_mask
.
getMat
());
_dst
.
create
(
npoints
,
1
,
dtype
);
dst
=
_dst
.
getMat
();
}
}
int
n
=
cvFindFundamentalMat
(
&
_pt1
,
&
_pt2
,
&
matF
,
method
,
param1
,
param2
,
p_mask
);
CV_Assert
(
dst
.
isContinuous
()
);
if
(
n
<=
0
)
F
=
Scalar
(
0
);
if
(
n
==
1
)
F
=
F
.
rowRange
(
0
,
3
);
return
F
;
}
cv
::
Mat
cv
::
findFundamentalMat
(
InputArray
_points1
,
InputArray
_points2
,
OutputArray
_mask
,
int
method
,
double
param1
,
double
param2
)
{
return
cv
::
findFundamentalMat
(
_points1
,
_points2
,
method
,
param1
,
param2
,
_mask
);
}
void
cv
::
computeCorrespondEpilines
(
InputArray
_points
,
int
whichImage
,
if
(
depth
==
CV_32S
)
InputArray
_Fmat
,
OutputArray
_lines
)
{
Mat
points
=
_points
.
getMat
(),
F
=
_Fmat
.
getMat
();
int
npoints
=
points
.
checkVector
(
2
);
if
(
npoints
<
0
)
npoints
=
points
.
checkVector
(
3
);
CV_Assert
(
npoints
>=
0
&&
(
points
.
depth
()
==
CV_32F
||
points
.
depth
()
==
CV_32S
));
_lines
.
create
(
npoints
,
1
,
CV_32FC3
,
-
1
,
true
);
CvMat
c_points
=
points
,
c_lines
=
_lines
.
getMat
(),
c_F
=
F
;
cvComputeCorrespondEpilines
(
&
c_points
,
whichImage
,
&
c_F
,
&
c_lines
);
}
void
cv
::
convertPointsFromHomogeneous
(
InputArray
_src
,
OutputArray
_dst
)
{
Mat
src
=
_src
.
getMat
();
int
npoints
=
src
.
checkVector
(
3
),
cn
=
3
;
if
(
npoints
<
0
)
{
{
npoints
=
src
.
checkVector
(
4
);
if
(
cn
==
2
)
if
(
npoints
>=
0
)
{
cn
=
4
;
const
Point2i
*
sptr
=
(
const
Point2i
*
)
src
.
data
;
Point3i
*
dptr
=
(
Point3i
*
)
dst
.
data
;
for
(
i
=
0
;
i
<
npoints
;
i
++
)
dptr
[
i
]
=
Point3i
(
sptr
[
i
].
x
,
sptr
[
i
].
y
,
1
);
}
else
{
const
Point3i
*
sptr
=
(
const
Point3i
*
)
src
.
data
;
Vec4i
*
dptr
=
(
Vec4i
*
)
dst
.
data
;
for
(
i
=
0
;
i
<
npoints
;
i
++
)
dptr
[
i
]
=
Vec4i
(
sptr
[
i
].
x
,
sptr
[
i
].
y
,
sptr
[
i
].
z
,
1
);
}
}
}
CV_Assert
(
npoints
>=
0
&&
(
src
.
depth
()
==
CV_32F
||
src
.
depth
()
==
CV_32S
));
else
if
(
depth
==
CV_32F
)
_dst
.
create
(
npoints
,
1
,
CV_MAKETYPE
(
CV_32F
,
cn
-
1
));
CvMat
c_src
=
src
,
c_dst
=
_dst
.
getMat
();
cvConvertPointsHomogeneous
(
&
c_src
,
&
c_dst
);
}
void
cv
::
convertPointsToHomogeneous
(
InputArray
_src
,
OutputArray
_dst
)
{
Mat
src
=
_src
.
getMat
();
int
npoints
=
src
.
checkVector
(
2
),
cn
=
2
;
if
(
npoints
<
0
)
{
{
npoints
=
src
.
checkVector
(
3
);
if
(
cn
==
2
)
if
(
npoints
>=
0
)
{
cn
=
3
;
const
Point2f
*
sptr
=
(
const
Point2f
*
)
src
.
data
;
Point3f
*
dptr
=
(
Point3f
*
)
dst
.
data
;
for
(
i
=
0
;
i
<
npoints
;
i
++
)
dptr
[
i
]
=
Point3f
(
sptr
[
i
].
x
,
sptr
[
i
].
y
,
1.
f
);
}
else
{
const
Point3f
*
sptr
=
(
const
Point3f
*
)
src
.
data
;
Vec4f
*
dptr
=
(
Vec4f
*
)
dst
.
data
;
for
(
i
=
0
;
i
<
npoints
;
i
++
)
dptr
[
i
]
=
Vec4f
(
sptr
[
i
].
x
,
sptr
[
i
].
y
,
sptr
[
i
].
z
,
1.
f
);
}
}
}
CV_Assert
(
npoints
>=
0
&&
(
src
.
depth
()
==
CV_32F
||
src
.
depth
()
==
CV_32S
));
else
if
(
depth
==
CV_64F
)
{
_dst
.
create
(
npoints
,
1
,
CV_MAKETYPE
(
CV_32F
,
cn
+
1
));
if
(
cn
==
2
)
CvMat
c_src
=
src
,
c_dst
=
_dst
.
getMat
();
{
cvConvertPointsHomogeneous
(
&
c_src
,
&
c_dst
);
const
Point2d
*
sptr
=
(
const
Point2d
*
)
src
.
data
;
Point3d
*
dptr
=
(
Point3d
*
)
dst
.
data
;
for
(
i
=
0
;
i
<
npoints
;
i
++
)
dptr
[
i
]
=
Point3d
(
sptr
[
i
].
x
,
sptr
[
i
].
y
,
1.
);
}
else
{
const
Point3d
*
sptr
=
(
const
Point3d
*
)
src
.
data
;
Vec4d
*
dptr
=
(
Vec4d
*
)
dst
.
data
;
for
(
i
=
0
;
i
<
npoints
;
i
++
)
dptr
[
i
]
=
Vec4d
(
sptr
[
i
].
x
,
sptr
[
i
].
y
,
sptr
[
i
].
z
,
1.
);
}
}
else
CV_Error
(
CV_StsUnsupportedFormat
,
""
);
}
}
void
cv
::
convertPointsHomogeneous
(
InputArray
_src
,
OutputArray
_dst
)
void
cv
::
convertPointsHomogeneous
(
InputArray
_src
,
OutputArray
_dst
)
{
{
int
stype
=
_src
.
type
(),
dtype
=
_dst
.
type
();
int
stype
=
_src
.
type
(),
dtype
=
_dst
.
type
();
...
...
modules/calib3d/src/levmarq.cpp
0 → 100644
View file @
6569a585
/*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, Intel Corporation, 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*/
#include "precomp.hpp"
#include <stdio.h>
/*
This is translation to C++ of the Matlab's LMSolve package by Miroslav Balda.
Here is the original copyright:
============================================================================
Copyright (c) 2007, Miroslav Balda
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
namespace
cv
{
class
LMSolverImpl
:
public
LMSolver
{
public
:
LMSolverImpl
()
:
maxIters
(
100
)
{
init
();
};
LMSolverImpl
(
const
Ptr
<
LMSolver
::
Callback
>&
_cb
,
int
_maxIters
)
:
cb
(
_cb
),
maxIters
(
_maxIters
)
{
init
();
}
void
init
()
{
epsx
=
epsf
=
FLT_EPSILON
;
printInterval
=
0
;
}
int
run
(
InputOutputArray
_param0
)
const
{
Mat
param0
=
_param0
.
getMat
(),
x
,
xd
,
r
,
rd
,
J
,
A
,
Ap
,
v
,
temp_d
,
d
;
int
ptype
=
param0
.
type
();
CV_Assert
(
(
param0
.
cols
==
1
||
param0
.
rows
==
1
)
&&
(
ptype
==
CV_32F
||
ptype
==
CV_64F
));
CV_Assert
(
!
cb
.
empty
()
);
int
lx
=
param0
.
rows
+
param0
.
cols
-
1
;
param0
.
convertTo
(
x
,
CV_64F
);
if
(
x
.
cols
!=
1
)
transpose
(
x
,
x
);
if
(
!
cb
->
compute
(
x
,
r
,
J
)
)
return
-
1
;
double
S
=
norm
(
r
,
NORM_L2SQR
);
int
nfJ
=
2
;
mulTransposed
(
J
,
A
,
true
);
gemm
(
J
,
r
,
1
,
noArray
(),
0
,
v
,
GEMM_1_T
);
Mat
D
=
A
.
diag
().
clone
();
const
double
Rlo
=
0.25
,
Rhi
=
0.75
;
double
lambda
=
1
,
lc
=
0.75
;
int
i
,
iter
=
0
;
if
(
printInterval
!=
0
)
{
printf
(
"************************************************************************************
\n
"
);
printf
(
"
\t
itr
\t
nfJ
\t\t
SUM(r^2)
\t\t
x
\t\t
dx
\t\t
l
\t\t
lc
\n
"
);
printf
(
"************************************************************************************
\n
"
);
}
for
(
;;
)
{
CV_Assert
(
A
.
type
()
==
CV_64F
&&
A
.
rows
==
lx
);
A
.
copyTo
(
Ap
);
for
(
i
=
0
;
i
<
lx
;
i
++
)
Ap
.
at
<
double
>
(
i
,
i
)
+=
lambda
*
D
.
at
<
double
>
(
i
);
solve
(
Ap
,
v
,
d
,
DECOMP_EIG
);
subtract
(
x
,
d
,
xd
);
if
(
!
cb
->
compute
(
xd
,
rd
,
noArray
())
)
return
-
1
;
nfJ
++
;
double
Sd
=
norm
(
rd
,
NORM_L2SQR
);
gemm
(
A
,
d
,
-
1
,
v
,
2
,
temp_d
);
double
dS
=
d
.
dot
(
temp_d
);
double
R
=
(
S
-
Sd
)
/
(
fabs
(
dS
)
>
DBL_EPSILON
?
dS
:
1
);
if
(
R
>
Rhi
)
{
lambda
*=
0.5
;
if
(
lambda
<
lc
)
lambda
=
0
;
}
else
if
(
R
<
Rlo
)
{
// find new nu if R too low
double
t
=
d
.
dot
(
v
);
double
nu
=
(
Sd
-
S
)
/
(
fabs
(
t
)
>
DBL_EPSILON
?
t
:
1
)
+
2
;
nu
=
std
::
min
(
std
::
max
(
nu
,
2.
),
10.
);
if
(
lambda
==
0
)
{
invert
(
A
,
Ap
,
DECOMP_EIG
);
double
maxval
=
DBL_EPSILON
;
for
(
i
=
0
;
i
<
lx
;
i
++
)
maxval
=
std
::
max
(
maxval
,
std
::
abs
(
Ap
.
at
<
double
>
(
i
,
i
)));
lambda
=
lc
=
1.
/
maxval
;
nu
*=
0.5
;
}
lambda
*=
nu
;
}
if
(
Sd
<
S
)
{
nfJ
++
;
S
=
Sd
;
std
::
swap
(
x
,
xd
);
if
(
!
cb
->
compute
(
x
,
r
,
J
)
)
return
-
1
;
mulTransposed
(
J
,
A
,
true
);
gemm
(
J
,
r
,
1
,
noArray
(),
0
,
v
,
GEMM_1_T
);
}
iter
++
;
bool
proceed
=
iter
<
maxIters
&&
norm
(
d
,
NORM_INF
)
>=
epsx
&&
norm
(
r
,
NORM_INF
)
>=
epsf
;
if
(
printInterval
!=
0
&&
(
iter
%
printInterval
==
0
||
iter
==
1
||
!
proceed
)
)
{
printf
(
"%c%10d %10d %15.4e %16.4e %17.4e %16.4e %17.4e
\n
"
,
(
proceed
?
' '
:
'*'
),
iter
,
nfJ
,
S
,
x
.
at
<
double
>
(
0
),
d
.
at
<
double
>
(
0
),
lambda
,
lc
);
}
if
(
!
proceed
)
break
;
}
if
(
param0
.
size
!=
x
.
size
)
transpose
(
x
,
x
);
x
.
convertTo
(
param0
,
ptype
);
if
(
iter
==
maxIters
)
iter
=
-
iter
;
return
iter
;
}
void
setCallback
(
const
Ptr
<
LMSolver
::
Callback
>&
_cb
)
{
cb
=
_cb
;
}
AlgorithmInfo
*
info
()
const
;
Ptr
<
LMSolver
::
Callback
>
cb
;
double
epsx
;
double
epsf
;
int
maxIters
;
int
printInterval
;
};
CV_INIT_ALGORITHM
(
LMSolverImpl
,
"LMSolver"
,
obj
.
info
()
->
addParam
(
obj
,
"epsx"
,
obj
.
epsx
);
obj
.
info
()
->
addParam
(
obj
,
"epsf"
,
obj
.
epsf
);
obj
.
info
()
->
addParam
(
obj
,
"maxIters"
,
obj
.
maxIters
);
obj
.
info
()
->
addParam
(
obj
,
"printInterval"
,
obj
.
printInterval
));
Ptr
<
LMSolver
>
createLMSolver
(
const
Ptr
<
LMSolver
::
Callback
>&
cb
,
int
maxIters
)
{
CV_Assert
(
!
LMSolverImpl_info_auto
.
name
().
empty
()
);
return
new
LMSolverImpl
(
cb
,
maxIters
);
}
}
modules/calib3d/src/modelest.cpp
deleted
100644 → 0
View file @
816adcfd
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include "_modelest.h"
#include <algorithm>
#include <iterator>
#include <limits>
CvModelEstimator2
::
CvModelEstimator2
(
int
_modelPoints
,
CvSize
_modelSize
,
int
_maxBasicSolutions
)
{
modelPoints
=
_modelPoints
;
modelSize
=
_modelSize
;
maxBasicSolutions
=
_maxBasicSolutions
;
checkPartialSubsets
=
true
;
rng
=
cvRNG
(
-
1
);
}
CvModelEstimator2
::~
CvModelEstimator2
()
{
}
void
CvModelEstimator2
::
setSeed
(
int64
seed
)
{
rng
=
cvRNG
(
seed
);
}
int
CvModelEstimator2
::
findInliers
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
const
CvMat
*
model
,
CvMat
*
_err
,
CvMat
*
_mask
,
double
threshold
)
{
int
i
,
count
=
_err
->
rows
*
_err
->
cols
,
goodCount
=
0
;
const
float
*
err
=
_err
->
data
.
fl
;
uchar
*
mask
=
_mask
->
data
.
ptr
;
computeReprojError
(
m1
,
m2
,
model
,
_err
);
threshold
*=
threshold
;
for
(
i
=
0
;
i
<
count
;
i
++
)
goodCount
+=
mask
[
i
]
=
err
[
i
]
<=
threshold
;
return
goodCount
;
}
CV_IMPL
int
cvRANSACUpdateNumIters
(
double
p
,
double
ep
,
int
model_points
,
int
max_iters
)
{
if
(
model_points
<=
0
)
CV_Error
(
CV_StsOutOfRange
,
"the number of model points should be positive"
);
p
=
MAX
(
p
,
0.
);
p
=
MIN
(
p
,
1.
);
ep
=
MAX
(
ep
,
0.
);
ep
=
MIN
(
ep
,
1.
);
// avoid inf's & nan's
double
num
=
MAX
(
1.
-
p
,
DBL_MIN
);
double
denom
=
1.
-
pow
(
1.
-
ep
,
model_points
);
if
(
denom
<
DBL_MIN
)
return
0
;
num
=
log
(
num
);
denom
=
log
(
denom
);
return
denom
>=
0
||
-
num
>=
max_iters
*
(
-
denom
)
?
max_iters
:
cvRound
(
num
/
denom
);
}
bool
CvModelEstimator2
::
runRANSAC
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
model
,
CvMat
*
mask0
,
double
reprojThreshold
,
double
confidence
,
int
maxIters
)
{
bool
result
=
false
;
cv
::
Ptr
<
CvMat
>
mask
=
cvCloneMat
(
mask0
);
cv
::
Ptr
<
CvMat
>
models
,
err
,
tmask
;
cv
::
Ptr
<
CvMat
>
ms1
,
ms2
;
int
iter
,
niters
=
maxIters
;
int
count
=
m1
->
rows
*
m1
->
cols
,
maxGoodCount
=
0
;
CV_Assert
(
CV_ARE_SIZES_EQ
(
m1
,
m2
)
&&
CV_ARE_SIZES_EQ
(
m1
,
mask
)
);
if
(
count
<
modelPoints
)
return
false
;
models
=
cvCreateMat
(
modelSize
.
height
*
maxBasicSolutions
,
modelSize
.
width
,
CV_64FC1
);
err
=
cvCreateMat
(
1
,
count
,
CV_32FC1
);
tmask
=
cvCreateMat
(
1
,
count
,
CV_8UC1
);
if
(
count
>
modelPoints
)
{
ms1
=
cvCreateMat
(
1
,
modelPoints
,
m1
->
type
);
ms2
=
cvCreateMat
(
1
,
modelPoints
,
m2
->
type
);
}
else
{
niters
=
1
;
ms1
=
cvCloneMat
(
m1
);
ms2
=
cvCloneMat
(
m2
);
}
for
(
iter
=
0
;
iter
<
niters
;
iter
++
)
{
int
i
,
goodCount
,
nmodels
;
if
(
count
>
modelPoints
)
{
bool
found
=
getSubset
(
m1
,
m2
,
ms1
,
ms2
,
300
);
if
(
!
found
)
{
if
(
iter
==
0
)
return
false
;
break
;
}
// Here we check for model specific geometrical
// constraints that allow to avoid "runKernel"
// and not checking for inliers if not fulfilled.
//
// The usefullness of this constraint for homographies is explained in the paper:
//
// "Speeding-up homography estimation in mobile devices"
// Journal of Real-Time Image Processing. 2013. DOI: 10.1007/s11554-012-0314-1
// Pablo Márquez-Neila, Javier López-Alberca, José M. Buenaposada, Luis Baumela
if
(
!
isMinimalSetConsistent
(
ms1
,
ms2
)
)
continue
;
}
nmodels
=
runKernel
(
ms1
,
ms2
,
models
);
if
(
nmodels
<=
0
)
continue
;
for
(
i
=
0
;
i
<
nmodels
;
i
++
)
{
CvMat
model_i
;
cvGetRows
(
models
,
&
model_i
,
i
*
modelSize
.
height
,
(
i
+
1
)
*
modelSize
.
height
);
goodCount
=
findInliers
(
m1
,
m2
,
&
model_i
,
err
,
tmask
,
reprojThreshold
);
if
(
goodCount
>
MAX
(
maxGoodCount
,
modelPoints
-
1
)
)
{
std
::
swap
(
tmask
,
mask
);
cvCopy
(
&
model_i
,
model
);
maxGoodCount
=
goodCount
;
niters
=
cvRANSACUpdateNumIters
(
confidence
,
(
double
)(
count
-
goodCount
)
/
count
,
modelPoints
,
niters
);
}
}
}
if
(
maxGoodCount
>
0
)
{
if
(
mask
!=
mask0
)
cvCopy
(
mask
,
mask0
);
result
=
true
;
}
return
result
;
}
static
CV_IMPLEMENT_QSORT
(
icvSortDistances
,
int
,
CV_LT
)
bool
CvModelEstimator2
::
runLMeDS
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
model
,
CvMat
*
mask
,
double
confidence
,
int
maxIters
)
{
const
double
outlierRatio
=
0.45
;
bool
result
=
false
;
cv
::
Ptr
<
CvMat
>
models
;
cv
::
Ptr
<
CvMat
>
ms1
,
ms2
;
cv
::
Ptr
<
CvMat
>
err
;
int
iter
,
niters
=
maxIters
;
int
count
=
m1
->
rows
*
m1
->
cols
;
double
minMedian
=
DBL_MAX
,
sigma
;
CV_Assert
(
CV_ARE_SIZES_EQ
(
m1
,
m2
)
&&
CV_ARE_SIZES_EQ
(
m1
,
mask
)
);
if
(
count
<
modelPoints
)
return
false
;
models
=
cvCreateMat
(
modelSize
.
height
*
maxBasicSolutions
,
modelSize
.
width
,
CV_64FC1
);
err
=
cvCreateMat
(
1
,
count
,
CV_32FC1
);
if
(
count
>
modelPoints
)
{
ms1
=
cvCreateMat
(
1
,
modelPoints
,
m1
->
type
);
ms2
=
cvCreateMat
(
1
,
modelPoints
,
m2
->
type
);
}
else
{
niters
=
1
;
ms1
=
cvCloneMat
(
m1
);
ms2
=
cvCloneMat
(
m2
);
}
niters
=
cvRound
(
log
(
1
-
confidence
)
/
log
(
1
-
pow
(
1
-
outlierRatio
,(
double
)
modelPoints
)));
niters
=
MIN
(
MAX
(
niters
,
3
),
maxIters
);
for
(
iter
=
0
;
iter
<
niters
;
iter
++
)
{
int
i
,
nmodels
;
if
(
count
>
modelPoints
)
{
bool
found
=
getSubset
(
m1
,
m2
,
ms1
,
ms2
,
300
);
if
(
!
found
)
{
if
(
iter
==
0
)
return
false
;
break
;
}
}
nmodels
=
runKernel
(
ms1
,
ms2
,
models
);
if
(
nmodels
<=
0
)
continue
;
for
(
i
=
0
;
i
<
nmodels
;
i
++
)
{
CvMat
model_i
;
cvGetRows
(
models
,
&
model_i
,
i
*
modelSize
.
height
,
(
i
+
1
)
*
modelSize
.
height
);
computeReprojError
(
m1
,
m2
,
&
model_i
,
err
);
icvSortDistances
(
err
->
data
.
i
,
count
,
0
);
double
median
=
count
%
2
!=
0
?
err
->
data
.
fl
[
count
/
2
]
:
(
err
->
data
.
fl
[
count
/
2
-
1
]
+
err
->
data
.
fl
[
count
/
2
])
*
0.5
;
if
(
median
<
minMedian
)
{
minMedian
=
median
;
cvCopy
(
&
model_i
,
model
);
}
}
}
if
(
minMedian
<
DBL_MAX
)
{
sigma
=
2.5
*
1.4826
*
(
1
+
5.
/
(
count
-
modelPoints
))
*
std
::
sqrt
(
minMedian
);
sigma
=
MAX
(
sigma
,
0.001
);
count
=
findInliers
(
m1
,
m2
,
model
,
err
,
mask
,
sigma
);
result
=
count
>=
modelPoints
;
}
return
result
;
}
bool
CvModelEstimator2
::
getSubset
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
ms1
,
CvMat
*
ms2
,
int
maxAttempts
)
{
cv
::
AutoBuffer
<
int
>
_idx
(
modelPoints
);
int
*
idx
=
_idx
;
int
i
=
0
,
j
,
k
,
idx_i
,
iters
=
0
;
int
type
=
CV_MAT_TYPE
(
m1
->
type
),
elemSize
=
CV_ELEM_SIZE
(
type
);
const
int
*
m1ptr
=
m1
->
data
.
i
,
*
m2ptr
=
m2
->
data
.
i
;
int
*
ms1ptr
=
ms1
->
data
.
i
,
*
ms2ptr
=
ms2
->
data
.
i
;
int
count
=
m1
->
cols
*
m1
->
rows
;
assert
(
CV_IS_MAT_CONT
(
m1
->
type
&
m2
->
type
)
&&
(
elemSize
%
sizeof
(
int
)
==
0
)
);
elemSize
/=
sizeof
(
int
);
for
(;
iters
<
maxAttempts
;
iters
++
)
{
for
(
i
=
0
;
i
<
modelPoints
&&
iters
<
maxAttempts
;
)
{
idx
[
i
]
=
idx_i
=
cvRandInt
(
&
rng
)
%
count
;
for
(
j
=
0
;
j
<
i
;
j
++
)
if
(
idx_i
==
idx
[
j
]
)
break
;
if
(
j
<
i
)
continue
;
for
(
k
=
0
;
k
<
elemSize
;
k
++
)
{
ms1ptr
[
i
*
elemSize
+
k
]
=
m1ptr
[
idx_i
*
elemSize
+
k
];
ms2ptr
[
i
*
elemSize
+
k
]
=
m2ptr
[
idx_i
*
elemSize
+
k
];
}
if
(
checkPartialSubsets
&&
(
!
checkSubset
(
ms1
,
i
+
1
)
||
!
checkSubset
(
ms2
,
i
+
1
)))
{
iters
++
;
continue
;
}
i
++
;
}
if
(
!
checkPartialSubsets
&&
i
==
modelPoints
&&
(
!
checkSubset
(
ms1
,
i
)
||
!
checkSubset
(
ms2
,
i
)))
continue
;
break
;
}
return
i
==
modelPoints
&&
iters
<
maxAttempts
;
}
bool
CvModelEstimator2
::
checkSubset
(
const
CvMat
*
m
,
int
count
)
{
if
(
count
<=
2
)
return
true
;
int
j
,
k
,
i
,
i0
,
i1
;
CvPoint2D64f
*
ptr
=
(
CvPoint2D64f
*
)
m
->
data
.
ptr
;
assert
(
CV_MAT_TYPE
(
m
->
type
)
==
CV_64FC2
);
if
(
checkPartialSubsets
)
i0
=
i1
=
count
-
1
;
else
i0
=
0
,
i1
=
count
-
1
;
for
(
i
=
i0
;
i
<=
i1
;
i
++
)
{
// check that the i-th selected point does not belong
// to a line connecting some previously selected points
for
(
j
=
0
;
j
<
i
;
j
++
)
{
double
dx1
=
ptr
[
j
].
x
-
ptr
[
i
].
x
;
double
dy1
=
ptr
[
j
].
y
-
ptr
[
i
].
y
;
for
(
k
=
0
;
k
<
j
;
k
++
)
{
double
dx2
=
ptr
[
k
].
x
-
ptr
[
i
].
x
;
double
dy2
=
ptr
[
k
].
y
-
ptr
[
i
].
y
;
if
(
fabs
(
dx2
*
dy1
-
dy2
*
dx1
)
<=
FLT_EPSILON
*
(
fabs
(
dx1
)
+
fabs
(
dy1
)
+
fabs
(
dx2
)
+
fabs
(
dy2
)))
break
;
}
if
(
k
<
j
)
break
;
}
if
(
j
<
i
)
break
;
}
return
i
>
i1
;
}
namespace
cv
{
class
Affine3DEstimator
:
public
CvModelEstimator2
{
public
:
Affine3DEstimator
()
:
CvModelEstimator2
(
4
,
cvSize
(
4
,
3
),
1
)
{}
virtual
int
runKernel
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
model
);
protected
:
virtual
void
computeReprojError
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
const
CvMat
*
model
,
CvMat
*
error
);
virtual
bool
checkSubset
(
const
CvMat
*
ms1
,
int
count
);
};
}
int
cv
::
Affine3DEstimator
::
runKernel
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
CvMat
*
model
)
{
const
Point3d
*
from
=
reinterpret_cast
<
const
Point3d
*>
(
m1
->
data
.
ptr
);
const
Point3d
*
to
=
reinterpret_cast
<
const
Point3d
*>
(
m2
->
data
.
ptr
);
Mat
A
(
12
,
12
,
CV_64F
);
Mat
B
(
12
,
1
,
CV_64F
);
A
=
Scalar
(
0.0
);
for
(
int
i
=
0
;
i
<
modelPoints
;
++
i
)
{
*
B
.
ptr
<
Point3d
>
(
3
*
i
)
=
to
[
i
];
double
*
aptr
=
A
.
ptr
<
double
>
(
3
*
i
);
for
(
int
k
=
0
;
k
<
3
;
++
k
)
{
aptr
[
3
]
=
1.0
;
*
reinterpret_cast
<
Point3d
*>
(
aptr
)
=
from
[
i
];
aptr
+=
16
;
}
}
CvMat
cvA
=
A
;
CvMat
cvB
=
B
;
CvMat
cvX
;
cvReshape
(
model
,
&
cvX
,
1
,
12
);
cvSolve
(
&
cvA
,
&
cvB
,
&
cvX
,
CV_SVD
);
return
1
;
}
void
cv
::
Affine3DEstimator
::
computeReprojError
(
const
CvMat
*
m1
,
const
CvMat
*
m2
,
const
CvMat
*
model
,
CvMat
*
error
)
{
int
count
=
m1
->
rows
*
m1
->
cols
;
const
Point3d
*
from
=
reinterpret_cast
<
const
Point3d
*>
(
m1
->
data
.
ptr
);
const
Point3d
*
to
=
reinterpret_cast
<
const
Point3d
*>
(
m2
->
data
.
ptr
);
const
double
*
F
=
model
->
data
.
db
;
float
*
err
=
error
->
data
.
fl
;
for
(
int
i
=
0
;
i
<
count
;
i
++
)
{
const
Point3d
&
f
=
from
[
i
];
const
Point3d
&
t
=
to
[
i
];
double
a
=
F
[
0
]
*
f
.
x
+
F
[
1
]
*
f
.
y
+
F
[
2
]
*
f
.
z
+
F
[
3
]
-
t
.
x
;
double
b
=
F
[
4
]
*
f
.
x
+
F
[
5
]
*
f
.
y
+
F
[
6
]
*
f
.
z
+
F
[
7
]
-
t
.
y
;
double
c
=
F
[
8
]
*
f
.
x
+
F
[
9
]
*
f
.
y
+
F
[
10
]
*
f
.
z
+
F
[
11
]
-
t
.
z
;
err
[
i
]
=
(
float
)
std
::
sqrt
(
a
*
a
+
b
*
b
+
c
*
c
);
}
}
bool
cv
::
Affine3DEstimator
::
checkSubset
(
const
CvMat
*
ms1
,
int
count
)
{
CV_Assert
(
CV_MAT_TYPE
(
ms1
->
type
)
==
CV_64FC3
);
int
j
,
k
,
i
=
count
-
1
;
const
Point3d
*
ptr
=
reinterpret_cast
<
const
Point3d
*>
(
ms1
->
data
.
ptr
);
// check that the i-th selected point does not belong
// to a line connecting some previously selected points
for
(
j
=
0
;
j
<
i
;
++
j
)
{
Point3d
d1
=
ptr
[
j
]
-
ptr
[
i
];
double
n1
=
norm
(
d1
);
for
(
k
=
0
;
k
<
j
;
++
k
)
{
Point3d
d2
=
ptr
[
k
]
-
ptr
[
i
];
double
n
=
norm
(
d2
)
*
n1
;
if
(
fabs
(
d1
.
dot
(
d2
)
/
n
)
>
0.996
)
break
;
}
if
(
k
<
j
)
break
;
}
return
j
==
i
;
}
int
cv
::
estimateAffine3D
(
InputArray
_from
,
InputArray
_to
,
OutputArray
_out
,
OutputArray
_inliers
,
double
param1
,
double
param2
)
{
Mat
from
=
_from
.
getMat
(),
to
=
_to
.
getMat
();
int
count
=
from
.
checkVector
(
3
);
CV_Assert
(
count
>=
0
&&
to
.
checkVector
(
3
)
==
count
);
_out
.
create
(
3
,
4
,
CV_64F
);
Mat
out
=
_out
.
getMat
();
Mat
inliers
(
1
,
count
,
CV_8U
);
inliers
=
Scalar
::
all
(
1
);
Mat
dFrom
,
dTo
;
from
.
convertTo
(
dFrom
,
CV_64F
);
to
.
convertTo
(
dTo
,
CV_64F
);
dFrom
=
dFrom
.
reshape
(
3
,
1
);
dTo
=
dTo
.
reshape
(
3
,
1
);
CvMat
F3x4
=
out
;
CvMat
mask
=
inliers
;
CvMat
m1
=
dFrom
;
CvMat
m2
=
dTo
;
const
double
epsilon
=
std
::
numeric_limits
<
double
>::
epsilon
();
param1
=
param1
<=
0
?
3
:
param1
;
param2
=
(
param2
<
epsilon
)
?
0.99
:
(
param2
>
1
-
epsilon
)
?
0.99
:
param2
;
int
ok
=
Affine3DEstimator
().
runRANSAC
(
&
m1
,
&
m2
,
&
F3x4
,
&
mask
,
param1
,
param2
);
if
(
_inliers
.
needed
()
)
transpose
(
inliers
,
_inliers
);
return
ok
;
}
modules/calib3d/src/precomp.hpp
View file @
6569a585
...
@@ -59,4 +59,51 @@
...
@@ -59,4 +59,51 @@
#define GET_OPTIMIZED(func) (func)
#define GET_OPTIMIZED(func) (func)
#endif
#endif
namespace
cv
{
int
RANSACUpdateNumIters
(
double
p
,
double
ep
,
int
modelPoints
,
int
maxIters
);
class
CV_EXPORTS
LMSolver
:
public
Algorithm
{
public
:
class
CV_EXPORTS
Callback
{
public
:
virtual
~
Callback
()
{}
virtual
bool
compute
(
InputArray
param
,
OutputArray
err
,
OutputArray
J
)
const
=
0
;
};
virtual
void
setCallback
(
const
Ptr
<
LMSolver
::
Callback
>&
cb
)
=
0
;
virtual
int
run
(
InputOutputArray
_param0
)
const
=
0
;
};
CV_EXPORTS
Ptr
<
LMSolver
>
createLMSolver
(
const
Ptr
<
LMSolver
::
Callback
>&
cb
,
int
maxIters
);
class
CV_EXPORTS
PointSetRegistrator
:
public
Algorithm
{
public
:
class
CV_EXPORTS
Callback
{
public
:
virtual
~
Callback
()
{}
virtual
int
runKernel
(
InputArray
m1
,
InputArray
m2
,
OutputArray
model
)
const
=
0
;
virtual
void
computeError
(
InputArray
m1
,
InputArray
m2
,
InputArray
model
,
OutputArray
err
)
const
=
0
;
virtual
bool
checkSubset
(
InputArray
,
InputArray
,
int
)
const
{
return
true
;
}
};
virtual
void
setCallback
(
const
Ptr
<
PointSetRegistrator
::
Callback
>&
cb
)
=
0
;
virtual
bool
run
(
InputArray
m1
,
InputArray
m2
,
OutputArray
model
,
OutputArray
mask
)
const
=
0
;
};
CV_EXPORTS
Ptr
<
PointSetRegistrator
>
createRANSACPointSetRegistrator
(
const
Ptr
<
PointSetRegistrator
::
Callback
>&
cb
,
int
modelPoints
,
double
threshold
,
double
confidence
=
0.99
,
int
maxIters
=
1000
);
CV_EXPORTS
Ptr
<
PointSetRegistrator
>
createLMeDSPointSetRegistrator
(
const
Ptr
<
PointSetRegistrator
::
Callback
>&
cb
,
int
modelPoints
,
double
confidence
=
0.99
,
int
maxIters
=
1000
);
}
#endif
#endif
modules/calib3d/src/ptsetreg.cpp
0 → 100644
View file @
6569a585
/*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*/
#include "precomp.hpp"
#include <algorithm>
#include <iterator>
#include <limits>
namespace
cv
{
int
RANSACUpdateNumIters
(
double
p
,
double
ep
,
int
modelPoints
,
int
maxIters
)
{
if
(
modelPoints
<=
0
)
CV_Error
(
CV_StsOutOfRange
,
"the number of model points should be positive"
);
p
=
MAX
(
p
,
0.
);
p
=
MIN
(
p
,
1.
);
ep
=
MAX
(
ep
,
0.
);
ep
=
MIN
(
ep
,
1.
);
// avoid inf's & nan's
double
num
=
MAX
(
1.
-
p
,
DBL_MIN
);
double
denom
=
1.
-
std
::
pow
(
1.
-
ep
,
modelPoints
);
if
(
denom
<
DBL_MIN
)
return
0
;
num
=
std
::
log
(
num
);
denom
=
std
::
log
(
denom
);
return
denom
>=
0
||
-
num
>=
maxIters
*
(
-
denom
)
?
maxIters
:
cvRound
(
num
/
denom
);
}
class
RANSACPointSetRegistrator
:
public
PointSetRegistrator
{
public
:
RANSACPointSetRegistrator
(
const
Ptr
<
PointSetRegistrator
::
Callback
>&
_cb
=
Ptr
<
PointSetRegistrator
::
Callback
>
(),
int
_modelPoints
=
0
,
double
_threshold
=
0
,
double
_confidence
=
0.99
,
int
_maxIters
=
1000
)
:
cb
(
_cb
),
modelPoints
(
_modelPoints
),
threshold
(
_threshold
),
confidence
(
_confidence
),
maxIters
(
_maxIters
)
{
checkPartialSubsets
=
true
;
}
int
findInliers
(
const
Mat
&
m1
,
const
Mat
&
m2
,
const
Mat
&
model
,
Mat
&
err
,
Mat
&
mask
,
double
thresh
)
const
{
cb
->
computeError
(
m1
,
m2
,
model
,
err
);
mask
.
create
(
err
.
size
(),
CV_8U
);
CV_Assert
(
err
.
isContinuous
()
&&
err
.
type
()
==
CV_32F
&&
mask
.
isContinuous
()
&&
mask
.
type
()
==
CV_8U
);
const
float
*
errptr
=
err
.
ptr
<
float
>
();
uchar
*
maskptr
=
mask
.
ptr
<
uchar
>
();
float
t
=
(
float
)(
thresh
*
thresh
);
int
i
,
n
=
(
int
)
err
.
total
(),
nz
=
0
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
int
f
=
errptr
[
i
]
<=
t
;
maskptr
[
i
]
=
(
uchar
)
f
;
nz
+=
f
;
}
return
nz
;
}
bool
getSubset
(
const
Mat
&
m1
,
const
Mat
&
m2
,
Mat
&
ms1
,
Mat
&
ms2
,
RNG
&
rng
,
int
maxAttempts
=
1000
)
const
{
cv
::
AutoBuffer
<
int
>
_idx
(
modelPoints
);
int
*
idx
=
_idx
;
int
i
=
0
,
j
,
k
,
iters
=
0
;
int
esz1
=
(
int
)
m1
.
elemSize
(),
esz2
=
(
int
)
m2
.
elemSize
();
int
d1
=
m1
.
channels
()
>
1
?
m1
.
channels
()
:
m1
.
cols
;
int
d2
=
m2
.
channels
()
>
1
?
m2
.
channels
()
:
m2
.
cols
;
int
count
=
m1
.
checkVector
(
d1
),
count2
=
m2
.
checkVector
(
d2
);
const
int
*
m1ptr
=
(
const
int
*
)
m1
.
data
,
*
m2ptr
=
(
const
int
*
)
m2
.
data
;
ms1
.
create
(
modelPoints
,
1
,
CV_MAKETYPE
(
m1
.
depth
(),
d1
));
ms2
.
create
(
modelPoints
,
1
,
CV_MAKETYPE
(
m2
.
depth
(),
d2
));
int
*
ms1ptr
=
(
int
*
)
ms1
.
data
,
*
ms2ptr
=
(
int
*
)
ms2
.
data
;
CV_Assert
(
count
>=
modelPoints
&&
count
==
count2
);
CV_Assert
(
(
esz1
%
sizeof
(
int
))
==
0
&&
(
esz2
%
sizeof
(
int
))
==
0
);
esz1
/=
sizeof
(
int
);
esz2
/=
sizeof
(
int
);
for
(;
iters
<
maxAttempts
;
iters
++
)
{
for
(
i
=
0
;
i
<
modelPoints
&&
iters
<
maxAttempts
;
)
{
int
idx_i
=
0
;
for
(;;)
{
idx_i
=
idx
[
i
]
=
rng
.
uniform
(
0
,
count
);
for
(
j
=
0
;
j
<
i
;
j
++
)
if
(
idx_i
==
idx
[
j
]
)
break
;
if
(
j
==
i
)
break
;
}
for
(
k
=
0
;
k
<
esz1
;
k
++
)
ms1ptr
[
i
*
esz1
+
k
]
=
m1ptr
[
idx_i
*
esz1
+
k
];
for
(
k
=
0
;
k
<
esz2
;
k
++
)
ms2ptr
[
i
*
esz2
+
k
]
=
m2ptr
[
idx_i
*
esz2
+
k
];
if
(
checkPartialSubsets
&&
!
cb
->
checkSubset
(
ms1
,
ms2
,
i
+
1
))
{
iters
++
;
continue
;
}
i
++
;
}
if
(
!
checkPartialSubsets
&&
i
==
modelPoints
&&
!
cb
->
checkSubset
(
ms1
,
ms2
,
i
))
continue
;
break
;
}
return
i
==
modelPoints
&&
iters
<
maxAttempts
;
}
bool
run
(
InputArray
_m1
,
InputArray
_m2
,
OutputArray
_model
,
OutputArray
_mask
)
const
{
bool
result
=
false
;
Mat
m1
=
_m1
.
getMat
(),
m2
=
_m2
.
getMat
();
Mat
err
,
mask
,
model
,
bestModel
,
ms1
,
ms2
;
int
iter
,
niters
=
MAX
(
maxIters
,
1
);
int
d1
=
m1
.
channels
()
>
1
?
m1
.
channels
()
:
m1
.
cols
;
int
d2
=
m2
.
channels
()
>
1
?
m2
.
channels
()
:
m2
.
cols
;
int
count
=
m1
.
checkVector
(
d1
),
count2
=
m2
.
checkVector
(
d2
),
maxGoodCount
=
0
;
RNG
rng
((
uint64
)
-
1
);
CV_Assert
(
!
cb
.
empty
()
);
CV_Assert
(
confidence
>
0
&&
confidence
<
1
);
CV_Assert
(
count
>=
0
&&
count2
==
count
);
if
(
count
<
modelPoints
)
return
false
;
Mat
bestMask0
,
bestMask
;
if
(
_mask
.
needed
()
)
{
_mask
.
create
(
count
,
1
,
CV_8U
,
-
1
,
true
);
bestMask0
=
bestMask
=
_mask
.
getMat
();
CV_Assert
(
(
bestMask
.
cols
==
1
||
bestMask
.
rows
==
1
)
&&
(
int
)
bestMask
.
total
()
==
count
);
}
else
{
bestMask
.
create
(
count
,
1
,
CV_8U
);
bestMask0
=
bestMask
;
}
if
(
count
==
modelPoints
)
{
if
(
cb
->
runKernel
(
m1
,
m2
,
bestModel
)
<=
0
)
return
false
;
bestModel
.
copyTo
(
_model
);
bestMask
.
setTo
(
Scalar
::
all
(
1
));
return
true
;
}
for
(
iter
=
0
;
iter
<
niters
;
iter
++
)
{
int
i
,
goodCount
,
nmodels
;
if
(
count
>
modelPoints
)
{
bool
found
=
getSubset
(
m1
,
m2
,
ms1
,
ms2
,
rng
);
if
(
!
found
)
{
if
(
iter
==
0
)
return
false
;
break
;
}
}
nmodels
=
cb
->
runKernel
(
ms1
,
ms2
,
model
);
if
(
nmodels
<=
0
)
continue
;
CV_Assert
(
model
.
rows
%
nmodels
==
0
);
Size
modelSize
(
model
.
cols
,
model
.
rows
/
nmodels
);
for
(
i
=
0
;
i
<
nmodels
;
i
++
)
{
Mat
model_i
=
model
.
rowRange
(
i
*
modelSize
.
height
,
(
i
+
1
)
*
modelSize
.
height
);
goodCount
=
findInliers
(
m1
,
m2
,
model_i
,
err
,
mask
,
threshold
);
if
(
goodCount
>
MAX
(
maxGoodCount
,
modelPoints
-
1
)
)
{
std
::
swap
(
mask
,
bestMask
);
model_i
.
copyTo
(
bestModel
);
maxGoodCount
=
goodCount
;
niters
=
RANSACUpdateNumIters
(
confidence
,
(
double
)(
count
-
goodCount
)
/
count
,
modelPoints
,
niters
);
}
}
}
if
(
maxGoodCount
>
0
)
{
if
(
bestMask
.
data
!=
bestMask0
.
data
)
{
if
(
bestMask
.
size
()
==
bestMask0
.
size
()
)
bestMask
.
copyTo
(
bestMask0
);
else
transpose
(
bestMask
,
bestMask0
);
}
bestModel
.
copyTo
(
_model
);
result
=
true
;
}
else
_model
.
release
();
return
result
;
}
void
setCallback
(
const
Ptr
<
PointSetRegistrator
::
Callback
>&
_cb
)
{
cb
=
_cb
;
}
AlgorithmInfo
*
info
()
const
;
Ptr
<
PointSetRegistrator
::
Callback
>
cb
;
int
modelPoints
;
int
maxBasicSolutions
;
bool
checkPartialSubsets
;
double
threshold
;
double
confidence
;
int
maxIters
;
};
static
CV_IMPLEMENT_QSORT
(
sortDistances
,
int
,
CV_LT
)
class
LMeDSPointSetRegistrator
:
public
RANSACPointSetRegistrator
{
public
:
LMeDSPointSetRegistrator
(
const
Ptr
<
PointSetRegistrator
::
Callback
>&
_cb
=
Ptr
<
PointSetRegistrator
::
Callback
>
(),
int
_modelPoints
=
0
,
double
_confidence
=
0.99
,
int
_maxIters
=
1000
)
:
RANSACPointSetRegistrator
(
_cb
,
_modelPoints
,
0
,
_confidence
,
_maxIters
)
{}
bool
run
(
InputArray
_m1
,
InputArray
_m2
,
OutputArray
_model
,
OutputArray
_mask
)
const
{
const
double
outlierRatio
=
0.45
;
bool
result
=
false
;
Mat
m1
=
_m1
.
getMat
(),
m2
=
_m2
.
getMat
();
Mat
ms1
,
ms2
,
err
,
errf
,
model
,
bestModel
,
mask
,
mask0
;
int
d1
=
m1
.
channels
()
>
1
?
m1
.
channels
()
:
m1
.
cols
;
int
d2
=
m2
.
channels
()
>
1
?
m2
.
channels
()
:
m2
.
cols
;
int
count
=
m1
.
checkVector
(
d1
),
count2
=
m2
.
checkVector
(
d2
);
double
minMedian
=
DBL_MAX
,
sigma
;
RNG
rng
((
uint64
)
-
1
);
CV_Assert
(
!
cb
.
empty
()
);
CV_Assert
(
confidence
>
0
&&
confidence
<
1
);
CV_Assert
(
count
>=
0
&&
count2
==
count
);
if
(
count
<
modelPoints
)
return
false
;
if
(
_mask
.
needed
()
)
{
_mask
.
create
(
count
,
1
,
CV_8U
,
-
1
,
true
);
mask0
=
mask
=
_mask
.
getMat
();
CV_Assert
(
(
mask
.
cols
==
1
||
mask
.
rows
==
1
)
&&
(
int
)
mask
.
total
()
==
count
);
}
if
(
count
==
modelPoints
)
{
if
(
cb
->
runKernel
(
m1
,
m2
,
bestModel
)
<=
0
)
return
false
;
bestModel
.
copyTo
(
_model
);
mask
.
setTo
(
Scalar
::
all
(
1
));
return
true
;
}
int
iter
,
niters
=
RANSACUpdateNumIters
(
confidence
,
outlierRatio
,
modelPoints
,
maxIters
);
niters
=
MAX
(
niters
,
3
);
for
(
iter
=
0
;
iter
<
niters
;
iter
++
)
{
int
i
,
nmodels
;
if
(
count
>
modelPoints
)
{
bool
found
=
getSubset
(
m1
,
m2
,
ms1
,
ms2
,
rng
);
if
(
!
found
)
{
if
(
iter
==
0
)
return
false
;
break
;
}
}
nmodels
=
cb
->
runKernel
(
ms1
,
ms2
,
model
);
if
(
nmodels
<=
0
)
continue
;
CV_Assert
(
model
.
rows
%
nmodels
==
0
);
Size
modelSize
(
model
.
cols
,
model
.
rows
/
nmodels
);
for
(
i
=
0
;
i
<
nmodels
;
i
++
)
{
Mat
model_i
=
model
.
rowRange
(
i
*
modelSize
.
height
,
(
i
+
1
)
*
modelSize
.
height
);
cb
->
computeError
(
m1
,
m2
,
model_i
,
err
);
if
(
err
.
depth
()
!=
CV_32F
)
err
.
convertTo
(
errf
,
CV_32F
);
else
errf
=
err
;
CV_Assert
(
errf
.
isContinuous
()
&&
errf
.
type
()
==
CV_32F
&&
(
int
)
errf
.
total
()
==
count
);
sortDistances
(
(
int
*
)
errf
.
data
,
count
,
0
);
double
median
=
count
%
2
!=
0
?
errf
.
at
<
float
>
(
count
/
2
)
:
(
errf
.
at
<
float
>
(
count
/
2
-
1
)
+
errf
.
at
<
float
>
(
count
/
2
))
*
0.5
;
if
(
median
<
minMedian
)
{
minMedian
=
median
;
model_i
.
copyTo
(
bestModel
);
}
}
}
if
(
minMedian
<
DBL_MAX
)
{
sigma
=
2.5
*
1.4826
*
(
1
+
5.
/
(
count
-
modelPoints
))
*
std
::
sqrt
(
minMedian
);
sigma
=
MAX
(
sigma
,
0.001
);
count
=
findInliers
(
m1
,
m2
,
bestModel
,
err
,
mask
,
sigma
);
if
(
_mask
.
needed
()
&&
mask0
.
data
!=
mask
.
data
)
{
if
(
mask0
.
size
()
==
mask
.
size
()
)
mask
.
copyTo
(
mask0
);
else
transpose
(
mask
,
mask0
);
}
bestModel
.
copyTo
(
_model
);
result
=
count
>=
modelPoints
;
}
else
_model
.
release
();
return
result
;
}
AlgorithmInfo
*
info
()
const
;
};
CV_INIT_ALGORITHM
(
RANSACPointSetRegistrator
,
"PointSetRegistrator.RANSAC"
,
obj
.
info
()
->
addParam
(
obj
,
"threshold"
,
obj
.
threshold
);
obj
.
info
()
->
addParam
(
obj
,
"confidence"
,
obj
.
confidence
);
obj
.
info
()
->
addParam
(
obj
,
"maxIters"
,
obj
.
maxIters
));
CV_INIT_ALGORITHM
(
LMeDSPointSetRegistrator
,
"PointSetRegistrator.LMeDS"
,
obj
.
info
()
->
addParam
(
obj
,
"confidence"
,
obj
.
confidence
);
obj
.
info
()
->
addParam
(
obj
,
"maxIters"
,
obj
.
maxIters
));
Ptr
<
PointSetRegistrator
>
createRANSACPointSetRegistrator
(
const
Ptr
<
PointSetRegistrator
::
Callback
>&
_cb
,
int
_modelPoints
,
double
_threshold
,
double
_confidence
,
int
_maxIters
)
{
CV_Assert
(
!
RANSACPointSetRegistrator_info_auto
.
name
().
empty
()
);
return
new
RANSACPointSetRegistrator
(
_cb
,
_modelPoints
,
_threshold
,
_confidence
,
_maxIters
);
}
Ptr
<
PointSetRegistrator
>
createLMeDSPointSetRegistrator
(
const
Ptr
<
PointSetRegistrator
::
Callback
>&
_cb
,
int
_modelPoints
,
double
_confidence
,
int
_maxIters
)
{
CV_Assert
(
!
LMeDSPointSetRegistrator_info_auto
.
name
().
empty
()
);
return
new
LMeDSPointSetRegistrator
(
_cb
,
_modelPoints
,
_confidence
,
_maxIters
);
}
class
Affine3DEstimatorCallback
:
public
PointSetRegistrator
::
Callback
{
public
:
int
runKernel
(
InputArray
_m1
,
InputArray
_m2
,
OutputArray
_model
)
const
{
Mat
m1
=
_m1
.
getMat
(),
m2
=
_m2
.
getMat
();
const
Point3f
*
from
=
m1
.
ptr
<
Point3f
>
();
const
Point3f
*
to
=
m2
.
ptr
<
Point3f
>
();
const
int
N
=
12
;
double
buf
[
N
*
N
+
N
+
N
];
Mat
A
(
N
,
N
,
CV_64F
,
&
buf
[
0
]);
Mat
B
(
N
,
1
,
CV_64F
,
&
buf
[
0
]
+
N
*
N
);
Mat
X
(
N
,
1
,
CV_64F
,
&
buf
[
0
]
+
N
*
N
+
N
);
double
*
Adata
=
A
.
ptr
<
double
>
();
double
*
Bdata
=
B
.
ptr
<
double
>
();
A
=
Scalar
::
all
(
0
);
for
(
int
i
=
0
;
i
<
(
N
/
3
);
i
++
)
{
Bdata
[
i
*
3
]
=
to
[
i
].
x
;
Bdata
[
i
*
3
+
1
]
=
to
[
i
].
y
;
Bdata
[
i
*
3
+
2
]
=
to
[
i
].
z
;
double
*
aptr
=
Adata
+
i
*
3
*
N
;
for
(
int
k
=
0
;
k
<
3
;
++
k
)
{
aptr
[
0
]
=
from
[
i
].
x
;
aptr
[
1
]
=
from
[
i
].
y
;
aptr
[
2
]
=
from
[
i
].
z
;
aptr
[
3
]
=
1.0
;
aptr
+=
16
;
}
}
solve
(
A
,
B
,
X
,
DECOMP_SVD
);
X
.
reshape
(
1
,
3
).
copyTo
(
_model
);
return
1
;
}
void
computeError
(
InputArray
_m1
,
InputArray
_m2
,
InputArray
_model
,
OutputArray
_err
)
const
{
Mat
m1
=
_m1
.
getMat
(),
m2
=
_m2
.
getMat
(),
model
=
_model
.
getMat
();
const
Point3f
*
from
=
m1
.
ptr
<
Point3f
>
();
const
Point3f
*
to
=
m2
.
ptr
<
Point3f
>
();
const
double
*
F
=
model
.
ptr
<
double
>
();
int
count
=
m1
.
checkVector
(
3
);
CV_Assert
(
count
>
0
);
_err
.
create
(
count
,
1
,
CV_32F
);
Mat
err
=
_err
.
getMat
();
float
*
errptr
=
err
.
ptr
<
float
>
();
for
(
int
i
=
0
;
i
<
count
;
i
++
)
{
const
Point3f
&
f
=
from
[
i
];
const
Point3f
&
t
=
to
[
i
];
double
a
=
F
[
0
]
*
f
.
x
+
F
[
1
]
*
f
.
y
+
F
[
2
]
*
f
.
z
+
F
[
3
]
-
t
.
x
;
double
b
=
F
[
4
]
*
f
.
x
+
F
[
5
]
*
f
.
y
+
F
[
6
]
*
f
.
z
+
F
[
7
]
-
t
.
y
;
double
c
=
F
[
8
]
*
f
.
x
+
F
[
9
]
*
f
.
y
+
F
[
10
]
*
f
.
z
+
F
[
11
]
-
t
.
z
;
errptr
[
i
]
=
(
float
)
std
::
sqrt
(
a
*
a
+
b
*
b
+
c
*
c
);
}
}
bool
checkSubset
(
InputArray
_ms1
,
InputArray
_ms2
,
int
count
)
const
{
const
float
threshold
=
0.996
f
;
Mat
ms1
=
_ms1
.
getMat
(),
ms2
=
_ms2
.
getMat
();
for
(
int
inp
=
1
;
inp
<=
2
;
inp
++
)
{
int
j
,
k
,
i
=
count
-
1
;
const
Mat
*
msi
=
inp
==
1
?
&
ms1
:
&
ms2
;
const
Point3f
*
ptr
=
msi
->
ptr
<
Point3f
>
();
CV_Assert
(
count
<=
msi
->
rows
);
// check that the i-th selected point does not belong
// to a line connecting some previously selected points
for
(
j
=
0
;
j
<
i
;
++
j
)
{
Point3f
d1
=
ptr
[
j
]
-
ptr
[
i
];
float
n1
=
d1
.
x
*
d1
.
x
+
d1
.
y
*
d1
.
y
;
for
(
k
=
0
;
k
<
j
;
++
k
)
{
Point3f
d2
=
ptr
[
k
]
-
ptr
[
i
];
float
denom
=
(
d2
.
x
*
d2
.
x
+
d2
.
y
*
d2
.
y
)
*
n1
;
float
num
=
d1
.
x
*
d2
.
x
+
d1
.
y
*
d2
.
y
;
if
(
num
*
num
>
threshold
*
threshold
*
denom
)
return
false
;
}
}
}
return
true
;
}
};
}
int
cv
::
estimateAffine3D
(
InputArray
_from
,
InputArray
_to
,
OutputArray
_out
,
OutputArray
_inliers
,
double
param1
,
double
param2
)
{
Mat
from
=
_from
.
getMat
(),
to
=
_to
.
getMat
();
int
count
=
from
.
checkVector
(
3
);
CV_Assert
(
count
>=
0
&&
to
.
checkVector
(
3
)
==
count
);
Mat
dFrom
,
dTo
;
from
.
convertTo
(
dFrom
,
CV_32F
);
to
.
convertTo
(
dTo
,
CV_32F
);
dFrom
=
dFrom
.
reshape
(
3
,
count
);
dTo
=
dTo
.
reshape
(
3
,
count
);
const
double
epsilon
=
DBL_EPSILON
;
param1
=
param1
<=
0
?
3
:
param1
;
param2
=
(
param2
<
epsilon
)
?
0.99
:
(
param2
>
1
-
epsilon
)
?
0.99
:
param2
;
return
createRANSACPointSetRegistrator
(
new
Affine3DEstimatorCallback
,
4
,
param1
,
param2
)
->
run
(
dFrom
,
dTo
,
_out
,
_inliers
);
}
modules/calib3d/test/test_affine3d_estimator.cpp
View file @
6569a585
...
@@ -163,6 +163,8 @@ bool CV_Affine3D_EstTest::testNPoints()
...
@@ -163,6 +163,8 @@ bool CV_Affine3D_EstTest::testNPoints()
const
double
thres
=
1e-4
;
const
double
thres
=
1e-4
;
if
(
norm
(
aff_est
,
aff
,
NORM_INF
)
>
thres
)
if
(
norm
(
aff_est
,
aff
,
NORM_INF
)
>
thres
)
{
{
cout
<<
"aff est: "
<<
aff_est
<<
endl
;
cout
<<
"aff ref: "
<<
aff
<<
endl
;
ts
->
set_failed_test_info
(
cvtest
::
TS
::
FAIL_MISMATCH
);
ts
->
set_failed_test_info
(
cvtest
::
TS
::
FAIL_MISMATCH
);
return
false
;
return
false
;
}
}
...
...
modules/calib3d/test/test_fundam.cpp
View file @
6569a585
...
@@ -1020,7 +1020,7 @@ void CV_FundamentalMatTest::prepare_to_validation( int test_case_idx )
...
@@ -1020,7 +1020,7 @@ void CV_FundamentalMatTest::prepare_to_validation( int test_case_idx )
F0
*=
1.
/
f0
[
8
];
F0
*=
1.
/
f0
[
8
];
uchar
*
status
=
test_mat
[
TEMP
][
1
].
data
;
uchar
*
status
=
test_mat
[
TEMP
][
1
].
data
;
double
err_level
=
get_success_error_level
(
test_case_idx
,
OUTPUT
,
1
);
double
err_level
=
method
<=
CV_FM_8POINT
?
1
:
get_success_error_level
(
test_case_idx
,
OUTPUT
,
1
);
uchar
*
mtfm1
=
test_mat
[
REF_OUTPUT
][
1
].
data
;
uchar
*
mtfm1
=
test_mat
[
REF_OUTPUT
][
1
].
data
;
uchar
*
mtfm2
=
test_mat
[
OUTPUT
][
1
].
data
;
uchar
*
mtfm2
=
test_mat
[
OUTPUT
][
1
].
data
;
double
*
f_prop1
=
(
double
*
)
test_mat
[
REF_OUTPUT
][
0
].
data
;
double
*
f_prop1
=
(
double
*
)
test_mat
[
REF_OUTPUT
][
0
].
data
;
...
...
modules/calib3d/test/test_modelest.cpp
View file @
6569a585
...
@@ -40,6 +40,8 @@
...
@@ -40,6 +40,8 @@
//M*/
//M*/
#include "test_precomp.hpp"
#include "test_precomp.hpp"
#if 0
#include "_modelest.h"
#include "_modelest.h"
using namespace std;
using namespace std;
...
@@ -225,3 +227,6 @@ void CV_ModelEstimator2_Test::run_func()
...
@@ -225,3 +227,6 @@ void CV_ModelEstimator2_Test::run_func()
}
}
TEST(Calib3d_ModelEstimator2, accuracy) { CV_ModelEstimator2_Test test; test.safe_run(); }
TEST(Calib3d_ModelEstimator2, accuracy) { CV_ModelEstimator2_Test test; test.safe_run(); }
#endif
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