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
ba9466e1
Commit
ba9466e1
authored
Apr 17, 2024
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improving matching stability, added parameters
parent
f468c5ba
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
359 additions
and
59 deletions
+359
-59
ComboMatch.java
src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java
+55
-42
OrthoMapsCollection.java
...va/com/elphel/imagej/orthomosaic/OrthoMapsCollection.java
+217
-13
PairwiseOrthoMatch.java
...ava/com/elphel/imagej/orthomosaic/PairwiseOrthoMatch.java
+13
-1
IntersceneMatchParameters.java
...lphel/imagej/tileprocessor/IntersceneMatchParameters.java
+74
-3
No files found.
src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java
View file @
ba9466e1
...
...
@@ -150,7 +150,7 @@ public class ComboMatch {
int
zoom_lev
=
-
3
;
// 0; // +1 - zoom in twice, -1 - zoom out twice
// boolean show_map_stats = false;
boolean
show_combo
=
false
;
// true;
boolean
create_overlaps
=
false
;
// boolean show_combo_mask = false; // generate image mas (where it is defined)_
// boolean use_alt = false;
// boolean show_centers = true;
...
...
@@ -182,7 +182,7 @@ public class ComboMatch {
}
GenericJTabbedDialog
gd
=
new
GenericJTabbedDialog
(
"Set image pair"
,
1200
,
9
00
);
GenericJTabbedDialog
gd
=
new
GenericJTabbedDialog
(
"Set image pair"
,
1200
,
6
00
);
gd
.
addChoice
(
"Files list/data path (w/o extension):"
,
files_lists_paths
,
files_lists_paths
[
default_list_choice
]);
gd
.
addCheckbox
(
"Use saved maps collection"
,
use_saved_collection
,
"If false - use files list."
);
gd
.
addCheckbox
(
"Save maps collection"
,
save_collection
,
"Save maps collection to be able to restore."
);
...
...
@@ -218,7 +218,8 @@ public class ComboMatch {
"GPU image height"
);
// gd.addCheckbox ("Show transformation centers", show_centers, "Mark verticals from the UAS on the ground.");
// gd.addCheckbox ("Show statistics for ortho images", show_map_stats, "Generate and show statistics for ortho maps.");
gd
.
addCheckbox
(
"Show combo maps/stats"
,
show_combo
,
"Generate/save combo maps and stats."
);
gd
.
addCheckbox
(
"Show combo maps/stats"
,
show_combo
,
"Generate/save combo maps and stats."
);
gd
.
addCheckbox
(
"Create overlap pairs"
,
create_overlaps
,
"Create scene pairs overlaps."
);
// gd.addCheckbox ("Show combo image mask", show_combo_mask, "Display combo binary image.");
// gd.addCheckbox ("Show altitude combo image", use_alt, "Load and process altitude maps.");
gd
.
addNumericField
(
"Remove fraction of worst matches"
,
frac_remove
,
3
,
7
,
""
,
"When fitting scenes remove this fraction of worst match."
);
...
...
@@ -270,14 +271,8 @@ public class ComboMatch {
OrthoMap
.
setGPUWidthHeight
(
gpu_width
,
gpu_height
);
// show_centers = gd.getNextBoolean();
// show_map_stats = gd.getNextBoolean();
show_combo
=
gd
.
getNextBoolean
();
// show_combo_mask = gd.getNextBoolean();
// use_alt = gd.getNextBoolean();
// gpu_spair[0] = gd.getNextString();
// gpu_spair[1] = gd.getNextString();
show_combo
=
gd
.
getNextBoolean
();
create_overlaps
=
gd
.
getNextBoolean
();
frac_remove
=
gd
.
getNextNumber
();
metric_error
=
gd
.
getNextNumber
();
if
(
use_marked_image
)
{
// will only be used if found and asked
...
...
@@ -770,6 +765,10 @@ public class ComboMatch {
maps_collection
.
processComboMap
(
debugLevel
);
return
true
;
}
if
(
create_overlaps
)
{
boolean
ok
=
maps_collection
.
getIntersectedPairs
(
debugLevel
);
if
(!
ok
)
return
false
;
}
if
(
process_correlation
||
render_match
||
pattern_match
)
{
// int [] gpu_pair;
if
(
gpu_spair
==
null
)
{
...
...
@@ -792,7 +791,7 @@ public class ComboMatch {
String
[]
choices_all
=
new
String
[
choices
.
length
+
1
];
System
.
arraycopy
(
choices
,
0
,
choices_all
,
0
,
choices
.
length
);
choices_all
[
choices_all
.
length
-
1
]
=
"--- select a single image ---"
;
GenericJTabbedDialog
gdc
=
new
GenericJTabbedDialog
(
"Select image pair"
,
1200
,
4
00
);
GenericJTabbedDialog
gdc
=
new
GenericJTabbedDialog
(
"Select image pair"
,
1200
,
1
00
);
int
num_choice_lines
=
50
;
gdc
.
addChoice
(
"Image pair:"
,
choices_all
,
...
...
@@ -804,25 +803,23 @@ public class ComboMatch {
if
(
pair
>=
choices
.
length
)
{
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,
gpu_spair
=
maps_collection
.
selectTwoScenes
(
default_choice1
,
// int default_choice,
num_scene_lines
);
// int num_choice_lines)
if
(
scene_name1
==
null
)
{
if
(
gpu_spair
==
null
)
{
return
false
;
}
}
else
{
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
;
}
gpu_spair
=
new
String
[]
{
scene_name
,
scene_name1
};
}
else
{
// pattern match - single image
gpu_spair
=
new
String
[]
{
scene_name
};
}
}
else
{
...
...
@@ -913,7 +910,7 @@ public class ComboMatch {
num_tries_fit
=
0
;
update_match
=
false
;
}
debugLevel
=
0
;
//
debugLevel = 0;
boolean
batch_mode
=
true
;
// false; // true;
boolean
ignore_prev_rms
=
true
;
Rectangle
woi
=
new
Rectangle
();
// used to return actual woi from correlateOrthoPair()
...
...
@@ -976,6 +973,9 @@ public class ComboMatch {
System
.
out
.
println
(
"adjusted affines[1] for a pair: "
+
gpu_spair
[
0
]+
"/"
+
gpu_spair
[
1
]);
System
.
out
.
println
(
"[["
+
affines
[
1
][
0
][
0
]+
","
+
affines
[
1
][
0
][
1
]+
","
+
affines
[
1
][
0
][
2
]+
"],"
);
System
.
out
.
println
(
" ["
+
affines
[
1
][
1
][
0
]+
","
+
affines
[
1
][
1
][
1
]+
","
+
affines
[
1
][
1
][
2
]+
"]]"
);
if
(
pmatch
!=
null
)
{
System
.
out
.
println
(
"RMSE="
+
pmatch
.
rms
);
}
System
.
out
.
println
();
}
}
...
...
@@ -1040,45 +1040,57 @@ public class ComboMatch {
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
;
boolean
use_existing_pair
=
clt_parameters
.
imp
.
ospir_existing
;
// false
boolean
invert_exixting_pair
=
clt_parameters
.
imp
.
ospir_invert
;
// false
double
search_step
=
clt_parameters
.
imp
.
ospir_step
;
// 8.0; // pix
double
search_range
=
clt_parameters
.
imp
.
ospir_range
;
// 50.0; // pix
double
good_rms
=
clt_parameters
.
imp
.
ospir_good_rms
;
// 0.27; //
double
max_rms
=
clt_parameters
.
imp
.
ospir_max_rms
;
// 0.35; //
int
min_overlap
=
clt_parameters
.
imp
.
ospir_overlap
;
// 3000; // do not try to match if there is too small overlap (scaled pixels)
int
num_iter_lma
=
clt_parameters
.
imp
.
ospir_num_iter
;
// 5;
boolean
ignore_rms
=
clt_parameters
.
imp
.
ospir_ignore_rms
;
// false
int
spiral_debug
=
clt_parameters
.
imp
.
ospir_debug
;
// -3;
GenericJTabbedDialog
gd
=
new
GenericJTabbedDialog
(
"Setup SpiralMatch"
,
1200
,
300
);
if
(
pairwiseOrthoMatch
!=
null
)
{
gd
.
addCheckbox
(
"Use existing image pair"
,
use_exixting_pair
,
"Use existing affine settings for this pair, do not use spiral search."
);
gd
.
addCheckbox
(
"Use existing image pair"
,
use_existing_pair
,
"Use existing affine settings for this pair, do not use spiral search."
);
}
else
{
use_existing_pair
=
false
;
}
if
(
inv_match
!=
null
)
{
gd
.
addCheckbox
(
"Invert existing image pair"
,
invert_exixting_pair
,
"Invert existing image pair affine transform, do not use spiral search."
);
}
else
{
invert_exixting_pair
=
false
;
}
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
(
"RMSE to end search"
,
good_rms
,
3
,
7
,
"scaled pix"
,
"Maximal RMSE to consider match, in scaled pixels."
);
gd
.
addNumericField
(
"Satisfactory RMSE"
,
max_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
.
addCheckbox
(
"Ignore worsening RMSE"
,
ignore_rms
,
"Ignore worsening/not improving RMSE during spiral search."
);
gd
.
addNumericField
(
"Spiral search debug level"
,
spiral_debug
,
0
,
3
,
""
,
"Debug level during Spiral search."
);
gd
.
showDialog
();
if
(
gd
.
wasCanceled
())
return
null
;
if
(
pairwiseOrthoMatch
!=
null
)
{
use_exi
x
ting_pair
=
gd
.
getNextBoolean
();
use_exi
s
ting_pair
=
gd
.
getNextBoolean
();
}
if
(
inv_match
!=
null
)
{
invert_exixting_pair
=
gd
.
getNextBoolean
();
}
search_step
=
gd
.
getNextNumber
();
search_range
=
gd
.
getNextNumber
();
maximal_rms
=
gd
.
getNextNumber
();
good_rms
=
gd
.
getNextNumber
();
max_rms
=
gd
.
getNextNumber
();
min_overlap
=
(
int
)
gd
.
getNextNumber
();
num_iter_lma
=
(
int
)
gd
.
getNextNumber
();
if
(
use_exixting_pair
)
{
ignore_rms
=
gd
.
getNextBoolean
();
spiral_debug
=
(
int
)
gd
.
getNextNumber
();
if
(
use_existing_pair
)
{
if
(
invert_exixting_pair
)
{
System
.
out
.
println
(
"Both direct and inverted matches are selected, using direct match"
);
}
...
...
@@ -1095,7 +1107,6 @@ public class ComboMatch {
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,
...
...
@@ -1103,10 +1114,12 @@ public class ComboMatch {
initial_zoom
,
// int zoom_lev,
search_step
,
// double pix_step,
search_range
,
// double pix_range,
maximal_rms
,
// double need_rms,
good_rms
,
// double good_rms,
max_rms
,
// double max_rms,
num_iter_lma
,
// int num_tries, // = 5
min_overlap
,
// int min_overlap, // 3000
debugLevel
);
// int debugLevel){
ignore_rms
,
// boolean ignore_rms,
spiral_debug
);
// int debugLevel){
return
pairwiseOrthoMatch
;
}
...
...
src/main/java/com/elphel/imagej/orthomosaic/OrthoMapsCollection.java
View file @
ba9466e1
...
...
@@ -22,6 +22,7 @@ import java.util.ArrayList;
import
java.util.Arrays
;
import
java.util.Calendar
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.concurrent.atomic.AtomicInteger
;
...
...
@@ -987,7 +988,6 @@ public class OrthoMapsCollection implements Serializable{
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
,
...
...
@@ -995,15 +995,16 @@ public class OrthoMapsCollection implements Serializable{
int
zoom_lev
,
double
pix_step
,
double
pix_range
,
double
need_rms
,
double
good_rms
,
double
max_rms
,
int
num_tries
,
// = 5
int
min_overlap
,
// = 5
boolean
ignore_rms
,
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)
...
...
@@ -1015,7 +1016,8 @@ public class OrthoMapsCollection implements Serializable{
zoom_lev
);
// int zoom_lev);
double
max_std
=
0.5
;
// maximal standard deviation to limit center area
double
min_std_rad
=
2.0
;
// minimal radius of the central area (if less - fail)
int
best_nx
=
-
1
,
best_ny
=
-
1
;
PairwiseOrthoMatch
best_pom
=
null
;
while
((
Math
.
abs
(
nx
)
<=
nabs
)
&&
(
Math
.
abs
(
ny
)
<=
nabs
))
{
for
(
int
i
=
0
;
i
<
affines_init
.
length
;
i
++)
{
System
.
arraycopy
(
affines_init
[
1
][
i
],
0
,
affine1
[
i
],
0
,
affine1
[
i
].
length
);
...
...
@@ -1032,7 +1034,7 @@ public class OrthoMapsCollection implements Serializable{
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,
ignore_
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,
...
...
@@ -1042,15 +1044,20 @@ public class OrthoMapsCollection implements Serializable{
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)
debugLevel
-
4
);
// 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
<
nee
d_rms
)
{
if
(
pairwiseOrthoMatch
.
rms
<
goo
d_rms
)
{
break
;
}
if
(!
Double
.
isNaN
(
pairwiseOrthoMatch
.
rms
)
&&
((
best_pom
==
null
)
||
!(
best_pom
.
rms
<=
pairwiseOrthoMatch
.
rms
)))
{
best_pom
=
pairwiseOrthoMatch
.
clone
();
best_nx
=
nx
;
best_ny
=
ny
;
}
// update nx, ny
if
((
nx
>
ny
)
&&
(
nx
>
-
ny
)){
ny
++;
...
...
@@ -1062,10 +1069,21 @@ public class OrthoMapsCollection implements Serializable{
nx
++;
}
}
if
(!(
pairwiseOrthoMatch
.
rms
<
need_rms
))
{
// failed
return
null
;
if
(
pairwiseOrthoMatch
.
rms
<
good_rms
)
{
// failed
return
pairwiseOrthoMatch
;
// pairwiseOrthoMatch.affine will have adjusted affine[1]
}
if
((
best_pom
!=
null
)
&&
(
best_pom
.
rms
<=
max_rms
))
{
if
(
debugLevel
>
-
4
)
{
System
.
out
.
println
(
"SpiralMatch(): best RMSE="
+
best_pom
.
rms
+
" < "
+
max_rms
+
" for nx = "
+
best_nx
+
", ny="
+
best_ny
+
", using it."
);
}
return
best_pom
;
}
if
(
debugLevel
>
-
4
)
{
System
.
out
.
println
(
"SpiralMatch(): Failed to find a good match candidate. Best RMSE="
+
((
best_pom
!=
null
)?
best_pom
.
rms
:
"N/A"
)+
", max_rms= "
+
max_rms
+
""
);
}
return
pairwiseOrthoMatch
;
// pairwiseOrthoMatch.affine will have adjusted affine[1]
return
null
;
// pairwiseOrthoMatch.affine will have adjusted affine[1]
}
...
...
@@ -1132,6 +1150,7 @@ public class OrthoMapsCollection implements Serializable{
boolean
show_vf
,
double
[][]
ground_planes
,
// null or double[2] - will return ground planes:
int
debugLevel
){
double
center_radius_change
=
1.5
;
// if increases by more than this, disregard RMSE worsening
boolean
show_lma_dbg
=
!
batch_mode
&&
(
debugLevel
>
1
);
if
(
woi
==
null
)
{
woi
=
new
Rectangle
();
...
...
@@ -1268,6 +1287,7 @@ public class OrthoMapsCollection implements Serializable{
double
[][]
jtj
=
null
;
double
rms
=
Double
.
NaN
;
double
last_center_radius
=
0
;
double
previous_center_radius
=
1.0
;
for
(
int
ntry
=
0
;
ntry
<
num_tries
;
ntry
++)
{
if
(!
batch_mode
)
{
if
(
debugLevel
>-
3
)
{
...
...
@@ -1508,6 +1528,13 @@ public class OrthoMapsCollection implements Serializable{
debugLevel
);
// final int debug_level)
last_center_radius
=
orthoPairLMA
.
getCenterRadius
();
double
center_radius_increase
=
Double
.
isInfinite
(
previous_center_radius
)?
(
Double
.
isInfinite
(
last_center_radius
)?
1
:
0
):
last_center_radius
/
previous_center_radius
;
if
((
ntry
==
0
)
&&
Double
.
isInfinite
(
last_center_radius
))
{
center_radius_increase
=
1.0
;
// if starts with infinity - no increase
}
if
((
min_std_rad
>
0
)
&&
(
last_center_radius
<
1
))
{
if
(
debugLevel
>-
3
)
{
System
.
out
.
println
(
"correlateOrthoPair(): center_radius="
+
...
...
@@ -1550,7 +1577,7 @@ public class OrthoMapsCollection implements Serializable{
if
(
rms
>
prev_rms
)
{
if
(
debugLevel
>
-
3
)
{
if
((
rms
-
prev_rms
)/
prev_rms
<
rel_improve
)
{
System
.
out
.
println
(
"LMA RMSE worsened, but less than improvement threshold: new"
+
rms
+
" ("
+
orthoPairLMA
.
getInitialRms
()+
"), prev="
+
prev_rms
);
System
.
out
.
println
(
"LMA RMSE worsened, but less than improvement threshold: new
"
+
rms
+
" ("
+
orthoPairLMA
.
getInitialRms
()+
"), prev="
+
prev_rms
);
}
else
{
System
.
out
.
println
(
"LMA RMSE worsened: new "
+
rms
+
" ("
+
orthoPairLMA
.
getInitialRms
()+
"), prev="
+
prev_rms
);
}
...
...
@@ -1560,7 +1587,15 @@ public class OrthoMapsCollection implements Serializable{
System
.
out
.
println
(
"Will continue, as ignore_prev_rms is set"
);
}
}
else
{
break
;
if
(
center_radius_increase
>
center_radius_change
)
{
if
(
debugLevel
>
-
3
)
{
System
.
out
.
println
(
"Will continue, as center_radius increased from "
+
previous_center_radius
+
" to "
+
last_center_radius
+
" (more than "
+
center_radius_change
+
"x)."
);
}
}
else
{
break
;
}
}
}
affines_gpu
[
1
]=
OrthoMap
.
combineAffine
(
affines_gpu
[
1
],
orthoPairLMA
.
getAffine
());
...
...
@@ -1574,10 +1609,31 @@ public class OrthoMapsCollection implements Serializable{
System
.
out
.
println
(
"Will continue, as ignore_prev_rms is set"
);
}
}
else
{
break
;
if
(
center_radius_increase
>
center_radius_change
)
{
if
(
debugLevel
>
-
3
)
{
System
.
out
.
println
(
"Will continue, as center_radius increased from "
+
previous_center_radius
+
" to "
+
last_center_radius
+
" (more than "
+
center_radius_change
+
"x)."
);
}
}
else
{
break
;
}
}
}
if
(
center_radius_increase
>
center_radius_change
)
{
num_tries
++;
if
(
debugLevel
>
-
2
)
{
System
.
out
.
println
(
"Increasing num_tries to "
+
num_tries
+
", as center_radius increased from "
+
previous_center_radius
+
" to "
+
last_center_radius
+
" (more than "
+
center_radius_change
+
"x)."
);
}
}
prev_rms
=
rms
;
previous_center_radius
=
last_center_radius
;
}
// for (int ntry = 0; ntry < num_tries; ntry++) {
if
((
min_std_rad
>
0
)
&&
(
last_center_radius
<
min_std_rad
))
{
...
...
@@ -3727,6 +3783,42 @@ public class OrthoMapsCollection implements Serializable{
int
scene_number
=
gd
.
getNextChoiceIndex
();
return
ortho_maps
[
scene_number
].
getName
();
}
public
String
[]
selectTwoScenes
(
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
++)
{
OrthoMap
map
=
ortho_maps
[
indx
];
LocalDateTime
ldt
=
map
.
getLocalDateTime
();
ZonedDateTime
zonedUTC
=
ldt
.
atZone
(
ZoneId
.
of
(
"UTC"
));
// that time is UTC
ZonedDateTime
zonedDateTime
=
zonedUTC
.
withZoneSameInstant
(
ZoneId
.
of
(
"Europe/Kyiv"
));
String
sdt
=
zonedDateTime
.
format
(
formatter
);
String
name
=
map
.
getName
();
double
agl
=
map
.
getAGL
();
lines
[
indx
]=
String
.
format
(
"%3d %17s %26s %6.2f"
,
indx
,
name
,
sdt
,
agl
);
}
GenericJTabbedDialog
gd
=
new
GenericJTabbedDialog
(
"Select two image scenes"
,
1200
,
150
);
for
(
int
num_scene
=
0
;
num_scene
<
2
;
num_scene
++)
{
gd
.
addChoice
(
fs
[
num_scene
]+
" image:"
,
lines
,
lines
[
default_choice
],
"Select "
+
fs
[
num_scene
]+
" scene"
,
num_choice_lines
);
}
gd
.
showDialog
();
if
(
gd
.
wasCanceled
())
return
null
;
String
[]
names
=
new
String
[
2
];
for
(
int
num_scene
=
0
;
num_scene
<
2
;
num_scene
++)
{
int
scene_number
=
gd
.
getNextChoiceIndex
();
names
[
num_scene
]
=
ortho_maps
[
scene_number
].
getName
();
}
return
names
;
}
public
String
[]
getScenesList
()
{
String
[]
lines
=
new
String
[
ortho_maps
.
length
];
...
...
@@ -3806,6 +3898,84 @@ public class OrthoMapsCollection implements Serializable{
return
indices
;
}
public
boolean
getIntersectedPairs
(
int
debugLevel
)
{
int
[]
indices
=
getScenesSelection
(
null
,
// boolean select_all,
" to find intersects"
);
// String purpose)
if
(
indices
==
null
)
{
return
false
;
}
int
zoom_lev
=
-
5
;
double
min_overlap
=
0.25
;
boolean
bounds_to_indices
=
true
;
GenericJTabbedDialog
gd
=
new
GenericJTabbedDialog
(
"Combo map/stats generation"
,
1200
,
1000
);
gd
.
addNumericField
(
"Zoom level"
,
zoom_lev
,
0
,
4
,
""
,
"Zoom level: +1 - zoom in twice, -1 - zoom out twice"
);
gd
.
addNumericField
(
"Minimal overlap"
,
min_overlap
,
3
,
7
,
""
,
"Minimal overlap as a fraction of the smaller image."
);
gd
.
showDialog
();
if
(
gd
.
wasCanceled
())
return
false
;
zoom_lev
=
(
int
)
gd
.
getNextNumber
();
min_overlap
=
gd
.
getNextNumber
();
int
[]
wh
=
new
int
[
2
];
int
[]
origin
=
new
int
[
2
];
double
[][]
centers
=
new
double
[
indices
.
length
][];
double
[][]
dmulti
=
renderMultiDouble
(
null
,
// double [][] ground_planes, // null - images, non-null altitudes. use new double[2][3] for old way alt
indices
,
// int [] indices, // null or which indices to use (normally just 2 for pairwise comparison)
bounds_to_indices
,
// boolean bounds_to_indices,
null
,
// affines, // double [][][] affines, // null or [indices.length][2][3]
null
,
// warp, // FineXYCorr warp,,
zoom_lev
,
// int zoom_level,
wh
,
// int [] wh,
origin
,
// int [] origin){ // maps[0] as a reference
centers
);
// double [][] centers)
double
[]
overlaps
=
getFracOverlaps
(
dmulti
);
// final double [][] dmulti) {
int
num_overlaps_all
=
0
,
num_overlaps_sel
=
0
;
boolean
[][]
intersects
=
new
boolean
[
dmulti
.
length
][
dmulti
.
length
];
for
(
int
i
=
0
;
i
<
overlaps
.
length
;
i
++)
if
(!
Double
.
isNaN
(
overlaps
[
i
])){
num_overlaps_all
++;
if
(
overlaps
[
i
]
>=
min_overlap
)
{
num_overlaps_sel
++;
int
row
=
i
/
dmulti
.
length
;
int
col
=
i
%
dmulti
.
length
;
intersects
[
row
][
col
]
=
true
;
}
}
int
[]
groups
=
new
int
[
dmulti
.
length
];
for
(
int
i
=
0
;
i
<
groups
.
length
;
i
++)
{
groups
[
i
]
=
i
;
}
for
(
int
i
=
0
;
i
<
(
groups
.
length
-
1
);
i
++)
{
for
(
int
j
=
i
+
1
;
j
<
groups
.
length
;
j
++)
if
(
groups
[
j
]
!=
groups
[
i
]){
int
g0
=
groups
[
i
];
int
g1
=
groups
[
j
];
for
(
int
k
=
0
;
k
<
groups
.
length
;
k
++)
{
if
(
groups
[
k
]
==
g1
)
{
groups
[
k
]
=
g0
;
}
}
}
}
HashSet
<
Integer
>
hs
=
new
HashSet
<
Integer
>();
for
(
int
i:
groups
)
{
hs
.
add
(
i
);
}
System
.
out
.
println
(
"getIntersectedPairs(): num_overlaps_all="
+
num_overlaps_all
+
", num_overlaps_sel="
+
num_overlaps_sel
+
", number of disconnected groups="
+
hs
.
size
());
if
(
debugLevel
>
0
)
{
ShowDoubleFloatArrays
.
showArrays
(
overlaps
,
"Overlaps"
);
}
return
true
;
}
public
boolean
processComboMap
(
int
debugLevel
)
{
int
[]
indices
=
getScenesSelection
(
...
...
@@ -4331,4 +4501,38 @@ public class OrthoMapsCollection implements Serializable{
}
}
public
static
double
[]
getFracOverlaps
(
final
double
[][]
dmulti
)
{
final
double
[]
overlaps
=
new
double
[
dmulti
.
length
*
dmulti
.
length
];
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
();
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
public
void
run
()
{
for
(
int
nscene
=
ai
.
getAndIncrement
();
nscene
<
(
dmulti
.
length
-
1
);
nscene
=
ai
.
getAndIncrement
())
{
double
[]
data0
=
dmulti
[
nscene
];
int
num0
=
0
;
for
(
int
i
=
0
;
i
<
data0
.
length
;
i
++)
if
(!
Double
.
isNaN
(
data0
[
i
]))
{
num0
++;
}
for
(
int
nscene1
=
nscene
+
1
;
nscene1
<
dmulti
.
length
;
nscene1
++)
{
double
[]
data1
=
dmulti
[
nscene1
];
int
num1
=
0
,
num_intersect
=
0
;
for
(
int
i
=
0
;
i
<
data0
.
length
;
i
++)
if
(!
Double
.
isNaN
(
data1
[
i
]))
{
num1
++;
if
(!
Double
.
isNaN
(
data0
[
i
]))
{
num_intersect
++;
}
}
overlaps
[
nscene
*
dmulti
.
length
+
nscene1
]
=
(
1.0
*
num_intersect
)/
Math
.
min
(
num0
,
num1
);
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
return
overlaps
;
}
}
src/main/java/com/elphel/imagej/orthomosaic/PairwiseOrthoMatch.java
View file @
ba9466e1
...
...
@@ -23,7 +23,19 @@ public class PairwiseOrthoMatch implements Serializable {
this
.
jtj
=
jtj
;
this
.
zoom_lev
=
zoom_lev
;
}
public
PairwiseOrthoMatch
clone
()
{
double
[][]
affine
=
{
this
.
affine
[
0
].
clone
(),
this
.
affine
[
1
].
clone
()};
double
[][]
jtj
=
new
double
[
this
.
jtj
.
length
][];
for
(
int
i
=
0
;
i
<
this
.
jtj
.
length
;
i
++)
{
jtj
[
i
]
=
this
.
jtj
[
i
].
clone
();
}
PairwiseOrthoMatch
pom
=
new
PairwiseOrthoMatch
(
affine
,
jtj
,
this
.
rms
,
this
.
zoom_lev
);
return
pom
;
}
public
PairwiseOrthoMatch
getInverse
(
double
[]
rd
)
{
double
[][]
affine
=
OrthoMap
.
invertAffine
(
getAffine
());
PairwiseOrthoMatch
inverted_match
=
new
PairwiseOrthoMatch
(
...
...
src/main/java/com/elphel/imagej/tileprocessor/IntersceneMatchParameters.java
View file @
ba9466e1
...
...
@@ -107,6 +107,20 @@ public class IntersceneMatchParameters {
public
double
rln_sngl_rstr
=
0.3
;
// minimal single-tile phase correlation maximums relative to max str
public
double
rln_neib_rstr
=
0.4
;
// minimal neighbors phase correlation maximums relative to max str
public
boolean
ospir_existing
=
false
;
// use existing pair
public
boolean
ospir_invert
=
false
;
// invert existing pair
public
double
ospir_step
=
8.0
;
// spiral step (pix)
public
double
ospir_range
=
50.0
;
// spiral radius (pix)
public
double
ospir_good_rms
=
0.27
;
// maximal immediately acceptable LMA RMS for the initial search
public
double
ospir_max_rms
=
0.35
;
// maximal acceptable LMA RMS - best during initial search
public
int
ospir_overlap
=
3000
;
// do not try to match if there is too small overlap (scaled pixels)
public
int
ospir_num_iter
=
5
;
// maximal number of LMA iterations during initial search
public
boolean
ospir_ignore_rms
=
false
;
// ignore RMS worsening during spiral search
public
int
ospir_debug
=
0
;
// Debug level during sppiral search
public
double
[]
getImsMountATR
()
{
return
new
double
[]
{
ims_mount_atr
[
0
]
*
Math
.
PI
/
180
,
...
...
@@ -694,6 +708,20 @@ public class IntersceneMatchParameters {
"Minimal single-tile phase correlation maximums relative to maximal strength."
);
gd
.
addNumericField
(
"Minimal relative strength (neighbors)"
,
this
.
rln_neib_rstr
,
5
,
8
,
""
,
"Minimal neighbors phase correlation maximums relative to maximal strength."
);
gd
.
addMessage
(
"Initial spiral search for image matching"
);
gd
.
addCheckbox
(
"Use existing image pair"
,
this
.
ospir_existing
,
"Use existing affine settings for this pair, do not use spiral search."
);
gd
.
addCheckbox
(
"Invert existing image pair"
,
this
.
ospir_invert
,
"Invert existing image pair affine transform, do not use spiral search."
);
gd
.
addNumericField
(
"Spiral search step"
,
this
.
ospir_step
,
3
,
7
,
"scaled pix"
,
"Distance between spiral search probes, in scaled pixels."
);
gd
.
addNumericField
(
"Spiral search radius"
,
this
.
ospir_range
,
3
,
7
,
"scaled pix"
,
"Maximal radius of the spiral search, in scaled pixels."
);
gd
.
addNumericField
(
"RMSE to end search"
,
this
.
ospir_good_rms
,
3
,
7
,
"scaled pix"
,
"Maximal RMSE to consider match, in scaled pixels."
);
gd
.
addNumericField
(
"Satisfactory RMSE"
,
this
.
ospir_max_rms
,
3
,
7
,
"scaled pix"
,
"Maximal RMSE to consider match, in scaled pixels."
);
gd
.
addNumericField
(
"Minimal overlap"
,
this
.
ospir_overlap
,
0
,
4
,
"scaled pix ^ 2"
,
"Minimal overlap area in square scaled pixels."
);
gd
.
addNumericField
(
"LMA iterations"
,
this
.
ospir_num_iter
,
0
,
2
,
""
,
"Number of LMA iterations during spiral search."
);
gd
.
addCheckbox
(
"Ignore worsening RMSE"
,
this
.
ospir_ignore_rms
,
"Ignore worsening/not improving RMSE during spiral search."
);
gd
.
addNumericField
(
"Spiral search debug level"
,
this
.
ospir_debug
,
0
,
3
,
""
,
"Debug level during Spiral search."
);
//
gd
.
addTab
(
"Scene Series"
,
"Processing series of scenes and multi-series sets"
);
gd
.
addMessage
(
"Build series options"
);
...
...
@@ -1534,7 +1562,18 @@ public class IntersceneMatchParameters {
this
.
rln_n_recenter
=
(
int
)
gd
.
getNextNumber
();
this
.
rln_sngl_rstr
=
gd
.
getNextNumber
();
this
.
rln_neib_rstr
=
gd
.
getNextNumber
();
this
.
ospir_existing
=
gd
.
getNextBoolean
();
this
.
ospir_invert
=
gd
.
getNextBoolean
();
this
.
ospir_step
=
gd
.
getNextNumber
();
this
.
ospir_range
=
gd
.
getNextNumber
();
this
.
ospir_good_rms
=
gd
.
getNextNumber
();
this
.
ospir_max_rms
=
gd
.
getNextNumber
();
this
.
ospir_overlap
=
(
int
)
gd
.
getNextNumber
();
this
.
ospir_num_iter
=
(
int
)
gd
.
getNextNumber
();
this
.
ospir_ignore_rms
=
gd
.
getNextBoolean
();
this
.
ospir_debug
=
(
int
)
gd
.
getNextNumber
();
this
.
center_reference
=
gd
.
getNextBoolean
();
this
.
overlap_sequences
=
gd
.
getNextBoolean
();
this
.
reset_photometric
=
gd
.
getNextBoolean
();
...
...
@@ -1994,7 +2033,18 @@ public class IntersceneMatchParameters {
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
properties
.
setProperty
(
prefix
+
"rln_neib_rstr"
,
this
.
rln_neib_rstr
+
""
);
// double
properties
.
setProperty
(
prefix
+
"rln_neib_rstr"
,
this
.
rln_neib_rstr
+
""
);
properties
.
setProperty
(
prefix
+
"ospir_existing"
,
this
.
ospir_existing
+
""
);
// boolean
properties
.
setProperty
(
prefix
+
"ospir_invert"
,
this
.
ospir_invert
+
""
);
// boolean
properties
.
setProperty
(
prefix
+
"ospir_step"
,
this
.
ospir_step
+
""
);
// double
properties
.
setProperty
(
prefix
+
"ospir_range"
,
this
.
ospir_range
+
""
);
// double
properties
.
setProperty
(
prefix
+
"ospir_good_rms"
,
this
.
ospir_good_rms
+
""
);
// double
properties
.
setProperty
(
prefix
+
"ospir_max_rms"
,
this
.
ospir_max_rms
+
""
);
// double
properties
.
setProperty
(
prefix
+
"ospir_overlap"
,
this
.
ospir_overlap
+
""
);
// int
properties
.
setProperty
(
prefix
+
"ospir_num_iter"
,
this
.
ospir_num_iter
+
""
);
// int
properties
.
setProperty
(
prefix
+
"ospir_ignore_rms"
,
this
.
ospir_ignore_rms
+
""
);
// boolean
properties
.
setProperty
(
prefix
+
"ospir_debug"
,
this
.
ospir_debug
+
""
);
// int
properties
.
setProperty
(
prefix
+
"center_reference"
,
this
.
center_reference
+
""
);
// boolean
properties
.
setProperty
(
prefix
+
"overlap_sequences"
,
this
.
overlap_sequences
+
""
);
// boolean
...
...
@@ -2420,6 +2470,17 @@ public class IntersceneMatchParameters {
if
(
properties
.
getProperty
(
prefix
+
"rln_sngl_rstr"
)!=
null
)
this
.
rln_sngl_rstr
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"rln_sngl_rstr"
));
if
(
properties
.
getProperty
(
prefix
+
"rln_neib_rstr"
)!=
null
)
this
.
rln_neib_rstr
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"rln_neib_rstr"
));
if
(
properties
.
getProperty
(
prefix
+
"ospir_existing"
)!=
null
)
this
.
ospir_existing
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"ospir_existing"
));
if
(
properties
.
getProperty
(
prefix
+
"ospir_invert"
)!=
null
)
this
.
ospir_invert
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"ospir_invert"
));
if
(
properties
.
getProperty
(
prefix
+
"ospir_step"
)!=
null
)
this
.
ospir_step
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"ospir_step"
));
if
(
properties
.
getProperty
(
prefix
+
"ospir_range"
)!=
null
)
this
.
ospir_range
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"ospir_range"
));
if
(
properties
.
getProperty
(
prefix
+
"ospir_good_rms"
)!=
null
)
this
.
ospir_good_rms
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"ospir_good_rms"
));
if
(
properties
.
getProperty
(
prefix
+
"ospir_max_rms"
)!=
null
)
this
.
ospir_max_rms
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"ospir_max_rms"
));
if
(
properties
.
getProperty
(
prefix
+
"ospir_overlap"
)!=
null
)
this
.
ospir_overlap
=
Integer
.
parseInt
(
properties
.
getProperty
(
prefix
+
"ospir_overlap"
));
if
(
properties
.
getProperty
(
prefix
+
"ospir_num_iter"
)!=
null
)
this
.
ospir_num_iter
=
Integer
.
parseInt
(
properties
.
getProperty
(
prefix
+
"ospir_num_iter"
));
if
(
properties
.
getProperty
(
prefix
+
"ospir_ignore_rms"
)!=
null
)
this
.
ospir_ignore_rms
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"ospir_ignore_rms"
));
if
(
properties
.
getProperty
(
prefix
+
"ospir_debug"
)!=
null
)
this
.
ospir_debug
=
Integer
.
parseInt
(
properties
.
getProperty
(
prefix
+
"ospir_debug"
));
if
(
properties
.
getProperty
(
prefix
+
"center_reference"
)!=
null
)
this
.
center_reference
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"center_reference"
));
if
(
properties
.
getProperty
(
prefix
+
"overlap_sequences"
)!=
null
)
this
.
overlap_sequences
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"overlap_sequences"
));
if
(
properties
.
getProperty
(
prefix
+
"reset_photometric"
)!=
null
)
this
.
reset_photometric
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"reset_photometric"
));
...
...
@@ -2871,7 +2932,17 @@ public class IntersceneMatchParameters {
imp
.
rln_cent_radius
=
this
.
rln_cent_radius
;
imp
.
rln_n_recenter
=
this
.
rln_n_recenter
;
imp
.
rln_sngl_rstr
=
this
.
rln_sngl_rstr
;
imp
.
rln_neib_rstr
=
this
.
rln_neib_rstr
;
imp
.
rln_neib_rstr
=
this
.
rln_neib_rstr
;
imp
.
ospir_existing
=
this
.
ospir_existing
;
imp
.
ospir_step
=
this
.
ospir_step
;
imp
.
ospir_range
=
this
.
ospir_range
;
imp
.
ospir_good_rms
=
this
.
ospir_good_rms
;
imp
.
ospir_max_rms
=
this
.
ospir_max_rms
;
imp
.
ospir_overlap
=
this
.
ospir_overlap
;
imp
.
ospir_num_iter
=
this
.
ospir_num_iter
;
imp
.
ospir_ignore_rms
=
this
.
ospir_ignore_rms
;
imp
.
ospir_debug
=
this
.
ospir_debug
;
imp
.
center_reference
=
this
.
center_reference
;
imp
.
overlap_sequences
=
this
.
overlap_sequences
;
...
...
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