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
84bd8cc0
Commit
84bd8cc0
authored
Jan 11, 2026
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improved flat ground detection
parent
cac11d90
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
385 additions
and
14 deletions
+385
-14
GroundPlane.java
...ain/java/com/elphel/imagej/tileprocessor/GroundPlane.java
+366
-14
OpticalFlow.java
...ain/java/com/elphel/imagej/tileprocessor/OpticalFlow.java
+19
-0
No files found.
src/main/java/com/elphel/imagej/tileprocessor/GroundPlane.java
View file @
84bd8cc0
...
@@ -227,9 +227,21 @@ public class GroundPlane {
...
@@ -227,9 +227,21 @@ public class GroundPlane {
final
double
gnd_percent_high
=
0.2
;
// 0.9; // high ground percentile
final
double
gnd_percent_high
=
0.2
;
// 0.9; // high ground percentile
final
double
gnd_max_high_over
=
0.1
;
// 0.5; // pix = make dependent on average disparity?
final
double
gnd_max_high_over
=
0.1
;
// 0.5; // pix = make dependent on average disparity?
final
int
min_good1
=
10
;
// 50; // minimal good tiles after pass1
final
int
min_good1
=
10
;
// 50; // minimal good tiles after pass1
final
double
max_abs_diff
=
0.03
;
// maximal absolute disparity difference from the plane
final
double
max_abs_diff
=
0.03
;
// maximal absolute disparity difference from the plane
final
double
max_rel_diff
=
0.03
;
// 0.1; // maximal relative disparity difference from the plane
final
double
max_rel_diff
=
0.03
;
// 0.1; // maximal relative disparity difference from the plane
final
double
normal_damping
=
0.001
;
// pull to horizontal if not enough data
final
double
normal_damping
=
0.001
;
// pull to horizontal if not enough data
final
double
blur_frac
=
0.01
;
// 0.03
final
double
weight_frac
=
0.3
;
// multiply weight by w= 1/(1 + (err/k_max_diff)^2)
final
int
mtile_size
=
16
;
final
double
min_ev_rel
=
0.3
;
final
double
max_tilt
=
0.2
;
final
double
top_percent
=
0.5
;
// remove above 50% center intersection
final
int
min_macro_tiles
=
3
;
final
boolean
[]
good_tiles
=
new
boolean
[
ref_scene
.
getTilesX
()*
ref_scene
.
getTilesY
()];
final
boolean
[]
good_tiles
=
new
boolean
[
ref_scene
.
getTilesX
()*
ref_scene
.
getTilesY
()];
String
dbg_title
=
ref_scene
.
getImageName
()+
"-ground tilts"
;
String
dbg_title
=
ref_scene
.
getImageName
()+
"-ground tilts"
;
double
[][]
to_ground_xyzatr_frac
=
GroundPlane
.
getPlaneDualPassMetric
(
// returns to_ground_xyzatr (rotated around the ground point nadir of teh drone)
double
[][]
to_ground_xyzatr_frac
=
GroundPlane
.
getPlaneDualPassMetric
(
// returns to_ground_xyzatr (rotated around the ground point nadir of teh drone)
...
@@ -240,6 +252,13 @@ public class GroundPlane {
...
@@ -240,6 +252,13 @@ public class GroundPlane {
min_good1
,
// final int min_good1, // minimal good tiles after pass1
min_good1
,
// final int min_good1, // minimal good tiles after pass1
max_abs_diff
,
// final double max_abs_diff, // maximal absolute disparity difference from the plane
max_abs_diff
,
// final double max_abs_diff, // maximal absolute disparity difference from the plane
max_rel_diff
,
// final double max_rel_diff, // maximal relative disparity difference from the plane
max_rel_diff
,
// final double max_rel_diff, // maximal relative disparity difference from the plane
blur_frac
,
// final double blur_frac, // = 0.01; // 0.03
weight_frac
,
// final double weight_frac, // = 0.3; // multiply weight by w= 1/(1 + (err/k_max_diff)^2)
mtile_size
,
// final int mtile_size, // = 16;
min_ev_rel
,
// final double min_ev_rel, // = 0.3;
max_tilt
,
// final double max_tilt, // = 0.2;
top_percent
,
// final double top_percent, // = 0.5; // remove above 50% center intersection
min_macro_tiles
,
// final int min_macro_tiles, // = 3;
normal_damping
,
// final double normal_damping,
normal_damping
,
// final double normal_damping,
ref_scene
.
getTilesX
(),
// final int width,
ref_scene
.
getTilesX
(),
// final int width,
good_tiles
,
// final boolean [] good_tiles, // null or boolean[data.length] // should all be false
good_tiles
,
// final boolean [] good_tiles, // null or boolean[data.length] // should all be false
...
@@ -286,6 +305,15 @@ public class GroundPlane {
...
@@ -286,6 +305,15 @@ public class GroundPlane {
final
int
min_good1
,
// minimal good tiles after pass1
final
int
min_good1
,
// minimal good tiles after pass1
final
double
max_abs_diff
,
// maximal absolute disparity difference from the plane
final
double
max_abs_diff
,
// maximal absolute disparity difference from the plane
final
double
max_rel_diff
,
// maximal relative disparity difference from the plane
final
double
max_rel_diff
,
// maximal relative disparity difference from the plane
final
double
blur_frac
,
// = 0.01; // 0.03
final
double
weight_frac
,
// = 0.3; // multiply weight by w= 1/(1 + (err/k_max_diff)^2)
final
int
mtile_size
,
// = 16;
final
double
min_ev_rel
,
// = 0.3;
final
double
max_tilt
,
// = 0.2;
final
double
top_percent
,
// = 0.5; // remove above 50% center intersection
final
int
min_macro_tiles
,
// = 3;
final
double
normal_damping
,
final
double
normal_damping
,
final
int
width
,
final
int
width
,
final
boolean
[]
good_tiles
,
// null or boolean[data.length] // should all be false
final
boolean
[]
good_tiles
,
// null or boolean[data.length] // should all be false
...
@@ -293,9 +321,7 @@ public class GroundPlane {
...
@@ -293,9 +321,7 @@ public class GroundPlane {
final
String
dbg_title
,
final
String
dbg_title
,
final
int
debugLevel
)
{
final
int
debugLevel
)
{
boolean
print_histogram
=
debugLevel
>
0
;
boolean
print_histogram
=
debugLevel
>
0
;
double
blur_frac
=
0.01
;
// 0.03
// boolean eig_weight = false;
double
weight_frac
=
0.3
;
// multiply weight by w= 1/(1 + (err/k_max_diff)^2)
boolean
use_lma
=
true
;
boolean
use_lma
=
true
;
int
num_bins
=
1000
;
int
num_bins
=
1000
;
String
dbg_title1
=
(
dbg_title
!=
null
)
?
(
dbg_title
+
"-stage1"
)
:
null
;
String
dbg_title1
=
(
dbg_title
!=
null
)
?
(
dbg_title
+
"-stage1"
)
:
null
;
...
@@ -484,6 +510,39 @@ public class GroundPlane {
...
@@ -484,6 +510,39 @@ public class GroundPlane {
normal_damping
,
// final double normal_damping,
normal_damping
,
// final double normal_damping,
dbg_title
+
"-metric"
,
// final String dbg_title,
dbg_title
+
"-metric"
,
// final String dbg_title,
debugLevel
);
// final int debugLevel) {
debugLevel
);
// final int debugLevel) {
double
[][]
macroplanes
=
getMacroPlanes
(
// no weights
wxyz
,
// final double [][] wxyz,
mask3
,
// final boolean [] mask,
weights
,
// final double [] weight,
false
,
// final boolean eig_weight, // use weights when calculating eiget values (false - only mask)
width
,
// final int tilesX,
mtile_size
,
// final int mtile_size,
normal_damping
,
// final double normal_damping,
dbg_title
+
"-macroplanes"
,
// final String dbg_title,
debugLevel
);
// final int debugLevel) {
boolean
[]
macro_mask
=
getMaskFromMacro
(
mask3
,
// boolean [] mask_in,
macroplanes
,
// double [][] macroplanes,
min_ev_rel
,
// double min_ev_rel,
max_tilt
,
// double max_tilt,
top_percent
,
// double top_percent, // remove above percentile
min_macro_tiles
,
// int min_macro_tiles,
width
,
// int tilesX,
mtile_size
,
// int mtile_size,
debugLevel
);
// int debugLevel)
double
[][]
macroplanes_weights
=
getMacroPlanes
(
wxyz
,
// final double [][] wxyz,
mask3
,
// final boolean [] mask,
weights
,
// final double [] weight,
true
,
// final boolean eig_weight, // use weights when calculating eiget values (false - only mask)
width
,
// final int tilesX,
mtile_size
,
// final int mtile_size,
normal_damping
,
// final double normal_damping,
dbg_title
+
"-macroplanes"
,
// final String dbg_title,
debugLevel
);
// final int debugLevel) {
double
[][]
ground_xyzatr
=
ErsCorrection
.
invertXYZATR
(
to_ground_xyzatr
);
// straight down from the camera, then rotated
double
[][]
ground_xyzatr
=
ErsCorrection
.
invertXYZATR
(
to_ground_xyzatr
);
// straight down from the camera, then rotated
double
[][]
virtual_camera_from_ground_xyz
=
ErsCorrection
.
invertXYZATR
(
new
double
[][]
{
ground_xyzatr
[
0
],
new
double
[
3
]});
double
[][]
virtual_camera_from_ground_xyz
=
ErsCorrection
.
invertXYZATR
(
new
double
[][]
{
ground_xyzatr
[
0
],
new
double
[
3
]});
double
[][]
virtual_camera_from_camera
=
ErsCorrection
.
combineXYZATR
(
ground_xyzatr
,
virtual_camera_from_ground_xyz
);
double
[][]
virtual_camera_from_camera
=
ErsCorrection
.
combineXYZATR
(
ground_xyzatr
,
virtual_camera_from_ground_xyz
);
...
@@ -510,6 +569,10 @@ public class GroundPlane {
...
@@ -510,6 +569,10 @@ public class GroundPlane {
};
};
*/
*/
if
((
dbg_title
!=
null
)
||
(
gnd_disp
!=
null
))
{
if
((
dbg_title
!=
null
)
||
(
gnd_disp
!=
null
))
{
// expand macrotiles results to match tiles
// rotate ref_disparity and show
// rotate ref_disparity and show
double
[][]
pXpYD_ground
=
OpticalFlow
.
transformToScenePxPyD
(
double
[][]
pXpYD_ground
=
OpticalFlow
.
transformToScenePxPyD
(
null
,
// final Rectangle full_woi_in, // show larger than sensor WOI (or null) IN TILES
null
,
// final Rectangle full_woi_in, // show larger than sensor WOI (or null) IN TILES
...
@@ -525,6 +588,41 @@ public class GroundPlane {
...
@@ -525,6 +588,41 @@ public class GroundPlane {
}
}
}
}
if
(
dbg_title
!=
null
)
{
if
(
dbg_title
!=
null
)
{
int
tilesX
=
width
;
int
tilesY
=
wxyz
.
length
/
width
;
int
mtile_half
=
mtile_size
/
2
;
int
mtilesX
=
(
tilesX
-
mtile_size
)/
mtile_half
+
1
;
// int mtilesY = (tilesY - mtile_size)/mtile_half + 1;
double
[][]
macro_exp
=
new
double
[
tilesX
*
tilesY
][];
double
[][]
macro_wexp
=
new
double
[
tilesX
*
tilesY
][];
for
(
int
mtile
=
0
;
mtile
<
macroplanes
.
length
;
mtile
++){
int
mtileX
=
mtile
%
mtilesX
;
int
mtileY
=
mtile
/
mtilesX
;
int
min_y
=
mtileY
*
mtile_half
+
mtile_half
/
2
;
int
min_x
=
mtileX
*
mtile_half
+
mtile_half
/
2
;
int
max_y
=
min_y
+
mtile_half
;
int
max_x
=
min_x
+
mtile_half
;
if
(
min_y
<
mtile_half
)
min_y
=
0
;
if
(
min_x
<
mtile_half
)
min_x
=
0
;
if
(
max_y
>
(
tilesY
-
mtile_half
))
max_y
=
tilesY
;
if
(
max_x
>
(
tilesX
-
mtile_half
))
max_x
=
tilesX
;
if
(
macroplanes
[
mtile
]
!=
null
)
{
for
(
int
tileY
=
min_y
;
tileY
<
max_y
;
tileY
++)
{
for
(
int
tileX
=
min_x
;
tileX
<
max_x
;
tileX
++)
{
int
ntile
=
tileY
*
tilesX
+
tileX
;
macro_exp
[
ntile
]
=
macroplanes
[
mtile
];
}
}
}
if
(
macroplanes_weights
[
mtile
]
!=
null
)
{
for
(
int
tileY
=
min_y
;
tileY
<
max_y
;
tileY
++)
{
for
(
int
tileX
=
min_x
;
tileX
<
max_x
;
tileX
++)
{
int
ntile
=
tileY
*
tilesX
+
tileX
;
macro_wexp
[
ntile
]
=
macroplanes_weights
[
mtile
];
}
}
}
}
double
[][]
wxyz_gnd
=
OpticalFlow
.
transformToWorldXYZ
(
double
[][]
wxyz_gnd
=
OpticalFlow
.
transformToWorldXYZ
(
gnd_disparity
,
// final double [] disparity_ref, // invalid tiles - NaN in disparity
gnd_disparity
,
// final double [] disparity_ref, // invalid tiles - NaN in disparity
...
@@ -542,21 +640,49 @@ public class GroundPlane {
...
@@ -542,21 +640,49 @@ public class GroundPlane {
}
}
String
[]
dbg_titles
=
{
"ref_disparity"
,
"ground_disparity"
,
"ref_z"
,
"gnd_z"
,
"masked_z"
,
"weights"
};
String
[]
dbg_titles
=
{
"ref_disparity"
,
"ground_disparity"
,
"ref_z"
,
"gnd_z"
,
"masked_z"
,
"weights"
,
"offs_macro"
,
"tX_macro"
,
"ty_macro"
,
"eigen_prod"
,
"eigen0"
,
"eigen1"
,
"weigen_prod"
,
"weigen0"
,
"weigen1"
,
"z_macro"
,
// masked ref_z after evaluating macro tiles
"z-center"
};
// masked intersection of camera axis with the macro plane
double
[][]
dbg_data
=
new
double
[
dbg_titles
.
length
][];
double
[][]
dbg_data
=
new
double
[
dbg_titles
.
length
][];
dbg_data
[
0
]
=
ref_disparity
;
dbg_data
[
0
]
=
ref_disparity
;
dbg_data
[
1
]
=
gnd_disparity
;
dbg_data
[
1
]
=
gnd_disparity
;
dbg_data
[
2
]
=
ref_z
;
dbg_data
[
2
]
=
ref_z
;
dbg_data
[
3
]
=
gnd_z
;
dbg_data
[
3
]
=
gnd_z
;
dbg_data
[
4
]
=
gnd_z
.
clone
();
dbg_data
[
4
]
=
gnd_z
.
clone
();
dbg_data
[
5
]
=
weights
.
clone
();
dbg_data
[
5
]
=
weights
.
clone
();
dbg_data
[
6
]
=
new
double
[
tilesX
*
tilesY
];
Arrays
.
fill
(
dbg_data
[
6
],
Double
.
NaN
);
dbg_data
[
7
]
=
dbg_data
[
6
].
clone
();
dbg_data
[
8
]
=
dbg_data
[
6
].
clone
();
dbg_data
[
9
]
=
dbg_data
[
6
].
clone
();
dbg_data
[
10
]
=
dbg_data
[
6
].
clone
();
dbg_data
[
11
]
=
dbg_data
[
6
].
clone
();
dbg_data
[
12
]
=
dbg_data
[
6
].
clone
();
dbg_data
[
13
]
=
dbg_data
[
6
].
clone
();
dbg_data
[
14
]
=
dbg_data
[
6
].
clone
();
dbg_data
[
15
]
=
dbg_data
[
6
].
clone
();
dbg_data
[
16
]
=
dbg_data
[
6
].
clone
();
for
(
int
i
=
0
;
i
<
mask3
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
mask3
.
length
;
i
++)
{
if
(!
mask3
[
i
])
{
if
(!
mask3
[
i
])
{
dbg_data
[
4
][
i
]
=
Double
.
NaN
;
dbg_data
[
4
][
i
]
=
Double
.
NaN
;
dbg_data
[
5
][
i
]
=
Double
.
NaN
;
dbg_data
[
5
][
i
]
=
Double
.
NaN
;
}
}
if
(
macro_exp
[
i
]
!=
null
)
{
for
(
int
j
=
0
;
j
<
macro_exp
[
i
].
length
;
j
++)
{
dbg_data
[
6
+
j
][
i
]
=
macro_exp
[
i
][
j
];
}
}
if
(
macro_wexp
[
i
]
!=
null
)
{
for
(
int
j
=
0
;
j
<
3
;
j
++)
{
dbg_data
[
12
+
j
][
i
]
=
macro_wexp
[
i
][
3
+
j
];
}
}
if
(
macro_mask
[
i
])
{
dbg_data
[
15
][
i
]
=
ref_z
[
i
];
dbg_data
[
16
][
i
]
=
dbg_data
[
6
][
i
];
// offset
}
}
}
ref_Clt
.
saveDoubleArrayInModelDirectory
(
ref_Clt
.
saveDoubleArrayInModelDirectory
(
dbg_title
+
"-result"
,
// String suffix,
dbg_title
+
"-result"
,
// String suffix,
dbg_titles
,
// String [] labels, // or null
dbg_titles
,
// String [] labels, // or null
...
@@ -576,6 +702,102 @@ public class GroundPlane {
...
@@ -576,6 +702,102 @@ public class GroundPlane {
// return to_ground_xyzatr_centered;
// return to_ground_xyzatr_centered;
}
}
public
static
boolean
[]
getMaskFromMacro
(
boolean
[]
mask_in
,
double
[][]
macroplanes
,
double
min_ev_rel
,
double
max_tilt
,
double
top_percent
,
// remove above percentile
int
min_macro_tiles
,
int
tilesX
,
int
mtile_size
,
int
debugLevel
)
{
// int min_macro_tiles = 3;
int
num_bins
=
100
;
double
max_tilt2
=
max_tilt
*
max_tilt
;
boolean
[]
mask
=
mask_in
.
clone
();
int
tilesY
=
mask
.
length
/
tilesX
;
int
mtile_half
=
mtile_size
/
2
;
int
mtilesX
=
(
tilesX
-
mtile_size
)/
mtile_half
+
1
;
boolean
[]
keep_macro
=
new
boolean
[
macroplanes
.
length
];
double
[]
min_max_macro
=
null
;
int
num_macro
=
0
;
double
[]
macro_weights
=
new
double
[
macroplanes
.
length
];
double
[]
macro_offsets
=
new
double
[
macroplanes
.
length
];
for
(
int
mtile
=
0
;
mtile
<
macroplanes
.
length
;
mtile
++){
keep_macro
[
mtile
]
=
macroplanes
[
mtile
]
!=
null
;
if
(
keep_macro
[
mtile
])
{
keep_macro
[
mtile
]
=
(
macroplanes
[
mtile
][
1
]*
macroplanes
[
mtile
][
1
]
+
macroplanes
[
mtile
][
2
]*
macroplanes
[
mtile
][
2
])
<
max_tilt2
;
}
if
(
keep_macro
[
mtile
])
{
double
z
=
macroplanes
[
mtile
][
0
];
if
(
min_max_macro
==
null
)
{
min_max_macro
=
new
double
[]
{
z
,
z
};
}
else
{
if
(
z
<
min_max_macro
[
0
])
min_max_macro
[
0
]
=
z
;
if
(
z
>
min_max_macro
[
1
])
min_max_macro
[
1
]
=
z
;
}
num_macro
++;
macro_weights
[
mtile
]
=
macroplanes
[
mtile
][
3
];
// eigenvalues product
macro_offsets
[
mtile
]
=
macroplanes
[
mtile
][
0
];
//
}
}
if
((
num_macro
>=
min_macro_tiles
)
&&
(
min_max_macro
[
1
]
>
min_max_macro
[
0
]))
{
double
[]
hist
=
getHistogram1d
(
macro_offsets
,
// double [] data, // may have NaNs
macro_weights
,
// double [] weights,
min_max_macro
[
0
],
// double hist_low,
min_max_macro
[
1
],
// double hist_high,
num_bins
,
// int num_bins,
debugLevel
);
// int debugLevel)
double
[]
fractions
=
{
top_percent
};
double
[]
percentiles
=
getPercentiles
(
hist
,
// double [] hist,
fractions
);
// double [] fractions)
double
high_lim
=
min_max_macro
[
0
]
+
percentiles
[
0
]
*
(
min_max_macro
[
1
]
-
min_max_macro
[
0
]);
// if (high_lim > (low_lim + gnd_max_high_over)) high_lim = low_lim + gnd_max_high_over;
for
(
int
mtile
=
0
;
mtile
<
macroplanes
.
length
;
mtile
++)
if
(
keep_macro
[
mtile
]){
if
(
macro_offsets
[
mtile
]
>
high_lim
)
{
keep_macro
[
mtile
]
=
false
;
}
}
}
for
(
int
mtile
=
0
;
mtile
<
macroplanes
.
length
;
mtile
++){
int
mtileX
=
mtile
%
mtilesX
;
int
mtileY
=
mtile
/
mtilesX
;
int
min_y
=
mtileY
*
mtile_half
+
mtile_half
/
2
;
int
min_x
=
mtileX
*
mtile_half
+
mtile_half
/
2
;
int
max_y
=
min_y
+
mtile_half
;
int
max_x
=
min_x
+
mtile_half
;
if
(
min_y
<
mtile_half
)
min_y
=
0
;
if
(
min_x
<
mtile_half
)
min_x
=
0
;
if
(
max_y
>
(
tilesY
-
mtile_half
))
max_y
=
tilesY
;
if
(
max_x
>
(
tilesX
-
mtile_half
))
max_x
=
tilesX
;
/*
boolean mask_out = macroplanes[mtile] == null;
if (!mask_out) {
mask_out |= macroplanes[mtile][3] < min_ev_rel;
}
if (!mask_out) {
mask_out |= (macroplanes[mtile][1]* macroplanes[mtile][1] + macroplanes[mtile][2]* macroplanes[mtile][2]) > max_tilt2;
}
if (mask_out) {
*/
if
(!
keep_macro
[
mtile
])
{
for
(
int
tileY
=
min_y
;
tileY
<
max_y
;
tileY
++)
{
for
(
int
tileX
=
min_x
;
tileX
<
max_x
;
tileX
++)
{
int
ntile
=
tileY
*
tilesX
+
tileX
;
mask
[
ntile
]
=
false
;
}
}
}
}
return
mask
;
}
public
static
double
[]
getDisparityPlaneDualPass
(
// returns to_ground_xyzatr (rotated around the ground point nadir of teh drone)
public
static
double
[]
getDisparityPlaneDualPass
(
// returns to_ground_xyzatr (rotated around the ground point nadir of teh drone)
final
QuadCLT
ref_Clt
,
final
QuadCLT
ref_Clt
,
final
double
gnd_percent_low
,
final
double
gnd_percent_low
,
...
@@ -1197,6 +1419,136 @@ public class GroundPlane {
...
@@ -1197,6 +1419,136 @@ public class GroundPlane {
return
null
;
return
null
;
}
}
/**
* Split frame area into 50% macro tiles, and calculate tilts, offset, and confidence
* derived from the eigenvalues
* @param wxyz array of X, Y, Z of the elevation surface relative to the camera reference scene. May have nulls
* @param mask corresponding tile mask
* @param weight array of tile weights
* @param tilesX elevation map width (in tiles). Now 80
* @param mtile_size width of the square macrotiles in tiles (also 16?)
* @param normal_damping regularization parameter to make tilts 0 if there is not enough data to calculate them
* @param dbg_title if not null, use it to generate debug images
* @param debugLevel debug level, now is tested if (debugLevel > -3)
* @return array of per-macrotile: offset at frame center, tiltX, tiltY, product of eigenvalues, both eigenvalues (starting with smaller)
*/
public
static
double
[][]
getMacroPlanes
(
final
double
[][]
wxyz
,
final
boolean
[]
mask
,
final
double
[]
weight
,
final
boolean
eig_weight
,
// use weights when calculating eiget values (false - only mask)
final
int
tilesX
,
final
int
mtile_size
,
final
double
normal_damping
,
final
String
dbg_title
,
final
int
debugLevel
)
{
final
int
tilesY
=
wxyz
.
length
/
tilesX
;
final
int
mtile_half
=
mtile_size
/
2
;
final
int
mtilesX
=
(
tilesX
-
mtile_size
)/
mtile_half
+
1
;
final
int
mtilesY
=
(
tilesY
-
mtile_size
)/
mtile_half
+
1
;
final
double
[][]
mtiles
=
new
double
[
mtilesX
*
mtilesY
][];
final
double
[]
damping
=
Double
.
isNaN
(
normal_damping
)
?
null
:
(
new
double
[]
{
normal_damping
,
normal_damping
});
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
();
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
// Calculate eigenvalues for all square is full of weight = 1.0;
final
int
eig_full
=
((
mtile_half
-
1
)*
mtile_half
*(
2
*
mtile_half
-
1
)/
3
+
mtile_half
*(
mtile_half
-
1
)
+
mtile_half
/
2
)*
2
*
mtile_half
;
final
double
scale_eig
=
1.0
/
eig_full
;
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
public
void
run
()
{
final
double
[][][]
mdata
=
new
double
[
mtile_size
*
mtile_size
][][];
for
(
int
mTile
=
ai
.
getAndIncrement
();
mTile
<
mtiles
.
length
;
mTile
=
ai
.
getAndIncrement
()){
int
ntile
=
((
mTile
/
mtilesX
)
*
tilesX
+
(
mTile
%
mtilesX
))
*
mtile_half
;
// top-left
int
local_xc
=
((
mTile
%
mtilesX
)
+
1
)
*
mtile_half
;
int
local_yc
=
((
mTile
/
mtilesX
)
+
1
)
*
mtile_half
;
int
ntile_center
=
local_xc
+
tilesX
*
local_yc
;
// wxyz may be null, will not use local center
int
mindx
=
0
;
// for centroid and eigenvalues
double
x0
=
mtile_half
,
y0
=
mtile_half
;
double
s0
=
0
,
sx
=
0
,
sy
=
0
,
sx2
=
0
,
sy2
=
0
,
sxy
=
0
;
for
(
int
my
=
0
;
my
<
mtile_size
;
my
++)
{
double
y
=
my
-
y0
;
for
(
int
mx
=
0
;
mx
<
mtile_size
;
mx
++)
{
if
((
wxyz
[
ntile
]
!=
null
)
&&
((
mask
==
null
)
||
mask
[
ntile
]))
{
double
x
=
mx
-
x0
;
double
w
=
(
weight
==
null
)?
1.0
:
weight
[
ntile
];
mdata
[
mindx
]
=
new
double
[
3
][];
mdata
[
mindx
][
0
]
=
new
double
[
2
];
mdata
[
mindx
][
0
][
0
]
=
wxyz
[
ntile
][
0
];
// from global center
mdata
[
mindx
][
0
][
1
]
=
wxyz
[
ntile
][
1
];
mdata
[
mindx
][
1
]
=
new
double
[
1
];
mdata
[
mindx
][
1
][
0
]
=
wxyz
[
ntile
][
2
];
mdata
[
mindx
][
2
]
=
new
double
[
1
];
mdata
[
mindx
][
2
][
0
]
=
w
;
// for eigenvalues
if
(!
eig_weight
)
{
w
=
1.0
;
}
s0
+=
w
;
sx
+=
w
*
x
;
sy
+=
w
*
y
;
sx2
+=
w
*
x
*
x
;
sy2
+=
w
*
y
*
y
;
sxy
+=
w
*
x
*
y
;
mindx
++;
}
ntile
++;
}
ntile
+=
(
tilesX
-
mtile_size
);
}
if
(
mindx
>
0
)
{
// OK to have even a single tile
Arrays
.
fill
(
mdata
,
mindx
,
mdata
.
length
,
null
);
double
[][]
approx2d
=
(
new
PolynomialApproximation
()).
quadraticApproximation
(
mdata
,
true
,
// boolean forceLinear, // use linear approximation
damping
,
// damping, // double [] damping, null OK
-
1
);
// debug level
if
(
approx2d
==
null
)
{
continue
;
}
// z_tilts= new double [] { approx2d[0][2], approx2d[0][0], approx2d[0][1]};
// int ntile = ((mTile / mtilesX) * tilesX + (mTile % mtilesX)) * mtile_half;
int
dx
=
tilesX
/
2
-
local_xc
;
// center relative to this
int
dy
=
tilesY
/
2
-
local_yc
;
mtiles
[
mTile
]
=
new
double
[
6
];
// center offset, tiltx, tilty, eigenvalues product, eigenvalue0, eigenvalue1
// can not shift as do not know wx, wy at local center
mtiles
[
mTile
][
0
]
=
approx2d
[
0
][
2
];
// + dx * approx2d[0][0] + dy * approx2d[0][1]; // shift to center
mtiles
[
mTile
][
1
]
=
approx2d
[
0
][
0
];
mtiles
[
mTile
][
2
]
=
approx2d
[
0
][
1
];
mtiles
[
mTile
][
3
]
=
Double
.
NaN
;
mtiles
[
mTile
][
4
]
=
Double
.
NaN
;
mtiles
[
mTile
][
5
]
=
Double
.
NaN
;
// calculate eigenvalues of weight*mask? Use both or a product as a measure of confidence
x0
+=
sx
/
s0
;
// will these be used?
y0
+=
sy
/
s0
;
//https://users.cs.utah.edu/~tch/CS4640/resources/A%20geometric%20interpretation%20of%20the%20covariance%20matrix.pdf
double
cxx
=
sx2
-
sx
*
sx
/
s0
,
cyy
=
sy2
-
sy
*
sy
/
s0
,
cxy
=
sxy
-
sx
*
sy
/
s0
;
if
((
sx2
!=
0
)
&&
(
sy2
!=
0
)
&&
(
cxx
!=
0
)
&&
(
cyy
!=
0
)){
double
[][]
acovar
=
{{
cxx
,
cxy
},{
cxy
,
cyy
}};
double
[]
eig
=
Correlation2d
.
getEigen2x2
(
acovar
);
// return 4-element array: first eigenvector x, y, lambda0, lambda1 (lambda0 <= lampda1)
if
(
eig
!=
null
)
{
double
eig0
=
Math
.
sqrt
(
scale_eig
*
eig
[
2
]);
double
eig1
=
Math
.
sqrt
(
scale_eig
*
eig
[
3
]);
mtiles
[
mTile
][
3
]
=
Math
.
sqrt
(
eig0
*
eig1
);
mtiles
[
mTile
][
4
]
=
eig0
;
// eig[2] < eig[3];
mtiles
[
mTile
][
5
]
=
eig1
;
}
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
return
mtiles
;
}
public
static
double
[][]
getPlane
(
// from the camera coordinates to in-plane coordinates
public
static
double
[][]
getPlane
(
// from the camera coordinates to in-plane coordinates
final
double
[][]
wxyz
,
final
double
[][]
wxyz
,
final
boolean
use_parallel_proj
,
// for parallel xyz is 0, otherwise - point on the ground under the camera
final
boolean
use_parallel_proj
,
// for parallel xyz is 0, otherwise - point on the ground under the camera
...
...
src/main/java/com/elphel/imagej/tileprocessor/OpticalFlow.java
View file @
84bd8cc0
...
@@ -6506,6 +6506,18 @@ public class OpticalFlow {
...
@@ -6506,6 +6506,18 @@ public class OpticalFlow {
final
double
max_abs_diff
=
0.05
;
// maximal absolute disparity difference from the plane
final
double
max_abs_diff
=
0.05
;
// maximal absolute disparity difference from the plane
final
double
max_rel_diff
=
0.1
;
// maximal relative disparity difference from the plane
final
double
max_rel_diff
=
0.1
;
// maximal relative disparity difference from the plane
final
double
normal_damping
=
0.001
;
// pull to horizontal if not enough data
final
double
normal_damping
=
0.001
;
// pull to horizontal if not enough data
final
double
blur_frac
=
0.01
;
// 0.03
final
double
weight_frac
=
0.3
;
// multiply weight by w= 1/(1 + (err/k_max_diff)^2)
final
int
mtile_size
=
16
;
final
double
min_ev_rel
=
0.3
;
final
double
max_tilt
=
0.2
;
final
double
top_percent
=
0.5
;
// remove above 50% center intersection
final
int
min_macro_tiles
=
3
;
final
boolean
[]
good_tiles
=
new
boolean
[
ds
[
0
].
length
];
final
boolean
[]
good_tiles
=
new
boolean
[
ds
[
0
].
length
];
// String dbg_title =master_CLT.getImageName()+"-ground tilts";
// String dbg_title =master_CLT.getImageName()+"-ground tilts";
String
dbg_title
=
"-ground_tilts"
;
String
dbg_title
=
"-ground_tilts"
;
...
@@ -6518,6 +6530,13 @@ public class OpticalFlow {
...
@@ -6518,6 +6530,13 @@ public class OpticalFlow {
min_good1
,
// final int min_good1, // minimal good tiles after pass1
min_good1
,
// final int min_good1, // minimal good tiles after pass1
max_abs_diff
,
// final double max_abs_diff, // maximal absolute disparity difference from the plane
max_abs_diff
,
// final double max_abs_diff, // maximal absolute disparity difference from the plane
max_rel_diff
,
// final double max_rel_diff, // maximal relative disparity difference from the plane
max_rel_diff
,
// final double max_rel_diff, // maximal relative disparity difference from the plane
blur_frac
,
// final double blur_frac, // = 0.01; // 0.03
weight_frac
,
// final double weight_frac, // = 0.3; // multiply weight by w= 1/(1 + (err/k_max_diff)^2)
mtile_size
,
// final int mtile_size, // = 16;
min_ev_rel
,
// final double min_ev_rel, // = 0.3;
max_tilt
,
// final double max_tilt, // = 0.2;
top_percent
,
// final double top_percent, // = 0.5; // remove above 50% center intersection
min_macro_tiles
,
// final int min_macro_tiles, // = 3;
normal_damping
,
// final double normal_damping,
normal_damping
,
// final double normal_damping,
master_CLT
.
getTilesX
(),
// final int width,
master_CLT
.
getTilesX
(),
// final int width,
good_tiles
,
// final boolean [] good_tiles, // null or boolean[data.length] // should all be false
good_tiles
,
// final boolean [] good_tiles, // null or boolean[data.length] // should all be false
...
...
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