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
25c2bbf2
Commit
25c2bbf2
authored
Mar 19, 2024
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Detect mines with morning/evenimg pair
parent
2ebcdb9c
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
1247 additions
and
54 deletions
+1247
-54
ComboMatch.java
src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java
+14
-8
ItemMatch.java
src/main/java/com/elphel/imagej/orthomosaic/ItemMatch.java
+97
-0
ItemPatternMatch.java
.../java/com/elphel/imagej/orthomosaic/ItemPatternMatch.java
+52
-0
ObjectLocation.java
...in/java/com/elphel/imagej/orthomosaic/ObjectLocation.java
+236
-0
OrthoMapsCollection.java
...va/com/elphel/imagej/orthomosaic/OrthoMapsCollection.java
+848
-46
No files found.
src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java
View file @
25c2bbf2
...
@@ -104,7 +104,7 @@ public class ComboMatch {
...
@@ -104,7 +104,7 @@ public class ComboMatch {
"/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_19_sep13_25-50-75-100m"
,
"/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_19_sep13_25-50-75-100m"
,
"/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75"
,
"/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75"
,
"/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_sep12-50m"
};
"/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_sep12-50m"
};
int
default_list_choice
=
0
;
// files_lists_paths.length-1;
// String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75.list";
// String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75.list";
// String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75.data";
// String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75.data";
//maps_nov3_50-75
//maps_nov3_50-75
...
@@ -148,10 +148,11 @@ public class ComboMatch {
...
@@ -148,10 +148,11 @@ public class ComboMatch {
boolean
use_saved_collection
=
true
;
// false;
boolean
use_saved_collection
=
true
;
// false;
boolean
save_collection
=
true
;
boolean
save_collection
=
true
;
boolean
process_correlation
=
true
;
// use false to save new version of data
boolean
process_correlation
=
true
;
// use false to save new version of data
int
num_tries_fit
=
10
;
boolean
update_match
=
true
;
// use false to save new version of data
boolean
update_match
=
true
;
// use false to save new version of data
boolean
render_match
=
true
;
boolean
render_match
=
false
;
//
true;
boolean
pattern_match
=
false
;
boolean
pattern_match
=
true
;
//
false;
boolean
bounds_to_indices
=
true
;
boolean
bounds_to_indices
=
true
;
int
temp_mode
=
1
;
int
temp_mode
=
1
;
...
@@ -166,10 +167,13 @@ public class ComboMatch {
...
@@ -166,10 +167,13 @@ public class ComboMatch {
GenericJTabbedDialog
gd
=
new
GenericJTabbedDialog
(
"Set image pair"
,
1200
,
900
);
GenericJTabbedDialog
gd
=
new
GenericJTabbedDialog
(
"Set image pair"
,
1200
,
900
);
gd
.
addChoice
(
"Files list/data path (w/o extension):"
,
files_lists_paths
,
files_lists_paths
[
files_lists_paths
.
length
-
1
]);
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
(
"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."
);
gd
.
addCheckbox
(
"Save maps collection"
,
save_collection
,
"Save maps collection to be able to restore."
);
gd
.
addCheckbox
(
"Process correlations"
,
process_correlation
,
"false to skip to just regenerate new save file."
);
gd
.
addCheckbox
(
"Process correlations"
,
process_correlation
,
"false to skip to just regenerate new save file."
);
// int num_tries_fit = 10;
gd
.
addNumericField
(
"Num tries fit"
,
num_tries_fit
,
0
,
4
,
""
,
"Try matching images this number of times"
);
gd
.
addCheckbox
(
"Update match if calculated"
,
update_match
,
"Will update correlation match for a pair if found."
);
gd
.
addCheckbox
(
"Update match if calculated"
,
update_match
,
"Will update correlation match for a pair if found."
);
gd
.
addCheckbox
(
"Render match"
,
render_match
,
"Render a pair of matched images."
);
gd
.
addCheckbox
(
"Render match"
,
render_match
,
"Render a pair of matched images."
);
...
@@ -215,6 +219,7 @@ public class ComboMatch {
...
@@ -215,6 +219,7 @@ public class ComboMatch {
use_saved_collection
=
gd
.
getNextBoolean
();
use_saved_collection
=
gd
.
getNextBoolean
();
save_collection
=
gd
.
getNextBoolean
();
save_collection
=
gd
.
getNextBoolean
();
process_correlation
=
gd
.
getNextBoolean
();
process_correlation
=
gd
.
getNextBoolean
();
num_tries_fit
=
(
int
)
gd
.
getNextNumber
();
update_match
=
gd
.
getNextBoolean
();
update_match
=
gd
.
getNextBoolean
();
render_match
=
gd
.
getNextBoolean
();
render_match
=
gd
.
getNextBoolean
();
...
@@ -728,10 +733,10 @@ public class ComboMatch {
...
@@ -728,10 +733,10 @@ public class ComboMatch {
double
[][][]
affines
=
{
affine0
,
affine1
};
double
[][][]
affines
=
{
affine0
,
affine1
};
int
[]
zooms
=
{
initial_zoom
,
min_zoom_lev
,
1000
,
1000
};
// make automatic
int
[]
zooms
=
{
initial_zoom
,
min_zoom_lev
,
1000
,
1000
};
// make automatic
double
scale
=
2.0
;
// scale vectors when warping;
double
scale
=
2.0
;
// scale vectors when warping;
int
num_tries
=
5
;
// int num_tries = 5; // make configurable
if
(!
process_correlation
)
{
if
(!
process_correlation
)
{
zooms
=
new
int
[]
{
min_zoom_lev
,
1000
};
zooms
=
new
int
[]
{
min_zoom_lev
,
1000
};
num_tries
=
0
;
num_tries
_fit
=
0
;
update_match
=
false
;
update_match
=
false
;
}
}
debugLevel
=
0
;
debugLevel
=
0
;
...
@@ -750,7 +755,7 @@ public class ComboMatch {
...
@@ -750,7 +755,7 @@ public class ComboMatch {
frac_remove
,
// double frac_remove, // = 0.25
frac_remove
,
// double frac_remove, // = 0.25
metric_error
,
// double metric_error,
metric_error
,
// double metric_error,
ignore_prev_rms
,
// boolean ignore_prev_rms,
ignore_prev_rms
,
// boolean ignore_prev_rms,
num_tries
,
// = 5int num_tries, // = 5
num_tries
_fit
,
// = 5int num_tries, // = 5
true
,
// boolean calc_warp,
true
,
// boolean calc_warp,
batch_mode
,
// boolean batch_mode,
batch_mode
,
// boolean batch_mode,
gpu_pair
,
// String [] gpu_spair,
gpu_pair
,
// String [] gpu_spair,
...
@@ -814,6 +819,7 @@ public class ComboMatch {
...
@@ -814,6 +819,7 @@ public class ComboMatch {
// TODO Auto-generated catch block
// TODO Auto-generated catch block
e
.
printStackTrace
();
e
.
printStackTrace
();
}
}
System
.
out
.
println
(
"Saved data to "
+
orthoMapsCollection_path
);
}
}
return
true
;
return
true
;
}
}
...
@@ -942,7 +948,7 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341
...
@@ -942,7 +948,7 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341
ImageDtt
.
THREADS_MAX
,
// int threadsMax,
ImageDtt
.
THREADS_MAX
,
// int threadsMax,
debugLevel
);
// int debug_level)
debugLevel
);
// int debug_level)
}
}
if
(
debugLevel
>
0
)
{
if
(
debugLevel
>
1
)
{
String
[]
dbg_titles
=
{
"x-raw"
,
"x_filled"
,
"y-raw"
,
"y_filled"
};
String
[]
dbg_titles
=
{
"x-raw"
,
"x_filled"
,
"y-raw"
,
"y_filled"
};
double
[][]
dbg_img
=
{
vf
[
0
],
vf_filled
[
0
],
vf
[
1
],
vf_filled
[
1
]};
double
[][]
dbg_img
=
{
vf
[
0
],
vf_filled
[
0
],
vf
[
1
],
vf_filled
[
1
]};
ShowDoubleFloatArrays
.
showArrays
(
ShowDoubleFloatArrays
.
showArrays
(
...
...
src/main/java/com/elphel/imagej/orthomosaic/ItemMatch.java
0 → 100644
View file @
25c2bbf2
package
com
.
elphel
.
imagej
.
orthomosaic
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.HashMap
;
public
class
ItemMatch
{
public
double
[]
combo_pxy
;
// combo image {pixel_x, pixel_y}
public
double
[]
lla
;
// add later
public
HashMap
<
String
,
ItemPatternMatch
>
pattern_matches
=
new
HashMap
<
String
,
ItemPatternMatch
>();
public
ItemMatch
(
double
[]
combo_pxy
)
{
this
.
combo_pxy
=
combo_pxy
;
}
public
double
[]
getXY
()
{
return
combo_pxy
;
}
public
int
[]
getIntXY
()
{
return
new
int
[]
{(
int
)
Math
.
round
(
combo_pxy
[
0
]),
(
int
)
Math
.
round
(
combo_pxy
[
1
])};
}
public
void
addPatternMatches
(
GroundObjectPattern
groundObjectPattern
,
double
[]
matches
,
int
best_sub
)
{
String
pattern_path
=
groundObjectPattern
.
getPatternPath
();
ItemPatternMatch
match
=
pattern_matches
.
get
(
pattern_path
);
if
(
match
==
null
)
{
match
=
new
ItemPatternMatch
(
groundObjectPattern
);
pattern_matches
.
put
(
pattern_path
,
match
);
}
match
.
setMatches
(
matches
);
match
.
setBestSub
(
best_sub
);
}
public
ItemPatternMatch
getPatternMatch
(
GroundObjectPattern
groundObjectPattern
)
{
return
getPatternMatch
(
groundObjectPattern
.
getPatternPath
());
}
public
ItemPatternMatch
getPatternMatch
(
String
pattern_path
)
{
return
pattern_matches
.
get
(
pattern_path
);
}
public
double
[]
getMatchValues
(
String
pattern_path
)
{
ItemPatternMatch
match
=
pattern_matches
.
get
(
pattern_path
);
if
(
match
==
null
)
{
System
.
out
.
println
(
"No matches found for pattern "
+
pattern_path
);
return
null
;
}
return
match
.
getMatches
();
}
public
double
[]
getMatchValues
(
GroundObjectPattern
groundObjectPattern
)
{
return
getMatchValues
(
groundObjectPattern
.
getPatternPath
());
}
public
double
getMatchValue
(
String
pattern_path
,
int
indx
)
{
ItemPatternMatch
match
=
pattern_matches
.
get
(
pattern_path
);
if
(
match
==
null
)
{
System
.
out
.
println
(
"No matches found for pattern "
+
pattern_path
);
return
Double
.
NaN
;
}
return
match
.
getMatch
(
indx
);
}
public
double
getMatchValue
(
GroundObjectPattern
groundObjectPattern
,
int
indx
)
{
return
getMatchValue
(
groundObjectPattern
.
getPatternPath
(),
indx
);
}
public
static
ArrayList
<
Integer
>
sortByMatch
(
ArrayList
<
ItemMatch
>
match_list
,
GroundObjectPattern
groundObjectPattern
,
int
indx
){
String
pattern_path
=
groundObjectPattern
.
getPatternPath
();
return
sortByMatch
(
match_list
,
pattern_path
,
indx
);
}
public
static
ArrayList
<
Integer
>
sortByMatch
(
ArrayList
<
ItemMatch
>
match_list
,
String
pattern_path
,
int
indx
){
ArrayList
<
Integer
>
result_list
=
new
ArrayList
<
Integer
>(
match_list
.
size
());
for
(
int
i
=
0
;
i
<
match_list
.
size
();
i
++)
{
result_list
.
add
(
i
);
}
Collections
.
sort
(
result_list
,
new
Comparator
<
Integer
>()
{
@Override
public
int
compare
(
Integer
lhs
,
Integer
rhs
)
{
double
rhsd
=
match_list
.
get
(
rhs
).
getMatchValue
(
pattern_path
,
indx
);
double
lhsd
=
match_list
.
get
(
lhs
).
getMatchValue
(
pattern_path
,
indx
);
return
(
rhsd
>
lhsd
)
?
1
:
(
rhsd
<
lhsd
)
?
-
1
:
0
;
// recreasing
}
});
return
result_list
;
}
}
src/main/java/com/elphel/imagej/orthomosaic/ItemPatternMatch.java
0 → 100644
View file @
25c2bbf2
package
com
.
elphel
.
imagej
.
orthomosaic
;
import
java.util.Arrays
;
public
class
ItemPatternMatch
{
// public String pattern_path;
public
double
[]
sub_matches
;
// array of sub-pattern match qualities. [0] - is usually combo, [1] - full pattern, [2+] - obscured
public
int
best_sub
=
-
1
;
// best subpattern
public
GroundObjectPattern
groundObjectPattern
;
public
ItemPatternMatch
(
GroundObjectPattern
groundObjectPattern
)
{
this
.
groundObjectPattern
=
groundObjectPattern
;
}
public
void
setMatches
(
double
[]
matches
)
{
sub_matches
=
matches
;
}
public
void
setMatch
(
int
indx
,
double
match_value
)
{
if
(
sub_matches
==
null
)
{
sub_matches
=
new
double
[
indx
+
1
];
Arrays
.
fill
(
sub_matches
,
Double
.
NaN
);
}
else
if
(
sub_matches
.
length
<=
indx
)
{
double
[]
old_matches
=
sub_matches
;
sub_matches
=
new
double
[
indx
+
1
];
Arrays
.
fill
(
sub_matches
,
Double
.
NaN
);
System
.
arraycopy
(
old_matches
,
0
,
sub_matches
,
0
,
old_matches
.
length
);
}
sub_matches
[
indx
]
=
match_value
;
}
public
void
setBestSub
(
int
sub
)
{
best_sub
=
sub
;
}
public
int
getBestSub
()
{
return
best_sub
;
}
public
double
getMatch
(
int
indx
)
{
if
((
sub_matches
==
null
)
||
(
sub_matches
.
length
<=
indx
))
{
return
Double
.
NaN
;
}
return
sub_matches
[
indx
];
}
public
double
[]
getMatches
()
{
return
sub_matches
;
}
public
GroundObjectPattern
getGroundObjectPattern
()
{
return
groundObjectPattern
;
}
}
src/main/java/com/elphel/imagej/orthomosaic/ObjectLocation.java
View file @
25c2bbf2
...
@@ -10,6 +10,8 @@ import com.elphel.imagej.common.ShowDoubleFloatArrays;
...
@@ -10,6 +10,8 @@ import com.elphel.imagej.common.ShowDoubleFloatArrays;
import
com.elphel.imagej.tileprocessor.Correlation2d
;
import
com.elphel.imagej.tileprocessor.Correlation2d
;
import
com.elphel.imagej.tileprocessor.TileNeibs
;
import
com.elphel.imagej.tileprocessor.TileNeibs
;
import
Jama.EigenvalueDecomposition
;
import
Jama.Matrix
;
import
ij.ImagePlus
;
import
ij.ImagePlus
;
import
ij.gui.PointRoi
;
import
ij.gui.PointRoi
;
...
@@ -79,6 +81,240 @@ public class ObjectLocation {
...
@@ -79,6 +81,240 @@ public class ObjectLocation {
}
}
return
dcrop
;
return
dcrop
;
}
}
public
static
double
[]
extractObjectImage
(
double
[]
center_xy
,
int
size
,
double
[]
src_img
,
int
width
)
{
int
height
=
src_img
.
length
/
width
;
double
[]
dcrop
=
new
double
[
size
*
size
];
Arrays
.
fill
(
dcrop
,
Double
.
NaN
);
int
hsize
=
size
/
2
;
int
[]
xy
=
{(
int
)
Math
.
round
(
center_xy
[
0
]),
(
int
)
Math
.
round
(
center_xy
[
1
])};
boolean
has_NaN
=
false
;
for
(
int
y
=
0
;
y
<
size
;
y
++)
{
int
src_y
=
y
-
hsize
+
xy
[
1
];
if
((
src_y
>=
0
)
&&
(
y
<
height
))
{
for
(
int
x
=
0
;
x
<
size
;
x
++)
{
int
src_x
=
x
-
hsize
+
xy
[
0
];
if
((
src_x
>=
0
)
&&
(
x
<
width
))
{
double
d
=
src_img
[
src_x
+
src_y
*
width
];
dcrop
[
x
+
size
*
y
]
=
d
;
has_NaN
|=
Double
.
isNaN
(
d
);
}
else
{
has_NaN
=
true
;
}
}
}
else
{
has_NaN
=
true
;
}
}
if
(
has_NaN
)
{
TileNeibs
tn
=
new
TileNeibs
(
size
,
size
);
OrthoMap
.
fillNaNs
(
dcrop
,
// double [] data,
tn
,
// TileNeibs tn,
3
);
// int min_neibs)
}
return
dcrop
;
}
/**
* Search for maximum within specified radius from the center or specified offset from the center
* @param data square data
* @param cent_xy offset from the square center to search
* @param radius search for maximum within this radius
* @param frac_max fraction of maximum to measure area
* @return {maximum, area, dist, x, y}. No interpolation yet, each returned value is integer.
* Returns null if no local maximum within area. x,y are offsets from the (provided) center
*/
public
static
double
[]
getMaxLocAreaNaN
(
double
[]
data
,
// square data
double
[]
cent_xy
,
// if null, use center of the square
double
radius
,
// search for maximum within this radius
double
frac_max
,
int
debugLevel
)
{
double
[]
rslt
=
getMaxLocArea
(
data
,
// square data
cent_xy
,
// if null, use center of the square
radius
,
// search for maximum within this radius
frac_max
,
debugLevel
);
if
(
rslt
!=
null
)
{
return
rslt
;
}
else
{
return
new
double
[]
{
Double
.
NaN
,
Double
.
NaN
,
Double
.
NaN
,
Double
.
NaN
,
Double
.
NaN
,
Double
.
NaN
};
}
}
public
static
double
[]
getMaxLocArea
(
double
[]
data
,
// square data
double
[]
cent_xy
,
// if null, use center of the square
double
radius
,
// search for maximum within this radius
double
frac_max
,
int
debugLevel
)
{
boolean
debug
=
debugLevel
>
1
;
int
size
=
(
int
)
Math
.
sqrt
(
data
.
length
);
if
(
cent_xy
==
null
)
{
cent_xy
=
new
double
[]
{
size
/
2
,
size
/
2
};
}
double
maxr2
=
radius
*
radius
;
double
best_d
=
0
;
int
best_indx
=
-
1
;
int
min_x
=
Math
.
max
(
1
,
(
int
)
Math
.
floor
(
cent_xy
[
0
]-
radius
));
int
min_y
=
Math
.
max
(
1
,
(
int
)
Math
.
floor
(
cent_xy
[
1
]-
radius
));
int
max_x
=
Math
.
min
(
size
-
2
,
(
int
)
Math
.
ceil
(
cent_xy
[
0
]+
radius
));
int
max_y
=
Math
.
min
(
size
-
2
,
(
int
)
Math
.
ceil
(
cent_xy
[
1
]+
radius
));
for
(
int
y
=
min_y
;
y
<=
max_y
;
y
++)
{
// do not search on very edges
double
dy
=
(
y
-
cent_xy
[
1
]);
double
y2
=
dy
*
dy
;
if
(
y2
<
maxr2
)
{
for
(
int
x
=
min_x
;
x
<=
max_x
;
x
++)
{
double
dx
=
x
-
cent_xy
[
0
];
double
r2
=
y2
+
dx
*
dx
;
if
(
r2
<
maxr2
)
{
int
indx
=
y
*
size
+
x
;
double
d
=
data
[
indx
];
if
(
d
>
best_d
)
{
best_indx
=
indx
;
best_d
=
d
;
}
}
}
}
}
// is it local max?
if
((
data
[
best_indx
-
1
]
>
best_d
)
||
(
data
[
best_indx
+
1
]
>
best_d
)
||
(
data
[
best_indx
-
size
]
>
best_d
)
||
(
data
[
best_indx
+
size
]
>
best_d
))
{
return
null
;
// on the edge, not a local max
}
boolean
[]
above_thresh
=
new
boolean
[
data
.
length
];
double
thresh
=
best_d
*
frac_max
;
for
(
int
i
=
0
;
i
<
data
.
length
;
i
++)
{
above_thresh
[
i
]
=
data
[
i
]
>
thresh
;
}
int
[]
clusters
=
(
new
TileNeibs
(
size
,
size
)).
enumerateClusters
(
above_thresh
,
// boolean [] tiles,
null
,
// int [] num_clusters,
false
);
// boolean ordered)
int
center_cluster
=
clusters
[
best_indx
];
double
xc
=
best_indx
%
size
-
cent_xy
[
0
];
double
yc
=
best_indx
/
size
-
cent_xy
[
1
];
double
s0
=
0
,
sx
=
0
,
sy
=
0
,
sx2
=
0
,
sy2
=
0
,
sxy
=
0
;
for
(
int
i
=
0
;
i
<
clusters
.
length
;
i
++)
{
if
(
clusters
[
i
]
==
center_cluster
)
{
double
y
=
i
/
size
-
(
yc
+
cent_xy
[
1
]);
//(yc + cent_xy[1]) - absolute, from (0,0)
double
x
=
i
%
size
-
(
xc
+
cent_xy
[
0
]);
double
w
=
data
[
i
]-
thresh
;
s0
+=
w
;
sx
+=
w
*
x
;
sy
+=
w
*
y
;
sx2
+=
w
*
x
*
x
;
sy2
+=
w
*
y
*
y
;
sxy
+=
w
*
x
*
y
;
}
}
double
cxx
=
sx2
-
sx
*
sx
/
s0
,
cyy
=
sy2
-
sy
*
sy
/
s0
,
cxy
=
sxy
-
sx
*
sy
/
s0
;
/*
* sum(Mi*(Xi-avg(X))^2) = SX2 - SX^2/S0
* sum(Mi*(Yi-avg(Y))^2) = SY2 - SY^2/S0
* sum(Mi*(Xi-avg(X)*(Yi-avg(Y))) = SXY - SX*SY / S0
*/
Matrix
covar
=
new
Matrix
(
new
double
[][]
{{
cxx
,
cxy
},{
cxy
,
cyy
}});
double
[]
cent_offs
=
{
sx
/
s0
+
xc
,
sy
/
s0
+
yc
};
EigenvalueDecomposition
eig
=
covar
.
eig
();
double
[]
eigval
=
{
eig
.
getD
().
get
(
0
,
0
),
eig
.
getD
().
get
(
1
,
1
)};
Arrays
.
sort
(
eigval
);
// ascending
double
elong
=
Math
.
sqrt
(
eigval
[
1
]/
eigval
[
0
]);
double
eff_rad
=
Math
.
sqrt
(
Math
.
sqrt
(
eigval
[
1
]*
eigval
[
0
]));
double
dist
=
Math
.
sqrt
(
cent_offs
[
0
]*
cent_offs
[
0
]
+
cent_offs
[
1
]*
cent_offs
[
1
]);
if
(
debug
)
{
System
.
out
.
println
(
"\ncenter offset ["
+(
sx
/
s0
)+
","
+(
sy
/
s0
)+
"] , from center: ["
+
cent_offs
[
0
]+
","
+
cent_offs
[
1
]+
"]"
);
System
.
out
.
println
(
"Covariance matrix:"
);
covar
.
print
(
8
,
6
);
System
.
out
.
println
(
"eig.getV()"
);
eig
.
getV
().
print
(
8
,
6
);
System
.
out
.
println
(
"eig.getD()"
);
eig
.
getD
().
print
(
8
,
6
);
System
.
out
.
println
(
String
.
format
(
"best_d=%7.5f, rad=%6.3f, elong=%6.3f, dist=%6.3f, dx=%6.3f, dy=%6.3f"
,
best_d
,
eff_rad
,
elong
,
dist
,
cent_offs
[
0
],
cent_offs
[
1
]));
}
return
new
double
[]
{
best_d
,
eff_rad
,
elong
,
dist
,
cent_offs
[
0
],
cent_offs
[
1
]}
;
}
public
static
double
[]
getMaxLocAreaInt
(
double
[]
data
,
// square data
double
[]
cent_xy
,
// if null, use center of the square
double
radius
,
// search for maximum within this radius
double
frac_max
)
{
int
size
=
(
int
)
Math
.
sqrt
(
data
.
length
);
if
(
cent_xy
==
null
)
{
cent_xy
=
new
double
[]
{
size
/
2
,
size
/
2
};
}
double
maxr2
=
radius
*
radius
;
double
best_d
=
0
;
int
best_indx
=
-
1
;
int
min_x
=
Math
.
max
(
1
,
(
int
)
Math
.
floor
(
cent_xy
[
0
]-
radius
));
int
min_y
=
Math
.
max
(
1
,
(
int
)
Math
.
floor
(
cent_xy
[
1
]-
radius
));
int
max_x
=
Math
.
min
(
size
-
2
,
(
int
)
Math
.
ceil
(
cent_xy
[
0
]+
radius
));
int
max_y
=
Math
.
min
(
size
-
2
,
(
int
)
Math
.
ceil
(
cent_xy
[
1
]+
radius
));
for
(
int
y
=
min_y
;
y
<=
max_y
;
y
++)
{
// do not search on very edges
double
dy
=
(
y
-
cent_xy
[
1
]);
double
y2
=
dy
*
dy
;
if
(
y2
<
maxr2
)
{
for
(
int
x
=
min_x
;
x
<=
max_x
;
x
++)
{
double
dx
=
x
-
cent_xy
[
0
];
double
r2
=
y2
+
dx
*
dx
;
if
(
r2
<
maxr2
)
{
int
indx
=
y
*
size
+
x
;
double
d
=
data
[
indx
];
if
(
d
>
best_d
)
{
best_indx
=
indx
;
best_d
=
d
;
}
}
}
}
}
// is it local max?
if
((
data
[
best_indx
-
1
]
>
best_d
)
||
(
data
[
best_indx
+
1
]
>
best_d
)
||
(
data
[
best_indx
-
size
]
>
best_d
)
||
(
data
[
best_indx
+
size
]
>
best_d
))
{
return
null
;
// on the edge, not a local max
}
boolean
[]
above_thresh
=
new
boolean
[
data
.
length
];
double
thresh
=
best_d
*
frac_max
;
for
(
int
i
=
0
;
i
<
data
.
length
;
i
++)
{
above_thresh
[
i
]
=
data
[
i
]
>
thresh
;
}
int
[]
clusters
=
(
new
TileNeibs
(
size
,
size
)).
enumerateClusters
(
above_thresh
,
// boolean [] tiles,
null
,
// int [] num_clusters,
false
);
// boolean ordered)
int
center_cluster
=
clusters
[
best_indx
];
double
area_max
=
0.0
;
for
(
int
i
=
0
;
i
<
clusters
.
length
;
i
++)
{
if
(
clusters
[
i
]
==
center_cluster
)
{
area_max
+=
1
;
}
}
double
x_max
=
best_indx
%
size
-
cent_xy
[
0
];
double
y_max
=
best_indx
/
size
-
cent_xy
[
1
];
double
dist
=
Math
.
sqrt
(
y_max
*
y_max
+
x_max
*
x_max
);
return
new
double
[]
{
best_d
,
area_max
,
dist
,
x_max
,
y_max
}
;
}
public
static
double
[]
getPatternCenter
(
public
static
double
[]
getPatternCenter
(
...
...
src/main/java/com/elphel/imagej/orthomosaic/OrthoMapsCollection.java
View file @
25c2bbf2
This diff is collapsed.
Click to expand it.
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