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
ca08b513
Commit
ca08b513
authored
Sep 12, 2022
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Started textured model
parent
951a84a6
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
641 additions
and
1 deletion
+641
-1
OpticalFlow.java
...ain/java/com/elphel/imagej/tileprocessor/OpticalFlow.java
+77
-0
TexturedModel.java
...n/java/com/elphel/imagej/tileprocessor/TexturedModel.java
+444
-0
TileCluster.java
...ain/java/com/elphel/imagej/tileprocessor/TileCluster.java
+106
-0
TileNeibs.java
src/main/java/com/elphel/imagej/tileprocessor/TileNeibs.java
+14
-1
No files found.
src/main/java/com/elphel/imagej/tileprocessor/OpticalFlow.java
View file @
ca08b513
...
@@ -5378,6 +5378,83 @@ public class OpticalFlow {
...
@@ -5378,6 +5378,83 @@ public class OpticalFlow {
}
// for (int mode3d = 0; mode3d<generate_modes3d.length; mode3d++) if (generate_modes3d[mode3d]) {
}
// for (int mode3d = 0; mode3d<generate_modes3d.length; mode3d++) if (generate_modes3d[mode3d]) {
}
// if (generate_mapped) {
}
// if (generate_mapped) {
// debugging 3D model
boolean
build_textured3d
=
true
;
double
textured_disp_adiffo
=
0.3
;
double
textured_disp_rdiffo
=
0.1
;
double
textured_disp_adiffd
=
0.4
;
double
textured_disp_rdiffd
=
0.12
;
double
textured_disp_fof
=
1.5
;
double
min_fg_bg
=
0.1
;
// NaN bg if difference from FG < this
if
(
build_textured3d
)
{
int
tilesX
=
quadCLTs
[
ref_index
].
getTileProcessor
().
getTilesX
();
int
tilesY
=
quadCLTs
[
ref_index
].
getTileProcessor
().
getTilesY
();
if
(
combo_dsn_final
==
null
)
{
combo_dsn_final
=
quadCLTs
[
ref_index
].
readDoubleArrayFromModelDirectory
(
"-INTER-INTRA-LMA"
,
// String suffix,
0
,
// int num_slices, // (0 - all)
null
);
// int [] wh);
}
boolean
[]
sky_tiles
=
new
boolean
[
combo_dsn_final
[
COMBO_DSN_INDX_BLUE_SKY
].
length
];
boolean
[]
sky_invert
=
new
boolean
[
combo_dsn_final
[
COMBO_DSN_INDX_BLUE_SKY
].
length
];
for
(
int
i
=
0
;
i
<
sky_tiles
.
length
;
i
++)
{
sky_tiles
[
i
]
=
combo_dsn_final
[
COMBO_DSN_INDX_BLUE_SKY
][
i
]
>
0.0
;
sky_invert
[
i
]
=
!
sky_tiles
[
i
];
}
// re-load , should create quadCLTs[ref_index].dsi
double
[][]
dls_fg
=
{
combo_dsn_final
[
COMBO_DSN_INDX_DISP
],
combo_dsn_final
[
COMBO_DSN_INDX_LMA
],
combo_dsn_final
[
COMBO_DSN_INDX_STRENGTH
]
};
double
[][]
ds_fg
=
conditionInitialDS
(
true
,
// boolean use_conf, // use configuration parameters, false - use following
clt_parameters
,
// CLTParameters clt_parameters,
dls_fg
,
// double [][] dls
quadCLTs
[
ref_index
],
// QuadCLT scene,
debugLevel
);
// int debug_level)
double
[][]
dls_bg
=
{
combo_dsn_final
[
COMBO_DSN_INDX_DISP_BG
].
clone
(),
combo_dsn_final
[
COMBO_DSN_INDX_LMA_BG
].
clone
(),
combo_dsn_final
[
COMBO_DSN_INDX_STRENGTH_BG
].
clone
()
};
for
(
int
i
=
0
;
i
<
sky_tiles
.
length
;
i
++)
if
(
Double
.
isNaN
(
dls_bg
[
0
][
i
])){
dls_bg
[
0
][
i
]
=
dls_fg
[
0
][
i
];
dls_bg
[
1
][
i
]
=
dls_fg
[
1
][
i
];
dls_bg
[
2
][
i
]
=
dls_fg
[
2
][
i
];
}
double
[][]
ds_bg
=
conditionInitialDS
(
true
,
// boolean use_conf, // use configuration parameters, false - use following
clt_parameters
,
// CLTParameters clt_parameters,
dls_bg
,
// double [][] dls
quadCLTs
[
ref_index
],
// QuadCLT scene,
debugLevel
);
// int debug_level)
// double[][] ds_fg_bg = {ds_fg[0], ds_bg[0]};
double
[][]
ds_fg_bg
=
{
ds_fg
[
0
],
ds_bg
[
0
].
clone
()};
for
(
int
i
=
0
;
i
<
sky_tiles
.
length
;
i
++)
{
if
(
Math
.
abs
(
ds_fg_bg
[
1
][
i
]-
ds_fg_bg
[
0
][
i
])
<
min_fg_bg
)
{
ds_fg_bg
[
1
][
i
]
=
Double
.
NaN
;
}
}
TileCluster
[]
tileCluster
=
TexturedModel
.
clusterizeFgBg
(
// wrong result type, not decided
tilesX
,
// final int tilesX,
ds_fg_bg
,
// final double [][] disparities, // may have more layers
sky_invert
,
// final boolean [] selected, // to remove sky (pre-filter by caller, like for ML?)
textured_disp_adiffo
,
// final double disp_adiffo,
textured_disp_rdiffo
,
// final double disp_rdiffo,
textured_disp_adiffd
,
// final double disp_adiffd,
textured_disp_rdiffd
,
// final double disp_rdiffd,
textured_disp_fof
,
// final double disp_fof, // enable higher difference (scale) for fried of a friend
1
);
// 2); // final int debugLevel)
System
.
out
.
println
(
"clusterizeFgBg() produces "
+
tileCluster
.
length
+
" cluster layers"
);
System
.
out
.
println
(
"clusterizeFgBg() produces "
+
tileCluster
.
length
+
" cluster layers"
);
}
if
(
export_images
)
{
if
(
export_images
)
{
if
(
combo_dsn_final
==
null
)
{
if
(
combo_dsn_final
==
null
)
{
combo_dsn_final
=
quadCLTs
[
ref_index
].
readDoubleArrayFromModelDirectory
(
combo_dsn_final
=
quadCLTs
[
ref_index
].
readDoubleArrayFromModelDirectory
(
...
...
src/main/java/com/elphel/imagej/tileprocessor/TexturedModel.java
0 → 100644
View file @
ca08b513
package
com
.
elphel
.
imagej
.
tileprocessor
;
import
java.awt.Point
;
import
java.awt.Rectangle
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
com.elphel.imagej.common.ShowDoubleFloatArrays
;
/**
** TexturedModel - Generate 3D mesh with textures
**
** Copyright (C) 2017 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** TexturedModel.java is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
public
class
TexturedModel
{
public
static
final
int
threadsMax
=
100
;
// maximal number of threads to launch
public
static
final
int
TILE_EMPTY
=
0
;
public
static
final
int
TILE_BORDER
=
1
;
public
static
final
int
TILE_CONFIRMED
=
2
;
public
static
final
int
TILE_CANDIDATE
=
3
;
// not used
public
static
final
int
CLUSTER_NAN
=
-
2
;
// disparity is NaN
public
static
final
int
CLUSTER_UNASSIGNED
=
-
1
;
// not yet assinged (>=0 - cluster number)
public
static
TileCluster
[]
clusterizeFgBg
(
//
final
int
tilesX
,
final
double
[][]
disparities
,
// may have more layers
final
boolean
[]
selected
,
// to remove sky (pre-filter by caller, like for ML?)
final
double
disp_adiffo
,
final
double
disp_rdiffo
,
final
double
disp_adiffd
,
final
double
disp_rdiffd
,
final
double
disp_fof
,
// enable higher difference (scale) for fried of a friend
final
int
debugLevel
)
{
final
double
disp_border
=
disp_fof
;
final
int
tiles
=
disparities
[
0
].
length
;
final
int
tilesY
=
tiles
/
tilesX
;
final
int
layers
=
disparities
.
length
;
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
threadsMax
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
final
TileNeibs
tn
=
new
TileNeibs
(
tilesX
,
tilesY
);
// final boolean [][][] connections = new boolean [tiles][][];
final
double
[][][][]
connections
=
new
double
[
tiles
][][][];
// final boolean [][][][] bconn = new double [boolean][][][];
// final int [][] num_neibs = new int[tiles][layers];
final
int
[][]
num_neibs_dir
=
new
int
[
tiles
][
layers
];
// -1 - none, otherwise - bitmask
final
int
[][]
ncluster
=
new
int
[
tiles
][
layers
];
// -2 - NaN, -1 - not yet assigned, 0+ - cluster number
for
(
int
tile
=
0
;
tile
<
tiles
;
tile
++)
{
Arrays
.
fill
(
ncluster
[
tile
],
CLUSTER_NAN
);
}
final
int
[]
num_bits
=
new
int
[
512
];
for
(
int
i
=
0
;
i
<
num_bits
.
length
;
i
++)
{
for
(
int
d
=
i
;
d
!=
0
;
d
>>=
1
)
{
num_bits
[
i
]+=(
d
&
1
);
}
}
final
int
dbg_tile
=
(
debugLevel
>
0
)?
977
:
-
1
;
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
public
void
run
()
{
for
(
int
tile
=
ai
.
getAndIncrement
();
tile
<
tiles
;
tile
=
ai
.
getAndIncrement
())
if
((
selected
==
null
)
||
selected
[
tile
])
{
if
(
tile
==
dbg_tile
)
{
System
.
out
.
println
(
"clusterizeFgBg().1: tile="
+
tile
);
}
for
(
int
layer
=
0
;
layer
<
layers
;
layer
++)
{
if
(!
Double
.
isNaN
(
disparities
[
layer
][
tile
]))
{
ncluster
[
tile
][
layer
]
=
CLUSTER_UNASSIGNED
;
// not yet assigned
if
(
connections
[
tile
]
==
null
)
{
connections
[
tile
]
=
new
double
[
layers
][][];
}
// connections[tile][layer] = new double [TileNeibs.DIRS/2][];
connections
[
tile
][
layer
]
=
new
double
[
TileNeibs
.
DIRS
][];
// leave room for future symmetry
for
(
int
dir
=
0
;
dir
<
TileNeibs
.
DIRS
/
2
;
dir
++)
{
int
tile1
=
tn
.
getNeibIndex
(
tile
,
dir
);
if
(
tile1
>=
0
)
{
for
(
int
layer1
=
0
;
layer1
<
layers
;
layer1
++)
{
if
(!
Double
.
isNaN
(
disparities
[
layer1
][
tile1
]))
{
if
(
connections
[
tile
][
layer
][
dir
]
==
null
)
{
connections
[
tile
][
layer
][
dir
]
=
new
double
[
layers
];
Arrays
.
fill
(
connections
[
tile
][
layer
][
dir
],
Double
.
NaN
);
}
double
mid_disp
=
Math
.
max
(
0.0
,
0.5
*(
disparities
[
layer
][
tile
]
+
disparities
[
layer1
][
tile1
]));
double
max_disp_diff
=
((
dir
&
1
)
==
0
)
?
(
disp_adiffo
+
mid_disp
*
disp_rdiffo
)
:
(
disp_adiffd
+
mid_disp
*
disp_rdiffd
);
connections
[
tile
][
layer
][
dir
][
layer1
]
=
Math
.
abs
(
disparities
[
layer
][
tile
]
-
disparities
[
layer1
][
tile1
])/
max_disp_diff
;
}
}
}
}
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
ai
.
set
(
0
);
// calculate total number of connections (w/o fof) by combining opposite directions
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
public
void
run
()
{
for
(
int
tile
=
ai
.
getAndIncrement
();
tile
<
tiles
;
tile
=
ai
.
getAndIncrement
())
if
(
connections
[
tile
]
!=
null
)
{
if
(
tile
==
dbg_tile
)
{
System
.
out
.
println
(
"clusterizeFgBg().2: tile="
+
tile
);
}
for
(
int
layer
=
0
;
layer
<
layers
;
layer
++)
if
(
connections
[
tile
][
layer
]
!=
null
){
for
(
int
dir0
=
0
;
dir0
<
TileNeibs
.
DIRS
/
2
;
dir0
++)
{
int
dir
=
TileNeibs
.
reverseDir
(
dir0
);
int
tile1
=
tn
.
getNeibIndex
(
tile
,
dir
);
if
((
tile1
>=
0
)
&&
(
connections
[
tile1
]
!=
null
))
{
if
(
connections
[
tile
][
layer
][
dir
]
==
null
)
{
connections
[
tile
][
layer
][
dir
]
=
new
double
[
layers
];
Arrays
.
fill
(
connections
[
tile
][
layer
][
dir
],
Double
.
NaN
);
}
for
(
int
layer1
=
0
;
layer1
<
layers
;
layer1
++)
{
if
(
(
connections
[
tile1
][
layer1
]
!=
null
)
&&
(
connections
[
tile1
][
layer1
][
dir0
]
!=
null
))
{
connections
[
tile
][
layer
][
dir
][
layer1
]
=
connections
[
tile1
][
layer1
][
dir0
][
layer
];
}
}
}
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
ai
.
set
(
0
);
// calculate total number of connections (w/o fof) by combining opposite directions
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
public
void
run
()
{
for
(
int
tile
=
ai
.
getAndIncrement
();
tile
<
tiles
;
tile
=
ai
.
getAndIncrement
())
if
(
connections
[
tile
]
!=
null
)
{
if
(
tile
==
dbg_tile
)
{
System
.
out
.
println
(
"clusterizeFgBg().3: tile="
+
tile
);
}
for
(
int
layer
=
0
;
layer
<
layers
;
layer
++)
if
(
connections
[
tile
][
layer
]
!=
null
){
// num_neibs[tile][layer]++; // has center tile, maximal will be 9
num_neibs_dir
[
tile
][
layer
]
=
1
;
// center tile
for
(
int
dir
=
0
;
dir
<
TileNeibs
.
DIRS
;
dir
++)
{
if
(
connections
[
tile
][
layer
][
dir
]
!=
null
)
{
for
(
int
layer1
=
0
;
layer1
<
layers
;
layer1
++)
{
if
(
connections
[
tile
][
layer
][
dir
][
layer1
]
<=
1.0
)
{
// Double.NaN - OK
// num_neibs[tile][layer]++;
num_neibs_dir
[
tile
][
layer
]
|=
2
<<
dir
;
// 9 bits
break
;
// increment once per dir
}
}
}
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
if
(
debugLevel
>
0
)
{
String
[]
dbg_titles
=
{
"FG"
,
"BG"
};
double
[][]
dbg_img
=
new
double
[
layers
][
tiles
];
for
(
int
i
=
0
;
i
<
tiles
;
i
++)
{
for
(
int
j
=
0
;
j
<
dbg_img
.
length
;
j
++)
{
dbg_img
[
j
][
i
]
=
num_bits
[
num_neibs_dir
[
i
][
j
]];
}
}
(
new
ShowDoubleFloatArrays
()).
showArrays
(
dbg_img
,
tilesX
,
tilesY
,
true
,
"num_neibs"
,
dbg_titles
);
(
new
ShowDoubleFloatArrays
()).
showArrays
(
disparities
,
tilesX
,
tilesY
,
true
,
"disparities"
,
dbg_titles
);
}
final
ArrayList
<
TileCluster
>
cluster_list
=
new
ArrayList
<
TileCluster
>();
// build all clusters
int
tile_start
=
0
;
double
disparity
[]
=
new
double
[
tiles
];
// current cluster disparities
int
[]
tile_stat
=
new
int
[
tiles
];
// int [] tile_layer = new int [tiles]; // just to know which layer was used for assigned tiles
// int current_cluster = 0;
while
(
true
)
{
// find remaining tile with maximal number of neighbors (usually 8) - this will require num_neibs update
int
best_tile
=
-
1
,
best_layer
=
-
1
,
nn
=
0
;
find_start:
{
int
tile_end
=
tile_start
+
tiles
;
for
(
int
tile1
=
tile_start
;
tile1
<
tile_end
;
tile1
++)
{
int
tile
=
(
tile1
>=
tiles
)
?
(
tile1
-
tiles
)
:
tile1
;
if
(!
tn
.
isBorder
(
tile
))
{
// do not start on the border
for
(
int
layer
=
0
;
layer
<
layers
;
layer
++)
{
int
n_neibs
=
num_bits
[
num_neibs_dir
[
tile
][
layer
]];
if
((
ncluster
[
tile
][
layer
]
==
CLUSTER_UNASSIGNED
)
&&
(
n_neibs
>
nn
))
{
// not yet assigned and >=0 neibs
nn
=
n_neibs
;
best_tile
=
tile
;
best_layer
=
layer
;
if
(
nn
==
(
TileNeibs
.
DIRS
+
1
))
{
break
find_start
;
}
}
}
}
}
}
tile_start
=
best_tile
;
// will start from this
if
(
nn
==
0
)
{
// no even single-tile clusters are left
break
;
// no more seeds for clusters
}
Arrays
.
fill
(
tile_stat
,
0
);
ArrayList
<
Point
>
tile_layer_list
=
new
ArrayList
<
Point
>();
// pair of int x tile, int y - layer
Point
p0
=
new
Point
(
best_tile
,
best_layer
);
// First point will always be good
int
num_tiles
=
0
;
tile_layer_list
.
add
(
p0
);
while
(!
tile_layer_list
.
isEmpty
())
{
Point
p
=
tile_layer_list
.
remove
(
0
);
// p is a candidate, initially will always be approved
int
tile
=
p
.
x
;
int
layer
=
p
.
y
;
// see if the current tile candidate is a good one
boolean
confirm
=
false
;
disparity
[
tile
]
=
disparities
[
layer
][
tile
];
if
(
tn
.
isBorder
(
tile
))
{
tile_stat
[
tile
]
=
TILE_BORDER
;
}
else
{
confirm
=
true
;
for
(
int
dir
=
0
;
dir
<
TileNeibs
.
DIRS
;
dir
++)
{
int
tile1
=
tn
.
getNeibIndex
(
tile
,
dir
);
// should always be > 0 here
//is it a border tile or already confirmed one ?
if
((
tile_stat
[
tile1
]
==
TILE_BORDER
)
||
(
tile_stat
[
tile1
]
==
TILE_CONFIRMED
)){
double
mid_disp
=
Math
.
max
(
0.0
,
0.5
*(
disparities
[
layer
][
tile
]
+
disparity
[
tile1
]));
double
max_disp_diff
=
((
dir
&
1
)
==
0
)
?
(
disp_adiffo
+
mid_disp
*
disp_rdiffo
)
:
(
disp_adiffd
+
mid_disp
*
disp_rdiffd
);
max_disp_diff
*=
(
tile_stat
[
tile1
]
==
TILE_BORDER
)?
disp_border
:
disp_fof
;
if
((
Math
.
abs
(
disparities
[
layer
][
tile
]
-
disparity
[
tile1
])/
max_disp_diff
)
>
1.0
){
confirm
=
false
;
// too large diff
// make it a border tile, but keep disparity
// disparity[tile] = disparities[layer][tile];
tile_stat
[
tile
]
=
TILE_BORDER
;
break
;
}
}
}
}
if
(
confirm
)
{
if
(
debugLevel
>
1
)
{
System
.
out
.
println
(
"Confirmed tile "
+
tile
+
" (x="
+(
tile
%
tilesX
)+
", y="
+(
tile
/
tilesX
)+
") -> "
+
tile_stat
[
tile
]);
}
tile_stat
[
tile
]
=
TILE_CONFIRMED
;
ncluster
[
tile
][
layer
]
=
cluster_list
.
size
();
// current cluster number - Mark as assigned
// tile_layer[tile] = layer;
// right here - update number of neighbors for used tile
num_neibs_dir
[
tile
][
layer
]
=
0
;
// bitmap, 0- -center, 1..8 - up, ...
// update number of neighbors pointed here
num_tiles
++;
// counting only core tiles, not the border one
// look around (including layers - select best), add candidates (if fit) and mark borders (if does not fit)
for
(
int
dir
=
0
;
dir
<
TileNeibs
.
DIRS
;
dir
++)
{
int
tile1
=
tn
.
getNeibIndex
(
tile
,
dir
);
// should always be > 0 here
if
(
tile_stat
[
tile1
]
==
TILE_EMPTY
)
{
// Do not consider already assigned tiles for this cluster
// update neighbors bits (for number of neighbors calculation)
int
rdir
=
TileNeibs
.
reverseDir
(
dir
);
num_neibs_dir
[
tile
][
layer
]
&=
~(
2
<<
rdir
);
// zero out pointed to this tile
for
(
int
layer1
=
0
;
layer1
<
layers
;
layer1
++)
if
(
ncluster
[
tile1
][
layer1
]
==
CLUSTER_UNASSIGNED
)
{
// from where connection
// ncluster[tile][layer] is already assigned
for
(
int
layer2
=
0
;
layer2
<
layers
;
layer2
++)
if
(
ncluster
[
tile
][
layer2
]
==
CLUSTER_UNASSIGNED
){
// to where connection
if
(
connections
[
tile1
][
layer1
][
rdir
][
layer2
]
<=
1.0
)
{
// Double.NaN - OK
num_neibs_dir
[
tile
][
layer
]
|=
2
<<
rdir
;
// restore as there is another layer that fits
break
;
}
}
}
// does it have any layers in this direction?
int
layer1
=
-
1
;
int
layer_assigned
=
-
1
;
//earlier assigned, can not continue but use disparity
if
((
connections
[
tile
][
layer
]
!=
null
)
&&
(
connections
[
tile
][
layer
][
dir
]
!=
null
))
{
for
(
int
l
=
0
;
l
<
layers
;
l
++)
if
(
connections
[
tile
][
layer
][
dir
][
l
]
<=
1.0
){
// verify it was not already used. If used - use used disparity for the border
// **** (select correct layer for that border disparity
if
(
ncluster
[
tile1
][
l
]
==
CLUSTER_UNASSIGNED
)
{
if
((
layer1
<
0
)
||
(
connections
[
tile
][
layer
][
dir
][
l
]
<
connections
[
tile
][
layer
][
dir
][
layer1
]))
{
layer1
=
l
;
}
}
else
{
// already assigned to some cluster that was split
if
((
layer_assigned
<
0
)
||
(
connections
[
tile
][
layer
][
dir
][
l
]
<
connections
[
tile
][
layer
][
dir
][
layer_assigned
]))
{
layer_assigned
=
l
;
}
}
}
}
if
(
layer_assigned
>=
0
)
{
// already assigned to some cluster that was split
tile_stat
[
tile1
]
=
TILE_BORDER
;
disparity
[
tile1
]
=
disparities
[
layer_assigned
][
tile
];
// Use interrupted cluster disparity
}
else
if
((
layer1
<
0
)
||
(
connections
[
tile
][
layer
][
dir
][
layer1
]
>
1.0
))
{
// no connections in this direction - add border using same disparity as this tile
if
(
tile_stat
[
tile1
]
==
TILE_EMPTY
)
{
// not yet set (otherwise keep)
tile_stat
[
tile1
]
=
TILE_BORDER
;
disparity
[
tile1
]
=
disparity
[
tile
];
}
}
else
{
// connection exists, add tile1/layer1 as a candidate to the list
tile_stat
[
tile1
]
=
TILE_CANDIDATE
;
// to avoid suggesting the same tile multiple times
tile_layer_list
.
add
(
new
Point
(
tile1
,
layer1
));
}
}
}
}
// }
}
// while (!tile_layer_list.isEmpty())
if
(
num_tiles
>
0
)
{
// generate/add new cluster, update
// Create and crop cluster,(update neighbors?)
int
min_x
=
tilesX
,
min_y
=
tilesY
,
max_x
=
0
,
max_y
=
0
;
for
(
int
ty
=
0
;
ty
<
tilesY
;
ty
++)
{
for
(
int
tx
=
0
;
tx
<
tilesX
;
tx
++)
{
int
tile
=
ty
*
tilesX
+
tx
;
if
(
tile_stat
[
tile
]
!=
TILE_EMPTY
)
{
if
(
ty
>
max_y
)
max_y
=
ty
;
if
(
ty
<
min_y
)
min_y
=
ty
;
if
(
tx
>
max_x
)
max_x
=
tx
;
if
(
tx
<
min_x
)
min_x
=
tx
;
}
}
}
int
width
=
max_x
-
min_x
+
1
;
int
height
=
max_y
-
min_y
+
1
;
Rectangle
bounds
=
new
Rectangle
(
min_x
,
min_y
,
width
,
height
);
double
[]
disparity_crop
=
new
double
[
width
*
height
];
boolean
[]
border_crop
=
new
boolean
[
width
*
height
];
for
(
int
dty
=
0
;
dty
<
height
;
dty
++)
{
int
ty
=
min_y
+
dty
;
for
(
int
dtx
=
0
;
dtx
<
width
;
dtx
++)
{
int
tdest
=
dty
*
width
+
dtx
;
int
tsrc
=
ty
*
tilesX
+
min_x
+
dtx
;
border_crop
[
tdest
]
=
tile_stat
[
tsrc
]
==
TILE_BORDER
;
disparity_crop
[
tdest
]
=
(
tile_stat
[
tsrc
]
==
TILE_EMPTY
)
?
Double
.
NaN
:
disparity
[
tsrc
];
}
}
TileCluster
tileCluster
=
(
new
TileCluster
(
bounds
,
border_crop
,
disparity_crop
));
cluster_list
.
add
(
tileCluster
);
// update
}
else
{
if
(
debugLevel
>-
2
)
{
System
.
out
.
println
(
"clusterizeFgBg(): Empty cluster started from tile="
+
p0
.
x
+
", layer="
+
p0
.
y
);
}
}
}
// while (true) { - generating clusters
// consolidate clusters "good enough"
int
[]
comb_clusters
=
new
int
[
cluster_list
.
size
()];
Arrays
.
fill
(
comb_clusters
,-
1
);
int
this_combo
=
0
;
for
(;
;
this_combo
++)
{
// find first unassigned cluster
int
index_first
=
-
1
;
for
(
int
i
=
0
;
i
<
comb_clusters
.
length
;
i
++)
{
if
(
comb_clusters
[
i
]
<
0
)
{
index_first
=
i
;
break
;
}
}
if
(
index_first
<
0
)
{
break
;
// all clusters assigned
}
comb_clusters
[
index_first
]
=
this_combo
;
for
(
int
index_other
=
index_first
;
index_other
<
comb_clusters
.
length
;
index_other
++)
if
(
comb_clusters
[
index_other
]
<
0
)
{
// check to intersection with all prior clusters in this combo
candidate_cluster:
{
Rectangle
new_bounds
=
cluster_list
.
get
(
index_other
).
getBounds
();
for
(
int
index_already
=
index_first
;
index_already
<
index_other
;
index_already
++)
if
(
comb_clusters
[
index_already
]
==
this_combo
)
{
if
(
cluster_list
.
get
(
index_already
).
getBounds
().
intersects
(
new_bounds
))
{
break
candidate_cluster
;
// intersects - skip it
}
}
comb_clusters
[
index_other
]
=
this_combo
;
}
}
}
TileCluster
[]
consolidated_clusters
=
new
TileCluster
[
this_combo
];
Rectangle
full_tiles
=
new
Rectangle
(
0
,
0
,
tilesX
,
tilesY
);
for
(
int
i
=
0
;
i
<
this_combo
;
i
++)
{
consolidated_clusters
[
i
]
=
new
TileCluster
(
full_tiles
,
null
,
null
);
}
for
(
int
i
=
0
;
i
<
comb_clusters
.
length
;
i
++)
{
consolidated_clusters
[
comb_clusters
[
i
]].
add
(
cluster_list
.
get
(
i
));
}
if
(
debugLevel
>
0
)
{
double
[][]
dbg_img
=
new
double
[
this_combo
][
tiles
];
double
[][]
dbg_borders
=
new
double
[
this_combo
][
tiles
];
for
(
int
n
=
0
;
n
<
dbg_img
.
length
;
n
++)
{
for
(
int
i
=
0
;
i
<
tiles
;
i
++)
{
dbg_img
[
n
][
i
]
=
consolidated_clusters
[
n
].
getDisparity
()[
i
];
dbg_borders
[
n
][
i
]
=
consolidated_clusters
[
n
].
getBorder
()[
i
]?
1.0
:
0.0
;
}
}
(
new
ShowDoubleFloatArrays
()).
showArrays
(
dbg_img
,
tilesX
,
tilesY
,
true
,
"cluster_disparity"
);
(
new
ShowDoubleFloatArrays
()).
showArrays
(
dbg_borders
,
tilesX
,
tilesY
,
true
,
"cluster_borders"
);
}
return
consolidated_clusters
;
}
}
src/main/java/com/elphel/imagej/tileprocessor/TileCluster.java
0 → 100644
View file @
ca08b513
package
com
.
elphel
.
imagej
.
tileprocessor
;
/**
** TileCluster - clusters from disparity map to generate textured mesh
**
** Copyright (C) 2017 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** TileCluster.java is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
import
java.awt.Rectangle
;
import
java.util.Arrays
;
class
TileCluster
{
Rectangle
bounds
;
boolean
[]
border
;
double
[]
disparity
;
public
TileCluster
(
Rectangle
bounds
,
boolean
[]
border
,
double
[]
disparity
){
this
.
bounds
=
bounds
;
if
(
border
==
null
)
{
border
=
new
boolean
[
bounds
.
width
*
bounds
.
height
];
}
this
.
border
=
border
;
if
(
disparity
==
null
)
{
disparity
=
new
double
[
bounds
.
width
*
bounds
.
height
];
Arrays
.
fill
(
disparity
,
Double
.
NaN
);
}
this
.
disparity
=
disparity
;
}
public
Rectangle
getBounds
()
{
return
bounds
;}
public
boolean
[]
getBorder
()
{
return
border
;}
public
double
[]
getDisparity
()
{
return
disparity
;}
/*
public TileCluster combine (TileCluster tileCluster) {
TileCluster outer, inner;
if (bounds.contains(tileCluster.bounds)) {
outer = this;
inner = tileCluster;
} else if (tileCluster.bounds.contains(bounds)) {
outer = tileCluster;
inner = this;
} else {
Rectangle outer_bounds = bounds.union(tileCluster.bounds);
outer = new TileCluster(outer_bounds, null, null);
outer.combine(this); //
inner = tileCluster;
}
int dst_x = inner.bounds.x - outer.bounds.x;
for (int src_y = 0; src_y < bounds.height; src_y++) {
int dst_y = src_y + inner.bounds.y - outer.bounds.y;
System.arraycopy(
inner.border,
src_y * bounds.width,
outer.border,
dst_y * outer.bounds.width + dst_x,
bounds.width);
System.arraycopy(
inner.disparity,
src_y * bounds.width,
outer.disparity,
dst_y * outer.bounds.width + dst_x,
bounds.width);
}
return outer;
}
*/
public
void
add
(
TileCluster
tileCluster
)
{
if
(!
bounds
.
contains
(
tileCluster
.
bounds
))
{
throw
new
IllegalArgumentException
(
"TileCluster.add(): Added cluster should fit into this "
);
}
int
dst_x
=
tileCluster
.
bounds
.
x
-
bounds
.
x
;
for
(
int
src_y
=
0
;
src_y
<
tileCluster
.
bounds
.
height
;
src_y
++)
{
int
dst_y
=
src_y
+
tileCluster
.
bounds
.
y
-
bounds
.
y
;
System
.
arraycopy
(
tileCluster
.
border
,
src_y
*
tileCluster
.
bounds
.
width
,
border
,
dst_y
*
bounds
.
width
+
dst_x
,
tileCluster
.
bounds
.
width
);
System
.
arraycopy
(
tileCluster
.
disparity
,
src_y
*
tileCluster
.
bounds
.
width
,
disparity
,
dst_y
*
bounds
.
width
+
dst_x
,
tileCluster
.
bounds
.
width
);
}
return
;
}
}
\ No newline at end of file
src/main/java/com/elphel/imagej/tileprocessor/TileNeibs.java
View file @
ca08b513
...
@@ -39,10 +39,17 @@ public class TileNeibs{
...
@@ -39,10 +39,17 @@ public class TileNeibs{
final
public
static
int
DIR_LEFT
=
2
;
// Right
final
public
static
int
DIR_LEFT
=
2
;
// Right
final
public
static
int
DIR_DOWN
=
4
;
// Down
final
public
static
int
DIR_DOWN
=
4
;
// Down
final
public
static
int
DIR_RIGHT
=
6
;
// Left
final
public
static
int
DIR_RIGHT
=
6
;
// Left
final
public
static
int
DIRS
=
8
;
// total dirs
public
static
int
reverseDir
(
int
dir
)
{
if
((
dir
<
0
)
||
(
dir
>=
DIRS
))
{
return
dir
;
}
return
(
dir
+
DIRS
/
2
)
%
DIRS
;
}
int
sizeX
;
int
sizeX
;
int
sizeY
;
int
sizeY
;
public
int
dirs
=
8
;
public
int
dirs
=
DIRS
;
public
TileNeibs
(
int
size
){
public
TileNeibs
(
int
size
){
this
.
sizeX
=
size
;
this
.
sizeX
=
size
;
this
.
sizeY
=
size
;
this
.
sizeY
=
size
;
...
@@ -63,6 +70,12 @@ public class TileNeibs{
...
@@ -63,6 +70,12 @@ public class TileNeibs{
return
sizeX
*
sizeY
;
return
sizeX
*
sizeY
;
}
}
boolean
isBorder
(
int
indx
)
{
int
[]
xy
=
{
indx
%
sizeX
,
indx
/
sizeX
};
return
(
xy
[
0
]==
0
)
||
(
xy
[
1
]==
0
)
||
(
xy
[
0
]==
(
sizeX
-
1
))
||
(
xy
[
1
]==(
sizeY
-
1
));
}
/**
/**
* Get x,y pair from index
* Get x,y pair from index
* @param indx element index
* @param indx element index
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment