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
5e03168f
Commit
5e03168f
authored
Apr 14, 2024
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed affine inversion
parent
0da53711
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
375 additions
and
34 deletions
+375
-34
ComboMatch.java
src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java
+158
-15
OrthoMap.java
src/main/java/com/elphel/imagej/orthomosaic/OrthoMap.java
+2
-0
OrthoMapsCollection.java
...va/com/elphel/imagej/orthomosaic/OrthoMapsCollection.java
+163
-14
OrthoPairLMA.java
...main/java/com/elphel/imagej/orthomosaic/OrthoPairLMA.java
+11
-2
PairwiseOrthoMatch.java
...ava/com/elphel/imagej/orthomosaic/PairwiseOrthoMatch.java
+31
-1
IntersceneMatchParameters.java
...lphel/imagej/tileprocessor/IntersceneMatchParameters.java
+10
-2
No files found.
src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java
View file @
5e03168f
...
...
@@ -805,12 +805,26 @@ public class ComboMatch {
int
default_choice
=
0
;
int
num_scene_lines
=
50
;
String
scene_name
=
maps_collection
.
selectOneScene
(
0
,
// int num_scene,
default_choice
,
// int default_choice,
num_scene_lines
);
// int num_choice_lines)
if
(
scene_name
==
null
)
{
return
false
;
}
if
(
process_correlation
)
{
// select a second image to match
// select a second image and set gpu_spair
int
default_choice1
=
0
;
String
scene_name1
=
maps_collection
.
selectOneScene
(
1
,
// int num_scene,
default_choice1
,
// int default_choice,
num_scene_lines
);
// int num_choice_lines)
if
(
scene_name1
==
null
)
{
return
false
;
}
gpu_spair
=
new
String
[]
{
scene_name
,
scene_name1
};
}
else
{
// pattern match - single image
gpu_spair
=
new
String
[]
{
scene_name
};
}
}
else
{
gpu_spair
=
new
String
[]
{
maps_collection
.
ortho_maps
[
available_pairs
[
pair
][
0
]].
getName
(),
...
...
@@ -818,15 +832,19 @@ public class ComboMatch {
}
}
int
[]
gpu_pair
=
new
int
[
gpu_spair
.
length
];
for
(
int
i
=
0
;
i
<
gpu_pair
.
length
;
i
++)
{
gpu_pair
[
i
]
=
maps_collection
.
getIndex
(
gpu_spair
[
i
]);
}
int
min_zoom_lev
=
maps_collection
.
ortho_maps
[
gpu_pair
[
0
]].
getOriginalZoomLevel
();
int
max_zoom_lev
=
maps_collection
.
ortho_maps
[
gpu_pair
[
0
]].
getOriginalZoomLevel
();
double
max_agl
=
maps_collection
.
ortho_maps
[
gpu_pair
[
0
]].
getAGL
();
for
(
int
i
=
0
;
i
<
gpu_pair
.
length
;
i
++)
{
gpu_pair
[
i
]
=
maps_collection
.
getIndex
(
gpu_spair
[
i
]
);
max_agl
=
Math
.
max
(
max_agl
,
maps_collection
.
ortho_maps
[
gpu_pair
[
i
]].
getAGL
()
);
min_zoom_lev
=
Math
.
min
(
min_zoom_lev
,
maps_collection
.
ortho_maps
[
gpu_pair
[
i
]].
getOriginalZoomLevel
());
max_zoom_lev
=
Math
.
max
(
max_zoom_lev
,
maps_collection
.
ortho_maps
[
gpu_pair
[
i
]].
getOriginalZoomLevel
());
}
double
agl_ratio
=
max_agl
/
50.0
;
double
metric_error_adj
=
metric_error
*
agl_ratio
*
agl_ratio
;
// metric_error settings is good for 50m. Increase for higher Maybe squared?
int
initial_zoom
=
max_zoom_lev
-
4
;
// another algorithm?
System
.
out
.
println
(
"Setting up GPU"
);
...
...
@@ -849,7 +867,7 @@ public class ComboMatch {
double
[][]
affine1
=
null
;
if
(
gpu_spair
.
length
<
2
)
{
System
.
out
.
println
(
"Selected a single image"
);
System
.
out
.
println
(
"Selected a single image
, not a pair
"
);
double
[][][]
affines
=
{
affine0
};
// or use affine1 = null as second?
if
(
pattern_match
)
{
ImagePlus
imp_pat_match
=
maps_collection
.
patternMatchDualWrap
(
...
...
@@ -860,9 +878,23 @@ public class ComboMatch {
// imp_pat_match.show();
}
}
else
{
if
(
process_correlation
&&
!
use_marked_image
)
{
// match may or may not exist
// if match exists - ask if use it. If not - open dialog and start spiral
pairwiseOrthoMatch
=
initialPairAdjust
(
clt_parameters
,
// CLTParameters clt_parameters,
maps_collection
,
// OrthoMapsCollection maps_collection,
frac_remove
,
// double frac_remove, // = 0.25
metric_error_adj
,
// double metric_error,
gpu_spair
,
// String[] gpu_spair,
debugLevel
);
// int debugLevel)
if
(
pairwiseOrthoMatch
==
null
)
{
// if OK - either match existed or created by SpiralMatch()
return
false
;
}
}
else
{
pairwiseOrthoMatch
=
maps_collection
.
ortho_maps
[
gpu_pair
[
0
]].
getMatch
(
maps_collection
.
ortho_maps
[
gpu_pair
[
1
]].
getName
());
}
if
(
pairwiseOrthoMatch
==
null
)
{
System
.
out
.
println
(
"No correlation data is available for pairs "
+
gpu_spair
[
0
]+
" - "
+
gpu_spair
[
1
]+
" need to implement/search reverse, a spiral search or restart command"
);
...
...
@@ -874,8 +906,10 @@ public class ComboMatch {
int
[]
zooms
=
{
initial_zoom
,
min_zoom_lev
,
1000
,
1000
};
// make automatic
double
scale
=
2.0
;
// scale vectors when warping;
// int num_tries = 5; // make configurable
if
(!
process_correlation
)
{
if
(!
process_correlation
||
!
use_marked_image
)
{
// skip low-res
zooms
=
new
int
[]
{
min_zoom_lev
,
1000
};
}
if
(!
process_correlation
)
{
// 0 LMA adjustments
num_tries_fit
=
0
;
update_match
=
false
;
}
...
...
@@ -884,24 +918,31 @@ public class ComboMatch {
boolean
ignore_prev_rms
=
true
;
Rectangle
woi
=
new
Rectangle
();
// used to return actual woi from correlateOrthoPair()
double
[][]
ground_planes
=
null
;
double
max_std
=
1.5
;
// maximal standard deviation to limit center area
double
min_std_rad
=
2.0
;
// minimal radius of the central area (if less - fail)
for
(
int
zi
=
0
;
zi
<
zooms
.
length
;
zi
++)
{
zoom_lev
=
zooms
[
zi
];
if
(
zoom_lev
>=
1000
)
{
break
;
}
boolean
show_vf
=
render_match
||
pattern_match
;
boolean
show_vf
=
false
;
//
render_match || pattern_match;
if
(
render_match
||
pattern_match
)
{
ground_planes
=
new
double
[
gpu_pair
.
length
][];
}
// will modify affines[1], later add jtj, weight, smth. else?
PairwiseOrthoMatch
pmatch
=
process_correlation
?
pairwiseOrthoMatch:
null
;
FineXYCorr
warp
=
maps_collection
.
correlateOrthoPair
(
clt_parameters
,
// CLTParameters clt_parameters,
(
process_correlation
?
pairwiseOrthoMatch:
null
),
//PairwiseOrthoMatch pairwiseOrthoMatch, // will return statistics
0
,
// int min_overlap,
max_std
,
// double max_std, // maximal standard deviation to limit center area
min_std_rad
,
// double min_std_rad, // minimal radius of the central area (if less - fail)
frac_remove
,
// double frac_remove, // = 0.25
metric_error
,
// double metric_error,
metric_error
_adj
,
// double metric_error,
ignore_prev_rms
,
// boolean ignore_prev_rms,
num_tries_fit
,
// = 5int num_tries, // = 5
true
,
// boolean calc_warp,
true
,
// boolean calc_warp,
(will return null if false)
batch_mode
,
// boolean batch_mode,
gpu_pair
,
// String [] gpu_spair,
affines
,
// double [][][] affines, // on top of GPS offsets
...
...
@@ -910,7 +951,7 @@ public class ComboMatch {
show_vf
,
// boolean show_vf,
ground_planes
,
// double [][] ground_planes, // null or double[2] - will return ground planes
debugLevel
);
// final int debugLevel)
if
(
warp
==
null
)
{
if
(
(
warp
==
null
)
||
((
pmatch
!=
null
)
&&
Double
.
isNaN
(
pmatch
.
rms
))
)
{
System
.
out
.
println
(
"Failed correlateOrthoPair()"
);
return
false
;
}
...
...
@@ -948,10 +989,10 @@ public class ComboMatch {
// imp_pat_match.show();
}
if
(
render_match
)
{
String
title
=
String
.
format
(
"multi_%03d-%03d_%s-%s_zoom%d_%d"
,
gpu_pair
[
0
],
gpu_pair
[
1
],
gpu_spair
[
0
],
gpu_spair
[
1
],
min_zoom_lev
,
zoom_lev
);
ImagePlus
imp_img_pair
=
maps_collection
.
renderMulti
(
//_zoom<integer> is needed for opening with "Extract Objects" command
"multi_"
+
gpu_spair
[
0
]+
"-"
+
gpu_spair
[
1
]+
"_zoom"
+
min_zoom_lev
+
"_"
+
zoom_lev
,
// String title,
// false, // boolean use_alt,
title
,
// String title,
OrthoMapsCollection
.
MODE_IMAGE
,
// int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask // boolean use_alt,
gpu_pair
,
// int [] indices, // null or which indices to use (normally just 2 for pairwise comparison)
bounds_to_indices
,
// boolean bounds_to_indices,
...
...
@@ -978,6 +1019,98 @@ public class ComboMatch {
}
return
true
;
}
public
static
PairwiseOrthoMatch
initialPairAdjust
(
CLTParameters
clt_parameters
,
OrthoMapsCollection
maps_collection
,
double
frac_remove
,
// = 0.25
double
metric_error
,
String
[]
gpu_spair
,
int
debugLevel
)
{
int
[]
gpu_pair
=
new
int
[
gpu_spair
.
length
];
gpu_pair
[
0
]
=
maps_collection
.
getIndex
(
gpu_spair
[
0
]);
int
min_zoom_lev
=
maps_collection
.
ortho_maps
[
gpu_pair
[
0
]].
getOriginalZoomLevel
();
int
max_zoom_lev
=
maps_collection
.
ortho_maps
[
gpu_pair
[
0
]].
getOriginalZoomLevel
();
for
(
int
i
=
0
;
i
<
gpu_pair
.
length
;
i
++)
{
gpu_pair
[
i
]
=
maps_collection
.
getIndex
(
gpu_spair
[
i
]);
min_zoom_lev
=
Math
.
min
(
min_zoom_lev
,
maps_collection
.
ortho_maps
[
gpu_pair
[
i
]].
getOriginalZoomLevel
());
max_zoom_lev
=
Math
.
max
(
max_zoom_lev
,
maps_collection
.
ortho_maps
[
gpu_pair
[
i
]].
getOriginalZoomLevel
());
}
int
initial_zoom
=
max_zoom_lev
-
4
;
// another algorithm?
PairwiseOrthoMatch
pairwiseOrthoMatch
=
maps_collection
.
ortho_maps
[
gpu_pair
[
0
]].
getMatch
(
maps_collection
.
ortho_maps
[
gpu_pair
[
1
]].
getName
());
// boolean has_match = pairwiseOrthoMatch != null;
PairwiseOrthoMatch
inv_match
=
maps_collection
.
ortho_maps
[
gpu_pair
[
1
]].
getMatch
(
maps_collection
.
ortho_maps
[
gpu_pair
[
0
]].
getName
());
// dialog - ask parameters and if has_match -ask if to use it (then just return true)
// if has inv - ask and, if yes, = create inverted as initial
boolean
use_exixting_pair
=
false
;
boolean
invert_exixting_pair
=
false
;
double
search_step
=
8.0
;
// pix
double
search_range
=
50.0
;
// pix
double
maximal_rms
=
0.25
;
//
int
min_overlap
=
3000
;
// do not try to match if there is too small overlap (scaled pixels)
int
num_iter_lma
=
5
;
GenericJTabbedDialog
gd
=
new
GenericJTabbedDialog
(
"Setup SpiralMatch"
,
1200
,
900
);
if
(
pairwiseOrthoMatch
!=
null
)
{
gd
.
addCheckbox
(
"Use existing image pair"
,
use_exixting_pair
,
"Use existing affine settings for this pair, do not use spiral search."
);
}
if
(
inv_match
!=
null
)
{
gd
.
addCheckbox
(
"Invert existing image pair"
,
invert_exixting_pair
,
"Invert existing image pair affine transform, do not use spiral search."
);
}
gd
.
addNumericField
(
"Spiral search step"
,
search_step
,
3
,
7
,
"scaled pix"
,
"Distance between spiral search probes, in scaled pixels."
);
gd
.
addNumericField
(
"Spiral search radius"
,
search_range
,
3
,
7
,
"scaled pix"
,
"Maximal radius of the spiral search, in scaled pixels."
);
gd
.
addNumericField
(
"Maximal RMSE"
,
maximal_rms
,
3
,
7
,
"scaled pix"
,
"Maximal RMSE to consider match, in scaled pixels."
);
gd
.
addNumericField
(
"Minimal overlap"
,
min_overlap
,
0
,
4
,
"scaled pix ^ 2"
,
"Minimal overlap area in square scaled pixels."
);
gd
.
addNumericField
(
"LMA iterations"
,
num_iter_lma
,
0
,
2
,
""
,
"Number of LMA iterations."
);
gd
.
showDialog
();
if
(
gd
.
wasCanceled
())
return
null
;
if
(
pairwiseOrthoMatch
!=
null
)
{
use_exixting_pair
=
gd
.
getNextBoolean
();
}
if
(
inv_match
!=
null
)
{
invert_exixting_pair
=
gd
.
getNextBoolean
();
}
search_step
=
gd
.
getNextNumber
();
search_range
=
gd
.
getNextNumber
();
maximal_rms
=
gd
.
getNextNumber
();
min_overlap
=
(
int
)
gd
.
getNextNumber
();
num_iter_lma
=
(
int
)
gd
.
getNextNumber
();
if
(
use_exixting_pair
)
{
if
(
invert_exixting_pair
)
{
System
.
out
.
println
(
"Both direct and inverted matches are selected, using direct match"
);
}
return
pairwiseOrthoMatch
;
}
else
if
(
invert_exixting_pair
)
{
double
[]
enuOffset
=
maps_collection
.
ortho_maps
[
gpu_pair
[
0
]].
enuOffsetTo
(
maps_collection
.
ortho_maps
[
gpu_pair
[
1
]]);
double
[]
rd
=
{
enuOffset
[
0
],
-
enuOffset
[
1
]};
// {right,down} of the image
// create inverted pairwiseOrthoMatch - move to PairwiseOrthoMatch
return
inv_match
.
getInverse
(
rd
);
}
double
[][]
affine0
=
{{
1
,
0
,
0
},{
0
,
1
,
0
}};
// will always stay the same
double
[][]
affine1
=
{{
1
,
0
,
0
},{
0
,
1
,
0
}};
// here (manual mode) start from the center, may use prediction in auto
double
[][][]
affines
=
new
double
[][][]
{
affine0
,
affine1
};
pairwiseOrthoMatch
=
maps_collection
.
SpiralMatch
(
clt_parameters
,
// CLTParameters clt_parameters,
// PairwiseOrthoMatch pairwiseOrthoMatch, // will return statistics, may be null if not needed
frac_remove
,
// double frac_remove, // = 0.25
metric_error
,
// double metric_error,
gpu_pair
,
// int [] gpu_pair,
affines
,
// double [][][] affines_init, // here in meters, relative to vertical points
initial_zoom
,
// int zoom_lev,
search_step
,
// double pix_step,
search_range
,
// double pix_range,
maximal_rms
,
// double need_rms,
num_iter_lma
,
// int num_tries, // = 5
min_overlap
,
// int min_overlap, // 3000
debugLevel
);
// int debugLevel){
return
pairwiseOrthoMatch
;
}
public
static
boolean
updateBlBcFileNames
(
String
suffix
,
...
...
@@ -1375,7 +1508,9 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341
// get TD interscene correlation of 2 scenes, use only combo (all channels) data
TDCorrTile
[]
corr_tiles
=
TDCorrTile
.
getFromGpu
(
GPU_QUAD_AFFINE
);
double
neib_radius
=
clt_parameters
.
imp
.
rln_neib_radius
;;
// depends on zoom level
double
neib_radius
=
clt_parameters
.
imp
.
rln_neib_radius
;
boolean
rln_neibs_fill
=
clt_parameters
.
imp
.
rln_neibs_fill
;
double
rln_fat_zero
=
clt_parameters
.
imp
.
rln_fat_zero
;
boolean
rln_use_neibs
=
clt_parameters
.
imp
.
rln_use_neibs
;
...
...
@@ -1384,6 +1519,14 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341
double
rln_sngl_rstr
=
clt_parameters
.
imp
.
rln_sngl_rstr
;
double
rln_neib_rstr
=
clt_parameters
.
imp
.
rln_neib_rstr
;
double
max_neib_radius
=
Math
.
min
(
woi
.
width
,
woi
.
height
)/
GPUTileProcessor
.
DTT_SIZE
*
clt_parameters
.
imp
.
rln_radius_frac
;
if
(
neib_radius
>
max_neib_radius
)
{
neib_radius
=
max_neib_radius
;
}
double
[][][]
corr_tiles_pd
=
new
double
[(
neib_radius
>
0
)?
2
:
1
][][];
// use TDCorrTile.calcNeibs() here to get 8-neighbors
corr_tiles_pd
[
0
]
=
TDCorrTile
.
convertTDtoPD
(
...
...
src/main/java/com/elphel/imagej/orthomosaic/OrthoMap.java
View file @
5e03168f
...
...
@@ -3005,6 +3005,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
}
return
true
;
}
public
static
double
[][]
combineAffine
(
double
[][]
ref_affine
,
double
[][]
other_affine
){
...
...
@@ -3023,6 +3024,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
}
/**
* Get planar approximation of the ground
*
...
...
src/main/java/com/elphel/imagej/orthomosaic/OrthoMapsCollection.java
View file @
5e03168f
...
...
@@ -985,6 +985,86 @@ public class OrthoMapsCollection implements Serializable{
return null;
} */
public
PairwiseOrthoMatch
SpiralMatch
(
CLTParameters
clt_parameters
,
// PairwiseOrthoMatch pairwiseOrthoMatch, // will return statistics, may be null if not needed
double
frac_remove
,
// = 0.25
double
metric_error
,
int
[]
gpu_pair
,
double
[][][]
affines_init
,
// here in meters, relative to vertical points
int
zoom_lev
,
double
pix_step
,
double
pix_range
,
double
need_rms
,
int
num_tries
,
// = 5
int
min_overlap
,
// = 5
int
debugLevel
){
double
[][]
affine1
=
new
double
[][]
{
affines_init
[
1
][
0
].
clone
(),
affines_init
[
1
][
1
].
clone
()};
double
[][][]
affines
=
new
double
[][][]
{
affines_init
[
0
],
affine1
};
boolean
show_vf
=
false
;
boolean
batch_mode
=
true
;
boolean
ignore_prev_rms
=
false
;
// true;
double
[][]
ground_planes
=
null
;
// null or double[2] - will return ground planes:
double
pix_size
=
OrthoMap
.
getPixelSizeMeters
(
zoom_lev
);
int
nx
=
0
,
ny
=
0
;
// number of steps (pix_step size) in hor and vert directions (both pos and neg)
int
nabs
=
(
int
)
Math
.
ceil
(
pix_range
/
pix_step
);
PairwiseOrthoMatch
pairwiseOrthoMatch
=
new
PairwiseOrthoMatch
(
affines
[
1
],
// double [][] affine,
null
,
// double [][] jtj,
Double
.
NaN
,
// double rms,
zoom_lev
);
// int zoom_lev);
double
max_std
=
1.5
;
// maximal standard deviation to limit center area
double
min_std_rad
=
2.0
;
// minimal radius of the central area (if less - fail)
while
((
Math
.
abs
(
nx
)
<=
nabs
)
&&
(
Math
.
abs
(
ny
)
<=
nabs
))
{
affine1
[
0
][
2
]
=
affines_init
[
1
][
0
][
2
]
+
pix_step
*
pix_size
*
nx
;
affine1
[
1
][
2
]
=
affines_init
[
1
][
1
][
2
]
+
pix_step
*
pix_size
*
ny
;
pairwiseOrthoMatch
.
rms
=
Double
.
NaN
;
correlateOrthoPair
(
clt_parameters
,
// CLTParameters clt_parameters,
pairwiseOrthoMatch
,
//PairwiseOrthoMatch pairwiseOrthoMatch, // will return statistics
min_overlap
,
// int min_overlap,
max_std
,
// double max_std, // maximal standard deviation to limit center area
min_std_rad
,
// double min_std_rad, // minimal radius of the central area (if less - fail)
frac_remove
,
// double frac_remove, // = 0.25
metric_error
,
// double metric_error,
ignore_prev_rms
,
// boolean ignore_prev_rms,
num_tries
,
// = 5int num_tries, // = 5
false
,
// boolean calc_warp, (will return null if false)
batch_mode
,
// boolean batch_mode,
gpu_pair
,
// String [] gpu_spair,
affines
,
// double [][][] affines, // on top of GPS offsets
null
,
// woi, // Rectangle woi,
zoom_lev
,
// int zoom_lev,
show_vf
,
// boolean show_vf,
ground_planes
,
// double [][] ground_planes, // null or double[2] - will return ground planes
debugLevel
);
// final int debugLevel)
pairwiseOrthoMatch
.
affine
=
affines
[
1
];
// modified by correlateOrthoPair
if
(
debugLevel
>
-
4
)
{
System
.
out
.
println
(
String
.
format
(
"SpiralMatch(): nx = %3d, ny=%3d, RMSE=%8.6f"
,
nx
,
ny
,
pairwiseOrthoMatch
.
rms
));
}
if
(
pairwiseOrthoMatch
.
rms
<
need_rms
)
{
break
;
}
// update nx, ny
if
((
nx
>
ny
)
&&
(
nx
>
-
ny
)){
ny
++;
}
else
if
((
nx
<=
ny
)
&&
(
nx
>
-
ny
)){
nx
--;
}
else
if
((
ny
<=
-
nx
)
&&
(
ny
>
nx
)){
ny
--;
}
else
{
nx
++;
}
}
if
(!(
pairwiseOrthoMatch
.
rms
<
need_rms
))
{
// failed
return
null
;
}
return
pairwiseOrthoMatch
;
// pairwiseOrthoMatch.affine will have adjusted affine[1]
}
public
FineXYCorr
correlateOrthoPair
(
// not used
CLTParameters
clt_parameters
,
...
...
@@ -1006,9 +1086,14 @@ public class OrthoMapsCollection implements Serializable{
for
(
int
i
=
0
;
i
<
gpu_pair
.
length
;
i
++)
{
gpu_pair
[
i
]
=
getIndex
(
gpu_spair
[
i
]);
}
double
max_std
=
1.5
;
// maximal standard deviation to limit center area
double
min_std_rad
=
2.0
;
// minimal radius of the central area (if less - fail)
return
correlateOrthoPair
(
clt_parameters
,
// CLTParameters clt_parameters,
pairwiseOrthoMatch
,
//PairwiseOrthoMatch pairwiseOrthoMatch, // will return statistics
0
,
// int min_overlap,
max_std
,
// double max_std, // maximal standard deviation to limit center area
min_std_rad
,
// double min_std_rad, // minimal radius of the central area (if less - fail)
frac_remove
,
// double frac_remove, // = 0.25
metric_error
,
// double metric_error,
ignore_prev_rms
,
// boolean ignore_prev_rms,
...
...
@@ -1027,6 +1112,9 @@ public class OrthoMapsCollection implements Serializable{
public
FineXYCorr
correlateOrthoPair
(
CLTParameters
clt_parameters
,
PairwiseOrthoMatch
pairwiseOrthoMatch
,
// will return statistics, may be null if not needed
int
min_overlap
,
double
max_std
,
// maximal standard deviation to limit center area
double
min_std_rad
,
// minimal radius of the central area (if less - fail)
double
frac_remove
,
// = 0.25
double
metric_error
,
boolean
ignore_prev_rms
,
...
...
@@ -1043,6 +1131,10 @@ public class OrthoMapsCollection implements Serializable{
if
(
woi
==
null
)
{
woi
=
new
Rectangle
();
}
int
min_tiles_overlap
=
min_overlap
/
GPUTileProcessor
.
DTT_SIZE
/
GPUTileProcessor
.
DTT_SIZE
;
if
(
pairwiseOrthoMatch
!=
null
)
{
pairwiseOrthoMatch
.
rms
=
Double
.
NaN
;
// mark as failed
}
boolean
show_gpu_img
=
true
;
// (debugLevel > 1);
boolean
show_tile_centers
=
false
;
// true; // (debugLevel > 1);
if
(!
batch_mode
)
{
...
...
@@ -1058,8 +1150,8 @@ public class OrthoMapsCollection implements Serializable{
affines
[
0
],
// double [][] ref_affine,
affines
[
1
]);
// double [][] other_affine
if
(
bounds_overlap_meters
==
null
)
{
if
(
debugLevel
>
-
3
)
{
if
(
(
bounds_overlap_meters
==
null
)
||
(
bounds_overlap_meters
[
0
]
==
null
)
||
(
bounds_overlap_meters
[
1
]
==
null
)
)
{
if
(
debugLevel
>
-
4
)
{
System
.
out
.
println
(
"correlateOrthoPair(): no overlap"
);
return
null
;
}
...
...
@@ -1109,6 +1201,9 @@ public class OrthoMapsCollection implements Serializable{
gpu_pair_img
[
n
]
=
ortho_maps
[
gpu_pair
[
n
]].
getPaddedGPU
(
zoom_lev
);
// int zoom_level,
}
boolean
invert_second
=
(
debugLevel
>
1000
);
if
(
debugLevel
>
10
)
{
return
null
;
}
if
(
invert_second
)
{
for
(
int
i
=
0
;
i
<
gpu_pair_img
[
1
].
length
;
i
++)
{
gpu_pair_img
[
1
][
i
]=
-
gpu_pair_img
[
1
][
i
];
...
...
@@ -1127,6 +1222,13 @@ public class OrthoMapsCollection implements Serializable{
}
woi
.
width
=
overlap_wh_pixel
[
0
];
woi
.
height
=
overlap_wh_pixel
[
1
];
// = new Rectangle(0, 0, overlap_wh_pixel[0], overlap_wh_pixel[1]);
if
(
woi
.
width
*
woi
.
height
<
min_overlap
)
{
if
(
debugLevel
>
-
4
)
{
System
.
out
.
println
(
"correlateOrthoPair(): too small overlap: "
+
woi
.
width
+
" * "
+
woi
.
height
+
" = "
+(
woi
.
width
*
woi
.
height
)+
" < "
+
min_overlap
+
""
);
}
return
null
;
}
if
(
woi
.
width
>
OrthoMap
.
gpu_width
)
{
if
(
debugLevel
>
-
3
)
{
System
.
out
.
println
(
"correlateOrthoPair() correlation woi.width="
+
woi
.
width
+
" > gpu_width="
+
OrthoMap
.
gpu_width
+
". Truncating."
);
...
...
@@ -1178,6 +1280,17 @@ public class OrthoMapsCollection implements Serializable{
batch_mode
,
// final boolean batch_mode,
dbg_suffix
,
// final String dbg_suffix, // for image_names
debugLevel
);
// final int debugLevel);
if
(
tp_tasks
[
0
].
length
<
min_tiles_overlap
)
{
if
(
pairwiseOrthoMatch
!=
null
)
{
pairwiseOrthoMatch
.
rms
=
Double
.
NaN
;
// mark as failed
}
if
(
debugLevel
>
-
4
)
{
System
.
out
.
println
(
"correlateOrthoPair(): too small non-null overlap: "
+
tp_tasks
[
0
].
length
+
" < "
+
min_tiles_overlap
+
""
);
}
return
null
;
}
// get elevations
int
zoom_lev_tiles
=
zoom_lev
-
3
;
double
[]
ground_planes_weight
=
null
;
...
...
@@ -1216,13 +1329,27 @@ public class OrthoMapsCollection implements Serializable{
ground_planes_weight
[
i
]
=
1.0
;
}
}
if
(
debugLevel
>
-
3
)
{
System
.
out
.
println
(
"correlateOrthoPair(): left "
+
num_left
+
" tiles (was "
+
tp_tasks
[
0
].
length
+
" before filtering). metric_error="
+
metric_error
);
System
.
out
.
println
();
}
if
(
num_left
<
tp_tasks
[
0
].
length
/
4
)
{
num_elevations
--;
System
.
out
.
println
(
"too few tiles remain, try again. metric_error="
+
metric_error
);
pairwiseOrthoMatch
.
rms
=
Double
.
NaN
;
// failed
return
null
;
}
if
(
num_left
<
min_tiles_overlap
)
{
if
(
pairwiseOrthoMatch
!=
null
)
{
pairwiseOrthoMatch
.
rms
=
Double
.
NaN
;
// mark as failed
}
if
(
debugLevel
>
-
4
)
{
System
.
out
.
println
(
"correlateOrthoPair(): too small non-null, filtered by elevations overlap: "
+
num_left
+
" < "
+
min_tiles_overlap
+
""
);
}
return
null
;
}
}
double
max_err
=
7.0
;
...
...
@@ -1357,14 +1484,32 @@ public class OrthoMapsCollection implements Serializable{
double
rms_diff
=
0.001
;
int
num_iter
=
20
;
boolean
last_run
=
false
;
orthoPairLMA
.
prepareLMA
(
int
min_good_tiles
=
min_tiles_overlap
/
2
;
int
num_good_tiles
=
orthoPairLMA
.
prepareLMA
(
// will always calculate relative affine, starting with unity
tilesX
,
// int width,
vector_field
[
1
],
// double [][] vector_XYS, // optical flow X,Y, confidence obtained from the correlate2DIterate()
tile_centers
,
// double [][] centers, // tile centers (in pixels)
null
,
// double [] weights_extra, // optional, may be null
true
,
// boolean first_run,
min_good_tiles
,
// int min_good_tiles,
max_std
,
// double max_std, // maximal standard deviation to limit center area
min_std_rad
,
// double min_std_rad, // minimal radius of the central area (if less - fail)
debugLevel
);
// final int debug_level)
if
(
num_good_tiles
<
min_good_tiles
)
{
if
(
debugLevel
>-
4
)
{
System
.
out
.
println
(
"correlateOrthoPair(): num_good_tiles="
+
num_good_tiles
+
" < "
+
min_good_tiles
);
}
if
(
pairwiseOrthoMatch
!=
null
)
{
pairwiseOrthoMatch
.
rms
=
Double
.
NaN
;
// mark as failed
}
return
null
;
}
int
lma_rslt
=
orthoPairLMA
.
runLma
(
// <0 - failed, >=0 iteration number (1 - immediately)
lambda
,
// double lambda, // 0.1
lambda_scale_good
,
// double lambda_scale_good,// 0.5
...
...
@@ -3529,7 +3674,11 @@ public class OrthoMapsCollection implements Serializable{
}
public
String
selectOneScene
(
int
default_choice
,
int
num_choice_lines
)
{
public
String
selectOneScene
(
int
num_scene
,
int
default_choice
,
int
num_choice_lines
)
{
String
[]
fs
=
{
"first"
,
"second"
};
String
[]
lines
=
new
String
[
ortho_maps
.
length
];
DateTimeFormatter
formatter
=
DateTimeFormatter
.
ofPattern
(
"MM/dd/yyyy HH:mm:ss.SS zzz"
);
// may be VV instead of zzz
for
(
int
indx
=
0
;
indx
<
ortho_maps
.
length
;
indx
++)
{
...
...
@@ -3543,11 +3692,11 @@ public class OrthoMapsCollection implements Serializable{
lines
[
indx
]=
String
.
format
(
"%3d %17s %26s %6.2f"
,
indx
,
name
,
sdt
,
agl
);
}
GenericJTabbedDialog
gd
=
new
GenericJTabbedDialog
(
"Select
I
mage from the list "
,
1200
,
1000
);
gd
.
addChoice
(
"Image pair
:"
,
GenericJTabbedDialog
gd
=
new
GenericJTabbedDialog
(
"Select
the "
+
fs
[
num_scene
]+
" i
mage from the list "
,
1200
,
1000
);
gd
.
addChoice
(
fs
[
num_scene
]+
" image
:"
,
lines
,
lines
[
default_choice
],
"Select scene"
,
num_choice_lines
);
"Select
"
+
fs
[
num_scene
]+
"
scene"
,
num_choice_lines
);
gd
.
showDialog
();
if
(
gd
.
wasCanceled
())
return
null
;
int
scene_number
=
gd
.
getNextChoiceIndex
();
...
...
src/main/java/com/elphel/imagej/orthomosaic/OrthoPairLMA.java
View file @
5e03168f
...
...
@@ -54,21 +54,26 @@ public class OrthoPairLMA {
private
double
[][]
last_jt
=
null
;
private
boolean
origin_center
=
false
;
// true - origin in overlap center, false - top left corner (as it was)
private
double
[]
origin
=
null
;
// either {0,0} for top-left or center of the woi
public
int
num_good_tiles
=
0
;
public
OrthoPairLMA
(
boolean
origin_center
)
{
this
.
origin_center
=
origin_center
;
}
public
void
prepareLMA
(
public
int
prepareLMA
(
// will always calculate relative affine, starting with unity
int
width
,
// tilesX
double
[][]
vector_XYS
,
// optical flow X,Y, confidence obtained from the correlate2DIterate()
double
[][]
centers
,
// tile centers (in pixels)
double
[]
weights_extra
,
// optional, may be null
boolean
first_run
,
int
min_good_tiles
,
double
max_std
,
// maximal standard deviation to limit center area
double
min_std_rad
,
// minimal radius of the central area (if less - fail)
final
int
debug_level
)
{
tile_centers
=
centers
;
this
.
width
=
width
;
int
height
=
vector_XYS
.
length
/
width
;
int
min_x
=
width
,
min_y
=
height
,
max_x
=
-
1
,
max_y
=-
1
;
num_good_tiles
=
0
;
for
(
int
tile
=
0
;
tile
<
vector_XYS
.
length
;
tile
++)
if
((
vector_XYS
[
tile
]
!=
null
))
{
int
tileX
=
tile
%
width
;
int
tileY
=
tile
/
width
;
...
...
@@ -76,8 +81,12 @@ public class OrthoPairLMA {
if
(
tileX
>
max_x
)
max_x
=
tileX
;
if
(
tileY
<
min_y
)
min_y
=
tileY
;
if
(
tileY
>
max_y
)
max_y
=
tileY
;
num_good_tiles
++;
}
woi
=
new
Rectangle
(
min_x
,
min_y
,
max_x
-
min_x
+
1
,
max_y
-
min_y
+
1
);
if
(
num_good_tiles
<
min_good_tiles
)
{
return
num_good_tiles
;
}
origin
=
new
double
[
2
];
if
(
origin_center
)
{
origin
=
new
double
[]
{
...
...
@@ -98,7 +107,7 @@ public class OrthoPairLMA {
last_rms
=
new
double
[
2
];
initial_rms
=
last_rms
.
clone
();
good_or_bad_rms
=
this
.
last_rms
.
clone
();
return
num_good_tiles
;
}
public
double
[][]
getAffine
(){
...
...
src/main/java/com/elphel/imagej/orthomosaic/PairwiseOrthoMatch.java
View file @
5e03168f
...
...
@@ -14,10 +14,40 @@ public class PairwiseOrthoMatch implements Serializable {
public
PairwiseOrthoMatch
()
{
}
public
PairwiseOrthoMatch
(
double
[][]
affine
,
double
[][]
jtj
,
double
rms
,
int
zoom_lev
)
{
public
PairwiseOrthoMatch
(
double
[][]
affine
,
double
[][]
jtj
,
double
rms
,
int
zoom_lev
)
{
this
.
affine
=
affine
;
this
.
jtj
=
jtj
;
this
.
zoom_lev
=
zoom_lev
;
}
public
PairwiseOrthoMatch
getInverse
(
double
[]
rd
)
{
double
[][]
affine
=
OrthoMap
.
invertAffine
(
getAffine
());
PairwiseOrthoMatch
inverted_match
=
new
PairwiseOrthoMatch
(
affine
,
// double [][] affine,
null
,
// double [][] jtj,
rms
,
// double rms,
zoom_lev
);
// int zoom_lev)
double
[]
corr
=
{
rd
[
0
]
*
(
affine
[
0
][
0
]-
1.0
)+
rd
[
1
]*
affine
[
0
][
1
],
rd
[
0
]
*
affine
[
1
][
0
]+
rd
[
1
]*(
affine
[
1
][
1
]-
1.0
)};
affine
[
0
][
2
]
+=
corr
[
0
];
affine
[
1
][
2
]
+=
corr
[
1
];
return
inverted_match
;
}
public
PairwiseOrthoMatch
getInverse
()
{
PairwiseOrthoMatch
inverted_match
=
new
PairwiseOrthoMatch
(
OrthoMap
.
invertAffine
(
getAffine
()),
// double [][] affine,
null
,
// double [][] jtj,
rms
,
// double rms,
zoom_lev
);
// int zoom_lev)
return
inverted_match
;
}
public
double
[][]
getAffine
(){
return
affine
;
}
...
...
src/main/java/com/elphel/imagej/tileprocessor/IntersceneMatchParameters.java
View file @
5e03168f
...
...
@@ -100,11 +100,12 @@ public class IntersceneMatchParameters {
public
double
rln_fat_zero
=
10000.0
;
// phase correlation fat zero
public
boolean
rln_use_neibs
=
true
;
// calculate TD neighbors in phase correlation
public
boolean
rln_neibs_fill
=
false
;
// fill empty neighbors centers
public
double
rln_neib_radius
=
2.9
;
// neighbors radius (tiles)
public
double
rln_neib_radius
=
5.9
;
// neighbors radius (tiles)
public
double
rln_radius_frac
=
0.1
;
// rln_neib_radius not less than this fraction of woi width/height
public
double
rln_cent_radius
=
4.0
;
// centroids center radius
public
int
rln_n_recenter
=
2
;
// when cosine window, re-center window these many times
public
double
rln_sngl_rstr
=
0.3
;
// minimal single-tile phase correlation maximums relative to max str
public
double
rln_neib_rstr
=
0.
5
;
// minimal neighbors phase correlation maximums relative to max str
public
double
rln_neib_rstr
=
0.
4
;
// minimal neighbors phase correlation maximums relative to max str
public
double
[]
getImsMountATR
()
{
return
new
double
[]
{
...
...
@@ -683,6 +684,8 @@ public class IntersceneMatchParameters {
"Fill empty neighbors centers (false - only non-empty)."
);
gd
.
addNumericField
(
"Neighbors radius"
,
this
.
rln_neib_radius
,
5
,
8
,
"tiles"
,
"Use these tiles around the center one."
);
gd
.
addNumericField
(
"Neighbors radius fraction woi"
,
this
.
rln_radius_frac
,
5
,
8
,
""
,
"Naighbors radius not less than this fraction of tiles WOI."
);
gd
.
addNumericField
(
"Centroids radius"
,
this
.
rln_cent_radius
,
5
,
8
,
""
,
"Centroids radius for maximums isolation."
);
gd
.
addNumericField
(
"Recenter centroid"
,
this
.
rln_n_recenter
,
0
,
3
,
""
,
...
...
@@ -1526,6 +1529,7 @@ public class IntersceneMatchParameters {
this
.
rln_use_neibs
=
gd
.
getNextBoolean
();
this
.
rln_neibs_fill
=
gd
.
getNextBoolean
();
this
.
rln_neib_radius
=
gd
.
getNextNumber
();
this
.
rln_radius_frac
=
gd
.
getNextNumber
();
this
.
rln_cent_radius
=
gd
.
getNextNumber
();
this
.
rln_n_recenter
=
(
int
)
gd
.
getNextNumber
();
this
.
rln_sngl_rstr
=
gd
.
getNextNumber
();
...
...
@@ -1986,6 +1990,7 @@ public class IntersceneMatchParameters {
properties
.
setProperty
(
prefix
+
"rln_use_neibs"
,
this
.
rln_use_neibs
+
""
);
// boolean
properties
.
setProperty
(
prefix
+
"rln_neibs_fill"
,
this
.
rln_neibs_fill
+
""
);
// boolean
properties
.
setProperty
(
prefix
+
"rln_neib_radius"
,
this
.
rln_neib_radius
+
""
);
// double
properties
.
setProperty
(
prefix
+
"rln_radius_frac"
,
this
.
rln_radius_frac
+
""
);
// double
properties
.
setProperty
(
prefix
+
"rln_cent_radius"
,
this
.
rln_cent_radius
+
""
);
// double
properties
.
setProperty
(
prefix
+
"rln_n_recenter"
,
this
.
rln_n_recenter
+
""
);
// int
properties
.
setProperty
(
prefix
+
"rln_sngl_rstr"
,
this
.
rln_sngl_rstr
+
""
);
// double
...
...
@@ -2409,6 +2414,7 @@ public class IntersceneMatchParameters {
if
(
properties
.
getProperty
(
prefix
+
"rln_use_neibs"
)!=
null
)
this
.
rln_use_neibs
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"rln_use_neibs"
));
if
(
properties
.
getProperty
(
prefix
+
"rln_neibs_fill"
)!=
null
)
this
.
rln_neibs_fill
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"rln_neibs_fill"
));
if
(
properties
.
getProperty
(
prefix
+
"rln_neib_radius"
)!=
null
)
this
.
rln_neib_radius
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"rln_neib_radius"
));
if
(
properties
.
getProperty
(
prefix
+
"rln_radius_frac"
)!=
null
)
this
.
rln_radius_frac
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"rln_radius_frac"
));
if
(
properties
.
getProperty
(
prefix
+
"rln_cent_radius"
)!=
null
)
this
.
rln_cent_radius
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"rln_cent_radius"
));
if
(
properties
.
getProperty
(
prefix
+
"rln_n_recenter"
)!=
null
)
this
.
rln_n_recenter
=
Integer
.
parseInt
(
properties
.
getProperty
(
prefix
+
"rln_n_recenter"
));
if
(
properties
.
getProperty
(
prefix
+
"rln_sngl_rstr"
)!=
null
)
this
.
rln_sngl_rstr
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"rln_sngl_rstr"
));
...
...
@@ -2860,6 +2866,8 @@ public class IntersceneMatchParameters {
imp
.
rln_use_neibs
=
this
.
rln_use_neibs
;
imp
.
rln_neibs_fill
=
this
.
rln_neibs_fill
;
imp
.
rln_neib_radius
=
this
.
rln_neib_radius
;
imp
.
rln_radius_frac
=
this
.
rln_radius_frac
;
imp
.
rln_cent_radius
=
this
.
rln_cent_radius
;
imp
.
rln_n_recenter
=
this
.
rln_n_recenter
;
imp
.
rln_sngl_rstr
=
this
.
rln_sngl_rstr
;
...
...
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