Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
imagej-elphel
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Board
Labels
Milestones
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Elphel
imagej-elphel
Commits
dd7e6ced
Commit
dd7e6ced
authored
Feb 25, 2026
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented multiple-reference (center and 1/4 and 3/4) global LMA pose
refining.
parent
6da5747a
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
2504 additions
and
74 deletions
+2504
-74
IntersceneGlobalLmaParameters.java
...l/imagej/tileprocessor/IntersceneGlobalLmaParameters.java
+24
-12
IntersceneGlobalLmaRefine.java
...lphel/imagej/tileprocessor/IntersceneGlobalLmaRefine.java
+1843
-47
IntersceneGlobalRefine.java
...m/elphel/imagej/tileprocessor/IntersceneGlobalRefine.java
+283
-15
OpticalFlow.java
...ain/java/com/elphel/imagej/tileprocessor/OpticalFlow.java
+340
-0
QuadCLTCPU.java
...main/java/com/elphel/imagej/tileprocessor/QuadCLTCPU.java
+14
-0
No files found.
src/main/java/com/elphel/imagej/tileprocessor/IntersceneGlobalLmaParameters.java
View file @
dd7e6ced
...
...
@@ -26,6 +26,8 @@ public class IntersceneGlobalLmaParameters {
public
boolean
glob_en
;
public
boolean
glob_exit_after_test
;
// exit OpticalFlow.buildSeries() immediately after running, do not increment num_orient
public
boolean
glob_recalculate_quarter_refs
;
// force regeneration of quarter-reference DSI/INTER-INTRA-LMA files
public
boolean
glob_quarter_refs_sfm_only
;
// generate quarter-reference INTER-INTRA-LMA using SfM-only (no pose LMA updates)
public
int
glob_solver_mode
;
// 0 - current sparse global refine, 1 - classic LMA-structure implementation
public
boolean
[]
param_sel
;
public
double
[]
param_regweights
;
...
...
@@ -53,9 +55,11 @@ public class IntersceneGlobalLmaParameters {
public
int
glob_center_pair_weight_mode
;
public
IntersceneGlobalLmaParameters
()
{
glob_en
=
true
;
glob_exit_after_test
=
true
;
// TODO: change default to false when debugging is over
glob_solver_mode
=
GLOB_SOLVER_SPARSE_BANDED
;
glob_en
=
true
;
glob_exit_after_test
=
true
;
// TODO: change default to false when debugging is over
glob_recalculate_quarter_refs
=
false
;
glob_quarter_refs_sfm_only
=
true
;
glob_solver_mode
=
GLOB_SOLVER_SPARSE_BANDED
;
param_sel
=
new
boolean
[
ErsCorrection
.
DP_XYZATR
.
length
];
param_regweights
=
new
double
[
ErsCorrection
.
DP_XYZATR
.
length
];
param_lpf
=
new
double
[
ErsCorrection
.
DP_XYZATR
.
length
];
...
...
@@ -93,6 +97,10 @@ public class IntersceneGlobalLmaParameters {
"Use global LMA for adjusting scenes poses."
);
gd
.
addCheckbox
(
"Exit after Global LMA (debug mode)"
,
this
.
glob_exit_after_test
,
"exit OpticalFlow.buildSeries() immediately after running, do not increment num_orient enabling re-running next time"
);
gd
.
addCheckbox
(
"Recalculate quarter refs each run (debug)"
,
this
.
glob_recalculate_quarter_refs
,
"Force regeneration of quarter-reference -DSI_MAIN and -INTER-INTRA-LMA before Global LMA."
);
gd
.
addCheckbox
(
"Quarter refs use SfM-only generation"
,
this
.
glob_quarter_refs_sfm_only
,
"For quarter references, run scanSfmIMS disparity refinement without per-scene pose LMA adjustment."
);
gd
.
addNumericField
(
"Global LMA solver mode (0/1)"
,
this
.
glob_solver_mode
,
0
,
3
,
""
,
"0: current sparse/banded global solver, 1: classic LMA-structure global solver."
);
gd
.
addStringField
(
"Select XYZATR parameters to fit"
,
IntersceneMatchParameters
.
booleansToString
(
this
.
param_sel
,
2
),
40
,
...
...
@@ -142,13 +150,15 @@ public class IntersceneGlobalLmaParameters {
"Display debug hyperstack in ImageJ UI."
);
gd
.
addCheckbox
(
"Save only initial+final CSV"
,
this
.
glob_save_initial_final_only
,
"Do not save intermediate outer-loop TIFF/CSV, save only combined initial+final CSV."
);
gd
.
addNumericField
(
"Center pair weight mode (
0/1/2)"
,
this
.
glob_center_pair_weight_mode
,
0
,
3
,
""
,
"0: all pairs enabled,
1: disable center +/-1 pairs, 2: disable center +/-1,+/-2 pairs
."
);
gd
.
addNumericField
(
"Center pair weight mode (
>=0)"
,
this
.
glob_center_pair_weight_mode
,
0
,
3
,
""
,
"0: all pairs enabled,
N>0: disable center-reference pairs with |scene-center| <= N
."
);
}
public
void
dialogAnswers
(
GenericJTabbedDialog
gd
)
{
this
.
glob_en
=
gd
.
getNextBoolean
();
this
.
glob_exit_after_test
=
gd
.
getNextBoolean
();
this
.
glob_solver_mode
=
clampSolverMode
((
int
)
gd
.
getNextNumber
());
this
.
glob_en
=
gd
.
getNextBoolean
();
this
.
glob_exit_after_test
=
gd
.
getNextBoolean
();
this
.
glob_recalculate_quarter_refs
=
gd
.
getNextBoolean
();
this
.
glob_quarter_refs_sfm_only
=
gd
.
getNextBoolean
();
this
.
glob_solver_mode
=
clampSolverMode
((
int
)
gd
.
getNextNumber
());
this
.
param_sel
=
IntersceneMatchParameters
.
StringToBooleans
(
gd
.
getNextString
(),
this
.
param_sel
);
this
.
param_regweights
=
IntersceneMatchParameters
.
StringToDoubles
(
gd
.
getNextString
(),
this
.
param_regweights
);
this
.
param_lpf
=
IntersceneMatchParameters
.
StringToDoubles
(
gd
.
getNextString
(),
this
.
param_lpf
);
...
...
@@ -179,14 +189,13 @@ public class IntersceneGlobalLmaParameters {
if
(
this
.
glob_center_pair_weight_mode
<
0
)
{
this
.
glob_center_pair_weight_mode
=
0
;
}
if
(
this
.
glob_center_pair_weight_mode
>
2
)
{
this
.
glob_center_pair_weight_mode
=
2
;
}
}
public
void
setProperties
(
String
prefix
,
Properties
properties
){
properties
.
setProperty
(
prefix
+
"glob_en"
,
this
.
glob_en
+
""
);
properties
.
setProperty
(
prefix
+
"glob_exit_after_test"
,
this
.
glob_exit_after_test
+
""
);
properties
.
setProperty
(
prefix
+
"glob_recalculate_quarter_refs"
,
this
.
glob_recalculate_quarter_refs
+
""
);
properties
.
setProperty
(
prefix
+
"glob_quarter_refs_sfm_only"
,
this
.
glob_quarter_refs_sfm_only
+
""
);
properties
.
setProperty
(
prefix
+
"glob_solver_mode"
,
this
.
glob_solver_mode
+
""
);
properties
.
setProperty
(
prefix
+
"param_sel"
,
IntersceneMatchParameters
.
booleansToString
(
this
.
param_sel
,
2
));
properties
.
setProperty
(
prefix
+
"param_regweights"
,
IntersceneMatchParameters
.
doublesToString
(
this
.
param_regweights
));
...
...
@@ -218,6 +227,8 @@ public class IntersceneGlobalLmaParameters {
public
void
getProperties
(
String
prefix
,
Properties
properties
){
if
(
properties
.
getProperty
(
prefix
+
"glob_en"
)!=
null
)
this
.
glob_en
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"glob_en"
));
if
(
properties
.
getProperty
(
prefix
+
"glob_exit_after_test"
)!=
null
)
this
.
glob_exit_after_test
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"glob_exit_after_test"
));
if
(
properties
.
getProperty
(
prefix
+
"glob_recalculate_quarter_refs"
)!=
null
)
this
.
glob_recalculate_quarter_refs
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"glob_recalculate_quarter_refs"
));
if
(
properties
.
getProperty
(
prefix
+
"glob_quarter_refs_sfm_only"
)!=
null
)
this
.
glob_quarter_refs_sfm_only
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"glob_quarter_refs_sfm_only"
));
if
(
properties
.
getProperty
(
prefix
+
"glob_solver_mode"
)!=
null
)
this
.
glob_solver_mode
=
Integer
.
parseInt
(
properties
.
getProperty
(
prefix
+
"glob_solver_mode"
));
this
.
glob_solver_mode
=
clampSolverMode
(
this
.
glob_solver_mode
);
if
(
properties
.
getProperty
(
prefix
+
"param_sel"
)!=
null
)
this
.
param_sel
=
IntersceneMatchParameters
.
StringToBooleans
(
properties
.
getProperty
(
prefix
+
"param_sel"
),
this
.
param_sel
);
...
...
@@ -246,7 +257,6 @@ public class IntersceneGlobalLmaParameters {
if
(
properties
.
getProperty
(
prefix
+
"glob_save_initial_final_only"
)!=
null
)
this
.
glob_save_initial_final_only
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"glob_save_initial_final_only"
));
if
(
properties
.
getProperty
(
prefix
+
"glob_center_pair_weight_mode"
)!=
null
)
this
.
glob_center_pair_weight_mode
=
Integer
.
parseInt
(
properties
.
getProperty
(
prefix
+
"glob_center_pair_weight_mode"
));
if
(
this
.
glob_center_pair_weight_mode
<
0
)
this
.
glob_center_pair_weight_mode
=
0
;
if
(
this
.
glob_center_pair_weight_mode
>
2
)
this
.
glob_center_pair_weight_mode
=
2
;
}
@Override
...
...
@@ -254,6 +264,8 @@ public class IntersceneGlobalLmaParameters {
IntersceneGlobalLmaParameters
iglp
=
new
IntersceneGlobalLmaParameters
();
iglp
.
glob_en
=
this
.
glob_en
;
iglp
.
glob_exit_after_test
=
this
.
glob_exit_after_test
;
iglp
.
glob_recalculate_quarter_refs
=
this
.
glob_recalculate_quarter_refs
;
iglp
.
glob_quarter_refs_sfm_only
=
this
.
glob_quarter_refs_sfm_only
;
iglp
.
glob_solver_mode
=
this
.
glob_solver_mode
;
iglp
.
param_sel
=
this
.
param_sel
.
clone
();
iglp
.
param_regweights
=
this
.
param_regweights
.
clone
();
...
...
src/main/java/com/elphel/imagej/tileprocessor/IntersceneGlobalLmaRefine.java
View file @
dd7e6ced
...
...
@@ -2,41 +2,165 @@ package com.elphel.imagej.tileprocessor;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
com.elphel.imagej.cameras.CLTParameters
;
import
com.elphel.imagej.gpu.TpTask
;
import
Jama.Matrix
;
/**
* Classic-LMA structured global refinement path.
*
* <p>
Phase-1 keeps numeric behavior stable by delegating the actual solve to
*
{@link IntersceneGlobalRefine}, while this class owns the classic LMA structure
*
({@code prepareLMA/getFxDerivs/getYminusFxWeighted/lmaStep/runLma}) for incremental migration
.
* <p>
This class keeps explicit LMA structure
*
({@code prepareLMA/getFxDerivs/getYminusFxWeighted/getWJtJlambda/lmaStep/runLma})
*
and assembles one combined residual/Jacobian consisting of correlation, LPF and pull terms
.
*/
public
class
IntersceneGlobalLmaRefine
{
private
static
final
int
[]
SCENE_POSE_PARAM_ORDER
=
ErsCorrection
.
DP_XYZATR
.
clone
();
private
static
final
int
[]
SCENE_RATE_ANG_PAR_INDICES
=
{
ErsCorrection
.
DP_DSVAZ
,
ErsCorrection
.
DP_DSVTL
,
ErsCorrection
.
DP_DSVRL
};
private
static
final
int
[]
SCENE_RATE_LIN_PAR_INDICES
=
{
ErsCorrection
.
DP_DSVX
,
ErsCorrection
.
DP_DSVY
,
ErsCorrection
.
DP_DSVZ
};
private
static
final
int
[]
REF_RATE_ANG_PAR_INDICES
=
{
ErsCorrection
.
DP_DVAZ
,
ErsCorrection
.
DP_DVTL
,
ErsCorrection
.
DP_DVRL
};
private
static
final
int
[]
REF_RATE_LIN_PAR_INDICES
=
{
ErsCorrection
.
DP_DVX
,
ErsCorrection
.
DP_DVY
,
ErsCorrection
.
DP_DVZ
};
private
static
final
double
MIN_DIAG
=
1.0
e
-
12
;
private
static
final
double
DEFAULT_PULL_WEIGHT
=
1.0
e
-
6
;
private
static
final
double
DEFAULT_DT
=
1.0
/
60.0
;
private
static
final
class
PairFactor
{
int
sceneIndex
;
int
refSceneIndex
;
double
pairWeight
;
PairFactor
(
final
int
sceneIndex
,
final
int
refSceneIndex
,
final
double
pairWeight
)
{
this
.
sceneIndex
=
sceneIndex
;
this
.
refSceneIndex
=
refSceneIndex
;
this
.
pairWeight
=
pairWeight
;
}
}
private
static
final
class
PairObservation
{
int
sceneIndex
;
int
refSceneIndex
;
double
pairWeight
=
1.0
;
double
[][]
centers
=
null
;
double
[][]
eigen
=
null
;
double
[][]
vectorXys
=
null
;
boolean
[]
reliableRef
=
null
;
int
yBase
=
0
;
int
wBase
=
0
;
}
private
static
final
class
ObservationCache
{
ArrayList
<
PairObservation
>
observations
=
new
ArrayList
<
PairObservation
>();
double
[]
yVector
=
null
;
double
[]
wVector
=
null
;
int
tilesPerPair
=
0
;
int
solvedPairs
=
0
;
int
failedPairs
=
0
;
}
private
static
final
class
RefGpuData
{
int
refSceneIndex
=
-
1
;
double
[][]
pXpYD
=
null
;
TpTask
[]
tasks
=
null
;
boolean
[]
reliableMask
=
null
;
}
private
static
final
class
RateTerm
{
int
sceneIndex
;
double
coeff
;
RateTerm
(
final
int
sceneIndex
,
final
double
coeff
)
{
this
.
sceneIndex
=
sceneIndex
;
this
.
coeff
=
coeff
;
}
}
private
static
final
class
VectorTerm
{
int
vectorIndex
;
double
coeff
;
VectorTerm
(
final
int
vectorIndex
,
final
double
coeff
)
{
this
.
vectorIndex
=
vectorIndex
;
this
.
coeff
=
coeff
;
}
}
private
static
final
class
CorrelationPairContext
{
PairObservation
obs
;
int
[]
localParamIndices
=
new
int
[
0
];
ArrayList
<
VectorTerm
>[]
vectorTerms
=
null
;
int
[]
validTiles
=
new
int
[
0
];
double
[][][]
eigTrans
=
null
;
double
[]
yRows
=
new
double
[
0
];
double
[]
rawWeights
=
new
double
[
0
];
int
rowBase
=
0
;
}
private
static
final
class
ClassicState
{
int
[]
activePoseParams
=
new
int
[
0
];
int
[]
vectorSceneIndices
=
new
int
[
0
];
int
[]
vectorParamIndices
=
new
int
[
0
];
HashMap
<
Long
,
Integer
>
vectorIndexBySceneParam
=
new
HashMap
<
Long
,
Integer
>();
double
[]
parameterVector
=
new
double
[
0
];
double
[]
parameterInitial
=
new
double
[
0
];
double
[]
parameterPull
=
new
double
[
0
];
int
correlationRows
=
0
;
int
pullBase
=
0
;
int
pullRows
=
0
;
int
lpfBase
=
0
;
int
[]
lpfVar
=
new
int
[
0
];
int
[]
lpfPrevVar
=
new
int
[
0
];
int
[]
lpfNextVar
=
new
int
[
0
];
double
[]
lpfPrevFixed
=
new
double
[
0
];
double
[]
lpfNextFixed
=
new
double
[
0
];
ArrayList
<
CorrelationPairContext
>
correlationPairs
=
new
ArrayList
<
CorrelationPairContext
>();
double
[][][]
rateSourceScenes
=
null
;
boolean
includeRateChain
=
true
;
double
[]
yVector
=
new
double
[
0
];
double
[]
weights
=
new
double
[
0
];
double
[][]
lastJt
=
null
;
double
[]
lastYminusFx
=
null
;
double
[]
lastRms
=
null
;
double
[]
initialRms
=
null
;
double
lastMaxDelta
=
Double
.
NaN
;
int
acceptedSteps
=
0
;
int
attemptedSteps
=
0
;
void
clearLinearization
()
{
lastJt
=
null
;
lastYminusFx
=
null
;
lastRms
=
null
;
initialRms
=
null
;
lastMaxDelta
=
Double
.
NaN
;
acceptedSteps
=
0
;
attemptedSteps
=
0
;
}
}
...
...
@@ -58,6 +182,10 @@ public class IntersceneGlobalLmaRefine {
private
final
IntersceneGlobalRefine
.
Options
options
;
private
final
ClassicState
classicState
=
new
ClassicState
();
private
double
[]
refDisparity
=
null
;
private
double
[][]
pXpYDCenter
=
null
;
private
double
[]
sceneTimes
=
null
;
private
IntersceneGlobalLmaRefine
(
final
CLTParameters
cltParameters
,
final
QuadCLT
[]
quadCLTs
,
...
...
@@ -163,7 +291,6 @@ public class IntersceneGlobalLmaRefine {
}
}
@SuppressWarnings
(
"unused"
)
private
static
void
setScenePoseParameter
(
final
double
[][]
scenePose
,
final
int
dpIndex
,
...
...
@@ -208,6 +335,32 @@ public class IntersceneGlobalLmaRefine {
return
values
[
index
];
}
private
static
long
getSceneParamKey
(
final
int
sceneIndex
,
final
int
dpIndex
)
{
return
(((
long
)
sceneIndex
)
<<
32
)
^
(
dpIndex
&
0xffffffff
L
);
}
private
static
int
[]
getParameterIndices
(
final
boolean
[]
mask
)
{
if
(
mask
==
null
)
{
return
new
int
[
0
];
}
int
n
=
0
;
for
(
int
i
=
0
;
i
<
mask
.
length
;
i
++)
{
if
(
mask
[
i
])
{
n
++;
}
}
final
int
[]
out
=
new
int
[
n
];
int
indx
=
0
;
for
(
int
i
=
0
;
i
<
mask
.
length
;
i
++)
{
if
(
mask
[
i
])
{
out
[
indx
++]
=
i
;
}
}
return
out
;
}
private
int
[]
buildActivePoseParameters
()
{
final
ArrayList
<
Integer
>
active
=
new
ArrayList
<
Integer
>();
for
(
final
int
dpIndex
:
SCENE_POSE_PARAM_ORDER
)
{
...
...
@@ -247,6 +400,99 @@ public class IntersceneGlobalLmaRefine {
return
out
;
}
private
static
double
[][][]
cloneScenePoses
(
final
double
[][][]
scenes_xyzatr
)
{
if
(
scenes_xyzatr
==
null
)
{
return
null
;
}
final
double
[][][]
copy
=
new
double
[
scenes_xyzatr
.
length
][][];
for
(
int
i
=
0
;
i
<
scenes_xyzatr
.
length
;
i
++)
{
if
(
scenes_xyzatr
[
i
]
==
null
)
{
continue
;
}
copy
[
i
]
=
new
double
[
scenes_xyzatr
[
i
].
length
][];
for
(
int
j
=
0
;
j
<
scenes_xyzatr
[
i
].
length
;
j
++)
{
if
(
scenes_xyzatr
[
i
][
j
]
!=
null
)
{
copy
[
i
][
j
]
=
scenes_xyzatr
[
i
][
j
].
clone
();
}
}
}
return
copy
;
}
private
void
buildLpfRows
()
{
final
int
nvars
=
classicState
.
parameterVector
.
length
;
final
ArrayList
<
Integer
>
lpfVar
=
new
ArrayList
<
Integer
>();
final
ArrayList
<
Integer
>
lpfPrevVar
=
new
ArrayList
<
Integer
>();
final
ArrayList
<
Integer
>
lpfNextVar
=
new
ArrayList
<
Integer
>();
final
ArrayList
<
Double
>
lpfPrevFixed
=
new
ArrayList
<
Double
>();
final
ArrayList
<
Double
>
lpfNextFixed
=
new
ArrayList
<
Double
>();
for
(
int
i
=
0
;
i
<
nvars
;
i
++)
{
final
int
scene
=
classicState
.
vectorSceneIndices
[
i
];
final
int
dpIndex
=
classicState
.
vectorParamIndices
[
i
];
final
double
lpfControl
=
getArrayValue
(
paramLpf
,
dpIndex
);
if
(!(
lpfControl
>
0.0
))
{
continue
;
}
final
int
prevScene
=
scene
-
1
;
final
int
nextScene
=
scene
+
1
;
if
((
prevScene
<
earliestScene
)
||
(
nextScene
>
lastScene
))
{
continue
;
}
int
prevVar
=
-
1
;
int
nextVar
=
-
1
;
double
prevFixed
=
0.0
;
double
nextFixed
=
0.0
;
final
Integer
prevIdx
=
classicState
.
vectorIndexBySceneParam
.
get
(
getSceneParamKey
(
prevScene
,
dpIndex
));
if
(
prevIdx
!=
null
)
{
prevVar
=
prevIdx
.
intValue
();
}
else
if
((
prevScene
>=
0
)
&&
(
prevScene
<
scenesXyzatr
.
length
)
&&
isPoseValid
(
scenesXyzatr
[
prevScene
]))
{
prevFixed
=
normalizeValue
(
getScenePoseParameter
(
scenesXyzatr
[
prevScene
],
dpIndex
));
}
else
{
continue
;
}
final
Integer
nextIdx
=
classicState
.
vectorIndexBySceneParam
.
get
(
getSceneParamKey
(
nextScene
,
dpIndex
));
if
(
nextIdx
!=
null
)
{
nextVar
=
nextIdx
.
intValue
();
}
else
if
((
nextScene
>=
0
)
&&
(
nextScene
<
scenesXyzatr
.
length
)
&&
isPoseValid
(
scenesXyzatr
[
nextScene
]))
{
nextFixed
=
normalizeValue
(
getScenePoseParameter
(
scenesXyzatr
[
nextScene
],
dpIndex
));
}
else
{
continue
;
}
lpfVar
.
add
(
Integer
.
valueOf
(
i
));
lpfPrevVar
.
add
(
Integer
.
valueOf
(
prevVar
));
lpfNextVar
.
add
(
Integer
.
valueOf
(
nextVar
));
lpfPrevFixed
.
add
(
Double
.
valueOf
(
prevFixed
));
lpfNextFixed
.
add
(
Double
.
valueOf
(
nextFixed
));
}
classicState
.
pullRows
=
nvars
;
classicState
.
lpfVar
=
new
int
[
lpfVar
.
size
()];
classicState
.
lpfPrevVar
=
new
int
[
lpfVar
.
size
()];
classicState
.
lpfNextVar
=
new
int
[
lpfVar
.
size
()];
classicState
.
lpfPrevFixed
=
new
double
[
lpfVar
.
size
()];
classicState
.
lpfNextFixed
=
new
double
[
lpfVar
.
size
()];
for
(
int
i
=
0
;
i
<
lpfVar
.
size
();
i
++)
{
classicState
.
lpfVar
[
i
]
=
lpfVar
.
get
(
i
).
intValue
();
classicState
.
lpfPrevVar
[
i
]
=
lpfPrevVar
.
get
(
i
).
intValue
();
classicState
.
lpfNextVar
[
i
]
=
lpfNextVar
.
get
(
i
).
intValue
();
classicState
.
lpfPrevFixed
[
i
]
=
lpfPrevFixed
.
get
(
i
).
doubleValue
();
classicState
.
lpfNextFixed
[
i
]
=
lpfNextFixed
.
get
(
i
).
doubleValue
();
}
}
private
void
buildStateVector
()
{
classicState
.
activePoseParams
=
buildActivePoseParameters
();
if
(
scenesXyzatr
==
null
)
{
...
...
@@ -255,6 +501,17 @@ public class IntersceneGlobalLmaRefine {
classicState
.
parameterVector
=
new
double
[
0
];
classicState
.
parameterInitial
=
new
double
[
0
];
classicState
.
parameterPull
=
new
double
[
0
];
classicState
.
vectorIndexBySceneParam
.
clear
();
classicState
.
pullRows
=
0
;
classicState
.
lpfVar
=
new
int
[
0
];
classicState
.
lpfPrevVar
=
new
int
[
0
];
classicState
.
lpfNextVar
=
new
int
[
0
];
classicState
.
lpfPrevFixed
=
new
double
[
0
];
classicState
.
lpfNextFixed
=
new
double
[
0
];
classicState
.
correlationRows
=
0
;
classicState
.
pullBase
=
0
;
classicState
.
lpfBase
=
0
;
classicState
.
correlationPairs
.
clear
();
classicState
.
yVector
=
new
double
[
0
];
classicState
.
weights
=
new
double
[
0
];
classicState
.
clearLinearization
();
...
...
@@ -282,14 +539,14 @@ public class IntersceneGlobalLmaRefine {
classicState
.
parameterVector
=
new
double
[
n
];
classicState
.
parameterInitial
=
new
double
[
n
];
classicState
.
parameterPull
=
new
double
[
n
];
classicState
.
yVector
=
new
double
[
n
];
classicState
.
weights
=
new
double
[
n
];
classicState
.
vectorIndexBySceneParam
.
clear
();
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
final
int
scene
=
vectorSceneIndices
.
get
(
i
);
final
int
dpIndex
=
vectorParamIndices
.
get
(
i
);
classicState
.
vectorSceneIndices
[
i
]
=
scene
;
classicState
.
vectorParamIndices
[
i
]
=
dpIndex
;
classicState
.
vectorIndexBySceneParam
.
put
(
getSceneParamKey
(
scene
,
dpIndex
),
i
);
final
double
current
=
normalizeValue
(
getScenePoseParameter
(
scenesXyzatr
[
scene
],
dpIndex
));
double
pull
=
current
;
...
...
@@ -298,17 +555,12 @@ public class IntersceneGlobalLmaRefine {
isPoseValid
(
scenesXyzatrPull
[
scene
]))
{
pull
=
normalizeValue
(
getScenePoseParameter
(
scenesXyzatrPull
[
scene
],
dpIndex
));
}
final
double
regWeight
=
getArrayValue
(
paramRegweights
,
dpIndex
);
final
double
lpfWeight
=
getArrayValue
(
paramLpf
,
dpIndex
);
final
double
rawWeight
=
(
regWeight
>
0.0
)
?
regWeight
:
((
lpfWeight
>
0.0
)
?
lpfWeight
:
1.0
);
classicState
.
parameterVector
[
i
]
=
current
;
classicState
.
parameterInitial
[
i
]
=
current
;
classicState
.
parameterPull
[
i
]
=
pull
;
classicState
.
yVector
[
i
]
=
0.0
;
classicState
.
weights
[
i
]
=
rawWeight
;
}
classicState
.
weights
=
normalizeWeights
(
classicState
.
weights
);
buildLpfRows
(
);
classicState
.
clearLinearization
();
}
...
...
@@ -325,15 +577,339 @@ public class IntersceneGlobalLmaRefine {
}
}
private
void
applyVectorToScenes
(
final
double
[]
vector
)
{
if
(
scenesXyzatr
==
null
)
{
return
;
}
for
(
int
i
=
0
;
i
<
vector
.
length
;
i
++)
{
final
int
scene
=
classicState
.
vectorSceneIndices
[
i
];
final
int
dpIndex
=
classicState
.
vectorParamIndices
[
i
];
if
((
scene
<
0
)
||
(
scene
>=
scenesXyzatr
.
length
)
||
!
isPoseValid
(
scenesXyzatr
[
scene
]))
{
continue
;
}
setScenePoseParameter
(
scenesXyzatr
[
scene
],
dpIndex
,
normalizeValue
(
vector
[
i
]));
}
}
private
static
double
[][][]
setEigenTransform
(
final
double
eigMaxSqrt
,
final
double
eigMinSqrt
,
final
double
[][]
eigen
)
{
if
(
eigen
==
null
)
{
return
null
;
}
final
double
[][][]
transform
=
new
double
[
eigen
.
length
][][];
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
QuadCLT
.
THREADS_MAX
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
final
double
k0
=
1.0
/
eigMaxSqrt
;
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
@Override
public
void
run
()
{
for
(
int
iTile
=
ai
.
getAndIncrement
();
iTile
<
eigen
.
length
;
iTile
=
ai
.
getAndIncrement
())
{
if
(
eigen
[
iTile
]
==
null
)
{
continue
;
}
final
double
[][]
am
=
{{
eigen
[
iTile
][
0
],
eigen
[
iTile
][
1
]},
{
eigen
[
iTile
][
1
],
-
eigen
[
iTile
][
0
]}};
if
(!
Double
.
isNaN
(
am
[
0
][
0
])
&&
!
Double
.
isNaN
(
am
[
0
][
1
]))
{
transform
[
iTile
]
=
new
double
[
2
][
2
];
for
(
int
i
=
0
;
i
<
2
;
i
++)
{
final
double
k
=
Math
.
max
(
0
,
1
/
Math
.
max
(
eigMinSqrt
,
Math
.
sqrt
(
eigen
[
iTile
][
2
+
i
]))
-
k0
);
for
(
int
j
=
0
;
j
<
2
;
j
++)
{
transform
[
iTile
][
i
][
j
]
=
k
*
am
[
i
][
j
];
}
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
return
transform
;
}
private
void
buildCombinedRows
(
final
ObservationCache
obsCache
,
final
int
firstScene
,
final
int
endScene
,
final
boolean
[]
activePoseScene
,
final
int
debugLevel
)
{
classicState
.
correlationPairs
.
clear
();
final
ArrayList
<
Double
>
corrY
=
new
ArrayList
<
Double
>();
final
ArrayList
<
Double
>
corrW
=
new
ArrayList
<
Double
>();
int
corrRows
=
0
;
for
(
int
iobs
=
0
;
iobs
<
obsCache
.
observations
.
size
();
iobs
++)
{
final
PairObservation
obs
=
obsCache
.
observations
.
get
(
iobs
);
if
(!(
obs
.
pairWeight
>
0.0
)
||
(
obs
.
vectorXys
==
null
)
||
(
obs
.
centers
==
null
))
{
continue
;
}
final
int
ivar
=
obs
.
sceneIndex
-
firstScene
;
if
((
ivar
<
0
)
||
(
ivar
>=
activePoseScene
.
length
)
||
!
activePoseScene
[
ivar
])
{
continue
;
}
final
boolean
[]
localMask
=
getLocalParamMaskForPair
(
paramSelect
,
obs
.
sceneIndex
,
obs
.
refSceneIndex
,
centerIndex
,
disableErs
);
final
int
[]
localParamIndices
=
getParameterIndices
(
localMask
);
if
(
localParamIndices
.
length
==
0
)
{
continue
;
}
@SuppressWarnings
(
"unchecked"
)
final
ArrayList
<
VectorTerm
>[]
vectorTerms
=
new
ArrayList
[
localParamIndices
.
length
];
for
(
int
ilp
=
0
;
ilp
<
localParamIndices
.
length
;
ilp
++)
{
vectorTerms
[
ilp
]
=
mapLocalParameterToVectorTerms
(
localParamIndices
[
ilp
],
obs
.
sceneIndex
,
obs
.
refSceneIndex
,
centerIndex
,
firstScene
,
endScene
,
activePoseScene
,
classicState
.
rateSourceScenes
,
classicState
.
includeRateChain
);
}
final
double
[][][]
eigTrans
=
setEigenTransform
(
cltParameters
.
imp
.
eig_max_sqrt
,
cltParameters
.
imp
.
eig_min_sqrt
,
obs
.
eigen
);
final
ArrayList
<
Integer
>
validTileList
=
new
ArrayList
<
Integer
>();
final
ArrayList
<
Double
>
yRows
=
new
ArrayList
<
Double
>();
final
ArrayList
<
Double
>
wRows
=
new
ArrayList
<
Double
>();
final
int
nt
=
Math
.
min
(
obs
.
vectorXys
.
length
,
obs
.
centers
.
length
);
for
(
int
itile
=
0
;
itile
<
nt
;
itile
++)
{
final
double
[]
v
=
obs
.
vectorXys
[
itile
];
final
double
[]
center
=
obs
.
centers
[
itile
];
if
((
v
==
null
)
||
(
v
.
length
<
3
)
||
(
center
==
null
)
||
(
center
.
length
<
3
))
{
continue
;
}
final
double
w
=
v
[
2
];
if
(!(
w
>
0.0
)
||
!
Double
.
isFinite
(
w
))
{
continue
;
}
final
double
[][]
tr
=
(
eigTrans
==
null
)
?
null
:
eigTrans
[
itile
];
if
((
eigTrans
!=
null
)
&&
(
tr
==
null
))
{
continue
;
}
double
y0
=
v
[
0
];
double
y1
=
v
[
1
];
if
(
tr
!=
null
)
{
final
double
ty0
=
tr
[
0
][
0
]
*
y0
+
tr
[
0
][
1
]
*
y1
;
final
double
ty1
=
tr
[
1
][
0
]
*
y0
+
tr
[
1
][
1
]
*
y1
;
y0
=
ty0
;
y1
=
ty1
;
}
validTileList
.
add
(
Integer
.
valueOf
(
itile
));
yRows
.
add
(
Double
.
valueOf
(
y0
));
yRows
.
add
(
Double
.
valueOf
(
y1
));
wRows
.
add
(
Double
.
valueOf
(
w
));
wRows
.
add
(
Double
.
valueOf
(
w
));
}
if
(
validTileList
.
isEmpty
())
{
continue
;
}
final
CorrelationPairContext
cpc
=
new
CorrelationPairContext
();
cpc
.
obs
=
obs
;
cpc
.
localParamIndices
=
localParamIndices
;
cpc
.
vectorTerms
=
vectorTerms
;
cpc
.
validTiles
=
new
int
[
validTileList
.
size
()];
for
(
int
i
=
0
;
i
<
cpc
.
validTiles
.
length
;
i
++)
{
cpc
.
validTiles
[
i
]
=
validTileList
.
get
(
i
).
intValue
();
}
cpc
.
eigTrans
=
eigTrans
;
cpc
.
yRows
=
new
double
[
yRows
.
size
()];
for
(
int
i
=
0
;
i
<
cpc
.
yRows
.
length
;
i
++)
{
cpc
.
yRows
[
i
]
=
yRows
.
get
(
i
).
doubleValue
();
}
cpc
.
rawWeights
=
new
double
[
wRows
.
size
()];
for
(
int
i
=
0
;
i
<
cpc
.
rawWeights
.
length
;
i
++)
{
cpc
.
rawWeights
[
i
]
=
wRows
.
get
(
i
).
doubleValue
();
}
cpc
.
rowBase
=
corrRows
;
corrRows
+=
cpc
.
yRows
.
length
;
classicState
.
correlationPairs
.
add
(
cpc
);
for
(
int
i
=
0
;
i
<
cpc
.
yRows
.
length
;
i
++)
{
corrY
.
add
(
Double
.
valueOf
(
cpc
.
yRows
[
i
]));
corrW
.
add
(
Double
.
valueOf
(
cpc
.
rawWeights
[
i
]));
}
}
classicState
.
correlationRows
=
corrRows
;
classicState
.
pullBase
=
corrRows
;
classicState
.
lpfBase
=
classicState
.
pullBase
+
classicState
.
pullRows
;
final
int
rows
=
classicState
.
lpfBase
+
classicState
.
lpfVar
.
length
;
classicState
.
yVector
=
new
double
[
rows
];
final
double
[]
rawWeights
=
new
double
[
rows
];
for
(
int
i
=
0
;
i
<
corrRows
;
i
++)
{
classicState
.
yVector
[
i
]
=
corrY
.
get
(
i
).
doubleValue
();
rawWeights
[
i
]
=
corrW
.
get
(
i
).
doubleValue
();
}
for
(
int
i
=
0
;
i
<
classicState
.
pullRows
;
i
++)
{
final
int
row
=
classicState
.
pullBase
+
i
;
classicState
.
yVector
[
row
]
=
0.0
;
final
int
dpIndex
=
classicState
.
vectorParamIndices
[
i
];
final
double
regWeight
=
getArrayValue
(
paramRegweights
,
dpIndex
);
rawWeights
[
row
]
=
(
regWeight
>
0.0
)
?
(
regWeight
*
regWeight
)
:
DEFAULT_PULL_WEIGHT
;
}
for
(
int
i
=
0
;
i
<
classicState
.
lpfVar
.
length
;
i
++)
{
final
int
row
=
classicState
.
lpfBase
+
i
;
classicState
.
yVector
[
row
]
=
0.0
;
final
int
iv
=
classicState
.
lpfVar
[
i
];
final
int
dpIndex
=
classicState
.
vectorParamIndices
[
iv
];
final
double
lpfControl
=
getArrayValue
(
paramLpf
,
dpIndex
);
rawWeights
[
row
]
=
(
lpfControl
>
0.0
)
?
(
lpfControl
*
lpfControl
)
:
0.0
;
}
classicState
.
weights
=
normalizeWeights
(
rawWeights
);
if
(
debugLevel
>
-
3
)
{
System
.
out
.
println
(
"IntersceneGlobalLmaRefine: combined rows built, corrPairs="
+
classicState
.
correlationPairs
.
size
()
+
", corrRows="
+
classicState
.
correlationRows
+
", pullRows="
+
classicState
.
pullRows
+
", lpfRows="
+
classicState
.
lpfVar
.
length
+
", totalRows="
+
rows
);
}
}
private
boolean
rebuildObservationRowsForOuter
(
final
int
debugLevel
)
{
if
((
classicState
.
parameterVector
==
null
)
||
(
classicState
.
parameterVector
.
length
==
0
))
{
classicState
.
correlationPairs
.
clear
();
classicState
.
correlationRows
=
0
;
classicState
.
pullBase
=
0
;
classicState
.
lpfBase
=
classicState
.
pullRows
;
final
int
rows
=
classicState
.
pullRows
+
classicState
.
lpfVar
.
length
;
classicState
.
yVector
=
new
double
[
rows
];
final
double
[]
rawWeights
=
new
double
[
rows
];
for
(
int
i
=
0
;
i
<
classicState
.
pullRows
;
i
++)
{
final
int
dpIndex
=
classicState
.
vectorParamIndices
[
i
];
final
double
regWeight
=
getArrayValue
(
paramRegweights
,
dpIndex
);
rawWeights
[
i
]
=
(
regWeight
>
0.0
)
?
(
regWeight
*
regWeight
)
:
DEFAULT_PULL_WEIGHT
;
}
for
(
int
i
=
0
;
i
<
classicState
.
lpfVar
.
length
;
i
++)
{
final
int
iv
=
classicState
.
lpfVar
[
i
];
final
int
dpIndex
=
classicState
.
vectorParamIndices
[
iv
];
final
double
lpfControl
=
getArrayValue
(
paramLpf
,
dpIndex
);
rawWeights
[
classicState
.
pullRows
+
i
]
=
(
lpfControl
>
0.0
)
?
(
lpfControl
*
lpfControl
)
:
0.0
;
}
classicState
.
weights
=
normalizeWeights
(
rawWeights
);
return
true
;
}
final
int
firstScene
=
Math
.
max
(
0
,
earliestScene
);
final
int
endScene
=
Math
.
min
(
lastScene
,
quadCLTs
.
length
-
1
);
final
int
nvars
=
endScene
-
firstScene
+
1
;
final
boolean
[]
activePoseScene
=
new
boolean
[
nvars
];
for
(
int
nscene
=
firstScene
;
nscene
<=
endScene
;
nscene
++)
{
final
int
ivar
=
nscene
-
firstScene
;
activePoseScene
[
ivar
]
=
(
nscene
!=
centerIndex
)
&&
(
quadCLTs
[
nscene
]
!=
null
)
&&
(
scenesXyzatr
[
nscene
]
!=
null
);
}
classicState
.
rateSourceScenes
=
options
.
freezeRateChainInInner
?
cloneScenePoses
(
scenesXyzatr
)
:
scenesXyzatr
;
classicState
.
includeRateChain
=
!
options
.
freezeRateChainInInner
;
final
ArrayList
<
PairFactor
>
pairFactors
=
buildPairFactors
(
cltParameters
,
quadCLTs
,
scenesXyzatr
,
activePoseScene
,
firstScene
,
endScene
,
centerIndex
,
options
.
minOffset
,
debugLevel
);
applyPairWeights
(
pairFactors
,
centerIndex
,
options
.
centerPairWeightMode
,
debugLevel
);
final
RefGpuData
[]
refGpuCache
=
new
RefGpuData
[
nvars
];
final
double
[]
minMax
=
{
options
.
minOffset
,
options
.
maxOffset
,
Double
.
NaN
};
final
ObservationCache
obsCache
=
buildObservationCache
(
cltParameters
,
quadCLTs
,
centerCLT
,
centerIndex
,
firstScene
,
endScene
,
scenesXyzatr
,
sceneTimes
,
pairFactors
,
refDisparity
,
pXpYDCenter
,
reliableRef
,
mbMaxGain
,
minMax
,
refGpuCache
,
debugLevel
);
if
(
obsCache
.
observations
.
isEmpty
())
{
classicState
.
correlationPairs
.
clear
();
classicState
.
correlationRows
=
0
;
classicState
.
pullBase
=
0
;
classicState
.
lpfBase
=
classicState
.
pullRows
;
final
int
rows
=
classicState
.
pullRows
+
classicState
.
lpfVar
.
length
;
classicState
.
yVector
=
new
double
[
rows
];
final
double
[]
rawWeights
=
new
double
[
rows
];
for
(
int
i
=
0
;
i
<
classicState
.
pullRows
;
i
++)
{
final
int
dpIndex
=
classicState
.
vectorParamIndices
[
i
];
final
double
regWeight
=
getArrayValue
(
paramRegweights
,
dpIndex
);
rawWeights
[
i
]
=
(
regWeight
>
0.0
)
?
(
regWeight
*
regWeight
)
:
DEFAULT_PULL_WEIGHT
;
}
for
(
int
i
=
0
;
i
<
classicState
.
lpfVar
.
length
;
i
++)
{
final
int
iv
=
classicState
.
lpfVar
[
i
];
final
int
dpIndex
=
classicState
.
vectorParamIndices
[
iv
];
final
double
lpfControl
=
getArrayValue
(
paramLpf
,
dpIndex
);
rawWeights
[
classicState
.
pullRows
+
i
]
=
(
lpfControl
>
0.0
)
?
(
lpfControl
*
lpfControl
)
:
0.0
;
}
classicState
.
weights
=
normalizeWeights
(
rawWeights
);
return
false
;
}
buildCombinedRows
(
obsCache
,
firstScene
,
endScene
,
activePoseScene
,
debugLevel
);
return
true
;
}
private
void
prepareLMA
(
final
int
debugLevel
)
{
buildStateVector
();
applyVectorToScenes
(
classicState
.
parameterVector
);
final
int
firstScene
=
Math
.
max
(
0
,
earliestScene
);
final
int
endScene
=
Math
.
min
(
lastScene
,
quadCLTs
.
length
-
1
);
if
((
endScene
>=
firstScene
)
&&
(
centerCLT
!=
null
))
{
refDisparity
=
(
centerDisparity
!=
null
)
?
centerDisparity
:
centerCLT
.
getDLS
()[
cltParameters
.
imp
.
use_lma_dsi
?
1
:
0
];
pXpYDCenter
=
OpticalFlow
.
transformToScenePxPyD
(
null
,
refDisparity
,
Interscene
.
ZERO3
,
Interscene
.
ZERO3
,
centerCLT
,
centerCLT
);
sceneTimes
=
getSceneTimes
(
quadCLTs
,
firstScene
,
endScene
);
}
rebuildObservationRowsForOuter
(
debugLevel
);
if
(
debugLevel
>
-
4
)
{
System
.
out
.
println
(
"IntersceneGlobalLmaRefine: prepareLMA() classic
scaffold
active; "
+
"IntersceneGlobalLmaRefine: prepareLMA() classic
LMA
active; "
+
"unknowns="
+
classicState
.
parameterVector
.
length
+
", rows="
+
classicState
.
yVector
.
length
+
", corrRows="
+
classicState
.
correlationRows
+
", pullRows="
+
classicState
.
pullRows
+
", lpfRows="
+
classicState
.
lpfVar
.
length
+
", activePoseParams="
+
Arrays
.
toString
(
classicState
.
activePoseParams
)
+
", center="
+
centerIndex
+
", range=["
+
earliestScene
+
","
+
lastScene
+
"]"
);
", range=["
+
earliestScene
+
","
+
lastScene
+
"]"
+
", includeRateChain="
+
classicState
.
includeRateChain
);
}
}
...
...
@@ -341,25 +917,202 @@ public class IntersceneGlobalLmaRefine {
final
double
[]
vector
,
final
double
[][]
jt
,
final
int
debugLevel
)
{
final
int
n
=
vector
.
length
;
final
double
[]
fx
=
new
double
[
n
];
applyVectorToScenes
(
vector
);
final
int
nvars
=
vector
.
length
;
final
int
nrows
=
classicState
.
yVector
.
length
;
final
double
[]
fx
=
new
double
[
nrows
];
if
(
jt
!=
null
)
{
for
(
int
p
=
0
;
p
<
n
;
p
++)
{
if
((
jt
[
p
]
==
null
)
||
(
jt
[
p
].
length
!=
n
))
{
jt
[
p
]
=
new
double
[
n
];
for
(
int
p
=
0
;
p
<
n
vars
;
p
++)
{
if
((
jt
[
p
]
==
null
)
||
(
jt
[
p
].
length
!=
n
rows
))
{
jt
[
p
]
=
new
double
[
n
rows
];
}
Arrays
.
fill
(
jt
[
p
],
0.0
);
}
}
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
final
double
pull
=
classicState
.
parameterPull
[
i
];
fx
[
i
]
=
vector
[
i
]
-
pull
;
// Correlation block: one multithreaded tile loop per pair.
for
(
int
ipair
=
0
;
ipair
<
classicState
.
correlationPairs
.
size
();
ipair
++)
{
final
CorrelationPairContext
cpc
=
classicState
.
correlationPairs
.
get
(
ipair
);
final
PairObservation
obs
=
cpc
.
obs
;
if
((
obs
==
null
)
||
(
obs
.
centers
==
null
)
||
(
cpc
.
validTiles
.
length
==
0
))
{
continue
;
}
final
int
nscene
=
obs
.
sceneIndex
;
final
int
refScene
=
obs
.
refSceneIndex
;
if
((
nscene
<
0
)
||
(
nscene
>=
quadCLTs
.
length
)
||
(
quadCLTs
[
nscene
]
==
null
)
||
(
refScene
<
0
)
||
(
refScene
>=
quadCLTs
.
length
)
||
(
quadCLTs
[
refScene
]
==
null
))
{
continue
;
}
final
double
[][]
poseNow
=
getScenePose
(
scenesXyzatr
,
nscene
,
centerIndex
);
final
double
[][]
refPose
=
getScenePose
(
scenesXyzatr
,
refScene
,
centerIndex
);
final
double
[][]
sceneRates
=
getSceneRates
(
nscene
,
classicState
.
rateSourceScenes
,
quadCLTs
,
sceneTimes
,
Math
.
max
(
0
,
earliestScene
),
Math
.
min
(
lastScene
,
quadCLTs
.
length
-
1
),
centerIndex
);
final
double
[][]
refRates
=
getSceneRates
(
refScene
,
classicState
.
rateSourceScenes
,
quadCLTs
,
sceneTimes
,
Math
.
max
(
0
,
earliestScene
),
Math
.
min
(
lastScene
,
quadCLTs
.
length
-
1
),
centerIndex
);
final
ErsCorrection
ersRef
=
quadCLTs
[
refScene
].
getErsCorrection
();
final
ErsCorrection
ersScene
=
quadCLTs
[
nscene
].
getErsCorrection
();
final
double
[]
refWatrBak
=
ersRef
.
ers_watr_center_dt
.
clone
();
final
double
[]
refWxyzBak
=
ersRef
.
ers_wxyz_center_dt
.
clone
();
final
double
[]
sceneWatrBak
=
ersScene
.
ers_watr_center_dt
.
clone
();
final
double
[]
sceneWxyzBak
=
ersScene
.
ers_wxyz_center_dt
.
clone
();
try
{
ersRef
.
ers_watr_center_dt
=
refRates
[
1
].
clone
();
ersRef
.
ers_wxyz_center_dt
=
refRates
[
0
].
clone
();
ersScene
.
ers_watr_center_dt
=
sceneRates
[
1
].
clone
();
ersScene
.
ers_wxyz_center_dt
=
sceneRates
[
0
].
clone
();
ersScene
.
setupERS
();
ersRef
.
setupERS
();
final
Matrix
[]
referenceMatricesInverse
=
ErsCorrection
.
getInterRotDeriveMatrices
(
refPose
[
1
],
true
);
final
Matrix
[]
sceneMatricesInverse
=
ErsCorrection
.
getInterRotDeriveMatrices
(
poseNow
[
1
],
true
);
final
Matrix
sceneRotMatrix
=
ErsCorrection
.
getInterRotDeriveMatrices
(
poseNow
[
1
],
false
)[
0
];
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
QuadCLT
.
THREADS_MAX
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
@Override
public
void
run
()
{
for
(
int
ilocal
=
ai
.
getAndIncrement
();
ilocal
<
cpc
.
validTiles
.
length
;
ilocal
=
ai
.
getAndIncrement
())
{
final
int
itile
=
cpc
.
validTiles
[
ilocal
];
if
((
itile
<
0
)
||
(
itile
>=
obs
.
centers
.
length
)
||
(
obs
.
centers
[
itile
]
==
null
)
||
(
obs
.
centers
[
itile
].
length
<
3
))
{
continue
;
}
final
double
[]
center
=
obs
.
centers
[
itile
];
final
boolean
isInfinity
=
center
[
2
]
<
0.0
;
final
double
[][]
derivParams
=
ersRef
.
getDPxSceneDParameters
(
ersScene
,
true
,
isInfinity
,
center
,
refPose
[
0
],
poseNow
[
0
],
referenceMatricesInverse
,
sceneMatricesInverse
,
sceneRotMatrix
,
debugLevel
);
if
((
derivParams
==
null
)
||
(
derivParams
.
length
==
0
)
||
(
derivParams
[
0
]
==
null
)
||
(
derivParams
[
0
].
length
<
2
))
{
continue
;
}
double
fx0
=
derivParams
[
0
][
0
];
double
fx1
=
derivParams
[
0
][
1
];
final
double
[][]
tr
=
(
cpc
.
eigTrans
==
null
)
?
null
:
cpc
.
eigTrans
[
itile
];
if
(
tr
!=
null
)
{
final
double
t0
=
tr
[
0
][
0
]
*
fx0
+
tr
[
0
][
1
]
*
fx1
;
final
double
t1
=
tr
[
1
][
0
]
*
fx0
+
tr
[
1
][
1
]
*
fx1
;
fx0
=
t0
;
fx1
=
t1
;
}
final
int
row0
=
cpc
.
rowBase
+
2
*
ilocal
;
final
int
row1
=
row0
+
1
;
fx
[
row0
]
=
fx0
;
fx
[
row1
]
=
fx1
;
if
(
jt
!=
null
)
{
for
(
int
ip
=
0
;
ip
<
cpc
.
localParamIndices
.
length
;
ip
++)
{
final
int
parIndex
=
cpc
.
localParamIndices
[
ip
];
final
int
dindx
=
parIndex
+
1
;
if
((
dindx
<
0
)
||
(
dindx
>=
derivParams
.
length
)
||
(
derivParams
[
dindx
]
==
null
)
||
(
derivParams
[
dindx
].
length
<
2
))
{
continue
;
}
double
j0
=
derivParams
[
dindx
][
0
];
double
j1
=
derivParams
[
dindx
][
1
];
if
(
tr
!=
null
)
{
final
double
tj0
=
tr
[
0
][
0
]
*
j0
+
tr
[
0
][
1
]
*
j1
;
final
double
tj1
=
tr
[
1
][
0
]
*
j0
+
tr
[
1
][
1
]
*
j1
;
j0
=
tj0
;
j1
=
tj1
;
}
final
ArrayList
<
VectorTerm
>
vt
=
cpc
.
vectorTerms
[
ip
];
for
(
int
it
=
0
;
it
<
vt
.
size
();
it
++)
{
final
VectorTerm
term
=
vt
.
get
(
it
);
jt
[
term
.
vectorIndex
][
row0
]
+=
term
.
coeff
*
j0
;
jt
[
term
.
vectorIndex
][
row1
]
+=
term
.
coeff
*
j1
;
}
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
}
finally
{
ersRef
.
ers_watr_center_dt
=
refWatrBak
;
ersRef
.
ers_wxyz_center_dt
=
refWxyzBak
;
ersScene
.
ers_watr_center_dt
=
sceneWatrBak
;
ersScene
.
ers_wxyz_center_dt
=
sceneWxyzBak
;
}
}
// Pull block: one equation per unknown.
for
(
int
i
=
0
;
i
<
classicState
.
pullRows
;
i
++)
{
final
int
row
=
classicState
.
pullBase
+
i
;
fx
[
row
]
=
vector
[
i
]
-
classicState
.
parameterPull
[
i
];
if
(
jt
!=
null
)
{
jt
[
i
][
i
]
=
1.0
;
jt
[
i
][
row
]
=
1.0
;
}
}
if
((
debugLevel
>
2
)
&&
(
n
>
0
))
{
System
.
out
.
println
(
"IntersceneGlobalLmaRefine: getFxDerivs() placeholder residual blocks active, samples="
+
n
);
// LPF block: x_i - 0.5*(x_{i-1}+x_{i+1}) for each valid row.
for
(
int
i
=
0
;
i
<
classicState
.
lpfVar
.
length
;
i
++)
{
final
int
row
=
classicState
.
lpfBase
+
i
;
final
int
iv
=
classicState
.
lpfVar
[
i
];
double
v
=
vector
[
iv
];
final
int
prevVar
=
classicState
.
lpfPrevVar
[
i
];
if
(
prevVar
>=
0
)
{
v
-=
0.5
*
vector
[
prevVar
];
if
(
jt
!=
null
)
{
jt
[
prevVar
][
row
]
-=
0.5
;
}
}
else
{
v
-=
0.5
*
classicState
.
lpfPrevFixed
[
i
];
}
final
int
nextVar
=
classicState
.
lpfNextVar
[
i
];
if
(
nextVar
>=
0
)
{
v
-=
0.5
*
vector
[
nextVar
];
if
(
jt
!=
null
)
{
jt
[
nextVar
][
row
]
-=
0.5
;
}
}
else
{
v
-=
0.5
*
classicState
.
lpfNextFixed
[
i
];
}
fx
[
row
]
=
v
;
if
(
jt
!=
null
)
{
jt
[
iv
][
row
]
+=
1.0
;
}
}
if
((
debugLevel
>
2
)
&&
(
nrows
>
0
))
{
System
.
out
.
println
(
"IntersceneGlobalLmaRefine: getFxDerivs() rows="
+
nrows
+
", corrRows="
+
classicState
.
correlationRows
+
", pullRows="
+
classicState
.
pullRows
+
", lpfRows="
+
classicState
.
lpfVar
.
length
+
", unknowns="
+
nvars
);
}
return
fx
;
}
...
...
@@ -370,6 +1123,7 @@ public class IntersceneGlobalLmaRefine {
final
boolean
noNaNs
)
{
final
double
[]
weighted
=
new
double
[
fx
.
length
];
double
sum
=
0.0
;
double
sumPure
=
0.0
;
for
(
int
i
=
0
;
i
<
fx
.
length
;
i
++)
{
double
d
=
classicState
.
yVector
[
i
]
-
fx
[
i
];
double
wd
=
d
*
classicState
.
weights
[
i
];
...
...
@@ -385,12 +1139,13 @@ public class IntersceneGlobalLmaRefine {
wd
=
0.0
;
}
weighted
[
i
]
=
wd
;
sum
+=
d
*
wd
;
final
double
dwd
=
d
*
wd
;
sum
+=
dwd
;
sumPure
+=
d
*
d
;
}
if
((
rms
!=
null
)
&&
(
rms
.
length
>=
2
))
{
final
double
v
=
Math
.
sqrt
(
sum
);
rms
[
0
]
=
v
;
rms
[
1
]
=
v
;
rms
[
0
]
=
Math
.
sqrt
(
Math
.
max
(
0.0
,
sum
));
rms
[
1
]
=
Math
.
sqrt
(
Math
.
max
(
0.0
,
sumPure
/
Math
.
max
(
1
,
Math
.
max
(
1
,
classicState
.
correlationRows
))));
}
return
weighted
;
}
...
...
@@ -408,7 +1163,7 @@ public class IntersceneGlobalLmaRefine {
}
wjtjl
[
i
][
j
]
=
d
;
if
(
i
==
j
)
{
wjtjl
[
i
][
i
]
+=
d
*
lambda
;
wjtjl
[
i
][
i
]
+=
Math
.
max
(
MIN_DIAG
,
d
)
*
lambda
;
}
else
{
wjtjl
[
j
][
i
]
=
d
;
}
...
...
@@ -428,7 +1183,6 @@ public class IntersceneGlobalLmaRefine {
return
max
;
}
@SuppressWarnings
(
"unused"
)
private
boolean
[]
lmaStep
(
final
double
lambda
,
final
double
rmsDiffStop
,
...
...
@@ -438,6 +1192,7 @@ public class IntersceneGlobalLmaRefine {
if
(
n
==
0
)
{
return
new
boolean
[]
{
true
,
true
};
}
classicState
.
attemptedSteps
++;
if
((
classicState
.
lastJt
==
null
)
||
(
classicState
.
lastJt
.
length
!=
n
))
{
classicState
.
lastJt
=
new
double
[
n
][];
}
...
...
@@ -469,6 +1224,7 @@ public class IntersceneGlobalLmaRefine {
final
double
[]
delta
=
deltaVector
.
getColumnPackedCopy
();
final
double
maxDelta
=
getMaxAbs
(
delta
);
classicState
.
lastMaxDelta
=
maxDelta
;
final
double
[]
oldVector
=
classicState
.
parameterVector
.
clone
();
final
double
[]
oldRms
=
classicState
.
lastRms
.
clone
();
final
double
[]
newVector
=
oldVector
.
clone
();
...
...
@@ -489,6 +1245,8 @@ public class IntersceneGlobalLmaRefine {
classicState
.
parameterVector
=
newVector
;
classicState
.
lastRms
=
rms
;
classicState
.
lastYminusFx
=
yMinusFxNew
;
classicState
.
acceptedSteps
++;
applyVectorToScenes
(
newVector
);
final
boolean
convergedByRms
=
rms
[
0
]
>=
(
oldRms
[
0
]
*
(
1.0
-
rmsDiffStop
));
final
boolean
convergedByDelta
=
maxDelta
<=
deltaStop
;
return
new
boolean
[]
{
true
,
convergedByRms
||
convergedByDelta
};
...
...
@@ -503,33 +1261,1071 @@ public class IntersceneGlobalLmaRefine {
classicState
.
lastRms
,
true
);
classicState
.
parameterVector
=
oldVector
;
applyVectorToScenes
(
oldVector
);
return
new
boolean
[]
{
false
,
false
};
}
private
IntersceneGlobalRefine
.
Result
runLma
(
final
int
debugLevel
)
{
final
IntersceneGlobalRefine
.
Result
result
=
new
IntersceneGlobalRefine
.
Result
();
final
int
unknowns
=
classicState
.
parameterVector
.
length
;
if
(
unknowns
==
0
)
{
return
result
;
}
double
lambda
=
(
options
!=
null
)
?
options
.
lambdaDiag
:
0.1
;
if
(!(
lambda
>
0.0
))
{
lambda
=
0.1
;
}
final
double
lambdaScaleGood
=
((
options
!=
null
)
&&
(
options
.
lambdaScaleGood
>
0.0
))
?
options
.
lambdaScaleGood
:
0.5
;
final
double
lambdaScaleBad
=
((
options
!=
null
)
&&
(
options
.
lambdaScaleBad
>
1.0
))
?
options
.
lambdaScaleBad
:
8.0
;
final
double
lambdaMax
=
((
options
!=
null
)
&&
(
options
.
lambdaMax
>
0.0
))
?
options
.
lambdaMax
:
100.0
;
final
double
rmsDiffStop
=
((
options
!=
null
)
&&
(
options
.
rmsDiffStop
>=
0.0
))
?
options
.
rmsDiffStop
:
0.001
;
final
double
deltaStop
=
((
options
!=
null
)
&&
(
options
.
deltaStop
>
0.0
))
?
options
.
deltaStop
:
1.0
e
-
5
;
final
int
outerIterations
=
((
options
!=
null
)
&&
(
options
.
outerIterations
>
0
))
?
options
.
outerIterations
:
1
;
final
int
innerIterations
=
((
options
!=
null
)
&&
(
options
.
innerIterations
>
0
))
?
options
.
innerIterations
:
1
;
boolean
converged
=
false
;
int
outerDone
=
0
;
int
innerDone
=
0
;
for
(
int
outer
=
0
;
outer
<
outerIterations
;
outer
++)
{
final
boolean
haveObs
=
rebuildObservationRowsForOuter
(
debugLevel
);
if
(!
haveObs
&&
(
classicState
.
correlationRows
==
0
))
{
if
(
debugLevel
>
-
2
)
{
System
.
out
.
println
(
"IntersceneGlobalLmaRefine: no valid correlation rows for outer="
+
outer
+
", stopping."
);
}
break
;
}
classicState
.
lastJt
=
null
;
classicState
.
lastYminusFx
=
null
;
classicState
.
lastRms
=
null
;
classicState
.
initialRms
=
null
;
for
(
int
inner
=
0
;
inner
<
innerIterations
;
inner
++)
{
final
boolean
[]
step
=
lmaStep
(
lambda
,
rmsDiffStop
,
deltaStop
,
debugLevel
);
if
(
step
==
null
)
{
converged
=
true
;
break
;
}
final
boolean
improved
=
step
[
0
];
final
boolean
stop
=
step
[
1
];
if
(
improved
)
{
lambda
*=
lambdaScaleGood
;
}
else
{
lambda
*=
lambdaScaleBad
;
}
if
(
lambda
>
lambdaMax
)
{
converged
=
true
;
}
innerDone
=
inner
+
1
;
outerDone
=
outer
+
1
;
if
(
debugLevel
>
-
3
&&
(
classicState
.
lastRms
!=
null
))
{
System
.
out
.
println
(
"IntersceneGlobalLmaRefine: outer="
+
outer
+
" inner="
+
inner
+
" improved="
+
improved
+
" stop="
+
stop
+
" avgPairRms="
+
classicState
.
lastRms
[
0
]
+
" avgPairRmsPure="
+
classicState
.
lastRms
[
1
]
+
" maxDelta="
+
classicState
.
lastMaxDelta
+
" lambda="
+
lambda
);
}
if
(
stop
||
converged
)
{
converged
=
true
;
break
;
}
}
if
(
converged
)
{
break
;
}
}
captureCurrentVectorFromScenes
();
final
HashSet
<
Integer
>
solved
=
new
HashSet
<
Integer
>();
for
(
final
int
scene
:
classicState
.
vectorSceneIndices
)
{
solved
.
add
(
Integer
.
valueOf
(
scene
));
}
result
.
solvedScenes
=
solved
.
size
();
result
.
failedScenes
=
0
;
result
.
outerDone
=
outerDone
;
result
.
maxDelta
=
classicState
.
lastMaxDelta
;
result
.
pcgIterationsLast
=
Math
.
max
(
innerDone
,
classicState
.
attemptedSteps
);
if
(
classicState
.
lastRms
!=
null
)
{
result
.
avgPairRms
=
classicState
.
lastRms
[
0
];
result
.
avgPairRmsPure
=
classicState
.
lastRms
[
1
];
}
if
(
debugLevel
>
-
4
)
{
System
.
out
.
println
(
"IntersceneGlobalLmaRefine: runLma() phase-1 delegating numeric solve to IntersceneGlobalRefine"
);
"IntersceneGlobalLmaRefine: finished, outerDone="
+
result
.
outerDone
+
", solvedScenes="
+
result
.
solvedScenes
+
", avgPairRms="
+
result
.
avgPairRms
+
", avgPairRmsPure="
+
result
.
avgPairRmsPure
+
", acceptedSteps="
+
classicState
.
acceptedSteps
+
", attemptedSteps="
+
classicState
.
attemptedSteps
);
}
final
IntersceneGlobalRefine
.
Result
result
=
IntersceneGlobalRefine
.
refineAllToReference
(
cltParameters
,
return
result
;
}
private
static
ArrayList
<
PairFactor
>
buildPairFactors
(
final
CLTParameters
cltParameters
,
final
QuadCLT
[]
quadCLTs
,
final
double
[][][]
scenes_xyzatr
,
final
boolean
[]
activePoseScene
,
final
int
firstScene
,
final
int
lastScene
,
final
int
centerIndex
,
final
double
minOffset
,
final
int
debugLevel
)
{
final
ArrayList
<
PairFactor
>
factors
=
new
ArrayList
<
PairFactor
>();
final
HashSet
<
Long
>
used
=
new
HashSet
<
Long
>();
for
(
int
nscene
=
firstScene
;
nscene
<=
lastScene
;
nscene
++)
{
final
int
ivar
=
nscene
-
firstScene
;
if
((
ivar
>=
0
)
&&
(
ivar
<
activePoseScene
.
length
)
&&
activePoseScene
[
ivar
])
{
final
long
key
=
(((
long
)
nscene
)
<<
32
)
|
(
centerIndex
&
0xffffffff
L
);
if
(
used
.
add
(
key
))
{
factors
.
add
(
new
PairFactor
(
nscene
,
centerIndex
,
1.0
));
}
}
}
if
(!
cltParameters
.
imp
.
fmg_initial_en
)
{
return
factors
;
}
final
double
avgZ
=
getAverageAbsZ
(
scenes_xyzatr
,
activePoseScene
,
firstScene
);
final
ArrayList
<
Integer
>
fpnList
=
new
ArrayList
<
Integer
>();
for
(
int
nscene
=
firstScene
;
nscene
<=
lastScene
;
nscene
++)
{
final
int
ivar
=
nscene
-
firstScene
;
if
((
ivar
<
0
)
||
(
ivar
>=
activePoseScene
.
length
)
||
!
activePoseScene
[
ivar
])
{
continue
;
}
double
estShift
=
quadCLTs
[
centerIndex
].
estimateAverageShift
(
getScenePose
(
scenes_xyzatr
,
centerIndex
,
centerIndex
),
getScenePose
(
scenes_xyzatr
,
nscene
,
centerIndex
),
avgZ
,
false
,
cltParameters
.
imp
.
fmg_rectilinear
);
if
(
estShift
<
minOffset
)
{
estShift
=
quadCLTs
[
centerIndex
].
estimateAverageShift
(
getScenePose
(
scenes_xyzatr
,
centerIndex
,
centerIndex
),
getScenePose
(
scenes_xyzatr
,
nscene
,
centerIndex
),
avgZ
,
true
,
cltParameters
.
imp
.
fmg_rectilinear
);
}
if
(
estShift
<
minOffset
)
{
fpnList
.
add
(
nscene
);
}
}
if
(
fpnList
.
isEmpty
())
{
return
factors
;
}
double
fmgDistance
=
cltParameters
.
imp
.
fmg_distance
;
if
(
fmgDistance
<
(
minOffset
+
2.0
))
{
fmgDistance
=
minOffset
+
2.0
;
}
final
int
[][]
fpnPairs
=
Interscene
.
getFPNPairs
(
fpnList
,
fmgDistance
,
cltParameters
.
imp
.
fmg_rectilinear
,
quadCLTs
,
centerCLT
,
scenes_xyzatr
,
avgZ
,
centerIndex
,
earliestScene
,
firstScene
);
for
(
int
i
=
0
;
i
<
fpnPairs
.
length
;
i
++)
{
final
int
scene
=
fpnPairs
[
i
][
0
];
final
int
ref
=
fpnPairs
[
i
][
1
];
if
((
scene
<
firstScene
)
||
(
scene
>
lastScene
)
||
(
ref
<
firstScene
)
||
(
ref
>
lastScene
))
{
continue
;
}
if
((
scene
==
ref
)
||
(
ref
==
centerIndex
))
{
continue
;
}
final
int
ivarScene
=
scene
-
firstScene
;
final
int
ivarRef
=
ref
-
firstScene
;
if
((
ivarScene
<
0
)
||
(
ivarScene
>=
activePoseScene
.
length
)
||
!
activePoseScene
[
ivarScene
])
{
continue
;
}
if
((
ivarRef
<
0
)
||
(
ivarRef
>=
activePoseScene
.
length
)
||
!
activePoseScene
[
ivarRef
])
{
continue
;
}
if
((
quadCLTs
[
ref
]
==
null
)
||
(
scenes_xyzatr
[
ref
]
==
null
))
{
continue
;
}
final
long
key
=
(((
long
)
scene
)
<<
32
)
|
(
ref
&
0xffffffff
L
);
if
(
used
.
add
(
key
))
{
factors
.
add
(
new
PairFactor
(
scene
,
ref
,
1.0
));
}
}
if
(
debugLevel
>
-
3
)
{
System
.
out
.
println
(
"IntersceneGlobalLmaRefine: pair factors total="
+
factors
.
size
());
}
return
factors
;
}
private
static
void
applyPairWeights
(
final
ArrayList
<
PairFactor
>
pairFactors
,
final
int
centerIndex
,
final
int
centerPairWeightMode
,
final
int
debugLevel
)
{
if
((
pairFactors
==
null
)
||
pairFactors
.
isEmpty
())
{
return
;
}
final
int
mode
=
Math
.
max
(
0
,
centerPairWeightMode
);
int
numZero
=
0
;
for
(
PairFactor
pf
:
pairFactors
)
{
double
w
=
1.0
;
if
((
mode
>
0
)
&&
(
pf
.
refSceneIndex
==
centerIndex
))
{
final
int
d
=
Math
.
abs
(
pf
.
sceneIndex
-
centerIndex
);
if
((
d
>
0
)
&&
(
d
<=
mode
))
{
w
=
0.0
;
}
}
pf
.
pairWeight
=
w
;
if
(!(
w
>
0.0
))
{
numZero
++;
}
}
if
(
debugLevel
>
-
3
)
{
System
.
out
.
println
(
"IntersceneGlobalLmaRefine: pair weights applied, mode="
+
mode
+
", zeroWeightedPairs="
+
numZero
+
"/"
+
pairFactors
.
size
());
}
}
private
static
double
getAverageAbsZ
(
final
double
[][][]
scenes_xyzatr
,
final
boolean
[]
activePoseScene
,
final
int
firstScene
)
{
double
sum
=
0.0
;
int
n
=
0
;
for
(
int
ivar
=
0
;
ivar
<
activePoseScene
.
length
;
ivar
++)
{
if
(!
activePoseScene
[
ivar
])
{
continue
;
}
final
int
nscene
=
firstScene
+
ivar
;
if
((
nscene
>=
0
)
&&
(
nscene
<
scenes_xyzatr
.
length
)
&&
(
scenes_xyzatr
[
nscene
]
!=
null
))
{
sum
+=
Math
.
abs
(
scenes_xyzatr
[
nscene
][
0
][
2
]);
n
++;
}
}
return
(
n
>
0
)
?
Math
.
max
(
1.0
,
sum
/
n
)
:
1.0
;
}
private
static
RefGpuData
getReferenceGpuData
(
final
CLTParameters
clt_parameters
,
final
QuadCLT
[]
quadCLTs
,
final
double
[][][]
scenes_xyzatr
,
final
double
[]
sceneTimes
,
final
int
firstScene
,
final
int
lastScene
,
final
int
centerIndex
,
final
int
refScene
,
final
double
[]
refDisparity
,
final
double
[][]
pXpYDCenter
,
final
boolean
[]
reliableRefCenter
,
final
double
mb_max_gain
,
final
RefGpuData
[]
cache
,
final
int
debugLevel
)
{
final
int
ivar
=
refScene
-
firstScene
;
if
((
ivar
>=
0
)
&&
(
ivar
<
cache
.
length
)
&&
(
cache
[
ivar
]
!=
null
)
&&
(
cache
[
ivar
].
refSceneIndex
==
refScene
)
&&
(
cache
[
ivar
].
tasks
!=
null
)
&&
(
cache
[
ivar
].
pXpYD
!=
null
))
{
return
cache
[
ivar
];
}
if
((
refScene
<
0
)
||
(
refScene
>=
quadCLTs
.
length
)
||
(
quadCLTs
[
refScene
]
==
null
))
{
return
null
;
}
final
RefGpuData
rslt
=
new
RefGpuData
();
rslt
.
refSceneIndex
=
refScene
;
final
double
[][]
refPose
=
getScenePose
(
scenes_xyzatr
,
refScene
,
centerIndex
);
final
double
[][]
refRates
=
getSceneRates
(
refScene
,
scenes_xyzatr
,
quadCLTs
,
sceneTimes
,
firstScene
,
lastScene
,
scenesXyzatr
,
scenesXyzatrPull
,
paramSelect
,
paramRegweights
,
paramLpf
,
centerDisparity
,
centerIndex
);
rslt
.
pXpYD
=
(
refScene
==
centerIndex
)
?
pXpYDCenter
:
OpticalFlow
.
transformToScenePxPyD
(
null
,
refDisparity
,
refPose
[
0
],
refPose
[
1
],
quadCLTs
[
refScene
],
quadCLTs
[
centerIndex
]);
rslt
.
reliableMask
=
(
refScene
==
centerIndex
)
?
reliableRefCenter
:
buildPairReliableMask
(
clt_parameters
,
quadCLTs
,
centerIndex
,
refScene
,
centerIndex
,
scenes_xyzatr
,
reliableRefCenter
,
debugLevel
);
double
[][]
mbVectorsRef
=
null
;
if
(
clt_parameters
.
imp
.
mb_en
)
{
final
double
[][]
refDt
=
QuadCLTCPU
.
scaleDtFromErs
(
clt_parameters
,
new
double
[][]
{
refRates
[
0
].
clone
(),
refRates
[
1
].
clone
()});
mbVectorsRef
=
OpticalFlow
.
getMotionBlur
(
quadCLTs
[
centerIndex
],
quadCLTs
[
refScene
],
pXpYDCenter
,
refPose
[
0
],
refPose
[
1
],
refDt
[
0
],
refDt
[
1
],
0
,
debugLevel
);
}
final
TpTask
[][]
tasks
=
Interscene
.
setReferenceGPU
(
clt_parameters
,
quadCLTs
[
refScene
],
refDisparity
,
rslt
.
pXpYD
,
null
,
rslt
.
reliableMask
,
0
,
clt_parameters
.
imp
.
mb_tau
,
mb_max_gain
,
mbVectorsRef
,
debugLevel
);
if
((
tasks
==
null
)
||
(
tasks
.
length
==
0
)
||
(
tasks
[
0
]
==
null
))
{
return
null
;
}
rslt
.
tasks
=
tasks
[
0
];
if
((
ivar
>=
0
)
&&
(
ivar
<
cache
.
length
))
{
cache
[
ivar
]
=
rslt
;
}
return
rslt
;
}
private
static
ObservationCache
buildObservationCache
(
final
CLTParameters
clt_parameters
,
final
QuadCLT
[]
quadCLTs
,
final
QuadCLT
centerCLT
,
final
int
centerIndex
,
final
int
firstScene
,
final
int
lastScene
,
final
double
[][][]
scenes_xyzatr
,
final
double
[]
sceneTimes
,
final
ArrayList
<
PairFactor
>
pairFactors
,
final
double
[]
refDisparity
,
final
double
[][]
pXpYDCenter
,
final
boolean
[]
reliableRef
,
final
double
mb_max_gain
,
final
double
[]
minMax
,
final
RefGpuData
[]
refGpuCache
,
final
int
debugLevel
)
{
final
ObservationCache
cache
=
new
ObservationCache
();
if
((
pairFactors
==
null
)
||
pairFactors
.
isEmpty
())
{
return
cache
;
}
final
int
tilesX
=
centerCLT
.
getTileProcessor
().
getTilesX
();
final
int
tilesY
=
centerCLT
.
getTileProcessor
().
getTilesY
();
cache
.
tilesPerPair
=
tilesX
*
tilesY
;
cache
.
yVector
=
new
double
[
2
*
cache
.
tilesPerPair
*
pairFactors
.
size
()];
cache
.
wVector
=
new
double
[
cache
.
tilesPerPair
*
pairFactors
.
size
()];
for
(
int
ifactor
=
0
;
ifactor
<
pairFactors
.
size
();
ifactor
++)
{
final
PairFactor
pf
=
pairFactors
.
get
(
ifactor
);
final
RefGpuData
refGpu
=
getReferenceGpuData
(
clt_parameters
,
quadCLTs
,
scenes_xyzatr
,
sceneTimes
,
firstScene
,
lastScene
,
centerIndex
,
pf
.
refSceneIndex
,
refDisparity
,
pXpYDCenter
,
reliableRef
,
mb_max_gain
,
refGpuCache
,
debugLevel
);
if
(
refGpu
==
null
)
{
cache
.
failedPairs
++;
continue
;
}
final
PairObservation
obs
=
buildPairObservation
(
clt_parameters
,
quadCLTs
,
centerCLT
,
centerIndex
,
pf
.
sceneIndex
,
pf
.
refSceneIndex
,
firstScene
,
lastScene
,
scenes_xyzatr
,
sceneTimes
,
refGpu
.
pXpYD
,
refGpu
.
tasks
,
refGpu
.
reliableMask
,
refDisparity
,
minMax
,
mb_max_gain
,
pf
.
pairWeight
,
ifactor
,
cache
,
debugLevel
);
if
(
obs
==
null
)
{
cache
.
failedPairs
++;
continue
;
}
cache
.
observations
.
add
(
obs
);
cache
.
solvedPairs
++;
}
return
cache
;
}
private
static
PairObservation
buildPairObservation
(
final
CLTParameters
clt_parameters
,
final
QuadCLT
[]
quadCLTs
,
final
QuadCLT
centerCLT
,
final
int
centerIndex
,
final
int
nscene
,
final
int
refScene
,
final
int
earliestScene
,
final
int
lastScene
,
final
double
[][][]
scenes_xyzatr
,
final
double
[]
sceneTimes
,
final
double
[][]
pXpYDRef
,
final
TpTask
[]
tpTaskRef
,
final
boolean
[]
reliableRef
,
final
double
[]
refDisparity
,
final
double
[]
minMax
,
final
double
mb_max_gain
,
final
double
pairWeight
,
final
int
pairOrdinal
,
final
ObservationCache
cache
,
final
int
debugLevel
)
{
if
((
quadCLTs
[
nscene
]
==
null
)
||
(
scenes_xyzatr
[
nscene
]
==
null
))
{
return
null
;
}
final
boolean
[]
reliablePair
=
buildPairReliableMask
(
clt_parameters
,
quadCLTs
,
centerIndex
,
nscene
,
refScene
,
scenes_xyzatr
,
reliableRef
,
disableErs
,
mbMaxGain
,
options
,
debugLevel
);
captureCurrentVectorFromScenes
();
return
result
;
final
double
[][]
poseNow
=
getScenePose
(
scenes_xyzatr
,
nscene
,
centerIndex
);
final
double
[][]
sceneRates
=
getSceneRates
(
nscene
,
scenes_xyzatr
,
quadCLTs
,
sceneTimes
,
earliestScene
,
lastScene
,
centerIndex
);
double
[][]
mbVectorsScene
=
null
;
if
(
clt_parameters
.
imp
.
mb_en
)
{
final
double
[][]
sceneDt
=
QuadCLTCPU
.
scaleDtFromErs
(
clt_parameters
,
new
double
[][]
{
sceneRates
[
0
].
clone
(),
sceneRates
[
1
].
clone
()});
mbVectorsScene
=
OpticalFlow
.
getMotionBlur
(
centerCLT
,
quadCLTs
[
nscene
],
pXpYDRef
,
poseNow
[
0
],
poseNow
[
1
],
sceneDt
[
0
],
sceneDt
[
1
],
0
,
debugLevel
);
}
final
int
[]
failReason
=
{
0
};
final
double
[][][]
coordMotion
=
Interscene
.
interCorrPair
(
clt_parameters
,
false
,
false
,
mb_max_gain
,
minMax
,
failReason
,
centerCLT
,
refDisparity
,
quadCLTs
[
refScene
],
pXpYDRef
,
tpTaskRef
,
quadCLTs
[
nscene
],
poseNow
[
0
],
poseNow
[
1
],
reliablePair
,
clt_parameters
.
imp
.
margin
,
clt_parameters
.
imp
.
sensor_mask_inter
,
null
,
null
,
false
,
false
,
true
,
mbVectorsScene
,
-
1
,
false
,
clt_parameters
.
imp
.
debug_level
,
debugLevel
);
if
((
coordMotion
==
null
)
||
(
coordMotion
.
length
<
2
)
||
(
coordMotion
[
0
]
==
null
)
||
(
coordMotion
[
1
]
==
null
))
{
return
null
;
}
final
PairObservation
obs
=
new
PairObservation
();
obs
.
sceneIndex
=
nscene
;
obs
.
refSceneIndex
=
refScene
;
obs
.
pairWeight
=
pairWeight
;
obs
.
centers
=
coordMotion
[
0
];
obs
.
eigen
=
(
coordMotion
.
length
>
2
)
?
coordMotion
[
2
]
:
null
;
obs
.
reliableRef
=
reliablePair
;
obs
.
yBase
=
pairOrdinal
*
2
*
cache
.
tilesPerPair
;
obs
.
wBase
=
pairOrdinal
*
cache
.
tilesPerPair
;
final
int
pairTiles
=
obs
.
centers
.
length
;
final
int
ntiles
=
Math
.
min
(
Math
.
min
(
cache
.
tilesPerPair
,
pairTiles
),
coordMotion
[
1
].
length
);
for
(
int
itile
=
0
;
itile
<
ntiles
;
itile
++)
{
final
double
[]
v
=
coordMotion
[
1
][
itile
];
if
((
v
==
null
)
||
(
v
.
length
<
3
))
{
continue
;
}
final
boolean
reliable
=
(
reliablePair
==
null
)
||
((
itile
<
reliablePair
.
length
)
&&
reliablePair
[
itile
]);
final
double
w
=
(
pairWeight
>
0.0
)
?
((
reliable
?
v
[
2
]
:
0.0
)
*
pairWeight
)
:
0.0
;
cache
.
yVector
[
obs
.
yBase
+
2
*
itile
+
0
]
=
v
[
0
];
cache
.
yVector
[
obs
.
yBase
+
2
*
itile
+
1
]
=
v
[
1
];
cache
.
wVector
[
obs
.
wBase
+
itile
]
=
w
;
}
obs
.
vectorXys
=
new
double
[
pairTiles
][];
for
(
int
itile
=
0
;
itile
<
pairTiles
;
itile
++)
{
if
(
itile
>=
cache
.
tilesPerPair
)
{
obs
.
vectorXys
[
itile
]
=
null
;
continue
;
}
final
double
w
=
cache
.
wVector
[
obs
.
wBase
+
itile
];
if
(
w
<=
0.0
)
{
obs
.
vectorXys
[
itile
]
=
null
;
}
else
{
obs
.
vectorXys
[
itile
]
=
new
double
[]
{
cache
.
yVector
[
obs
.
yBase
+
2
*
itile
+
0
],
cache
.
yVector
[
obs
.
yBase
+
2
*
itile
+
1
],
w
};
}
}
return
obs
;
}
private
static
boolean
[]
buildPairReliableMask
(
final
CLTParameters
clt_parameters
,
final
QuadCLT
[]
quadCLTs
,
final
int
centerIndex
,
final
int
sceneIndex
,
final
int
refSceneIndex
,
final
double
[][][]
scenes_xyzatr
,
final
boolean
[]
reliableBase
,
final
int
debugLevel
)
{
if
((
centerIndex
<
0
)
||
(
centerIndex
>=
quadCLTs
.
length
)
||
(
quadCLTs
[
centerIndex
]
==
null
))
{
return
reliableBase
;
}
final
QuadCLT
centerCLT
=
quadCLTs
[
centerIndex
];
final
int
tilesX
=
centerCLT
.
getTileProcessor
().
getTilesX
();
final
int
tilesY
=
centerCLT
.
getTileProcessor
().
getTilesY
();
boolean
[]
reliable
=
reliableBase
;
if
(
reliable
==
null
)
{
reliable
=
new
boolean
[
tilesX
*
tilesY
];
Arrays
.
fill
(
reliable
,
true
);
}
final
double
[][]
centerPose
=
getScenePose
(
scenes_xyzatr
,
centerIndex
,
centerIndex
);
final
double
[][]
scenePose
=
getScenePose
(
scenes_xyzatr
,
sceneIndex
,
centerIndex
);
final
double
avgZ
=
centerCLT
.
getAverageZ
(
true
);
final
boolean
fmgRectilinear
=
clt_parameters
.
imp
.
fmg_rectilinear
;
final
double
[]
centerToSceneOffset
=
centerCLT
.
estimateCenterShiftXY
(
centerPose
,
scenePose
,
avgZ
,
fmgRectilinear
);
if
(
centerToSceneOffset
!=
null
)
{
reliable
=
centerCLT
.
maskByOverlap
(
reliable
,
centerToSceneOffset
);
}
if
(
refSceneIndex
!=
centerIndex
)
{
final
double
[][]
refPose
=
getScenePose
(
scenes_xyzatr
,
refSceneIndex
,
centerIndex
);
final
double
[]
centerToRefOffset
=
centerCLT
.
estimateCenterShiftXY
(
centerPose
,
refPose
,
avgZ
,
fmgRectilinear
);
if
(
centerToRefOffset
!=
null
)
{
reliable
=
centerCLT
.
maskByOverlap
(
reliable
,
centerToRefOffset
);
}
}
if
(
debugLevel
>
1
)
{
int
selected
=
0
;
for
(
int
i
=
0
;
i
<
reliable
.
length
;
i
++)
{
if
(
reliable
[
i
])
{
selected
++;
}
}
System
.
out
.
println
(
"IntersceneGlobalLmaRefine: overlap mask scene="
+
sceneIndex
+
", ref="
+
refSceneIndex
+
", selected="
+
selected
+
"/"
+
reliable
.
length
);
}
return
reliable
;
}
private
static
double
parseSceneTimestamp
(
final
String
ts
)
{
if
(
ts
==
null
)
{
return
Double
.
NaN
;
}
final
String
[]
parts
=
ts
.
trim
().
split
(
"_"
);
if
(
parts
.
length
!=
2
)
{
return
Double
.
NaN
;
}
try
{
final
long
sec
=
Long
.
parseLong
(
parts
[
0
]);
final
long
usec
=
Long
.
parseLong
(
parts
[
1
]);
return
sec
+
(
usec
*
1.0
e
-
6
);
}
catch
(
NumberFormatException
nfe
)
{
return
Double
.
NaN
;
}
}
private
static
double
[]
getSceneTimes
(
final
QuadCLT
[]
quadCLTs
,
final
int
firstScene
,
final
int
lastScene
)
{
final
double
[]
out
=
new
double
[
quadCLTs
.
length
];
Arrays
.
fill
(
out
,
Double
.
NaN
);
for
(
int
nscene
=
firstScene
;
nscene
<=
lastScene
;
nscene
++)
{
if
(
quadCLTs
[
nscene
]
==
null
)
{
continue
;
}
out
[
nscene
]
=
parseSceneTimestamp
(
quadCLTs
[
nscene
].
getImageName
());
}
double
t
=
0.0
;
for
(
int
nscene
=
firstScene
;
nscene
<=
lastScene
;
nscene
++)
{
if
(
Double
.
isNaN
(
out
[
nscene
]))
{
out
[
nscene
]
=
t
;
}
t
=
out
[
nscene
]
+
DEFAULT_DT
;
}
return
out
;
}
private
static
int
findPrevScene
(
final
int
sceneIndex
,
final
int
firstScene
,
final
QuadCLT
[]
quadCLTs
,
final
double
[][][]
scenes_xyzatr
)
{
for
(
int
i
=
sceneIndex
-
1
;
i
>=
firstScene
;
i
--)
{
if
((
quadCLTs
[
i
]
!=
null
)
&&
(
scenes_xyzatr
[
i
]
!=
null
))
{
return
i
;
}
}
return
-
1
;
}
private
static
int
findNextScene
(
final
int
sceneIndex
,
final
int
lastScene
,
final
QuadCLT
[]
quadCLTs
,
final
double
[][][]
scenes_xyzatr
)
{
for
(
int
i
=
sceneIndex
+
1
;
i
<=
lastScene
;
i
++)
{
if
((
quadCLTs
[
i
]
!=
null
)
&&
(
scenes_xyzatr
[
i
]
!=
null
))
{
return
i
;
}
}
return
-
1
;
}
private
static
double
safeDt
(
final
int
i0
,
final
int
i1
,
final
double
[]
sceneTimes
)
{
if
((
sceneTimes
==
null
)
||
(
i0
<
0
)
||
(
i1
<
0
)
||
(
i0
>=
sceneTimes
.
length
)
||
(
i1
>=
sceneTimes
.
length
))
{
return
DEFAULT_DT
;
}
final
double
dt
=
Math
.
abs
(
sceneTimes
[
i1
]
-
sceneTimes
[
i0
]);
return
(
dt
>
MIN_DIAG
)
?
dt
:
DEFAULT_DT
;
}
private
static
double
wrapPi
(
double
a
)
{
while
(
a
>
Math
.
PI
)
{
a
-=
(
2.0
*
Math
.
PI
);
}
while
(
a
<
-
Math
.
PI
)
{
a
+=
(
2.0
*
Math
.
PI
);
}
return
a
;
}
private
static
double
getPoseComponent
(
final
double
[][][]
scenes_xyzatr
,
final
int
sceneIndex
,
final
int
centerIndex
,
final
boolean
angular
,
final
int
comp
)
{
if
(
sceneIndex
==
centerIndex
)
{
return
0.0
;
}
if
((
sceneIndex
<
0
)
||
(
sceneIndex
>=
scenes_xyzatr
.
length
)
||
(
scenes_xyzatr
[
sceneIndex
]
==
null
))
{
return
0.0
;
}
return
angular
?
scenes_xyzatr
[
sceneIndex
][
1
][
comp
]
:
scenes_xyzatr
[
sceneIndex
][
0
][
comp
];
}
private
static
ArrayList
<
RateTerm
>
getRateTerms
(
final
int
sceneIndex
,
final
int
firstScene
,
final
int
lastScene
,
final
QuadCLT
[]
quadCLTs
,
final
double
[][][]
scenes_xyzatr
,
final
double
[]
sceneTimes
)
{
final
int
prev
=
findPrevScene
(
sceneIndex
,
firstScene
,
quadCLTs
,
scenes_xyzatr
);
final
int
next
=
findNextScene
(
sceneIndex
,
lastScene
,
quadCLTs
,
scenes_xyzatr
);
final
ArrayList
<
RateTerm
>
terms
=
new
ArrayList
<
RateTerm
>(
2
);
if
((
prev
<
0
)
&&
(
next
<
0
))
{
return
terms
;
}
if
(
prev
<
0
)
{
final
double
dt
=
safeDt
(
sceneIndex
,
next
,
sceneTimes
);
terms
.
add
(
new
RateTerm
(
sceneIndex
,
-
1.0
/
dt
));
terms
.
add
(
new
RateTerm
(
next
,
1.0
/
dt
));
return
terms
;
}
if
(
next
<
0
)
{
final
double
dt
=
safeDt
(
prev
,
sceneIndex
,
sceneTimes
);
terms
.
add
(
new
RateTerm
(
prev
,
-
1.0
/
dt
));
terms
.
add
(
new
RateTerm
(
sceneIndex
,
1.0
/
dt
));
return
terms
;
}
final
double
dt
=
safeDt
(
prev
,
next
,
sceneTimes
);
terms
.
add
(
new
RateTerm
(
prev
,
-
1.0
/
dt
));
terms
.
add
(
new
RateTerm
(
next
,
1.0
/
dt
));
return
terms
;
}
private
static
double
getRateValue
(
final
int
sceneIndex
,
final
boolean
angular
,
final
int
comp
,
final
int
firstScene
,
final
int
lastScene
,
final
int
centerIndex
,
final
double
[][][]
scenes_xyzatr
,
final
QuadCLT
[]
quadCLTs
,
final
double
[]
sceneTimes
)
{
final
int
prev
=
findPrevScene
(
sceneIndex
,
firstScene
,
quadCLTs
,
scenes_xyzatr
);
final
int
next
=
findNextScene
(
sceneIndex
,
lastScene
,
quadCLTs
,
scenes_xyzatr
);
if
((
prev
<
0
)
&&
(
next
<
0
))
{
return
0.0
;
}
if
(
prev
<
0
)
{
final
double
dt
=
safeDt
(
sceneIndex
,
next
,
sceneTimes
);
final
double
d
=
getPoseComponent
(
scenes_xyzatr
,
next
,
centerIndex
,
angular
,
comp
)
-
getPoseComponent
(
scenes_xyzatr
,
sceneIndex
,
centerIndex
,
angular
,
comp
);
return
(
angular
?
wrapPi
(
d
)
:
d
)
/
dt
;
}
if
(
next
<
0
)
{
final
double
dt
=
safeDt
(
prev
,
sceneIndex
,
sceneTimes
);
final
double
d
=
getPoseComponent
(
scenes_xyzatr
,
sceneIndex
,
centerIndex
,
angular
,
comp
)
-
getPoseComponent
(
scenes_xyzatr
,
prev
,
centerIndex
,
angular
,
comp
);
return
(
angular
?
wrapPi
(
d
)
:
d
)
/
dt
;
}
final
double
dt
=
safeDt
(
prev
,
next
,
sceneTimes
);
final
double
d
=
getPoseComponent
(
scenes_xyzatr
,
next
,
centerIndex
,
angular
,
comp
)
-
getPoseComponent
(
scenes_xyzatr
,
prev
,
centerIndex
,
angular
,
comp
);
return
(
angular
?
wrapPi
(
d
)
:
d
)
/
dt
;
}
private
static
double
[][]
getSceneRates
(
final
int
sceneIndex
,
final
double
[][][]
scenes_xyzatr
,
final
QuadCLT
[]
quadCLTs
,
final
double
[]
sceneTimes
,
final
int
firstScene
,
final
int
lastScene
,
final
int
centerIndex
)
{
final
double
[][]
rates
=
new
double
[
2
][
3
];
for
(
int
i
=
0
;
i
<
3
;
i
++)
{
rates
[
0
][
i
]
=
getRateValue
(
sceneIndex
,
false
,
i
,
firstScene
,
lastScene
,
centerIndex
,
scenes_xyzatr
,
quadCLTs
,
sceneTimes
);
rates
[
1
][
i
]
=
getRateValue
(
sceneIndex
,
true
,
i
,
firstScene
,
lastScene
,
centerIndex
,
scenes_xyzatr
,
quadCLTs
,
sceneTimes
);
}
return
rates
;
}
private
static
double
[][]
getScenePose
(
final
double
[][][]
scenes_xyzatr
,
final
int
sceneIndex
,
final
int
centerIndex
)
{
if
(
sceneIndex
==
centerIndex
)
{
return
new
double
[][]
{
Interscene
.
ZERO3
.
clone
(),
Interscene
.
ZERO3
.
clone
()};
}
if
((
sceneIndex
<
0
)
||
(
sceneIndex
>=
scenes_xyzatr
.
length
)
||
(
scenes_xyzatr
[
sceneIndex
]
==
null
))
{
return
new
double
[][]
{
Interscene
.
ZERO3
.
clone
(),
Interscene
.
ZERO3
.
clone
()};
}
return
new
double
[][]
{
scenes_xyzatr
[
sceneIndex
][
0
].
clone
(),
scenes_xyzatr
[
sceneIndex
][
1
].
clone
()};
}
private
static
boolean
[]
getLocalParamMaskForPair
(
final
boolean
[]
paramSelect
,
final
int
sceneIndex
,
final
int
refSceneIndex
,
final
int
centerIndex
,
final
boolean
disableErs
)
{
final
boolean
[]
mask
=
new
boolean
[
ErsCorrection
.
DP_NUM_PARS
];
if
(
paramSelect
!=
null
)
{
for
(
int
i
=
0
;
i
<
SCENE_POSE_PARAM_ORDER
.
length
;
i
++)
{
final
int
pi
=
SCENE_POSE_PARAM_ORDER
[
i
];
if
(
pi
<
paramSelect
.
length
)
{
mask
[
pi
]
=
paramSelect
[
pi
];
}
}
}
else
{
for
(
int
i
=
0
;
i
<
SCENE_POSE_PARAM_ORDER
.
length
;
i
++)
{
mask
[
SCENE_POSE_PARAM_ORDER
[
i
]]
=
true
;
}
}
if
(
sceneIndex
==
centerIndex
)
{
for
(
int
i
=
0
;
i
<
SCENE_POSE_PARAM_ORDER
.
length
;
i
++)
{
mask
[
SCENE_POSE_PARAM_ORDER
[
i
]]
=
false
;
}
}
for
(
int
i
=
0
;
i
<
REF_RATE_ANG_PAR_INDICES
.
length
;
i
++)
{
mask
[
REF_RATE_ANG_PAR_INDICES
[
i
]]
=
!
disableErs
;
mask
[
SCENE_RATE_ANG_PAR_INDICES
[
i
]]
=
!
disableErs
;
mask
[
REF_RATE_LIN_PAR_INDICES
[
i
]]
=
true
;
mask
[
SCENE_RATE_LIN_PAR_INDICES
[
i
]]
=
true
;
}
return
mask
;
}
private
ArrayList
<
VectorTerm
>
mapLocalParameterToVectorTerms
(
final
int
parIndex
,
final
int
sceneIndex
,
final
int
refSceneIndex
,
final
int
centerIndex
,
final
int
firstScene
,
final
int
lastScene
,
final
boolean
[]
activePoseScene
,
final
double
[][][]
scenesRatesSource
,
final
boolean
includeRateChain
)
{
final
ArrayList
<
VectorTerm
>
rslt
=
new
ArrayList
<
VectorTerm
>(
2
);
switch
(
parIndex
)
{
case
ErsCorrection
.
DP_DSAZ
:
case
ErsCorrection
.
DP_DSTL
:
case
ErsCorrection
.
DP_DSRL
:
case
ErsCorrection
.
DP_DSX
:
case
ErsCorrection
.
DP_DSY
:
case
ErsCorrection
.
DP_DSZ
:
{
final
Integer
vidx
=
classicState
.
vectorIndexBySceneParam
.
get
(
getSceneParamKey
(
sceneIndex
,
parIndex
));
if
(
vidx
!=
null
)
{
rslt
.
add
(
new
VectorTerm
(
vidx
.
intValue
(),
1.0
));
}
break
;
}
case
ErsCorrection
.
DP_DSVAZ
:
case
ErsCorrection
.
DP_DSVTL
:
case
ErsCorrection
.
DP_DSVRL
:
{
if
(!
includeRateChain
)
{
break
;
}
final
int
comp
=
parIndex
-
ErsCorrection
.
DP_DSVAZ
;
final
int
posePar
=
ErsCorrection
.
DP_DSAZ
+
comp
;
final
ArrayList
<
RateTerm
>
rts
=
getRateTerms
(
sceneIndex
,
firstScene
,
lastScene
,
quadCLTs
,
scenesRatesSource
,
sceneTimes
);
for
(
int
i
=
0
;
i
<
rts
.
size
();
i
++)
{
final
RateTerm
rt
=
rts
.
get
(
i
);
if
(
rt
.
sceneIndex
==
centerIndex
)
{
continue
;
}
final
int
ivar
=
rt
.
sceneIndex
-
firstScene
;
if
((
ivar
<
0
)
||
(
ivar
>=
activePoseScene
.
length
)
||
!
activePoseScene
[
ivar
])
{
continue
;
}
final
Integer
vidx
=
classicState
.
vectorIndexBySceneParam
.
get
(
getSceneParamKey
(
rt
.
sceneIndex
,
posePar
));
if
(
vidx
!=
null
)
{
rslt
.
add
(
new
VectorTerm
(
vidx
.
intValue
(),
rt
.
coeff
));
}
}
break
;
}
case
ErsCorrection
.
DP_DSVX
:
case
ErsCorrection
.
DP_DSVY
:
case
ErsCorrection
.
DP_DSVZ
:
{
if
(!
includeRateChain
)
{
break
;
}
final
int
comp
=
parIndex
-
ErsCorrection
.
DP_DSVX
;
final
int
posePar
=
ErsCorrection
.
DP_DSX
+
comp
;
final
ArrayList
<
RateTerm
>
rts
=
getRateTerms
(
sceneIndex
,
firstScene
,
lastScene
,
quadCLTs
,
scenesRatesSource
,
sceneTimes
);
for
(
int
i
=
0
;
i
<
rts
.
size
();
i
++)
{
final
RateTerm
rt
=
rts
.
get
(
i
);
if
(
rt
.
sceneIndex
==
centerIndex
)
{
continue
;
}
final
int
ivar
=
rt
.
sceneIndex
-
firstScene
;
if
((
ivar
<
0
)
||
(
ivar
>=
activePoseScene
.
length
)
||
!
activePoseScene
[
ivar
])
{
continue
;
}
final
Integer
vidx
=
classicState
.
vectorIndexBySceneParam
.
get
(
getSceneParamKey
(
rt
.
sceneIndex
,
posePar
));
if
(
vidx
!=
null
)
{
rslt
.
add
(
new
VectorTerm
(
vidx
.
intValue
(),
rt
.
coeff
));
}
}
break
;
}
case
ErsCorrection
.
DP_DVAZ
:
case
ErsCorrection
.
DP_DVTL
:
case
ErsCorrection
.
DP_DVRL
:
{
if
(!
includeRateChain
)
{
break
;
}
final
int
comp
=
parIndex
-
ErsCorrection
.
DP_DVAZ
;
final
int
posePar
=
ErsCorrection
.
DP_DSAZ
+
comp
;
final
ArrayList
<
RateTerm
>
rts
=
getRateTerms
(
refSceneIndex
,
firstScene
,
lastScene
,
quadCLTs
,
scenesRatesSource
,
sceneTimes
);
for
(
int
i
=
0
;
i
<
rts
.
size
();
i
++)
{
final
RateTerm
rt
=
rts
.
get
(
i
);
if
(
rt
.
sceneIndex
==
centerIndex
)
{
continue
;
}
final
int
ivar
=
rt
.
sceneIndex
-
firstScene
;
if
((
ivar
<
0
)
||
(
ivar
>=
activePoseScene
.
length
)
||
!
activePoseScene
[
ivar
])
{
continue
;
}
final
Integer
vidx
=
classicState
.
vectorIndexBySceneParam
.
get
(
getSceneParamKey
(
rt
.
sceneIndex
,
posePar
));
if
(
vidx
!=
null
)
{
rslt
.
add
(
new
VectorTerm
(
vidx
.
intValue
(),
rt
.
coeff
));
}
}
break
;
}
case
ErsCorrection
.
DP_DVX
:
case
ErsCorrection
.
DP_DVY
:
case
ErsCorrection
.
DP_DVZ
:
{
if
(!
includeRateChain
)
{
break
;
}
final
int
comp
=
parIndex
-
ErsCorrection
.
DP_DVX
;
final
int
posePar
=
ErsCorrection
.
DP_DSX
+
comp
;
final
ArrayList
<
RateTerm
>
rts
=
getRateTerms
(
refSceneIndex
,
firstScene
,
lastScene
,
quadCLTs
,
scenesRatesSource
,
sceneTimes
);
for
(
int
i
=
0
;
i
<
rts
.
size
();
i
++)
{
final
RateTerm
rt
=
rts
.
get
(
i
);
if
(
rt
.
sceneIndex
==
centerIndex
)
{
continue
;
}
final
int
ivar
=
rt
.
sceneIndex
-
firstScene
;
if
((
ivar
<
0
)
||
(
ivar
>=
activePoseScene
.
length
)
||
!
activePoseScene
[
ivar
])
{
continue
;
}
final
Integer
vidx
=
classicState
.
vectorIndexBySceneParam
.
get
(
getSceneParamKey
(
rt
.
sceneIndex
,
posePar
));
if
(
vidx
!=
null
)
{
rslt
.
add
(
new
VectorTerm
(
vidx
.
intValue
(),
rt
.
coeff
));
}
}
break
;
}
default
:
}
return
rslt
;
}
}
src/main/java/com/elphel/imagej/tileprocessor/IntersceneGlobalRefine.java
View file @
dd7e6ced
...
...
@@ -1998,8 +1998,12 @@ public class IntersceneGlobalRefine {
}
/**
* Dump one combined CSV with initial and final states:
* plain columns are initial, apostrophe-suffixed columns are final.
* Dump initial/final CSV snapshots in two complementary layouts:
* one pair-centric (including legacy filename for compatibility) and one scene-centric.
*
* <p>Pair-centric rows preserve per-pair RMS and weight visibility when scene-to-reference
* mapping is no longer one-to-one. Scene-centric rows keep one row per scene and aggregate
* pair RMS statistics by role ({@code as-scene}, {@code as-reference}, {@code all}).
*/
private
static
void
dumpObservationCsvInitialFinal
(
final
ObservationCache
initialCache
,
...
...
@@ -2052,21 +2056,27 @@ public class IntersceneGlobalRefine {
return
Integer
.
compare
(
pairRef
(
a
.
longValue
()),
pairRef
(
b
.
longValue
()));
});
final
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
"index,scene,reference,weight"
)
final
HashMap
<
Integer
,
ScenePairStats
>
statsInitial
=
new
HashMap
<
Integer
,
ScenePairStats
>();
final
HashMap
<
Integer
,
ScenePairStats
>
statsFinal
=
new
HashMap
<
Integer
,
ScenePairStats
>();
final
StringBuilder
pairSb
=
new
StringBuilder
();
pairSb
.
append
(
"index,scene,reference,weight"
)
.
append
(
",X,Y,Z,A,T,R,CURV_X,CURV_Y,CURV_Z,CURV_A,CURV_T,CURV_R,RMS"
)
.
append
(
",X',Y',Z',A',T',R',CURV_X',CURV_Y',CURV_Z',CURV_A',CURV_T',CURV_R',RMS'"
)
.
append
(
",pair,scene_index,reference_index,weight'"
)
.
append
(
'\n'
);
int
pairOrdinal
=
0
;
for
(
Long
keyObj
:
keys
)
{
final
long
key
=
keyObj
.
longValue
();
final
int
sceneIndex
=
pairScene
(
key
);
final
int
refIndex
=
pairRef
(
key
);
final
String
sceneTs
=
((
sceneIndex
>=
0
)
&&
(
sceneIndex
<
quadCLTs
.
length
)
&&
(
quadCLTs
[
sceneIndex
]
!=
null
))
?
quadCLTs
[
sceneIndex
].
getImageName
()
:
(
"scene#"
+
sceneIndex
);
final
String
refTs
=
((
refIndex
>=
0
)
&&
(
refIndex
<
quadCLTs
.
length
)
&&
(
quadCLTs
[
refIndex
]
!=
null
))
?
quadCLTs
[
refIndex
].
getImageName
()
:
(
"ref#"
+
refIndex
);
final
String
sceneTs
=
getSceneTimestamp
(
quadCLTs
,
sceneIndex
,
"scene"
);
final
String
refTs
=
getSceneTimestamp
(
quadCLTs
,
refIndex
,
"ref"
);
final
double
[][]
pose0
=
getScenePose
(
scenesInitial
,
sceneIndex
,
...
...
@@ -2089,21 +2099,39 @@ public class IntersceneGlobalRefine {
scenesFinal
);
double
rms0
=
Double
.
NaN
;
double
rms1
=
Double
.
NaN
;
double
pairWeight
=
1.0
;
double
pairWeight0
=
Double
.
NaN
;
double
pairWeight1
=
Double
.
NaN
;
final
Integer
i0
=
initialMap
.
get
(
keyObj
);
if
((
i0
!=
null
)
&&
(
initialPairRms
!=
null
)
&&
(
i0
.
intValue
()
>=
0
)
&&
(
i0
.
intValue
()
<
initialPairRms
.
length
))
{
rms0
=
initialPairRms
[
i0
.
intValue
()];
}
if
((
i0
!=
null
)
&&
(
i0
.
intValue
()
>=
0
)
&&
(
i0
.
intValue
()
<
initialCache
.
observations
.
size
()))
{
pairWeight
=
initialCache
.
observations
.
get
(
i0
.
intValue
()).
pairWeight
;
pairWeight
0
=
initialCache
.
observations
.
get
(
i0
.
intValue
()).
pairWeight
;
}
final
Integer
i1
=
finalMap
.
get
(
keyObj
);
if
((
i1
!=
null
)
&&
(
finalPairRms
!=
null
)
&&
(
i1
.
intValue
()
>=
0
)
&&
(
i1
.
intValue
()
<
finalPairRms
.
length
))
{
rms1
=
finalPairRms
[
i1
.
intValue
()];
}
if
((
i1
!=
null
)
&&
(
i1
.
intValue
()
>=
0
)
&&
(
i1
.
intValue
()
<
finalCache
.
observations
.
size
()))
{
pairWeight
=
finalCache
.
observations
.
get
(
i1
.
intValue
()).
pairWeight
;
pairWeight
1
=
finalCache
.
observations
.
get
(
i1
.
intValue
()).
pairWeight
;
}
if
(
i0
!=
null
)
{
accumulateScenePairStats
(
statsInitial
,
sceneIndex
,
refIndex
,
pairWeight0
,
rms0
);
}
if
(
i1
!=
null
)
{
accumulateScenePairStats
(
statsFinal
,
sceneIndex
,
refIndex
,
pairWeight1
,
rms1
);
}
double
pairWeight
=
!
Double
.
isNaN
(
pairWeight1
)
?
pairWeight1
:
pairWeight0
;
if
((
sceneIndex
==
centerIndex
)
&&
(
refIndex
==
centerIndex
))
{
if
(
Double
.
isNaN
(
rms0
))
{
rms0
=
0.0
;
...
...
@@ -2111,9 +2139,15 @@ public class IntersceneGlobalRefine {
if
(
Double
.
isNaN
(
rms1
))
{
rms1
=
0.0
;
}
if
(
Double
.
isNaN
(
pairWeight0
))
{
pairWeight0
=
1.0
;
}
if
(
Double
.
isNaN
(
pairWeight1
))
{
pairWeight1
=
1.0
;
}
pairWeight
=
1.0
;
}
s
b
.
append
(
sceneIndex
).
append
(
','
)
pairS
b
.
append
(
sceneIndex
).
append
(
','
)
.
append
(
sceneTs
).
append
(
','
)
.
append
(
refTs
).
append
(
','
)
.
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
pairWeight
))
...
...
@@ -2143,14 +2177,248 @@ public class IntersceneGlobalRefine {
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
curv1
[
4
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
curv1
[
5
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
rms1
))
.
append
(
','
).
append
(
pairOrdinal
)
.
append
(
','
).
append
(
sceneIndex
)
.
append
(
','
).
append
(
refIndex
)
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
pairWeight1
))
.
append
(
'\n'
);
pairOrdinal
++;
}
final
StringBuilder
sceneSb
=
new
StringBuilder
();
sceneSb
.
append
(
"index,scene"
)
.
append
(
",X,Y,Z,A,T,R,CURV_X,CURV_Y,CURV_Z,CURV_A,CURV_T,CURV_R"
)
.
append
(
",X',Y',Z',A',T',R',CURV_X',CURV_Y',CURV_Z',CURV_A',CURV_T',CURV_R'"
)
.
append
(
",N_SCENE,NW_SCENE,WS_SCENE,RMS_SCENE,RMS_SCENE_MAX"
)
.
append
(
",N_REF,NW_REF,WS_REF,RMS_REF,RMS_REF_MAX"
)
.
append
(
",N_ALL,NW_ALL,WS_ALL,RMS_ALL,RMS_ALL_MAX"
)
.
append
(
",N_SCENE',NW_SCENE',WS_SCENE',RMS_SCENE',RMS_SCENE_MAX'"
)
.
append
(
",N_REF',NW_REF',WS_REF',RMS_REF',RMS_REF_MAX'"
)
.
append
(
",N_ALL',NW_ALL',WS_ALL',RMS_ALL',RMS_ALL_MAX'"
)
.
append
(
'\n'
);
for
(
int
sceneIndex
=
firstScene
;
sceneIndex
<=
lastScene
;
sceneIndex
++)
{
appendSceneInitialFinalRow
(
sceneSb
,
sceneIndex
,
quadCLTs
,
scenesInitial
,
scenesFinal
,
firstScene
,
lastScene
,
centerIndex
,
statsInitial
.
get
(
Integer
.
valueOf
(
sceneIndex
)),
statsFinal
.
get
(
Integer
.
valueOf
(
sceneIndex
)));
}
if
((
centerIndex
<
firstScene
)
||
(
centerIndex
>
lastScene
))
{
appendSceneInitialFinalRow
(
sceneSb
,
centerIndex
,
quadCLTs
,
scenesInitial
,
scenesFinal
,
firstScene
,
lastScene
,
centerIndex
,
statsInitial
.
get
(
Integer
.
valueOf
(
centerIndex
)),
statsFinal
.
get
(
Integer
.
valueOf
(
centerIndex
)));
}
centerCLT
.
saveStringInModelDirectory
(
sb
.
toString
(),
sceneSb
.
toString
(),
"-IGR_OBS_INITIAL_FINAL_SCENES.csv"
,
false
);
centerCLT
.
saveStringInModelDirectory
(
pairSb
.
toString
(),
"-IGR_OBS_INITIAL_FINAL_PAIRS.csv"
,
false
);
centerCLT
.
saveStringInModelDirectory
(
pairSb
.
toString
(),
"-IGR_OBS_INITIAL_FINAL.csv"
,
false
);
}
private
static
class
PairAggregate
{
int
count
=
0
;
int
weightedCount
=
0
;
double
weightSum
=
0.0
;
double
weightedRmsSum
=
0.0
;
double
rmsMax
=
Double
.
NaN
;
}
private
static
class
ScenePairStats
{
final
PairAggregate
asScene
=
new
PairAggregate
();
final
PairAggregate
asReference
=
new
PairAggregate
();
final
PairAggregate
all
=
new
PairAggregate
();
}
private
static
String
getSceneTimestamp
(
final
QuadCLT
[]
quadCLTs
,
final
int
sceneIndex
,
final
String
missingPrefix
)
{
return
((
sceneIndex
>=
0
)
&&
(
sceneIndex
<
quadCLTs
.
length
)
&&
(
quadCLTs
[
sceneIndex
]
!=
null
))
?
quadCLTs
[
sceneIndex
].
getImageName
()
:
(
missingPrefix
+
"#"
+
sceneIndex
);
}
private
static
ScenePairStats
getScenePairStats
(
final
HashMap
<
Integer
,
ScenePairStats
>
statsMap
,
final
int
sceneIndex
)
{
final
Integer
key
=
Integer
.
valueOf
(
sceneIndex
);
ScenePairStats
stats
=
statsMap
.
get
(
key
);
if
(
stats
==
null
)
{
stats
=
new
ScenePairStats
();
statsMap
.
put
(
key
,
stats
);
}
return
stats
;
}
private
static
void
updatePairAggregate
(
final
PairAggregate
acc
,
final
double
pairWeight
,
final
double
rms
)
{
acc
.
count
++;
if
(
Double
.
isNaN
(
rms
)
||
Double
.
isNaN
(
pairWeight
)
||
(
pairWeight
<=
0.0
))
{
return
;
}
acc
.
weightedCount
++;
acc
.
weightSum
+=
pairWeight
;
acc
.
weightedRmsSum
+=
pairWeight
*
rms
;
acc
.
rmsMax
=
Double
.
isNaN
(
acc
.
rmsMax
)
?
rms
:
Math
.
max
(
acc
.
rmsMax
,
rms
);
}
private
static
void
accumulateScenePairStats
(
final
HashMap
<
Integer
,
ScenePairStats
>
statsMap
,
final
int
sceneIndex
,
final
int
refIndex
,
final
double
pairWeight
,
final
double
rms
)
{
final
ScenePairStats
sceneStats
=
getScenePairStats
(
statsMap
,
sceneIndex
);
updatePairAggregate
(
sceneStats
.
asScene
,
pairWeight
,
rms
);
updatePairAggregate
(
sceneStats
.
all
,
pairWeight
,
rms
);
if
(
refIndex
!=
sceneIndex
)
{
final
ScenePairStats
refStats
=
getScenePairStats
(
statsMap
,
refIndex
);
updatePairAggregate
(
refStats
.
asReference
,
pairWeight
,
rms
);
updatePairAggregate
(
refStats
.
all
,
pairWeight
,
rms
);
}
}
private
static
double
getWeightedRmsMean
(
final
PairAggregate
acc
)
{
return
(
acc
.
weightSum
>
0.0
)
?
(
acc
.
weightedRmsSum
/
acc
.
weightSum
)
:
Double
.
NaN
;
}
private
static
void
appendPairAggregate
(
final
StringBuilder
sb
,
final
PairAggregate
acc
)
{
sb
.
append
(
','
).
append
(
acc
.
count
)
.
append
(
','
).
append
(
acc
.
weightedCount
)
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
acc
.
weightSum
))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
getWeightedRmsMean
(
acc
)))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
acc
.
rmsMax
));
}
private
static
void
appendSceneInitialFinalRow
(
final
StringBuilder
sb
,
final
int
sceneIndex
,
final
QuadCLT
[]
quadCLTs
,
final
double
[][][]
scenesInitial
,
final
double
[][][]
scenesFinal
,
final
int
firstScene
,
final
int
lastScene
,
final
int
centerIndex
,
final
ScenePairStats
statsInitial
,
final
ScenePairStats
statsFinal
)
{
final
String
sceneTs
=
getSceneTimestamp
(
quadCLTs
,
sceneIndex
,
"scene"
);
final
double
[][]
pose0
=
getScenePose
(
scenesInitial
,
sceneIndex
,
centerIndex
);
final
double
[]
curv0
=
getSceneCurvature
(
sceneIndex
,
firstScene
,
lastScene
,
centerIndex
,
scenesInitial
);
final
double
[][]
pose1
=
getScenePose
(
scenesFinal
,
sceneIndex
,
centerIndex
);
final
double
[]
curv1
=
getSceneCurvature
(
sceneIndex
,
firstScene
,
lastScene
,
centerIndex
,
scenesFinal
);
final
ScenePairStats
s0
=
(
statsInitial
!=
null
)
?
statsInitial
:
new
ScenePairStats
();
final
ScenePairStats
s1
=
(
statsFinal
!=
null
)
?
statsFinal
:
new
ScenePairStats
();
sb
.
append
(
sceneIndex
).
append
(
','
)
.
append
(
sceneTs
)
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
pose0
[
0
][
0
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
pose0
[
0
][
1
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
pose0
[
0
][
2
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
pose0
[
1
][
0
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
pose0
[
1
][
1
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
pose0
[
1
][
2
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
curv0
[
0
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
curv0
[
1
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
curv0
[
2
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
curv0
[
3
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
curv0
[
4
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
curv0
[
5
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
pose1
[
0
][
0
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
pose1
[
0
][
1
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
pose1
[
0
][
2
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
pose1
[
1
][
0
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
pose1
[
1
][
1
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
pose1
[
1
][
2
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
curv1
[
0
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
curv1
[
1
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
curv1
[
2
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
curv1
[
3
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
curv1
[
4
]))
.
append
(
','
).
append
(
String
.
format
(
Locale
.
US
,
"%.12g"
,
curv1
[
5
]));
appendPairAggregate
(
sb
,
s0
.
asScene
);
appendPairAggregate
(
sb
,
s0
.
asReference
);
appendPairAggregate
(
sb
,
s0
.
all
);
appendPairAggregate
(
sb
,
s1
.
asScene
);
appendPairAggregate
(
sb
,
s1
.
asReference
);
appendPairAggregate
(
sb
,
s1
.
all
);
sb
.
append
(
'\n'
);
}
private
static
long
makePairKey
(
final
int
sceneIndex
,
final
int
refIndex
)
{
...
...
src/main/java/com/elphel/imagej/tileprocessor/OpticalFlow.java
View file @
dd7e6ced
...
...
@@ -137,6 +137,189 @@ public class OpticalFlow {
return
"unknown scene-matching failure reason="
+
fr
;
}
}
private
static
int
findSceneIndexByTimestamp
(
final
QuadCLT
[]
quadCLTs
,
final
String
timestamp
)
{
if
((
quadCLTs
==
null
)
||
(
timestamp
==
null
)
||
timestamp
.
isEmpty
())
{
return
-
1
;
}
for
(
int
i
=
0
;
i
<
quadCLTs
.
length
;
i
++)
{
if
((
quadCLTs
[
i
]
!=
null
)
&&
timestamp
.
equals
(
quadCLTs
[
i
].
getImageName
()))
{
return
i
;
}
}
return
-
1
;
}
private
static
String
getInterIntraLmaPath
(
final
QuadCLT
scene
,
final
String
timestamp
)
{
if
((
scene
==
null
)
||
(
timestamp
==
null
)
||
timestamp
.
isEmpty
())
{
return
null
;
}
return
scene
.
getX3dDirectory
()
+
Prefs
.
getFileSeparator
()
+
timestamp
+
QuadCLTCPU
.
DSI_SUFFIXES
[
QuadCLTCPU
.
INDEX_INTER_LMA
]
+
".tiff"
;
}
private
static
String
getDsiMainPath
(
final
QuadCLT
scene
,
final
String
timestamp
)
{
if
((
scene
==
null
)
||
(
timestamp
==
null
)
||
timestamp
.
isEmpty
())
{
return
null
;
}
return
scene
.
getX3dDirectory
()
+
Prefs
.
getFileSeparator
()
+
timestamp
+
QuadCLTCPU
.
DSI_SUFFIXES
[
QuadCLTCPU
.
INDEX_DSI_MAIN
]
+
".tiff"
;
}
private
static
String
resolveQuarterInterIntraPath
(
final
QuadCLT
[]
quadCLTs
,
final
int
refIndex
,
final
int
fallbackIndex
,
final
String
timestamp
)
{
QuadCLT
dirScene
=
((
refIndex
>=
0
)
&&
(
refIndex
<
quadCLTs
.
length
))
?
quadCLTs
[
refIndex
]
:
null
;
String
ts
=
timestamp
;
if
((
ts
==
null
)
||
ts
.
isEmpty
())
{
if
((
fallbackIndex
>=
0
)
&&
(
fallbackIndex
<
quadCLTs
.
length
)
&&
(
quadCLTs
[
fallbackIndex
]
!=
null
))
{
ts
=
quadCLTs
[
fallbackIndex
].
getImageName
();
dirScene
=
quadCLTs
[
fallbackIndex
];
}
}
else
{
final
int
idx
=
findSceneIndexByTimestamp
(
quadCLTs
,
ts
);
if
((
idx
>=
0
)
&&
(
idx
<
quadCLTs
.
length
)
&&
(
quadCLTs
[
idx
]
!=
null
))
{
dirScene
=
quadCLTs
[
idx
];
}
}
return
getInterIntraLmaPath
(
dirScene
,
ts
);
}
private
static
int
resolveQuarterRefIndex
(
final
QuadCLT
[]
quadCLTs
,
final
int
rangeStart
,
final
int
rangeEnd
,
final
int
fallbackIndex
,
final
String
timestamp
)
{
int
idx
=
findSceneIndexByTimestamp
(
quadCLTs
,
timestamp
);
if
((
idx
<
rangeStart
)
||
(
idx
>
rangeEnd
))
{
idx
=
fallbackIndex
;
}
if
(
idx
<
rangeStart
)
{
idx
=
rangeStart
;
}
if
(
idx
>
rangeEnd
)
{
idx
=
rangeEnd
;
}
return
idx
;
}
private
static
boolean
ensureQuarterReferenceProducts
(
final
CLTParameters
clt_parameters
,
final
ColorProcParameters
colorProcParameters
,
final
EyesisCorrectionParameters
.
RGBParameters
rgbParameters
,
final
QuadCLT
quadCLT_main
,
final
QuadCLT
[]
quadCLTs
,
final
SetChannels
[]
set_channels
,
final
int
centerRefIndex
,
final
int
quarterRefIndex
,
final
int
rangeStart
,
final
int
rangeEnd
,
final
boolean
forceRecalculateQuarterRefs
,
final
boolean
quarterSfmOnly
,
final
boolean
batch_mode
,
final
int
threadsMax
,
final
boolean
updateStatus
,
final
int
debugLevel
)
{
if
((
quadCLTs
==
null
)
||
(
set_channels
==
null
)
||
(
centerRefIndex
<
0
)
||
(
centerRefIndex
>=
quadCLTs
.
length
)
||
(
quarterRefIndex
<
0
)
||
(
quarterRefIndex
>=
quadCLTs
.
length
)
||
(
rangeStart
>
rangeEnd
))
{
return
false
;
}
if
(
quadCLTs
[
centerRefIndex
]
==
null
)
{
return
false
;
}
if
(
quadCLTs
[
quarterRefIndex
]
==
null
)
{
quadCLTs
[
quarterRefIndex
]
=
quadCLTs
[
centerRefIndex
].
spawnNoModelQuadCLT
(
set_channels
[
quarterRefIndex
].
set_name
,
clt_parameters
,
colorProcParameters
,
threadsMax
,
debugLevel
-
2
);
}
if
(
quadCLTs
[
quarterRefIndex
]
==
null
)
{
return
false
;
}
if
(
forceRecalculateQuarterRefs
)
{
final
String
quarterTs
=
quadCLTs
[
quarterRefIndex
].
getImageName
();
final
String
quarterInterPath
=
getInterIntraLmaPath
(
quadCLTs
[
quarterRefIndex
],
quarterTs
);
final
String
quarterDsiMainPath
=
getDsiMainPath
(
quadCLTs
[
quarterRefIndex
],
quarterTs
);
if
(
debugLevel
>
-
3
)
{
System
.
out
.
println
(
"buildSeries(): forcing quarter-reference regeneration for "
+
quarterTs
);
}
if
(
quarterInterPath
!=
null
)
{
final
File
fInter
=
new
File
(
quarterInterPath
);
if
(
fInter
.
exists
()
&&
!
fInter
.
delete
())
{
System
.
out
.
println
(
"buildSeries(): WARNING failed to delete quarter INTER-INTRA-LMA "
+
quarterInterPath
);
}
}
if
(
quarterDsiMainPath
!=
null
)
{
final
File
fDsi
=
new
File
(
quarterDsiMainPath
);
if
(
fDsi
.
exists
()
&&
!
fDsi
.
delete
())
{
System
.
out
.
println
(
"buildSeries(): WARNING failed to delete quarter DSI_MAIN "
+
quarterDsiMainPath
);
}
}
quadCLTs
[
quarterRefIndex
].
setDSI
(
null
);
}
if
(!
quadCLTs
[
quarterRefIndex
].
dsiExists
())
{
if
(
debugLevel
>
-
3
)
{
System
.
out
.
println
(
"buildSeries(): generating -DSI_MAIN for quarter scene "
+
quadCLTs
[
quarterRefIndex
].
getImageName
());
}
buildRefDSI
(
clt_parameters
,
false
,
false
,
colorProcParameters
,
rgbParameters
,
batch_mode
,
set_channels
[
quarterRefIndex
].
set_name
,
quadCLT_main
,
quadCLTs
[
quarterRefIndex
],
threadsMax
,
updateStatus
,
debugLevel
);
}
if
(!
quadCLTs
[
quarterRefIndex
].
dsiExists
())
{
return
false
;
}
final
EstimateSceneRange
quarterRange
=
new
EstimateSceneRange
();
quarterRange
.
earliest
=
rangeStart
;
quarterRange
.
latest
=
rangeEnd
;
quarterRange
.
center
=
quarterRefIndex
;
quarterRange
.
earliest_prescan
=
rangeStart
;
quarterRange
.
latest_prescan
=
rangeEnd
;
quarterRange
.
needs_prescan
=
false
;
if
(
debugLevel
>
-
3
)
{
System
.
out
.
println
(
"buildSeries(): generating quarter INTER-INTRA-LMA with scanSfmIMS(), center="
+
quarterRefIndex
+
", range=["
+
rangeStart
+
","
+
rangeEnd
+
"], sfm_only="
+
quarterSfmOnly
);
}
final
boolean
sfmOk
=
EstimateSceneRange
.
scanSfmIMS
(
clt_parameters
,
quarterRange
,
quadCLTs
,
quadCLT_main
,
colorProcParameters
,
set_channels
,
batch_mode
,
updateStatus
,
debugLevel
,
quarterSfmOnly
);
if
(!
sfmOk
)
{
return
false
;
}
return
quadCLTs
[
quarterRefIndex
].
interDsiExists
();
}
public
static
double
[]
ZERO3
=
{
0.0
,
0.0
,
0.0
};
public
static
double
LINE_ERR
=
0.1
;
public
static
int
THREADS_MAX
=
100
;
// maximal number of threads to launch
...
...
@@ -6100,6 +6283,163 @@ java.lang.NullPointerException
int
[]
range
=
new
int
[]
{
earliest_scene
,
last_index
};
if
(
use_global_lma
)
{
final
QuadCLT
centerRefScene
=
((
ref_index
>=
0
)
&&
(
ref_index
<
quadCLTs
.
length
))
?
quadCLTs
[
ref_index
]
:
null
;
if
(
centerRefScene
!=
null
)
{
final
int
overlapScenes
=
Math
.
max
(
1
,
Math
.
min
(
4
,
(
range
[
1
]
-
range
[
0
]
+
1
)
/
20
+
1
));
final
int
q1RangeStart
=
range
[
0
];
final
int
q1RangeEnd
=
Math
.
min
(
range
[
1
],
ref_index
+
overlapScenes
);
final
int
q3RangeStart
=
Math
.
max
(
range
[
0
],
ref_index
-
overlapScenes
);
final
int
q3RangeEnd
=
range
[
1
];
final
int
q1Guess
=
Math
.
max
(
q1RangeStart
,
Math
.
min
(
ref_index
-
1
,
(
q1RangeStart
+
ref_index
)
/
2
));
final
int
q3Guess
=
Math
.
min
(
q3RangeEnd
,
Math
.
max
(
ref_index
+
1
,
(
q3RangeEnd
+
ref_index
)
/
2
));
final
int
q1Index
=
resolveQuarterRefIndex
(
quadCLTs
,
q1RangeStart
,
q1RangeEnd
,
q1Guess
,
centerRefScene
.
timestamp_quarter1
);
final
int
q3Index
=
resolveQuarterRefIndex
(
quadCLTs
,
q3RangeStart
,
q3RangeEnd
,
q3Guess
,
centerRefScene
.
timestamp_quarter3
);
String
q1Ts
=
(
quadCLTs
[
q1Index
]
!=
null
)
?
quadCLTs
[
q1Index
].
getImageName
()
:
set_channels
[
q1Index
].
set_name
;
String
q3Ts
=
(
quadCLTs
[
q3Index
]
!=
null
)
?
quadCLTs
[
q3Index
].
getImageName
()
:
set_channels
[
q3Index
].
set_name
;
boolean
tsUpdated
=
false
;
if
((
centerRefScene
.
timestamp_quarter1
==
null
)
||
!
centerRefScene
.
timestamp_quarter1
.
equals
(
q1Ts
))
{
centerRefScene
.
timestamp_quarter1
=
q1Ts
;
tsUpdated
=
true
;
}
if
((
centerRefScene
.
timestamp_quarter3
==
null
)
||
!
centerRefScene
.
timestamp_quarter3
.
equals
(
q3Ts
))
{
centerRefScene
.
timestamp_quarter3
=
q3Ts
;
tsUpdated
=
true
;
}
if
(
tsUpdated
)
{
centerRefScene
.
saveInterProperties
(
null
,
debugLevel
+
1
);
}
String
q1Path
=
resolveQuarterInterIntraPath
(
quadCLTs
,
q1Index
,
q1Index
,
centerRefScene
.
timestamp_quarter1
);
String
q3Path
=
resolveQuarterInterIntraPath
(
quadCLTs
,
q3Index
,
q3Index
,
centerRefScene
.
timestamp_quarter3
);
final
String
q1MsgPath
=
(
q1Path
!=
null
)
?
q1Path
:
(
centerRefScene
.
getX3dDirectory
()
+
Prefs
.
getFileSeparator
()
+
q1Ts
+
QuadCLTCPU
.
DSI_SUFFIXES
[
QuadCLTCPU
.
INDEX_INTER_LMA
]
+
".tiff"
);
final
String
q3MsgPath
=
(
q3Path
!=
null
)
?
q3Path
:
(
centerRefScene
.
getX3dDirectory
()
+
Prefs
.
getFileSeparator
()
+
q3Ts
+
QuadCLTCPU
.
DSI_SUFFIXES
[
QuadCLTCPU
.
INDEX_INTER_LMA
]
+
".tiff"
);
final
boolean
forceQuarterRecalc
=
clt_parameters
.
iglp
.
glob_recalculate_quarter_refs
;
final
boolean
q1Exists
=
(
q1Path
!=
null
)
&&
(
new
File
(
q1Path
).
exists
());
final
boolean
q3Exists
=
(
q3Path
!=
null
)
&&
(
new
File
(
q3Path
).
exists
());
final
boolean
q1Missing
=
!
q1Exists
||
forceQuarterRecalc
;
final
boolean
q3Missing
=
!
q3Exists
||
forceQuarterRecalc
;
if
(
debugLevel
>
-
3
)
{
System
.
out
.
println
(
"buildSeries(): quarter refs selected: q1 ts="
+
q1Ts
+
", idx="
+
q1Index
+
", range=["
+
q1RangeStart
+
","
+
q1RangeEnd
+
"], path="
+
q1MsgPath
+
", exists="
+
q1Exists
);
System
.
out
.
println
(
"buildSeries(): quarter refs selected: q3 ts="
+
q3Ts
+
", idx="
+
q3Index
+
", range=["
+
q3RangeStart
+
","
+
q3RangeEnd
+
"], path="
+
q3MsgPath
+
", exists="
+
q3Exists
);
if
(
forceQuarterRecalc
)
{
System
.
out
.
println
(
"buildSeries(): quarter-reference force regeneration is enabled"
);
}
}
if
(
q1Missing
)
{
if
(
q1Exists
&&
forceQuarterRecalc
)
{
System
.
out
.
println
(
"buildSeries(): quarter1 INTER-INTRA-LMA exists, but force regeneration is enabled, will regenerate "
+
q1MsgPath
);
}
else
{
System
.
out
.
println
(
"buildSeries(): quarter1 INTER-INTRA-LMA missing, will generate "
+
q1MsgPath
);
}
}
else
if
(
debugLevel
>
-
3
)
{
System
.
out
.
println
(
"buildSeries(): quarter1 INTER-INTRA-LMA present, using "
+
q1MsgPath
);
}
if
(
q3Missing
)
{
if
(
q3Exists
&&
forceQuarterRecalc
)
{
System
.
out
.
println
(
"buildSeries(): quarter3 INTER-INTRA-LMA exists, but force regeneration is enabled, will regenerate "
+
q3MsgPath
);
}
else
{
System
.
out
.
println
(
"buildSeries(): quarter3 INTER-INTRA-LMA missing, will generate "
+
q3MsgPath
);
}
}
else
if
(
debugLevel
>
-
3
)
{
System
.
out
.
println
(
"buildSeries(): quarter3 INTER-INTRA-LMA present, using "
+
q3MsgPath
);
}
if
(
q1Missing
||
q3Missing
)
{
System
.
out
.
println
(
"buildSeries(): quarter reference prerequisites missing, generating before Global LMA"
);
boolean
q1Ok
=
true
;
boolean
q3Ok
=
true
;
if
(
q1Missing
)
{
q1Ok
=
ensureQuarterReferenceProducts
(
clt_parameters
,
colorProcParameters
,
rgbParameters
,
quadCLT_main
,
quadCLTs
,
set_channels
,
ref_index
,
q1Index
,
q1RangeStart
,
q1RangeEnd
,
forceQuarterRecalc
,
clt_parameters
.
iglp
.
glob_quarter_refs_sfm_only
,
batch_mode
,
threadsMax
,
updateStatus
,
debugLevel
);
}
if
(
q3Missing
)
{
q3Ok
=
ensureQuarterReferenceProducts
(
clt_parameters
,
colorProcParameters
,
rgbParameters
,
quadCLT_main
,
quadCLTs
,
set_channels
,
ref_index
,
q3Index
,
q3RangeStart
,
q3RangeEnd
,
forceQuarterRecalc
,
clt_parameters
.
iglp
.
glob_quarter_refs_sfm_only
,
batch_mode
,
threadsMax
,
updateStatus
,
debugLevel
);
}
q1Path
=
resolveQuarterInterIntraPath
(
quadCLTs
,
q1Index
,
q1Index
,
centerRefScene
.
timestamp_quarter1
);
q3Path
=
resolveQuarterInterIntraPath
(
quadCLTs
,
q3Index
,
q3Index
,
centerRefScene
.
timestamp_quarter3
);
if
(!
q1Ok
||
(
q1Path
==
null
)
||
!(
new
File
(
q1Path
).
exists
()))
{
System
.
out
.
println
(
"buildSeries(): WARNING quarter1 generation failed or output missing: "
+
q1MsgPath
);
}
if
(!
q3Ok
||
(
q3Path
==
null
)
||
!(
new
File
(
q3Path
).
exists
()))
{
System
.
out
.
println
(
"buildSeries(): WARNING quarter3 generation failed or output missing: "
+
q3MsgPath
);
}
if
((
q1Path
!=
null
)
&&
new
File
(
q1Path
).
exists
())
{
System
.
out
.
println
(
"buildSeries(): generated quarter1 INTER-INTRA-LMA "
+
q1Path
);
}
if
((
q3Path
!=
null
)
&&
new
File
(
q3Path
).
exists
())
{
System
.
out
.
println
(
"buildSeries(): generated quarter3 INTER-INTRA-LMA "
+
q3Path
);
}
}
}
IntersceneGlobalRefine
.
Result
igr_result
=
Interscene
.
reAdjustPairsLMAIntersceneGlobalReference
(
clt_parameters
,
// final CLTParameters clt_parameters,
quadCLTs
,
// final QuadCLT[] quadCLTs,
...
...
src/main/java/com/elphel/imagej/tileprocessor/QuadCLTCPU.java
View file @
dd7e6ced
...
...
@@ -246,6 +246,8 @@ public class QuadCLTCPU {
// only reference scene has a pair of first/last scene in a sequence
public
String
timestamp_first
=
null
;
public
String
timestamp_last
=
null
;
public
String
timestamp_quarter1
=
null
;
public
String
timestamp_quarter3
=
null
;
public
String
timestamp_index
=
null
;
// timestamp of the scene with index of all reference scenes in this sequence
public
HashSet
<
String
>
ref_scenes
=
null
;
// Set of timestamps of the reference scenes in this sequence
// combined clt for center view, only used in cuas mode
...
...
@@ -7755,12 +7757,18 @@ LogTee.clearSceneLog(); // stop per‑scene logging
if
(
this
.
timestamp_first
!=
null
)
{
properties
.
setProperty
(
prefix
+
"timestamp_first"
,
this
.
timestamp_first
);
}
if
(
this
.
timestamp_quarter1
!=
null
)
{
properties
.
setProperty
(
prefix
+
"timestamp_quarter1"
,
this
.
timestamp_quarter1
);
}
if
(
this
.
timestamp_index
!=
null
)
{
properties
.
setProperty
(
prefix
+
"timestamp_index"
,
this
.
timestamp_index
);
}
if
(
this
.
timestamp_last
!=
null
)
{
properties
.
setProperty
(
prefix
+
"timestamp_last"
,
this
.
timestamp_last
);
}
if
(
this
.
timestamp_quarter3
!=
null
)
{
properties
.
setProperty
(
prefix
+
"timestamp_quarter3"
,
this
.
timestamp_quarter3
);
}
if
(
this
.
quat_corr
!=
null
)
{
properties
.
setProperty
(
prefix
+
"quat_corr"
,
IntersceneMatchParameters
.
doublesToString
(
this
.
quat_corr
));
...
...
@@ -7972,9 +7980,15 @@ LogTee.clearSceneLog(); // stop per‑scene logging
if
(
properties
.
getProperty
(
prefix
+
"timestamp_first"
)!=
null
)
{
this
.
timestamp_first
=
(
String
)
properties
.
getProperty
(
prefix
+
"timestamp_first"
);
}
if
(
properties
.
getProperty
(
prefix
+
"timestamp_quarter1"
)!=
null
)
{
this
.
timestamp_quarter1
=
(
String
)
properties
.
getProperty
(
prefix
+
"timestamp_quarter1"
);
}
if
(
properties
.
getProperty
(
prefix
+
"timestamp_last"
)!=
null
)
{
this
.
timestamp_last
=
(
String
)
properties
.
getProperty
(
prefix
+
"timestamp_last"
);
}
if
(
properties
.
getProperty
(
prefix
+
"timestamp_quarter3"
)!=
null
)
{
this
.
timestamp_quarter3
=
(
String
)
properties
.
getProperty
(
prefix
+
"timestamp_quarter3"
);
}
if
(
properties
.
getProperty
(
prefix
+
"timestamp_index"
)!=
null
)
{
this
.
timestamp_index
=
(
String
)
properties
.
getProperty
(
prefix
+
"timestamp_index"
);
}
...
...
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