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
0ab422e2
Commit
0ab422e2
authored
Jun 02, 2017
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
removing foreground bridges
parent
971dd284
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
889 additions
and
946 deletions
+889
-946
Conflicts.java
src/main/java/Conflicts.java
+4
-4
ConnectionCosts.java
src/main/java/ConnectionCosts.java
+6
-6
LinkPlanes.java
src/main/java/LinkPlanes.java
+16
-5
SuperTiles.java
src/main/java/SuperTiles.java
+154
-489
TileNeibs.java
src/main/java/TileNeibs.java
+366
-0
TilePlanes.java
src/main/java/TilePlanes.java
+342
-289
TileProcessor.java
src/main/java/TileProcessor.java
+1
-15
TileSurface.java
src/main/java/TileSurface.java
+0
-138
No files found.
src/main/java/Conflicts.java
View file @
0ab422e2
...
@@ -284,7 +284,7 @@ public class Conflicts {
...
@@ -284,7 +284,7 @@ public class Conflicts {
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
nStiles
=
stilesX
*
stilesY
;
final
int
nStiles
=
stilesX
*
stilesY
;
final
int
[][][]
conflicts
=
new
int
[
st
.
getPlanes
().
length
][][];
final
int
[][][]
conflicts
=
new
int
[
st
.
getPlanes
().
length
][][];
final
Tile
Surface
.
TileNeibs
tnSurface
=
st
.
getTileSurface
().
new
TileNeibs
(
stilesX
,
stilesY
);
final
Tile
Neibs
tnSurface
=
new
TileNeibs
(
stilesX
,
stilesY
);
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
st
.
getTileProcessor
().
threadsMax
);
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
st
.
getTileProcessor
().
threadsMax
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
...
@@ -343,7 +343,7 @@ public class Conflicts {
...
@@ -343,7 +343,7 @@ public class Conflicts {
HashMap
<
Integer
,
Integer
>
replacement_tiles
,
// null is OK
HashMap
<
Integer
,
Integer
>
replacement_tiles
,
// null is OK
int
[][][]
replacement_neibs
,
// null OK if replacement_tiles == null
int
[][][]
replacement_neibs
,
// null OK if replacement_tiles == null
double
[][][]
replacement_val_weights
,
double
[][][]
replacement_val_weights
,
Tile
Surface
.
Tile
Neibs
tnSurface
)
TileNeibs
tnSurface
)
{
{
TilePlanes
.
PlaneData
[][]
planes
=
st
.
getPlanes
();
TilePlanes
.
PlaneData
[][]
planes
=
st
.
getPlanes
();
// generate conflicts if not provided
// generate conflicts if not provided
...
@@ -405,7 +405,7 @@ public class Conflicts {
...
@@ -405,7 +405,7 @@ public class Conflicts {
HashMap
<
Integer
,
Integer
>
replacement_tiles
,
// null is OK
HashMap
<
Integer
,
Integer
>
replacement_tiles
,
// null is OK
int
[][][]
replacement_neibs
,
// null OK if replacement_tiles == null
int
[][][]
replacement_neibs
,
// null OK if replacement_tiles == null
ConnectionCosts
connectionCosts
,
ConnectionCosts
connectionCosts
,
Tile
Surface
.
Tile
Neibs
tnSurface
)
TileNeibs
tnSurface
)
{
{
TilePlanes
.
PlaneData
[][]
planes
=
st
.
getPlanes
();
TilePlanes
.
PlaneData
[][]
planes
=
st
.
getPlanes
();
// generate conflicts if not provided
// generate conflicts if not provided
...
@@ -465,7 +465,7 @@ public class Conflicts {
...
@@ -465,7 +465,7 @@ public class Conflicts {
int
nsTile0
,
int
nsTile0
,
HashMap
<
Integer
,
Integer
>
replacement_tiles
,
// null is OK - will use only planes data
HashMap
<
Integer
,
Integer
>
replacement_tiles
,
// null is OK - will use only planes data
int
[][][]
replacement_neibs
,
// null OK if replacement_tiles == null
int
[][][]
replacement_neibs
,
// null OK if replacement_tiles == null
Tile
Surface
.
Tile
Neibs
tnSurface
)
TileNeibs
tnSurface
)
{
{
TilePlanes
.
PlaneData
[][]
planes
=
st
.
getPlanes
();
TilePlanes
.
PlaneData
[][]
planes
=
st
.
getPlanes
();
ArrayList
<
Conflict
>
conflicts_list
=
new
ArrayList
<
Conflict
>();
ArrayList
<
Conflict
>
conflicts_list
=
new
ArrayList
<
Conflict
>();
...
...
src/main/java/ConnectionCosts.java
View file @
0ab422e2
...
@@ -28,7 +28,7 @@ import java.util.HashSet;
...
@@ -28,7 +28,7 @@ import java.util.HashSet;
public
class
ConnectionCosts
{
public
class
ConnectionCosts
{
TilePlanes
.
PlaneData
[][]
planes
=
null
;
TilePlanes
.
PlaneData
[][]
planes
=
null
;
boolean
preferDisparity
=
false
;
boolean
preferDisparity
=
false
;
Tile
Surface
.
Tile
Neibs
tnSurface
;
TileNeibs
tnSurface
;
double
orthoWeight
;
double
orthoWeight
;
double
diagonalWeight
;
double
diagonalWeight
;
double
starPwr
;
// Divide cost by number of connections to this power
double
starPwr
;
// Divide cost by number of connections to this power
...
@@ -57,7 +57,7 @@ public class ConnectionCosts {
...
@@ -57,7 +57,7 @@ public class ConnectionCosts {
double
starValPwr
,
// Raise value of each tile before averaging
double
starValPwr
,
// Raise value of each tile before averaging
int
steps
,
int
steps
,
TilePlanes
.
PlaneData
[][]
planes
,
TilePlanes
.
PlaneData
[][]
planes
,
Tile
Surface
.
Tile
Neibs
tnSurface
,
TileNeibs
tnSurface
,
boolean
preferDisparity
)
boolean
preferDisparity
)
{
{
this
.
planes
=
planes
;
this
.
planes
=
planes
;
...
@@ -481,7 +481,7 @@ public class ConnectionCosts {
...
@@ -481,7 +481,7 @@ public class ConnectionCosts {
double
diagonalWeight
,
double
diagonalWeight
,
double
starPwr
,
// Divide cost by number of connections to this power
double
starPwr
,
// Divide cost by number of connections to this power
double
starWeightPwr
,
// Use this power of tile weight when calculating connection cost
double
starWeightPwr
,
// Use this power of tile weight when calculating connection cost
Tile
Surface
.
Tile
Neibs
tnSurface
,
TileNeibs
tnSurface
,
boolean
preferDisparity
,
boolean
preferDisparity
,
int
debugLevel
)
int
debugLevel
)
{
{
...
@@ -506,7 +506,7 @@ public class ConnectionCosts {
...
@@ -506,7 +506,7 @@ public class ConnectionCosts {
double
diagonalWeight
,
double
diagonalWeight
,
double
starPwr
,
// Divide cost by number of connections to this power
double
starPwr
,
// Divide cost by number of connections to this power
double
starWeightPwr
,
// Use this power of tile weight when calculating connection cost
double
starWeightPwr
,
// Use this power of tile weight when calculating connection cost
Tile
Surface
.
Tile
Neibs
tnSurface
,
TileNeibs
tnSurface
,
boolean
preferDisparity
,
boolean
preferDisparity
,
int
debugLevel
)
int
debugLevel
)
{
{
...
@@ -566,7 +566,7 @@ public class ConnectionCosts {
...
@@ -566,7 +566,7 @@ public class ConnectionCosts {
double
diagonalWeight
,
double
diagonalWeight
,
double
starPwr
,
// Divide cost by number of connections to this power
double
starPwr
,
// Divide cost by number of connections to this power
double
starWeightPwr
,
// Use this power of tile weight when calculating connection cost
double
starWeightPwr
,
// Use this power of tile weight when calculating connection cost
Tile
Surface
.
Tile
Neibs
tnSurface
,
TileNeibs
tnSurface
,
boolean
preferDisparity
,
boolean
preferDisparity
,
int
debugLevel
)
int
debugLevel
)
{
{
...
@@ -594,7 +594,7 @@ public class ConnectionCosts {
...
@@ -594,7 +594,7 @@ public class ConnectionCosts {
double
diagonalWeight
,
double
diagonalWeight
,
double
starPwr
,
// Divide cost by number of connections to this power
double
starPwr
,
// Divide cost by number of connections to this power
double
starWeightPwr
,
// Use this power of tile weight when calculating connection cost
double
starWeightPwr
,
// Use this power of tile weight when calculating connection cost
Tile
Surface
.
Tile
Neibs
tnSurface
,
TileNeibs
tnSurface
,
boolean
preferDisparity
,
boolean
preferDisparity
,
int
debugLevel
)
int
debugLevel
)
{
{
...
...
src/main/java/LinkPlanes.java
View file @
0ab422e2
...
@@ -813,6 +813,17 @@ public class LinkPlanes {
...
@@ -813,6 +813,17 @@ public class LinkPlanes {
ImageDtt
.
startAndJoin
(
threads
);
ImageDtt
.
startAndJoin
(
threads
);
}
}
/**
* Merge the supertile planes with agreeing neighbors, non-exclusively (no considering other planes
* of the same supertile. Start with the best fit, then goes to lower quality, until the individual
* merge quality falls below scaled quality of the best, pre-set minimum or the merged plane becomes
* too thick
* Separately calculates merged weighted plane and with equal weights of the neighbors
* @param planes array of plane instances for the same supertile
* @param debugLevel
* @param dbg_X
* @param dbg_Y
*/
public
void
setNonExclusive
(
public
void
setNonExclusive
(
final
TilePlanes
.
PlaneData
[][]
planes
,
final
TilePlanes
.
PlaneData
[][]
planes
,
final
int
debugLevel
,
final
int
debugLevel
,
...
@@ -834,7 +845,7 @@ public class LinkPlanes {
...
@@ -834,7 +845,7 @@ public class LinkPlanes {
// final int debug_stile = 9 * stilesX + 26;
// final int debug_stile = 9 * stilesX + 26;
final
int
debug_stile
=
dbg_Y
*
stilesX
+
dbg_X
;
final
int
debug_stile
=
dbg_Y
*
stilesX
+
dbg_X
;
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
st
.
tileProcessor
.
threadsMax
);
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
(
debugLevel
>
1
)?
1
:
st
.
tileProcessor
.
threadsMax
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
...
@@ -2426,7 +2437,7 @@ public class LinkPlanes {
...
@@ -2426,7 +2437,7 @@ public class LinkPlanes {
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
nStiles
=
stilesX
*
stilesY
;
final
int
nStiles
=
stilesX
*
stilesY
;
final
Tile
Surface
.
TileNeibs
tnSurface
=
st
.
tileSurface
.
new
TileNeibs
(
stilesX
,
stilesY
);
final
Tile
Neibs
tnSurface
=
new
TileNeibs
(
stilesX
,
stilesY
);
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
st
.
tileProcessor
.
threadsMax
);
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
st
.
tileProcessor
.
threadsMax
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
...
@@ -2441,7 +2452,7 @@ public class LinkPlanes {
...
@@ -2441,7 +2452,7 @@ public class LinkPlanes {
starValPwr
,
//double starValPwr, // Raise value of each tile before averaging
starValPwr
,
//double starValPwr, // Raise value of each tile before averaging
steps
,
// int steps,
steps
,
// int steps,
planes
,
// TilePlanes.PlaneData [][] planes,
planes
,
// TilePlanes.PlaneData [][] planes,
tnSurface
,
// Tile
Surface.Tile
Neibs tnSurface,
tnSurface
,
// TileNeibs tnSurface,
preferDisparity
);
// boolean preferDisparity)
preferDisparity
);
// boolean preferDisparity)
int
[]
mod_supertiles
=
new
int
[
1
];
int
[]
mod_supertiles
=
new
int
[
1
];
for
(
int
nsTile
=
ai
.
getAndIncrement
();
nsTile
<
nStiles
;
nsTile
=
ai
.
getAndIncrement
())
{
for
(
int
nsTile
=
ai
.
getAndIncrement
();
nsTile
<
nStiles
;
nsTile
=
ai
.
getAndIncrement
())
{
...
@@ -2484,7 +2495,7 @@ public class LinkPlanes {
...
@@ -2484,7 +2495,7 @@ public class LinkPlanes {
// final int tileSize = tileProcessor.getTileSize();
// final int tileSize = tileProcessor.getTileSize();
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
Tile
Surface
.
TileNeibs
tnSurface
=
st
.
tileSurface
.
new
TileNeibs
(
stilesX
,
stilesY
);
final
Tile
Neibs
tnSurface
=
new
TileNeibs
(
stilesX
,
stilesY
);
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
st
.
tileProcessor
.
threadsMax
);
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
st
.
tileProcessor
.
threadsMax
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
...
@@ -2499,7 +2510,7 @@ public class LinkPlanes {
...
@@ -2499,7 +2510,7 @@ public class LinkPlanes {
starValPwr
,
//double starValPwr, // Raise value of each tile before averaging
starValPwr
,
//double starValPwr, // Raise value of each tile before averaging
steps
,
// int steps,
steps
,
// int steps,
planes
,
// TilePlanes.PlaneData [][] planes,
planes
,
// TilePlanes.PlaneData [][] planes,
tnSurface
,
// Tile
Surface.Tile
Neibs tnSurface,
tnSurface
,
// TileNeibs tnSurface,
preferDisparity
);
// boolean preferDisparity)
preferDisparity
);
// boolean preferDisparity)
int
[]
supertiles
=
new
int
[
1
];
int
[]
supertiles
=
new
int
[
1
];
for
(
int
isTile
=
ai
.
getAndIncrement
();
isTile
<
mod_supertiles
.
length
;
isTile
=
ai
.
getAndIncrement
())
{
for
(
int
isTile
=
ai
.
getAndIncrement
();
isTile
<
mod_supertiles
.
length
;
isTile
=
ai
.
getAndIncrement
())
{
...
...
src/main/java/SuperTiles.java
View file @
0ab422e2
...
@@ -1025,147 +1025,6 @@ public class SuperTiles{
...
@@ -1025,147 +1025,6 @@ public class SuperTiles{
return
bgTileDispStrength
;
return
bgTileDispStrength
;
}
}
public
void
processPlanes
(
final
boolean
[]
selected
,
// or null
final
double
min_disp
,
final
boolean
invert_disp
,
// use 1/disparity
final
double
plDispNorm
,
final
int
debugLevel
)
{
final
int
tilesX
=
tileProcessor
.
getTilesX
();
final
int
tilesY
=
tileProcessor
.
getTilesY
();
final
int
superTileSize
=
tileProcessor
.
getSuperTileSize
();
final
int
tileSize
=
tileProcessor
.
getTileSize
();
final
double
[]
disparity
=
cltPass3d
.
getDisparity
();
final
double
[]
strength
=
cltPass3d
.
getStrength
();
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
nStiles
=
stilesX
*
stilesY
;
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
tileProcessor
.
threadsMax
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
final
int
st_start
=
-
superTileSize
/
2
;
final
int
superTileSize2
=
2
*
superTileSize
;
final
double
[][]
lapWeight
=
getLapWeights
();
final
int
len2
=
superTileSize2
*
superTileSize2
;
final
double
[]
double_zero
=
new
double
[
len2
];
final
boolean
[]
boolean_zero
=
new
boolean
[
len2
];
final
int
debug_stile
=
18
*
stilesX
+
25
;
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
public
void
run
()
{
TilePlanes
tpl
=
new
TilePlanes
(
tileSize
,
superTileSize
);
double
[]
stDisparity
=
new
double
[
superTileSize2
*
superTileSize2
];
double
[]
stStrength
=
new
double
[
superTileSize2
*
superTileSize2
];
boolean
[]
stSel
=
new
boolean
[
superTileSize2
*
superTileSize2
];
for
(
int
nsTile
=
ai
.
getAndIncrement
();
nsTile
<
nStiles
;
nsTile
=
ai
.
getAndIncrement
())
{
int
stileY
=
nsTile
/
stilesX
;
int
stileX
=
nsTile
%
stilesX
;
double
sw
=
0.0
;
// sum weights
double
[]
hist
=
new
double
[
numBins
];
int
tY0
=
stileY
*
superTileSize
+
st_start
;
int
tX0
=
stileX
*
superTileSize
+
st_start
;
System
.
arraycopy
(
double_zero
,
0
,
stDisparity
,
0
,
len2
);
System
.
arraycopy
(
double_zero
,
0
,
stStrength
,
0
,
len2
);
System
.
arraycopy
(
boolean_zero
,
0
,
stSel
,
0
,
len2
);
for
(
int
tY
=
0
;
tY
<
superTileSize2
;
tY
++){
int
tileY
=
tY0
+
tY
;
if
((
tileY
>=
0
)
&&
(
tileY
<
tilesY
))
{
for
(
int
tX
=
0
;
tX
<
superTileSize2
;
tX
++){
int
tileX
=
tX0
+
tX
;
if
((
tileX
>=
0
)
&&
(
tileX
<
tilesX
))
{
int
indx
=
tileY
*
tilesX
+
tileX
;
double
d
=
disparity
[
indx
];
if
(!
Double
.
isNaN
(
d
)
&&
(
d
>=
min_disp
)
&&((
selected
==
null
)
||
selected
[
indx
])){
if
(
invert_disp
){
d
=
1.0
/
d
;
}
double
w
=
strength
[
indx
]
-
strength_floor
;
if
(
w
>
0.0
){
if
(
strength_pow
!=
1.0
)
w
=
Math
.
pow
(
w
,
strength_pow
);
w
*=
lapWeight
[
tY
][
tX
];
int
indx_out
=
tY
*
superTileSize2
+
tX
;
stDisparity
[
indx_out
]
=
d
;
stStrength
[
indx_out
]
=
w
;
stSel
[
indx_out
]
=
true
;
sw
+=
w
;
}
}
}
}
}
}
if
(
sw
>
0
){
// int dl = ((nsTile >= debug_stile-1) && (nsTile <= debug_stile+1) ) ? 1 : 0;
// int dl = (stileY == 17) ? 1 : 0;
int
dl
=
(
stileY
>=
0
)
?
1
:
0
;
double
[][][]
rslt
=
tpl
.
getCovar
(
stDisparity
,
stStrength
,
stSel
,
plDispNorm
,
0
);
// dl); // debugLevel);
if
(
dl
>
0
)
{
int
numPoints
=
(
int
)
rslt
[
2
][
0
][
2
];
double
kz
=
rslt
[
2
][
0
][
1
];
double
swc
=
rslt
[
2
][
0
][
0
];
double
[]
szxy
=
rslt
[
2
][
1
];
double
[][]
eig_val
=
rslt
[
0
];
double
[][]
eig_vect
=
rslt
[
1
];
if
(
swc
>
1.0
)
{
System
.
out
.
println
(
"Processing planes, nsTile="
+
nsTile
+
", stileX="
+
stileX
+
", stileY="
+
stileY
+
", numPoints="
+
numPoints
+
", kz = "
+
kz
+
", sw = "
+
sw
+
", swc = "
+
swc
+
", center=["
+
szxy
[
0
]+
","
+
szxy
[
1
]+
","
+
szxy
[
2
]+
"]"
+
", eig_val = {"
+
eig_val
[
0
][
0
]+
","
+
eig_val
[
1
][
1
]+
","
+
eig_val
[
2
][
2
]+
"}"
+
", eig_vect[0] = {"
+
eig_vect
[
0
][
0
]+
","
+
eig_vect
[
1
][
0
]+
","
+
eig_vect
[
2
][
0
]+
"}"
);
}
}
/*
double [][][] rslt = {
eig.getD().getArray(),
eig.getV().getArray(),
{
{sw,kz},
{swz, swx, swy}}};
return rslt;
*/
if
(
dl
>
1
)
{
System
.
out
.
println
(
"Processing planes with average disparity"
);
double
ss
=
0.0
,
sd
=
0.0
;
for
(
int
i
=
0
;
i
<
stDisparity
.
length
;
i
++){
if
(!
Double
.
isNaN
(
stDisparity
[
i
])
&&
stSel
[
i
]){
ss
+=
stStrength
[
i
];
sd
+=
stStrength
[
i
]
*
stDisparity
[
i
];
}
}
if
(
ss
>
0
)
{
sd
/=
ss
;
}
for
(
int
i
=
0
;
i
<
stDisparity
.
length
;
i
++){
stDisparity
[
i
]
=
sd
;
}
tpl
.
getCovar
(
stDisparity
,
stStrength
,
stSel
,
plDispNorm
,
dl
);
// debugLevel);
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
}
public
double
corrMaxEigen
(
public
double
corrMaxEigen
(
double
maxEigen
,
double
maxEigen
,
...
@@ -1766,13 +1625,38 @@ public class SuperTiles{
...
@@ -1766,13 +1625,38 @@ public class SuperTiles{
return
plane_selections
;
return
plane_selections
;
}
}
// use both horizontal and const disparity tiles to create tile clusters
/**
// Add max_diff (maximal disparity difference while extracting initial tile selection) and max_tries (2..3) parameters
* Use both horizontal and const disparity tiles to create tile clusters
*Add max_diff (maximal disparity difference while extracting initial tile selection) and max_tries (2..3) parameters
// Add separate method to create + remove outliers from all planes (2 different ones)?
* Add separate method to create + remove outliers from all planes (2 different ones)?
// TODO later re-assign pixels according to existing plane parameters
* TODO later re-assign pixels according to existing plane parameters
// Sort plane data by center (plane or supertile) disparity
* Sort plane data by center (plane or supertile) disparity
*
* @param growSelection
* @param stMeasSel
* @param plDispNorm
* @param plMinPoints
* @param plPreferDisparity
* @param geometryCorrection
* @param correct_distortions
* @param smplMode
* @param smplSide
* @param smplNum
* @param smplRms
* @param bin_blur_hor
* @param bin_blur_vert
* @param max_diff_hor
* @param max_diff_vert
* @param max_tries
* @param smallDiff
* @param highMix
* @param world_hor
* @param debugLevel
* @param dbg_X
* @param dbg_Y
* @return
*/
public
boolean
[][][][]
initialDiscriminateTiles
(
public
boolean
[][][][]
initialDiscriminateTiles
(
final
int
growSelection
,
// grow initial selection before processing
final
int
growSelection
,
// grow initial selection before processing
final
int
stMeasSel
,
// = 1; // Select measurements for supertiles : +1 - combo, +2 - quad +4 - hor +8 - vert
final
int
stMeasSel
,
// = 1; // Select measurements for supertiles : +1 - combo, +2 - quad +4 - hor +8 - vert
...
@@ -2057,16 +1941,37 @@ public class SuperTiles{
...
@@ -2057,16 +1941,37 @@ public class SuperTiles{
}
}
return
planes_selections
;
return
planes_selections
;
}
}
public
TilePlanes
.
PlaneData
[][]
createPlanesFromSelectionsOld
(
/**
final
boolean
[][][][]
plane_selections
,
// = new boolean [nStiles][][][]; // num_tiles
* Re-assign tiles to the planes according to fitted planes. Scans each known plane parallel with specified
final
double
[][][][]
disp_strength
,
* size steps and specified number of steps, maximizing overall fit quality.
* Total weight of the fitted tiles? RMS?
* @param planes per-supertile, per plane array of plane data instances. Should have
* nonexclusiveStar and nonexclusiveStarEq calculated
* @param plDispNorm - normalization of the measured disparity precision - closer objects will have disparity
* difference proportionally reduced
* @param plMinPoints minimal number of points in a plane
* @param plPreferDisparity kept for historical reasons - when true, select disparity-most vector even if it has higher eigenvalue
* @param geometryCorrection GeometryCorrection instance to use
* @param correct_distortions correct geometrical distortions when converting to/from world coordinates
* @param smplMode sample mode
* @param smplSide sample side for averaging/filtering tile disparities
* @param smplNum number of best samples used fro averaging
* @param smplRms maximal sample disparity rms to consider sample valid
* @param max_disp_diff maximal disparity difference from the planes
* @param disp_step disparity scan step when searching for optimal fit
* @param steps_per_plane number of disparity steps to try around initial plane
* @param mode which of the calculated planes to use - 0 - weighted, 1 - equalized, 2 heaviest of the two, weighted combination
* @param debugLevel debug level
* @param dbg_X supertile X for elevated debug level
* @param dbg_Y supertile X for elevated debug level
* @return per-tile, per plane, per measurement layer (type of correlation - combo, 4, hor, vert), per tile selections of
* filtered tiles
*/
public
boolean
[][][][]
refineDiscriminateTiles
(
final
TilePlanes
.
PlaneData
[][]
planes
,
final
double
plDispNorm
,
final
double
plDispNorm
,
final
int
plMinPoints
,
// = 5; // Minimal number of points for plane detection
final
int
plMinPoints
,
// = 5; // Minimal number of points for plane detection
final
double
plTargetEigen
,
// = 0.1; // Remove outliers until main axis eigenvalue (possibly scaled by plDispNorm) gets below
final
double
plFractOutliers
,
// = 0.3; // Maximal fraction of outliers to remove
final
int
plMaxOutliers
,
// = 20; // Maximal number of outliers to remove
// final double plVertWors, // = 1.5 // if rotating plane vertical does not increase 'eigenvalue' more, use vertical
final
boolean
plPreferDisparity
,
// Always start with disparity-most axis (false - lowest eigenvalue)
final
boolean
plPreferDisparity
,
// Always start with disparity-most axis (false - lowest eigenvalue)
final
GeometryCorrection
geometryCorrection
,
final
GeometryCorrection
geometryCorrection
,
final
boolean
correct_distortions
,
final
boolean
correct_distortions
,
...
@@ -2075,185 +1980,23 @@ public class SuperTiles{
...
@@ -2075,185 +1980,23 @@ public class SuperTiles{
final
int
smplSide
,
// = 2; // Sample size (side of a square)
final
int
smplSide
,
// = 2; // Sample size (side of a square)
final
int
smplNum
,
// = 3; // Number after removing worst
final
int
smplNum
,
// = 3; // Number after removing worst
final
double
smplRms
,
// = 0.1; // Maximal RMS of the remaining tiles in a sample
final
double
smplRms
,
// = 0.1; // Maximal RMS of the remaining tiles in a sample
final
double
max_disp_diff
,
// maximal disparity difference from the plane to consider tile
final
double
disp_step
,
// parallel move known planes around original know value for the best overall fit
final
int
steps_per_plane
,
// number of steps for each plane to search for the best fit
final
int
mode
,
// 0 - weighted, 1 - equalized, 2 - best, 3 - combined
final
int
debugLevel
,
final
int
debugLevel
,
final
int
dbg_X
,
final
int
dbg_X
,
final
int
dbg_Y
)
final
int
dbg_Y
)
{
{
final
int
tilesX
=
tileProcessor
.
getTilesX
();
// create a list of usable planes according to the mode
final
int
tilesY
=
tileProcessor
.
getTilesY
();
final
int
superTileSize
=
tileProcessor
.
getSuperTileSize
();
final
int
tileSize
=
tileProcessor
.
getTileSize
();
return
null
;
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
nStiles
=
stilesX
*
stilesY
;
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
tileProcessor
.
threadsMax
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
final
TilePlanes
.
PlaneData
[][]
result_planes
=
new
TilePlanes
.
PlaneData
[
nStiles
][];
// this.planes = new TilePlanes.PlaneData[nStiles][];
final
int
debug_stile
=
(
debugLevel
>
-
1
)?
(
dbg_Y
*
stilesX
+
dbg_X
):-
1
;
// TODO: Remove when promoting PlaneData
final
TilePlanes
tpl
=
new
TilePlanes
(
tileSize
,
superTileSize
,
geometryCorrection
);
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
public
void
run
()
{
for
(
int
nsTile
=
ai
.
getAndIncrement
();
nsTile
<
nStiles
;
nsTile
=
ai
.
getAndIncrement
())
{
if
(
nsTile
==
debug_stile
){
System
.
out
.
println
(
"createPlanesFromSelections(): nsTile="
+
nsTile
);
}
if
(
plane_selections
[
nsTile
]
!=
null
)
{
int
stileY
=
nsTile
/
stilesX
;
int
stileX
=
nsTile
%
stilesX
;
int
[]
sTiles
=
{
stileX
,
stileY
};
int
dl
=
(
nsTile
==
debug_stile
)
?
3
:
0
;
result_planes
[
nsTile
]
=
null
;
// first make a plane from all tiles
ArrayList
<
TilePlanes
.
PlaneData
>
st_planes
=
new
ArrayList
<
TilePlanes
.
PlaneData
>();
TilePlanes
.
PlaneData
pd0
=
tpl
.
new
PlaneData
(
sTiles
,
// int [] sTileXY,
tileSize
,
// int tileSize,
geometryCorrection
,
// GeometryCorrection geometryCorrection,
correct_distortions
,
measuredLayers
,
// MeasuredLayers measuredLayers,
plPreferDisparity
);
// boolean preferDisparity)
// iterate through all plane selections
for
(
int
ps
=
0
;
ps
<
plane_selections
[
nsTile
].
length
;
ps
++)
{
TilePlanes
.
PlaneData
pd
=
pd0
.
clone
();
boolean
OK
=
(
pd
.
getPlaneFromMeas
(
plane_selections
[
nsTile
][
ps
],
// tile_sel, // boolean [][] tile_sel, // null - do not use, {} use all (will be modified)
disp_strength
[
nsTile
],
Double
.
NaN
,
// double disp_far, // minimal disparity to select (or NaN)
Double
.
NaN
,
// double disp_near, // maximal disparity to select (or NaN)
plDispNorm
,
// 0.0, // plDispNorm, // double dispNorm, // Normalize disparities to the average if above
0.0
,
// double min_weight,
plMinPoints
,
// int min_tiles,
strength_floor
,
//
strength_pow
,
// double strength_pow,
// update !
smplMode
,
smplSide
,
smplNum
,
smplRms
,
dl
)
!=
null
);
// int debugLevel)
if
(
OK
)
{
if
(
dl
>
0
)
{
if
(
pd
.
getWeight
()
>
1.0
)
{
System
.
out
.
println
(
"Processing subplane["
+
nsTile
+
"]["
+
ps
+
"]"
+
", stileX="
+
stileX
+
", stileY="
+
stileY
+
", numPoints="
+
pd
.
getNumPoints
()+
", swc = "
+
pd
.
getWeight
()+
", center=["
+
pd
.
getZxy
()[
0
]+
","
+
pd
.
getZxy
()[
1
]+
","
+
pd
.
getZxy
()[
2
]+
"]"
+
", eig_val = {"
+
pd
.
getValues
()[
0
]+
","
+
pd
.
getValues
()[
1
]+
","
+
pd
.
getValues
()[
2
]+
"}"
+
", eig_vect[0] = {"
+
pd
.
getVector
()[
0
]+
","
+
pd
.
getVector
()[
1
]+
","
+
pd
.
getVector
()[
2
]+
"}"
);
}
}
// now try to remove outliers
int
max_outliers
=
(
int
)
Math
.
round
(
pd
.
getNumPoints
()
*
plFractOutliers
);
if
(
max_outliers
>
plMaxOutliers
)
max_outliers
=
plMaxOutliers
;
double
targetV
=
plTargetEigen
;
double
z0
=
pd
.
getZxy
()[
0
];
if
((
plDispNorm
>
0.0
)
&&
(
z0
>
plDispNorm
))
{
double
dd
=
(
plDispNorm
+
z0
)/
plDispNorm
;
// > 1
targetV
*=
dd
*
dd
;
// > original
}
if
(
pd
.
getValues
()[
0
]
>
targetV
)
{
OK
=
pd
.
removeOutliers
(
// getPlaneFromMeas should already have run
disp_strength
[
nsTile
],
targetV
,
// double targetEigen, // target eigenvalue for primary axis (is disparity-dependent, so is non-constant)
max_outliers
,
// int maxRemoved, // maximal number of tiles to remove (not a constant)
dl
);
// int debugLevel)
if
(!
OK
)
{
continue
;
}
if
(
dl
>
0
)
{
if
(
pd
.
getWeight
()
>
1.0
)
{
System
.
out
.
println
(
"Removed outliers["
+
nsTile
+
"]["
+
ps
+
"]"
+
", stileX="
+
stileX
+
", stileY="
+
stileY
+
", numPoints="
+
pd
.
getNumPoints
()+
", swc = "
+
pd
.
getWeight
()+
", center=["
+
pd
.
getZxy
()[
0
]+
","
+
pd
.
getZxy
()[
1
]+
","
+
pd
.
getZxy
()[
2
]+
"]"
+
", eig_val = {"
+
pd
.
getValues
()[
0
]+
","
+
pd
.
getValues
()[
1
]+
","
+
pd
.
getValues
()[
2
]+
"}"
+
", eig_vect[0] = {"
+
pd
.
getVector
()[
0
]+
","
+
pd
.
getVector
()[
1
]+
","
+
pd
.
getVector
()[
2
]+
"}"
);
}
}
}
double
[]
norm_xyz
=
pd
.
getWorldXYZ
(
correct_distortions
);
st_planes
.
add
(
pd
);
if
(
dl
>
0
)
{
System
.
out
.
println
(
"World normal["
+
nsTile
+
"]["
+
ps
+
"] = {"
+
norm_xyz
[
0
]+
", "
+
norm_xyz
[
1
]+
", "
+
norm_xyz
[
2
]+
"}"
);
}
// calculate the world planes too
// if (debugLevel > -1){
pd
.
getWorldPlaneFromMeas
(
plane_selections
[
nsTile
][
ps
],
// tile_sel, // boolean [][] tile_sel, // null - do not use, {} use all (will be modified)
disp_strength
[
nsTile
],
Double
.
NaN
,
// double disp_far, // minimal disparity to select (or NaN)
Double
.
NaN
,
// double disp_near, // maximal disparity to select (or NaN)
plDispNorm
,
// 0.0, // plDispNorm, // double dispNorm, // Normalize disparities to the average if above
0.0
,
// double min_weight,
plMinPoints
,
// int min_tiles,
strength_floor
,
//
strength_pow
,
// double strength_pow,
// update !
smplMode
,
smplSide
,
smplNum
,
smplRms
,
dl
);
// }
}
}
if
(
st_planes
.
size
()
>
0
){
// sort planes by increasing disparity (tile center or plane center ? ) Using plane center
Collections
.
sort
(
st_planes
,
new
Comparator
<
TilePlanes
.
PlaneData
>()
{
@Override
public
int
compare
(
TilePlanes
.
PlaneData
lhs
,
TilePlanes
.
PlaneData
rhs
)
{
// -1 - less than, 1 - greater than, 0 - equal
return
(
rhs
.
getZxy
()[
0
]
>
lhs
.
getZxy
()[
0
])
?
-
1
:
(
rhs
.
getZxy
()[
0
]
<
lhs
.
getZxy
()[
0
]
)
?
1
:
0
;
}
});
if
(
LOWEST_PLANE
(
2
)
>
0
)
st_planes
.
add
(
0
,
st_planes
.
get
(
0
));
// insert dummy at pos 0;
result_planes
[
nsTile
]
=
st_planes
.
toArray
(
new
TilePlanes
.
PlaneData
[
0
]
);
if
(
LOWEST_PLANE
(
2
)
>
0
)
result_planes
[
nsTile
][
0
]
=
null
;
// remove dummy
if
(
dl
>
0
){
System
.
out
.
println
(
"createPlanesFromSelections(): nsTile="
+
nsTile
);
}
}
if
(
dl
>
2
)
{
String
[]
dbg_titles
=
showSupertileSeparationTitles
(
disp_strength
[
nsTile
],
plane_selections
[
nsTile
],
result_planes
[
nsTile
]);
double
[][]
dbg_img
=
showSupertileSeparation
(
false
,
disp_strength
[
nsTile
],
plane_selections
[
nsTile
],
result_planes
[
nsTile
]);
showDoubleFloatArrays
sdfa_instance
=
new
showDoubleFloatArrays
();
sdfa_instance
.
showArrays
(
dbg_img
,
2
*
superTileSize
,
2
*
superTileSize
,
true
,
"create_planes_disp-"
+
nsTile
+
"-"
+
debugLevel
,
dbg_titles
);
dbg_img
=
showSupertileSeparation
(
true
,
disp_strength
[
nsTile
],
plane_selections
[
nsTile
],
result_planes
[
nsTile
]);
sdfa_instance
.
showArrays
(
dbg_img
,
2
*
superTileSize
,
2
*
superTileSize
,
true
,
"create_planes_world-"
+
nsTile
+
"-"
+
debugLevel
,
dbg_titles
);
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
return
result_planes
;
}
}
public
TilePlanes
.
PlaneData
[][]
createPlanesFromSelections
(
public
TilePlanes
.
PlaneData
[][]
createPlanesFromSelections
(
final
boolean
[][][][]
plane_selections
,
// = new boolean [nStiles][][][]; // num_tiles
final
boolean
[][][][]
plane_selections
,
// = new boolean [nStiles][][][]; // num_tiles
final
double
[][][][]
disp_strength
,
final
double
[][][][]
disp_strength
,
...
@@ -2284,7 +2027,9 @@ public class SuperTiles{
...
@@ -2284,7 +2027,9 @@ public class SuperTiles{
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
nStiles
=
stilesX
*
stilesY
;
final
int
nStiles
=
stilesX
*
stilesY
;
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
tileProcessor
.
threadsMax
);
// final Thread[] threads = ImageDtt.newThreadArray(tileProcessor.threadsMax);
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
((
debugLevel
>
1
)?
1
:
tileProcessor
.
threadsMax
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
final
TilePlanes
.
PlaneData
[][]
result_planes
=
new
TilePlanes
.
PlaneData
[
nStiles
][];
final
TilePlanes
.
PlaneData
[][]
result_planes
=
new
TilePlanes
.
PlaneData
[
nStiles
][];
// this.planes = new TilePlanes.PlaneData[nStiles][];
// this.planes = new TilePlanes.PlaneData[nStiles][];
...
@@ -2336,6 +2081,52 @@ public class SuperTiles{
...
@@ -2336,6 +2081,52 @@ public class SuperTiles{
dl
);
// int debugLevel);
dl
);
// int debugLevel);
if
((
st_planes
!=
null
)
&&
(!
st_planes
.
isEmpty
())){
if
((
st_planes
!=
null
)
&&
(!
st_planes
.
isEmpty
())){
if
(
dl
>
0
){
System
.
out
.
println
(
"======= createPlanesFromSelections(): nsTile="
+
nsTile
+
" detecting bridges =========="
);
}
boolean
[][][]
split_sels
=
pd0
.
filterBridges
(
st_planes
,
// ArrayList<PlaneData> tilePlanes,
3
,
// int max_grow, // make configurable?
3
,
// int max_grow_far,
dl
);
// int debugLevel)
if
(
split_sels
!=
null
){
if
(
dl
>
-
1
){
System
.
out
.
println
(
"======= createPlanesFromSelections(): nsTile="
+
nsTile
+
" removing bridges =========="
);
}
if
(
dl
>
2
)
{
String
[]
dbg_titles
=
showSupertileSeparationTitles
(
disp_strength
[
nsTile
],
plane_selections
[
nsTile
],
result_planes
[
nsTile
]);
double
[][]
dbg_img
=
showSupertileSeparation
(
false
,
disp_strength
[
nsTile
],
plane_selections
[
nsTile
],
result_planes
[
nsTile
]);
showDoubleFloatArrays
sdfa_instance
=
new
showDoubleFloatArrays
();
sdfa_instance
.
showArrays
(
dbg_img
,
2
*
superTileSize
,
2
*
superTileSize
,
true
,
"pre_bridge_disp-"
+
nsTile
+
"-"
+
debugLevel
,
dbg_titles
);
dbg_img
=
showSupertileSeparation
(
true
,
disp_strength
[
nsTile
],
plane_selections
[
nsTile
],
result_planes
[
nsTile
]);
sdfa_instance
.
showArrays
(
dbg_img
,
2
*
superTileSize
,
2
*
superTileSize
,
true
,
"pre_bridge_world-"
+
nsTile
+
"-"
+
debugLevel
,
dbg_titles
);
}
st_planes
=
pd0
.
createTilePlanesFromSelections
(
""
+
nsTile
+
" bridges "
,
// String suffix,
split_sels
,
// boolean [][][] plane_selections, // = new boolean [nStiles][][][]; // num_tiles
disp_strength
[
nsTile
],
// double [][][] disp_strength,
plDispNorm
,
// double dispNorm, // Normalize disparities to the average if above
plMinPoints
,
// int min_tiles,
plTargetEigen
,
// double plTargetEigen, // = 0.1; // Remove outliers until main axis eigenvalue (possibly scaled by plDispNorm) gets below
0.0
,
// double plFractOutliers, // = 0.3; // Maximal fraction of outliers to remove
0
,
// plMaxOutliers, // int plMaxOutliers, // = 20; // Maximal number of outliers to remove
strength_floor
,
// double strength_floor,
strength_pow
,
// double strength_pow,
correct_distortions
,
// boolean correct_distortions,
smplMode
,
// boolean smplMode, // = true; // Use sample mode (false - regular tile mode)
smplSide
,
// int smplSide, // = 2; // Sample size (side of a square)
smplNum
,
// int smplNum, // = 3; // Number after removing worst
smplRms
,
// double smplRms, // = 0.1; // Maximal RMS of the remaining tiles in a sample
dl
);
// int debugLevel);
}
}
if
((
st_planes
!=
null
)
&&
(!
st_planes
.
isEmpty
())){
if
(
LOWEST_PLANE
(
2
)
>
0
)
st_planes
.
add
(
0
,
st_planes
.
get
(
0
));
// insert dummy at pos 0;
if
(
LOWEST_PLANE
(
2
)
>
0
)
st_planes
.
add
(
0
,
st_planes
.
get
(
0
));
// insert dummy at pos 0;
result_planes
[
nsTile
]
=
st_planes
.
toArray
(
new
TilePlanes
.
PlaneData
[
0
]
);
result_planes
[
nsTile
]
=
st_planes
.
toArray
(
new
TilePlanes
.
PlaneData
[
0
]
);
if
(
LOWEST_PLANE
(
2
)
>
0
)
result_planes
[
nsTile
][
0
]
=
null
;
// remove dummy
if
(
LOWEST_PLANE
(
2
)
>
0
)
result_planes
[
nsTile
][
0
]
=
null
;
// remove dummy
...
@@ -2465,7 +2256,7 @@ public class SuperTiles{
...
@@ -2465,7 +2256,7 @@ public class SuperTiles{
smplNum
,
// final int smplNum, // = 3; // Number after removing worst
smplNum
,
// final int smplNum, // = 3; // Number after removing worst
smplRms
,
// final double smplRms, // = 0.1; // Maximal RMS of the remaining tiles in a sample
smplRms
,
// final double smplRms, // = 0.1; // Maximal RMS of the remaining tiles in a sample
debugLevel
+
1
,
// final int debugLevel,
debugLevel
+
2
,
//
1, // final int debugLevel,
dbg_X
,
// final int dbg_X,
dbg_X
,
// final int dbg_X,
dbg_Y
);
// final int dbg_Y)
dbg_Y
);
// final int dbg_Y)
this
.
planes
=
new_planes
;
// save as "measured" (as opposed to "smoothed" by neighbors) planes
this
.
planes
=
new_planes
;
// save as "measured" (as opposed to "smoothed" by neighbors) planes
...
@@ -2488,132 +2279,6 @@ public class SuperTiles{
...
@@ -2488,132 +2279,6 @@ public class SuperTiles{
return
wh
;
return
wh
;
}
}
// TODO: Obsolete (never used)?
TilePlanes
.
PlaneData
[][]
getNeibPlanes
(
final
int
dir
,
// 0: get from up (N), 1:from NE, ... 7 - from NW
final
boolean
preferDisparity
,
final
boolean
dbgMerge
,
// Combine 'other' plane with current
final
int
dbg_X
,
final
int
dbg_Y
)
{
final
int
tilesX
=
tileProcessor
.
getTilesX
();
final
int
tilesY
=
tileProcessor
.
getTilesY
();
final
int
superTileSize
=
tileProcessor
.
getSuperTileSize
();
final
int
tileSize
=
tileProcessor
.
getTileSize
();
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
double
[]
nan_plane
=
new
double
[
superTileSize
*
superTileSize
];
for
(
int
i
=
0
;
i
<
nan_plane
.
length
;
i
++)
nan_plane
[
i
]
=
Double
.
NaN
;
final
int
[][]
dirsYX
=
{{-
1
,
0
},{-
1
,
1
},{
0
,
1
},{
1
,
1
},{
1
,
0
},{
1
,-
1
},{
0
,-
1
},{-
1
,-
1
}};
TilePlanes
.
PlaneData
[][]
neib_planes
=
new
TilePlanes
.
PlaneData
[
stilesY
*
stilesX
][];
TilePlanes
tpl
=
null
;
// new TilePlanes(tileSize,superTileSize, geometryCorrection);
// final int debug_stile = 20 * stilesX + 27;
// final int debug_stile = 17 * stilesX + 27;
final
int
debug_stile
=
dbg_Y
*
stilesX
+
dbg_X
;
// final int debug_stile = -1;
for
(
int
sty0
=
0
;
sty0
<
stilesY
;
sty0
++){
int
sty
=
sty0
+
dirsYX
[
dir
][
0
];
for
(
int
stx0
=
0
;
stx0
<
stilesX
;
stx0
++){
int
nsTile0
=
sty0
*
stilesX
+
stx0
;
// result tile
int
stx
=
stx0
+
dirsYX
[
dir
][
1
];
int
nsTile
=
sty
*
stilesX
+
stx
;
// from where to get
if
((
sty
>=
0
)
&&
(
sty
<
stilesY
)
&&
(
stx
>=
0
)
&&
(
stx
<
stilesX
)
&&
(
planes
[
nsTile
]
!=
null
))
{
neib_planes
[
nsTile0
]
=
new
TilePlanes
.
PlaneData
[
planes
[
nsTile
].
length
];
for
(
int
np
=
0
;
np
<
planes
[
nsTile
].
length
;
np
++){
GeometryCorrection
geometryCorrection
=
planes
[
nsTile
][
np
].
getGeometryCorrection
();
boolean
correct_distortions
=
planes
[
nsTile
][
np
].
getCorrectDistortions
();
int
[]
sTileXY0
=
{
stx0
,
sty0
};
if
(
tpl
==
null
)
{
tpl
=
new
TilePlanes
(
tileSize
,
superTileSize
,
geometryCorrection
);
}
TilePlanes
.
PlaneData
pd
=
tpl
.
new
PlaneData
(
sTileXY0
,
tileSize
,
superTileSize
,
geometryCorrection
,
correct_distortions
);
/*
TilePlanes.PlaneData pd = planes[nsTile0][np].clone();
pd.setS
*/
if
(
nsTile0
==
debug_stile
)
{
System
.
out
.
println
(
"getNeibPlanes(): nsTile0="
+
nsTile0
+
", nsTile="
+
nsTile
+
", np = "
+
np
+
" dir = "
+
dir
);
}
TilePlanes
.
PlaneData
other_pd
=
pd
.
getPlaneToThis
(
planes
[
nsTile
][
np
],
// PlaneData otherPd,
(
nsTile0
==
debug_stile
)?
1
:
0
);
// int debugLevel)
int
num_this
=
(
planes
[
nsTile0
]
==
null
)?
0
:(
planes
[
nsTile0
].
length
);
int
best_index
=
0
;
if
(
dbgMerge
&&
(
num_this
>
0
))
{
double
best_value
=
Double
.
NaN
;
if
(
num_this
>
1
){
// find the best candidate for merge
for
(
int
indx
=
1
;
indx
<
planes
[
nsTile0
].
length
;
indx
++){
if
(
nsTile0
==
debug_stile
)
{
System
.
out
.
println
(
"this with this, same weight:"
);
TilePlanes
.
PlaneData
this_this_pd
=
planes
[
nsTile0
][
indx
].
mergePlaneToThis
(
planes
[
nsTile0
][
indx
],
// PlaneData otherPd,
1.0
,
// double scale_other,
1.0
,
// double starWeightPwr, // Use this power of tile weight when calculating connection cost
true
,
// boolean ignore_weights,
true
,
// boolean sum_weights,
preferDisparity
,
(
nsTile0
==
debug_stile
)?
1
:
0
);
// int debugLevel)
System
.
out
.
println
(
"other with other, same weight:"
);
TilePlanes
.
PlaneData
other_other_pd
=
other_pd
.
mergePlaneToThis
(
other_pd
,
// PlaneData otherPd,
1.0
,
// double scale_other,
1.0
,
// double starWeightPwr, // Use this power of tile weight when calculating connection cost
true
,
// boolean ignore_weights,
true
,
// boolean sum_weights,
preferDisparity
,
(
nsTile0
==
debug_stile
)?
1
:
0
);
// int debugLevel)
System
.
out
.
println
(
"other with this, same weight:"
);
}
TilePlanes
.
PlaneData
merged_pd
=
planes
[
nsTile0
][
indx
].
mergePlaneToThis
(
other_pd
,
// PlaneData otherPd,
1.0
,
// double scale_other,
1.0
,
// double starWeightPwr, // Use this power of tile weight when calculating connection cost
true
,
// boolean ignore_weights,
true
,
// boolean sum_weights,
preferDisparity
,
(
nsTile0
==
debug_stile
)?
1
:
0
);
// int debugLevel)
if
(!(
merged_pd
.
getValue
()
>
best_value
))
{
// Double.isNaN(best_value) will work too
best_value
=
merged_pd
.
getValue
();
best_index
=
indx
;
}
}
}
// now merge with weights with the best plane of this supertile
if
(
nsTile0
==
debug_stile
)
{
System
.
out
.
println
(
"this with this, proportional weight, np(other):"
+
np
+
" best fit(this):"
+
best_index
);
}
TilePlanes
.
PlaneData
merged_pd
=
planes
[
nsTile0
][
best_index
].
mergePlaneToThis
(
other_pd
,
// PlaneData otherPd,
1.0
,
// double scale_other,
1.0
,
// double starWeightPwr, // Use this power of tile weight when calculating connection cost
false
,
// boolean ignore_weights,
true
,
// boolean sum_weights,
preferDisparity
,
(
nsTile0
==
debug_stile
)?
1
:
0
);
// int debugLevel)
if
(
merged_pd
!=
null
)
{
merged_pd
.
scaleWeight
(
0.5
);
}
neib_planes
[
nsTile0
][
np
]
=
merged_pd
;
}
else
{
neib_planes
[
nsTile0
][
np
]
=
other_pd
;
}
}
}
else
{
neib_planes
[
nsTile0
]
=
null
;
}
}
}
return
neib_planes
;
}
public
int
fillSquares
()
public
int
fillSquares
()
{
{
final
int
tilesX
=
tileProcessor
.
getTilesX
();
final
int
tilesX
=
tileProcessor
.
getTilesX
();
...
@@ -2807,7 +2472,7 @@ public class SuperTiles{
...
@@ -2807,7 +2472,7 @@ public class SuperTiles{
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
dbgTile
=
dbg_Y
*
stilesX
+
dbg_X
;
final
int
dbgTile
=
dbg_Y
*
stilesX
+
dbg_X
;
final
Tile
Surface
.
TileNeibs
tnSurface
=
tileSurface
.
new
TileNeibs
(
stilesX
,
stilesY
);
final
Tile
Neibs
tnSurface
=
new
TileNeibs
(
stilesX
,
stilesY
);
int
[]
rslt
=
{
0
,
0
};
int
[]
rslt
=
{
0
,
0
};
for
(
int
nsTile
=
0
;
nsTile
<
conflicts
.
length
;
nsTile
++)
if
(
conflicts
[
nsTile
]
!=
null
)
{
for
(
int
nsTile
=
0
;
nsTile
<
conflicts
.
length
;
nsTile
++)
if
(
conflicts
[
nsTile
]
!=
null
)
{
// conflicts may disappear after being fixed, recheck for null
// conflicts may disappear after being fixed, recheck for null
...
@@ -2827,7 +2492,7 @@ public class SuperTiles{
...
@@ -2827,7 +2492,7 @@ public class SuperTiles{
start_dir4
,
// int start_dir4,
start_dir4
,
// int start_dir4,
right
,
// boolean right,
right
,
// boolean right,
reverse
,
// boolean reverse,
reverse
,
// boolean reverse,
tnSurface
,
// Tile
Surface.Tile
Neibs tnSurface,
tnSurface
,
// TileNeibs tnSurface,
conflicts
,
// int [][][] conflicts,
conflicts
,
// int [][][] conflicts,
conflict_stats
,
// Conflicts conflict_stats, // to be updated after applying resolution
conflict_stats
,
// Conflicts conflict_stats, // to be updated after applying resolution
starSteps
,
// How far to look around when calculationg connection cost
starSteps
,
// How far to look around when calculationg connection cost
...
@@ -2857,7 +2522,7 @@ public class SuperTiles{
...
@@ -2857,7 +2522,7 @@ public class SuperTiles{
int
start_dir4
,
int
start_dir4
,
boolean
right
,
boolean
right
,
boolean
reverse
,
boolean
reverse
,
Tile
Surface
.
Tile
Neibs
tnSurface
,
TileNeibs
tnSurface
,
int
[][][]
conflicts
,
int
[][][]
conflicts
,
Conflicts
conflict_stats
,
// to be updated after applying resolution
Conflicts
conflict_stats
,
// to be updated after applying resolution
int
starSteps
,
// How far to look around when calculationg connection cost
int
starSteps
,
// How far to look around when calculationg connection cost
...
@@ -2979,7 +2644,7 @@ public class SuperTiles{
...
@@ -2979,7 +2644,7 @@ public class SuperTiles{
nsTiles
[
isTile
],
// int nsTile0,
nsTiles
[
isTile
],
// int nsTile0,
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
neibs_prev
,
// int [][][] replacement_neibs,
neibs_prev
,
// int [][][] replacement_neibs,
tnSurface
);
// Tile
Surface.Tile
Neibs tnSurface)
tnSurface
);
// TileNeibs tnSurface)
}
}
if
(
debugLevel
>
1
)
{
if
(
debugLevel
>
1
)
{
System
.
out
.
println
(
"Calculating original conflicts"
);
System
.
out
.
println
(
"Calculating original conflicts"
);
...
@@ -3040,7 +2705,7 @@ public class SuperTiles{
...
@@ -3040,7 +2705,7 @@ public class SuperTiles{
nsTiles
[
isTile
],
// int nsTile0,
nsTiles
[
isTile
],
// int nsTile0,
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
neibs
,
// neibs, // int [][][] replacement_neibs,
neibs
,
// neibs, // int [][][] replacement_neibs,
tnSurface
);
// Tile
Surface.Tile
Neibs tnSurface)
tnSurface
);
// TileNeibs tnSurface)
}
}
Conflicts
new_conflicts_stats
=
new
Conflicts
(
Conflicts
new_conflicts_stats
=
new
Conflicts
(
new_conflicts
,
new_conflicts
,
...
@@ -3118,7 +2783,7 @@ public class SuperTiles{
...
@@ -3118,7 +2783,7 @@ public class SuperTiles{
int
nl1
,
int
nl1
,
int
nl2
,
int
nl2
,
int
dir_mask
,
int
dir_mask
,
Tile
Surface
.
Tile
Neibs
tnSurface
,
TileNeibs
tnSurface
,
int
[][][]
conflicts
,
int
[][][]
conflicts
,
Conflicts
conflict_stats
,
// to be updated after applying resolution
Conflicts
conflict_stats
,
// to be updated after applying resolution
int
starSteps
,
// How far to look around when calculationg connection cost
int
starSteps
,
// How far to look around when calculationg connection cost
...
@@ -3220,7 +2885,7 @@ public class SuperTiles{
...
@@ -3220,7 +2885,7 @@ public class SuperTiles{
nsTiles
[
isTile
],
// int nsTile0,
nsTiles
[
isTile
],
// int nsTile0,
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
neibs_prev
,
// int [][][] replacement_neibs,
neibs_prev
,
// int [][][] replacement_neibs,
tnSurface
);
// Tile
Surface.Tile
Neibs tnSurface)
tnSurface
);
// TileNeibs tnSurface)
}
}
if
(
debugLevel
>
1
)
{
if
(
debugLevel
>
1
)
{
System
.
out
.
println
(
"Involved supertiles:"
);
System
.
out
.
println
(
"Involved supertiles:"
);
...
@@ -3292,7 +2957,7 @@ public class SuperTiles{
...
@@ -3292,7 +2957,7 @@ public class SuperTiles{
nsTiles
[
isTile
],
// int nsTile0,
nsTiles
[
isTile
],
// int nsTile0,
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
neibs_vars
[
variant
],
// neibs, // int [][][] replacement_neibs,
neibs_vars
[
variant
],
// neibs, // int [][][] replacement_neibs,
tnSurface
);
// Tile
Surface.Tile
Neibs tnSurface)
tnSurface
);
// TileNeibs tnSurface)
}
}
variant_conflicts_stats
[
variant
]
=
new
Conflicts
(
variant_conflicts_stats
[
variant
]
=
new
Conflicts
(
variant_conflicts
[
variant
],
variant_conflicts
[
variant
],
...
@@ -3414,7 +3079,7 @@ public class SuperTiles{
...
@@ -3414,7 +3079,7 @@ public class SuperTiles{
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
dbgTile
=
dbg_Y
*
stilesX
+
dbg_X
;
final
int
dbgTile
=
dbg_Y
*
stilesX
+
dbg_X
;
final
Tile
Surface
.
TileNeibs
tnSurface
=
tileSurface
.
new
TileNeibs
(
stilesX
,
stilesY
);
final
Tile
Neibs
tnSurface
=
new
TileNeibs
(
stilesX
,
stilesY
);
int
[]
rslt
=
{
0
,
0
};
int
[]
rslt
=
{
0
,
0
};
for
(
int
nsTile
=
0
;
nsTile
<
conflicts
.
length
;
nsTile
++)
if
(
conflicts
[
nsTile
]
!=
null
)
{
for
(
int
nsTile
=
0
;
nsTile
<
conflicts
.
length
;
nsTile
++)
if
(
conflicts
[
nsTile
]
!=
null
)
{
// conflicts may disappear after being fixed, recheck for null
// conflicts may disappear after being fixed, recheck for null
...
@@ -3473,7 +3138,7 @@ public class SuperTiles{
...
@@ -3473,7 +3138,7 @@ public class SuperTiles{
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
dbgTile
=
dbg_Y
*
stilesX
+
dbg_X
;
final
int
dbgTile
=
dbg_Y
*
stilesX
+
dbg_X
;
final
Tile
Surface
.
TileNeibs
tnSurface
=
tileSurface
.
new
TileNeibs
(
stilesX
,
stilesY
);
final
Tile
Neibs
tnSurface
=
new
TileNeibs
(
stilesX
,
stilesY
);
int
[]
rslt
=
{
0
,
0
};
int
[]
rslt
=
{
0
,
0
};
for
(
int
nsTile
=
0
;
nsTile
<
conflicts
.
length
;
nsTile
++)
if
(
conflicts
[
nsTile
]
!=
null
)
{
for
(
int
nsTile
=
0
;
nsTile
<
conflicts
.
length
;
nsTile
++)
if
(
conflicts
[
nsTile
]
!=
null
)
{
// conflicts may disappear after being fixed, recheck for null
// conflicts may disappear after being fixed, recheck for null
...
@@ -3511,7 +3176,7 @@ public class SuperTiles{
...
@@ -3511,7 +3176,7 @@ public class SuperTiles{
int
nsTile
,
int
nsTile
,
int
nl1
,
int
nl1
,
int
nl2
,
int
nl2
,
Tile
Surface
.
Tile
Neibs
tnSurface
,
TileNeibs
tnSurface
,
int
[][][]
conflicts
,
int
[][][]
conflicts
,
Conflicts
conflict_stats
,
// to be updated after applying resolution
Conflicts
conflict_stats
,
// to be updated after applying resolution
int
starSteps
,
// How far to look around when calculationg connection cost
int
starSteps
,
// How far to look around when calculationg connection cost
...
@@ -3619,7 +3284,7 @@ public class SuperTiles{
...
@@ -3619,7 +3284,7 @@ public class SuperTiles{
nsTiles
[
isTile
],
// int nsTile0,
nsTiles
[
isTile
],
// int nsTile0,
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
neibs_prev
,
// int [][][] replacement_neibs,
neibs_prev
,
// int [][][] replacement_neibs,
tnSurface
);
// Tile
Surface.Tile
Neibs tnSurface)
tnSurface
);
// TileNeibs tnSurface)
}
}
if
(
debugLevel
>
1
)
{
if
(
debugLevel
>
1
)
{
System
.
out
.
println
(
"Involved supertiles:"
);
System
.
out
.
println
(
"Involved supertiles:"
);
...
@@ -3649,7 +3314,7 @@ public class SuperTiles{
...
@@ -3649,7 +3314,7 @@ public class SuperTiles{
nsTiles
[
isTile
],
// int nsTile0,
nsTiles
[
isTile
],
// int nsTile0,
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
neibs_vars
[
variant
],
// neibs, // int [][][] replacement_neibs,
neibs_vars
[
variant
],
// neibs, // int [][][] replacement_neibs,
tnSurface
);
// Tile
Surface.Tile
Neibs tnSurface)
tnSurface
);
// TileNeibs tnSurface)
}
}
variant_conflicts_stats
[
variant
]
=
new
Conflicts
(
variant_conflicts_stats
[
variant
]
=
new
Conflicts
(
variant_conflicts
[
variant
],
variant_conflicts
[
variant
],
...
@@ -3809,7 +3474,7 @@ public class SuperTiles{
...
@@ -3809,7 +3474,7 @@ public class SuperTiles{
int
nl1
,
int
nl1
,
int
nl2
,
int
nl2
,
LinkPlanes
lp
,
LinkPlanes
lp
,
Tile
Surface
.
Tile
Neibs
tnSurface
,
TileNeibs
tnSurface
,
int
[][][]
conflicts
,
int
[][][]
conflicts
,
Conflicts
conflict_stats
,
// to be updated after applying resolution
Conflicts
conflict_stats
,
// to be updated after applying resolution
int
starSteps
,
// How far to look around when calculationg connection cost
int
starSteps
,
// How far to look around when calculationg connection cost
...
@@ -3922,7 +3587,7 @@ public class SuperTiles{
...
@@ -3922,7 +3587,7 @@ public class SuperTiles{
nsTiles
[
isTile
],
// int nsTile0,
nsTiles
[
isTile
],
// int nsTile0,
replacement_tiles
,
// HashMap<Integer,Integer> replacement_tiles, //
replacement_tiles
,
// HashMap<Integer,Integer> replacement_tiles, //
neibs_prev
,
// int [][][] replacement_neibs,
neibs_prev
,
// int [][][] replacement_neibs,
tnSurface
);
// Tile
Surface.Tile
Neibs tnSurface)
tnSurface
);
// TileNeibs tnSurface)
// calculate cost of conflicts
// calculate cost of conflicts
conflicts_old_cost
+=
iconflicts
.
getConflictsCost
(
conflicts_old_cost
+=
iconflicts
.
getConflictsCost
(
...
@@ -3932,7 +3597,7 @@ public class SuperTiles{
...
@@ -3932,7 +3597,7 @@ public class SuperTiles{
replacement_tiles
,
// HashMap<Integer,Integer> replacement_tiles, // null is OK
replacement_tiles
,
// HashMap<Integer,Integer> replacement_tiles, // null is OK
neibs_prev
,
// int [][][] replacement_neibs, // null OK if replacement_tiles == null
neibs_prev
,
// int [][][] replacement_neibs, // null OK if replacement_tiles == null
connectionCosts
,
// ConnectionCosts connectionCosts,
connectionCosts
,
// ConnectionCosts connectionCosts,
tnSurface
);
// Tile
Surface.Tile
Neibs tnSurface)
tnSurface
);
// TileNeibs tnSurface)
}
}
...
@@ -3971,7 +3636,7 @@ public class SuperTiles{
...
@@ -3971,7 +3636,7 @@ public class SuperTiles{
nsTiles
[
isTile
],
// int nsTile0,
nsTiles
[
isTile
],
// int nsTile0,
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
neibs_vars
[
variant
],
// neibs, // int [][][] replacement_neibs,
neibs_vars
[
variant
],
// neibs, // int [][][] replacement_neibs,
tnSurface
);
// Tile
Surface.Tile
Neibs tnSurface)
tnSurface
);
// TileNeibs tnSurface)
// connectionCosts now contains last calculated val/weight pairs for broader array of tile data
// connectionCosts now contains last calculated val/weight pairs for broader array of tile data
conflicts_var_cost
[
variant
]
+=
iconflicts
.
getConflictsCost
(
conflicts_var_cost
[
variant
]
+=
iconflicts
.
getConflictsCost
(
nsTiles
[
isTile
],
// int nsTile0,
nsTiles
[
isTile
],
// int nsTile0,
...
@@ -3980,7 +3645,7 @@ public class SuperTiles{
...
@@ -3980,7 +3645,7 @@ public class SuperTiles{
replacement_tiles
,
// HashMap<Integer,Integer> replacement_tiles, // null is OK
replacement_tiles
,
// HashMap<Integer,Integer> replacement_tiles, // null is OK
neibs_vars
[
variant
],
// int [][][] replacement_neibs, // null OK if replacement_tiles == null
neibs_vars
[
variant
],
// int [][][] replacement_neibs, // null OK if replacement_tiles == null
connectionCosts
,
// ConnectionCosts connectionCosts,
connectionCosts
,
// ConnectionCosts connectionCosts,
tnSurface
);
// Tile
Surface.Tile
Neibs tnSurface)
tnSurface
);
// TileNeibs tnSurface)
}
}
variant_conflicts_stats
[
variant
]
=
new
Conflicts
(
variant_conflicts_stats
[
variant
]
=
new
Conflicts
(
variant_conflicts
[
variant
],
variant_conflicts
[
variant
],
...
@@ -4159,7 +3824,7 @@ public class SuperTiles{
...
@@ -4159,7 +3824,7 @@ public class SuperTiles{
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
nStiles
=
stilesX
*
stilesY
;
final
int
nStiles
=
stilesX
*
stilesY
;
final
Tile
Surface
.
TileNeibs
tnSurface
=
tileSurface
.
new
TileNeibs
(
stilesX
,
stilesY
);
final
Tile
Neibs
tnSurface
=
new
TileNeibs
(
stilesX
,
stilesY
);
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
tileProcessor
.
threadsMax
);
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
tileProcessor
.
threadsMax
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
...
@@ -4174,7 +3839,7 @@ public class SuperTiles{
...
@@ -4174,7 +3839,7 @@ public class SuperTiles{
starValPwr
,
//double starValPwr, // Raise value of each tile before averaging
starValPwr
,
//double starValPwr, // Raise value of each tile before averaging
steps
,
// int steps,
steps
,
// int steps,
planes
,
// TilePlanes.PlaneData [][] planes,
planes
,
// TilePlanes.PlaneData [][] planes,
tnSurface
,
// Tile
Surface.Tile
Neibs tnSurface,
tnSurface
,
// TileNeibs tnSurface,
preferDisparity
);
// boolean preferDisparity)
preferDisparity
);
// boolean preferDisparity)
int
[]
mod_supertiles
=
new
int
[
1
];
int
[]
mod_supertiles
=
new
int
[
1
];
for
(
int
nsTile
=
ai
.
getAndIncrement
();
nsTile
<
nStiles
;
nsTile
=
ai
.
getAndIncrement
())
{
for
(
int
nsTile
=
ai
.
getAndIncrement
();
nsTile
<
nStiles
;
nsTile
=
ai
.
getAndIncrement
())
{
...
@@ -4214,7 +3879,7 @@ public class SuperTiles{
...
@@ -4214,7 +3879,7 @@ public class SuperTiles{
// final int tileSize = tileProcessor.getTileSize();
// final int tileSize = tileProcessor.getTileSize();
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
Tile
Surface
.
TileNeibs
tnSurface
=
tileSurface
.
new
TileNeibs
(
stilesX
,
stilesY
);
final
Tile
Neibs
tnSurface
=
new
TileNeibs
(
stilesX
,
stilesY
);
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
tileProcessor
.
threadsMax
);
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
tileProcessor
.
threadsMax
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
...
@@ -4229,7 +3894,7 @@ public class SuperTiles{
...
@@ -4229,7 +3894,7 @@ public class SuperTiles{
starValPwr
,
//double starValPwr, // Raise value of each tile before averaging
starValPwr
,
//double starValPwr, // Raise value of each tile before averaging
steps
,
// int steps,
steps
,
// int steps,
planes
,
// TilePlanes.PlaneData [][] planes,
planes
,
// TilePlanes.PlaneData [][] planes,
tnSurface
,
// Tile
Surface.Tile
Neibs tnSurface,
tnSurface
,
// TileNeibs tnSurface,
preferDisparity
);
// boolean preferDisparity)
preferDisparity
);
// boolean preferDisparity)
int
[]
supertiles
=
new
int
[
1
];
int
[]
supertiles
=
new
int
[
1
];
for
(
int
isTile
=
ai
.
getAndIncrement
();
isTile
<
mod_supertiles
.
length
;
isTile
=
ai
.
getAndIncrement
())
{
for
(
int
isTile
=
ai
.
getAndIncrement
();
isTile
<
mod_supertiles
.
length
;
isTile
=
ai
.
getAndIncrement
())
{
...
@@ -4273,7 +3938,7 @@ public class SuperTiles{
...
@@ -4273,7 +3938,7 @@ public class SuperTiles{
int
nl1
,
int
nl1
,
int
nl2
,
int
nl2
,
int
dir_mask
,
int
dir_mask
,
Tile
Surface
.
Tile
Neibs
tnSurface
,
TileNeibs
tnSurface
,
int
debugLevel
)
int
debugLevel
)
{
{
int
[][]
layers0
=
new
int
[
5
][
2
];
// 4 - center, 0 - N, 1 - E, 2 - S, 3 - w. 4 has 2, each other 0,1 or 2 layers
int
[][]
layers0
=
new
int
[
5
][
2
];
// 4 - center, 0 - N, 1 - E, 2 - S, 3 - w. 4 has 2, each other 0,1 or 2 layers
...
@@ -4684,7 +4349,7 @@ public class SuperTiles{
...
@@ -4684,7 +4349,7 @@ public class SuperTiles{
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesX
=
(
tilesX
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
stilesY
=
(
tilesY
+
superTileSize
-
1
)/
superTileSize
;
final
int
dbgTile
=
dbg_Y
*
stilesX
+
dbg_X
;
final
int
dbgTile
=
dbg_Y
*
stilesX
+
dbg_X
;
final
Tile
Surface
.
TileNeibs
tnSurface
=
tileSurface
.
new
TileNeibs
(
stilesX
,
stilesY
);
final
Tile
Neibs
tnSurface
=
new
TileNeibs
(
stilesX
,
stilesY
);
final
Conflicts
iconflicts
=
new
Conflicts
(
this
);
final
Conflicts
iconflicts
=
new
Conflicts
(
this
);
int
[]
rslt
=
{
0
,
0
};
int
[]
rslt
=
{
0
,
0
};
...
@@ -4870,12 +4535,12 @@ public class SuperTiles{
...
@@ -4870,12 +4535,12 @@ public class SuperTiles{
nsTiles
[
isTile
],
// int nsTile0,
nsTiles
[
isTile
],
// int nsTile0,
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
neibs_prev
,
// int [][][] replacement_neibs,
neibs_prev
,
// int [][][] replacement_neibs,
tnSurface
);
// Tile
Surface.Tile
Neibs tnSurface)
tnSurface
);
// TileNeibs tnSurface)
conflicts_new
[
isTile
]
=
iconflicts
.
detectTriangularTileConflicts
(
conflicts_new
[
isTile
]
=
iconflicts
.
detectTriangularTileConflicts
(
nsTiles
[
isTile
],
// int nsTile0,
nsTiles
[
isTile
],
// int nsTile0,
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
replacement_tiles
,
//HashMap<Integer,Integer> replacement_tiles, //
neibs
,
// int [][][] replacement_neibs,
neibs
,
// int [][][] replacement_neibs,
tnSurface
);
// Tile
Surface.Tile
Neibs tnSurface)
tnSurface
);
// TileNeibs tnSurface)
}
}
if
(
debugLevel
>
1
)
{
if
(
debugLevel
>
1
)
{
System
.
out
.
println
(
"Involved supertiles:"
);
System
.
out
.
println
(
"Involved supertiles:"
);
...
@@ -4974,7 +4639,7 @@ public class SuperTiles{
...
@@ -4974,7 +4639,7 @@ public class SuperTiles{
int
dir4
,
int
dir4
,
double
maxEigen
,
// maximal eigenvalue of planes to consider
double
maxEigen
,
// maximal eigenvalue of planes to consider
double
starWeightPwr
,
// Use this power of tile weight when calculating connection cost
double
starWeightPwr
,
// Use this power of tile weight when calculating connection cost
Tile
Surface
.
Tile
Neibs
tnSurface
,
TileNeibs
tnSurface
,
boolean
preferDisparity
,
boolean
preferDisparity
,
int
debugLevel
)
int
debugLevel
)
{
{
...
@@ -5067,7 +4732,7 @@ public class SuperTiles{
...
@@ -5067,7 +4732,7 @@ public class SuperTiles{
double
diagonalWeight
,
double
diagonalWeight
,
double
starPwr
,
// Divide cost by number of connections to this power
double
starPwr
,
// Divide cost by number of connections to this power
double
starWeightPwr
,
// Use this power of tile weight when calculating connection cost
double
starWeightPwr
,
// Use this power of tile weight when calculating connection cost
Tile
Surface
.
Tile
Neibs
tnSurface
,
TileNeibs
tnSurface
,
boolean
preferDisparity
,
boolean
preferDisparity
,
int
debugLevel
)
int
debugLevel
)
{
{
...
@@ -5106,7 +4771,7 @@ public class SuperTiles{
...
@@ -5106,7 +4771,7 @@ public class SuperTiles{
public
int
[]
getInvolvedSupertiles
(
public
int
[]
getInvolvedSupertiles
(
int
[]
mod_supertiles
,
int
[]
mod_supertiles
,
Tile
Surface
.
Tile
Neibs
tnSurface
)
TileNeibs
tnSurface
)
{
{
HashSet
<
Integer
>
stiles_set
=
new
HashSet
<
Integer
>();
HashSet
<
Integer
>
stiles_set
=
new
HashSet
<
Integer
>();
for
(
int
i
=
0
;
i
<
mod_supertiles
.
length
;
i
++){
for
(
int
i
=
0
;
i
<
mod_supertiles
.
length
;
i
++){
...
@@ -5157,7 +4822,7 @@ public class SuperTiles{
...
@@ -5157,7 +4822,7 @@ public class SuperTiles{
double
diagonalWeight
,
double
diagonalWeight
,
double
starPwr
,
// Divide cost by number of connections to this power
double
starPwr
,
// Divide cost by number of connections to this power
double
starWeightPwr
,
// Use this power of tile weight when calculating connection cost
double
starWeightPwr
,
// Use this power of tile weight when calculating connection cost
Tile
Surface
.
Tile
Neibs
tnSurface
,
TileNeibs
tnSurface
,
boolean
preferDisparity
,
boolean
preferDisparity
,
int
debugLevel
)
int
debugLevel
)
{
{
...
@@ -6156,7 +5821,7 @@ public class SuperTiles{
...
@@ -6156,7 +5821,7 @@ public class SuperTiles{
smplSide
,
smplSide
,
smplNum
,
smplNum
,
smplRms
,
smplRms
,
dl
);
// int debugLevel)
dl
-
2
);
// int debugLevel)
if
(
disp_strength
==
null
)
{
if
(
disp_strength
==
null
)
{
System
.
out
.
println
(
"=== BUG in applyMergePlanes(): failed to getPlaneFromMeas() for merged planes"
);
System
.
out
.
println
(
"=== BUG in applyMergePlanes(): failed to getPlaneFromMeas() for merged planes"
);
break
;
break
;
...
@@ -6177,7 +5842,7 @@ public class SuperTiles{
...
@@ -6177,7 +5842,7 @@ public class SuperTiles{
smplSide
,
smplSide
,
smplNum
,
smplNum
,
smplRms
,
smplRms
,
dl
);
// int debugLevel)
dl
-
2
);
// int debugLevel)
...
...
src/main/java/TileNeibs.java
0 → 100644
View file @
0ab422e2
import
java.util.ArrayList
;
import
java.util.Arrays
;
/**
** TileNeibs - handles walking inside rectangular area
**
** Copyright (C) 2017 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** TileNeibs.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
TileNeibs
{
int
sizeX
;
int
sizeY
;
public
int
dirs
=
8
;
public
TileNeibs
(
int
size
){
this
.
sizeX
=
size
;
this
.
sizeY
=
size
;
}
public
TileNeibs
(
int
sizeX
,
int
sizeY
){
this
.
sizeX
=
sizeX
;
this
.
sizeY
=
sizeY
;
}
public
int
numNeibs
()
// TODO: make configurable to
{
return
dirs
;
}
public
int
opposite
(
int
dir
){
return
(
dir
+
dirs
/
2
)
%
dirs
;
}
/**
* Get x,y pair from index
* @param indx element index
* @return array of {x,y}
*/
int
[]
getXY
(
int
indx
)
{
int
[]
xy
=
{
indx
%
sizeX
,
indx
/
sizeX
};
return
xy
;
}
/**
* Get element index from x and y
* @param x horizontal position
* @param y vertical position
* @return element linescan index
*/
int
getIndex
(
int
x
,
int
y
){
return
y
*
sizeX
+
x
;
}
/**
* Get 2d element index after step N, NE, ... NW. Returns -1 if leaving array
* @param indx start index
* @param dir step direction (CW from up)
* @return new index or -1 if leaving
*/
int
getNeibIndex
(
int
indx
,
int
dir
)
{
int
y
=
indx
/
sizeX
;
int
x
=
indx
%
sizeX
;
if
(
dir
<
0
)
return
indx
;
switch
(
dir
%
dirs
){
case
0
:
return
(
y
==
0
)
?
-
1
:
(
indx
-
sizeX
);
case
1
:
return
((
y
==
0
)
||
(
x
==
(
sizeX
-
1
)))
?
-
1
:
(
indx
-
sizeX
+
1
);
case
2
:
return
(
(
x
==
(
sizeX
-
1
)))
?
-
1
:
(
indx
+
1
);
case
3
:
return
((
y
==
(
sizeY
-
1
))
||
(
x
==
(
sizeX
-
1
)))
?
-
1
:
(
indx
+
sizeX
+
1
);
case
4
:
return
((
y
==
(
sizeY
-
1
))
)
?
-
1
:
(
indx
+
sizeX
);
case
5
:
return
((
y
==
(
sizeY
-
1
))
||
(
x
==
0
))
?
-
1
:
(
indx
+
sizeX
-
1
);
case
6
:
return
(
(
x
==
0
))
?
-
1
:
(
indx
-
1
);
case
7
:
return
((
y
==
0
)
||
(
x
==
0
))
?
-
1
:
(
indx
-
sizeX
-
1
);
default
:
return
indx
;
}
}
/**
* Return tile segment for 50% overlap. -1 - center, 0 N, 1 - NE,... 7 - NW
* @param indx element index
* @return which of the 9 areas this element belongs
*/
int
getSegment
(
int
indx
)
{
int
s1x
=
sizeX
/
4
;
int
s3x
=
3
*
sizeX
/
4
;
int
s1y
=
sizeY
/
4
;
int
s3y
=
3
*
sizeY
/
4
;
int
x
=
indx
%
sizeX
;
int
y
=
indx
/
sizeX
;
boolean
up
=
y
<
s1y
;
boolean
down
=
y
>=
s3y
;
boolean
left
=
x
<
s1x
;
boolean
right
=
x
>=
s3x
;
if
(
up
){
if
(
left
)
return
7
;
if
(
right
)
return
1
;
return
0
;
}
if
(
down
){
if
(
left
)
return
5
;
if
(
right
)
return
3
;
return
4
;
}
if
(
left
)
return
6
;
if
(
right
)
return
2
;
return
-
1
;
}
/**
* Find if the step leaves the center half of all area
* @param indx start point
* @param dir direction
* @return direction to the new tile (assuming 50% overlap) or -1 if did not cross the border
*/
int
leaveOvderlapedCenter
(
int
indx
,
int
dir
)
{
int
segm
=
getSegment
(
indx
);
int
indx1
=
getNeibIndex
(
indx
,
dir
);
if
(
indx1
<
0
)
{
return
-
1
;
// should not happen
}
int
segm1
=
getSegment
(
indx1
);
if
(
segm1
==
segm
)
return
-
1
;
if
(
segm
==
-
1
)
return
segm1
;
int
[][]
dxy
=
{
{
0
,
0
},
{-
1
,
0
},
{-
1
,
1
},
{
0
,
1
},
{
1
,
1
},
{
1
,
0
},
{
1
,-
1
},
{
0
,-
1
},
{-
1
,-
1
}};
int
dx
=
dxy
[
segm1
+
1
][
1
]
-
dxy
[
segm
+
1
][
1
];
int
dy
=
dxy
[
segm1
+
1
][
0
]
-
dxy
[
segm
+
1
][
0
];
for
(
int
dp1
=
0
;
dp1
<=
8
;
dp1
++)
{
int
sdx
=
(
dx
>
0
)
?
1
:
(
(
dx
<
0
)
?
-
1
:
0
);
int
sdy
=
(
dy
>
0
)
?
1
:
(
(
dy
<
0
)
?
-
1
:
0
);
if
((
dxy
[
dp1
][
0
]
==
sdy
)
&&
(
dxy
[
dp1
][
1
]
==
sdx
)){
return
dp1
-
1
;
}
}
return
-
1
;
// should not happen
}
public
void
growSelection
(
int
grow
,
// grow tile selection by 1 over non-background tiles 1: 4 directions, 2 - 8 directions, 3 - 8 by 1, 4 by 1 more
boolean
[]
tiles
,
boolean
[]
prohibit
)
{
boolean
[]
src_tiles
=
tiles
.
clone
();
// just in case
// grow
boolean
hor
=
true
;
for
(;
grow
>
0
;
grow
--){
boolean
single
=
(
grow
==
1
)
&&
hor
;
src_tiles
=
tiles
.
clone
();
int
num_new
=
0
;
if
(
hor
){
for
(
int
tileY
=
0
;
tileY
<
sizeY
;
tileY
++){
for
(
int
tileX
=
0
;
tileX
<
(
sizeX
-
1
);
tileX
++){
int
tindx
=
tileY
*
sizeX
+
tileX
;
if
((
prohibit
==
null
)
||
(!
prohibit
[
tindx
]
&&
!
prohibit
[
tindx
+
1
]))
{
if
(!
tiles
[
tindx
+
1
]
&&
src_tiles
[
tindx
]){
num_new
++;
}
tiles
[
tindx
+
1
]
|=
src_tiles
[
tindx
];
}
}
for
(
int
tileX
=
1
;
tileX
<
sizeX
;
tileX
++){
int
tindx
=
tileY
*
sizeX
+
tileX
;
if
((
prohibit
==
null
)
||
(!
prohibit
[
tindx
]
&&
!
prohibit
[
tindx
-
1
]))
{
if
(!
tiles
[
tindx
-
1
]
&&
src_tiles
[
tindx
]){
num_new
++;
}
tiles
[
tindx
-
1
]
|=
src_tiles
[
tindx
];
}
}
}
}
if
(!
hor
||
single
){
// do vertically, but from previous state
for
(
int
tileX
=
0
;
tileX
<
sizeX
;
tileX
++){
for
(
int
tileY
=
0
;
tileY
<
(
sizeY
-
1
);
tileY
++){
int
tindx
=
tileY
*
sizeX
+
tileX
;
if
((
prohibit
==
null
)
||
(!
prohibit
[
tindx
]
&&
!
prohibit
[
tindx
+
sizeX
]))
{
if
(!
tiles
[
tindx
+
sizeX
]
&&
src_tiles
[
tindx
]){
num_new
++;
}
tiles
[
tindx
+
sizeX
]
|=
src_tiles
[
tindx
];
}
}
for
(
int
tileY
=
1
;
tileY
<
sizeY
;
tileY
++){
int
tindx
=
tileY
*
sizeX
+
tileX
;
if
((
prohibit
==
null
)
||
(!
prohibit
[
tindx
]
&&
!
prohibit
[
tindx
-
sizeX
]))
{
if
(!
tiles
[
tindx
-
sizeX
]
&&
src_tiles
[
tindx
]){
num_new
++;
}
tiles
[
tindx
-
sizeX
]
|=
src_tiles
[
tindx
];
}
}
}
}
hor
=
!
hor
;
if
(
num_new
==
0
){
break
;
}
}
}
public
boolean
[]
boundShape
(
boolean
[]
selection
,
boolean
octo
)
{
boolean
[]
bound_shape
=
new
boolean
[
selection
.
length
];
int
min_x
=-
1
,
max_x
=-
1
,
min_y
=-
1
,
max_y
=-
1
;
int
min_s
=-
1
,
max_s
=-
1
,
min_d
=-
1
,
max_d
=-
1
;
boolean
is_set
=
false
;
for
(
int
i
=
0
;
i
<
selection
.
length
;
i
++)
if
(
selection
[
i
]){
int
[]
xy
=
getXY
(
i
);
int
[]
sd
=
{
xy
[
0
]+
xy
[
1
],
xy
[
0
]-
xy
[
1
]};
if
(!
is_set
)
{
min_x
=
xy
[
0
];
max_x
=
xy
[
0
];
min_y
=
xy
[
1
];
max_y
=
xy
[
1
];
if
(
octo
)
{
min_s
=
sd
[
0
];
max_s
=
sd
[
0
];
min_d
=
sd
[
1
];
max_d
=
sd
[
1
];
}
is_set
=
true
;
}
else
{
if
(
xy
[
0
]
<
min_x
)
min_x
=
xy
[
0
];
else
if
(
xy
[
0
]
>
max_x
)
max_x
=
xy
[
0
];
if
(
xy
[
1
]
<
min_y
)
min_y
=
xy
[
1
];
else
if
(
xy
[
1
]
>
max_y
)
max_y
=
xy
[
1
];
if
(
octo
)
{
if
(
sd
[
0
]
<
min_s
)
min_s
=
sd
[
0
];
else
if
(
sd
[
0
]
>
max_s
)
max_s
=
sd
[
0
];
if
(
sd
[
1
]
<
min_d
)
min_d
=
sd
[
1
];
else
if
(
sd
[
1
]
>
max_d
)
max_d
=
sd
[
1
];
}
}
}
for
(
int
y
=
min_y
;
y
<=
max_y
;
y
++){
for
(
int
x
=
min_x
;
x
<=
max_x
;
x
++){
if
(!
octo
||
(((
x
+
y
)
>=
min_s
)
&&
((
x
+
y
)
<=
max_s
)
&&
((
x
-
y
)
>=
min_d
)
&&
((
x
-
y
)
<=
max_d
)))
{
bound_shape
[
getIndex
(
x
,
y
)]
=
true
;
}
}
}
return
bound_shape
;
}
/**
* Enumerate clusters on rectangular area
* @param tiles selected tiles, size should be sizeX * sizeY
* @param ordered if true, order tiles from largest to smallest5
* @return integer array, where 0 is unused, 1+ cluster it belongs to
*/
public
int
[]
enumerateClusters
(
boolean
[]
tiles
,
boolean
ordered
)
{
int
[]
waves
=
new
int
[
tiles
.
length
];
for
(
int
i
=
0
;
i
<
tiles
.
length
;
i
++)
waves
[
i
]
=
tiles
[
i
]
?
0
:
-
1
;
ArrayList
<
Integer
>
front
=
new
ArrayList
<
Integer
>();
int
[]
enum_clust
=
new
int
[
tiles
.
length
];
int
numClust
=
0
;
for
(
int
start_indx
=
0
;
start_indx
<
tiles
.
length
;
start_indx
++)
if
(
waves
[
start_indx
]
==
0
){
// found first pixel of a new cluster
numClust
++;
Integer
ipx
=
start_indx
;
Integer
ipx1
;
front
.
clear
();
int
area
=
1
;
waves
[
ipx
]
=
area
;
enum_clust
[
ipx
]
=
numClust
;
front
.
add
(
ipx
);
while
(!
front
.
isEmpty
())
{
ipx
=
front
.
remove
(
0
);
// get oldest element
for
(
int
d
=
0
;
d
<
dirs
;
d
++){
ipx1
=
getNeibIndex
(
ipx
,
d
);
if
(
ipx1
>=
0
){
if
(
waves
[
ipx1
]
==
0
)
{
area
++;
waves
[
ipx1
]
=
area
;
enum_clust
[
ipx1
]
=
numClust
;
front
.
add
(
ipx1
);
}
}
}
}
}
if
(!
ordered
)
{
return
enum_clust
;
}
// count cluster
int
[]
clustSizes
=
new
int
[
numClust
];
for
(
int
i
=
0
;
i
<
clustSizes
.
length
;
i
++)
clustSizes
[
i
]
=
0
;
for
(
int
i
=
0
;
i
<
enum_clust
.
length
;
i
++)
if
(
enum_clust
[
i
]
>
0
)
clustSizes
[
enum_clust
[
i
]-
1
]++;
class
Pair
implements
Comparable
<
Pair
>
{
public
final
int
index
;
public
final
int
value
;
public
Pair
(
int
index
,
int
value
)
{
this
.
index
=
index
;
this
.
value
=
value
;
}
@Override
public
int
compareTo
(
Pair
other
)
{
return
Integer
.
valueOf
(
this
.
value
).
compareTo
(
other
.
value
);
}
}
Pair
[]
pairs
=
new
Pair
[
numClust
];
for
(
int
i
=
0
;
i
<
clustSizes
.
length
;
i
++)
pairs
[
i
]
=
new
Pair
(
i
,
clustSizes
[
i
]);
Arrays
.
sort
(
pairs
);
int
[]
revIndex
=
new
int
[
numClust
];
for
(
int
i
=
0
;
i
<
revIndex
.
length
;
i
++)
revIndex
[
pairs
[
i
].
index
]
=
(
numClust
-
i
);
// array was in accending order
int
[]
enum_clust_ordered
=
new
int
[
tiles
.
length
];
for
(
int
i
=
0
;
i
<
enum_clust_ordered
.
length
;
i
++){
enum_clust_ordered
[
i
]
=
(
enum_clust
[
i
]
>
0
)
?
revIndex
[
enum_clust
[
i
]
-
1
]
:
0
;
}
return
enum_clust_ordered
;
}
public
int
getMax
(
int
[]
data
)
{
int
mx
=
data
[
0
];
for
(
int
i
=
1
;
i
<
data
.
length
;
i
++){
if
(
data
[
i
]
>
mx
){
mx
=
data
[
i
];
}
}
return
mx
;
}
}
src/main/java/TilePlanes.java
View file @
0ab422e2
...
@@ -22,8 +22,10 @@
...
@@ -22,8 +22,10 @@
**
**
*/
*/
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.Comparator
;
import
java.util.HashSet
;
import
Jama.EigenvalueDecomposition
;
import
Jama.EigenvalueDecomposition
;
import
Jama.Matrix
;
import
Jama.Matrix
;
...
@@ -2210,13 +2212,13 @@ public class TilePlanes {
...
@@ -2210,13 +2212,13 @@ public class TilePlanes {
return
plane
;
return
plane
;
}
}
public
double
[][]
getDoublePlaneDisparityStrength
(
public
double
[][]
getDoublePlaneDisparityStrength
_old
(
double
[]
window
,
double
[]
window
,
boolean
use_sel
,
boolean
use_sel
,
boolean
divide_by_area
,
boolean
divide_by_area
,
double
scale_projection
,
double
scale_projection
,
int
debugLevel
)
int
debugLevel
)
{
return
getDoublePlaneDisparityStrength
(
{
return
getDoublePlaneDisparityStrength
_old
(
true
,
true
,
window
,
window
,
use_sel
,
use_sel
,
...
@@ -2259,7 +2261,7 @@ public class TilePlanes {
...
@@ -2259,7 +2261,7 @@ public class TilePlanes {
* @return a pair of arrays {disparity, strength}, each [2*superTileSize * 2*superTileSize]
* @return a pair of arrays {disparity, strength}, each [2*superTileSize * 2*superTileSize]
*/
*/
// obsolete, convert to another version ?
// obsolete, convert to another version ?
public
double
[][]
getDoublePlaneDisparityStrength
(
public
double
[][]
getDoublePlaneDisparityStrength
_old
(
boolean
useWorld
,
boolean
useWorld
,
double
[]
window
,
double
[]
window
,
boolean
use_sel
,
boolean
use_sel
,
...
@@ -3331,14 +3333,11 @@ public class TilePlanes {
...
@@ -3331,14 +3333,11 @@ public class TilePlanes {
return
world_xyz
;
return
world_xyz
;
}
}
public
ArrayList
<
TilePlanes
.
PlaneData
>
createTilePlanesFromSelections
(
public
ArrayList
<
PlaneData
>
createTilePlanesFromSelections
(
String
suffix
,
String
suffix
,
boolean
[][][]
plane_selections
,
// = new boolean [nStiles][][][]; // num_tiles
boolean
[][][]
plane_selections
,
// = new boolean [nStiles][][][]; // num_tiles
double
[][][]
disp_strength
,
double
[][][]
disp_strength
,
// double disp_far, // minimal disparity to select (or NaN)
// double disp_near, // maximal disparity to select (or NaN)
double
dispNorm
,
// Normalize disparities to the average if above
double
dispNorm
,
// Normalize disparities to the average if above
// double min_weight,
int
min_tiles
,
int
min_tiles
,
double
plTargetEigen
,
// = 0.1; // Remove outliers until main axis eigenvalue (possibly scaled by plDispNorm) gets below
double
plTargetEigen
,
// = 0.1; // Remove outliers until main axis eigenvalue (possibly scaled by plDispNorm) gets below
double
plFractOutliers
,
// = 0.3; // Maximal fraction of outliers to remove
double
plFractOutliers
,
// = 0.3; // Maximal fraction of outliers to remove
...
@@ -3354,11 +3353,11 @@ public class TilePlanes {
...
@@ -3354,11 +3353,11 @@ public class TilePlanes {
{
{
// first make a plane from all tiles
// first make a plane from all tiles
ArrayList
<
TilePlanes
.
PlaneData
>
st_planes
=
new
ArrayList
<
TilePlanes
.
PlaneData
>();
ArrayList
<
PlaneData
>
st_planes
=
new
ArrayList
<
PlaneData
>();
// iterate through all plane selections
// iterate through all plane selections
for
(
int
ps
=
0
;
ps
<
plane_selections
.
length
;
ps
++)
{
for
(
int
ps
=
0
;
ps
<
plane_selections
.
length
;
ps
++)
{
TilePlanes
.
PlaneData
pd
=
this
.
clone
();
PlaneData
pd
=
this
.
clone
();
boolean
OK
=
(
pd
.
getPlaneFromMeas
(
boolean
OK
=
(
pd
.
getPlaneFromMeas
(
plane_selections
[
ps
],
// tile_sel, // boolean [][] tile_sel, // null - do not use, {} use all (will be modified)
plane_selections
[
ps
],
// tile_sel, // boolean [][] tile_sel, // null - do not use, {} use all (will be modified)
disp_strength
,
disp_strength
,
...
@@ -3426,7 +3425,6 @@ public class TilePlanes {
...
@@ -3426,7 +3425,6 @@ public class TilePlanes {
}
}
// calculate the world planes too
// calculate the world planes too
// if (debugLevel > -1){
pd
.
getWorldPlaneFromMeas
(
pd
.
getWorldPlaneFromMeas
(
plane_selections
[
ps
],
// tile_sel, // boolean [][] tile_sel, // null - do not use, {} use all (will be modified)
plane_selections
[
ps
],
// tile_sel, // boolean [][] tile_sel, // null - do not use, {} use all (will be modified)
disp_strength
,
disp_strength
,
...
@@ -3447,9 +3445,9 @@ public class TilePlanes {
...
@@ -3447,9 +3445,9 @@ public class TilePlanes {
}
}
if
(
st_planes
.
size
()
>
0
){
if
(
st_planes
.
size
()
>
0
){
// sort planes by increasing disparity (tile center or plane center ? ) Using plane center
// sort planes by increasing disparity (tile center or plane center ? ) Using plane center
Collections
.
sort
(
st_planes
,
new
Comparator
<
TilePlanes
.
PlaneData
>()
{
Collections
.
sort
(
st_planes
,
new
Comparator
<
PlaneData
>()
{
@Override
@Override
public
int
compare
(
TilePlanes
.
PlaneData
lhs
,
TilePlanes
.
PlaneData
rhs
)
{
public
int
compare
(
PlaneData
lhs
,
PlaneData
rhs
)
{
// -1 - less than, 1 - greater than, 0 - equal
// -1 - less than, 1 - greater than, 0 - equal
return
(
rhs
.
getZxy
()[
0
]
>
lhs
.
getZxy
()[
0
])
?
-
1
:
(
rhs
.
getZxy
()[
0
]
<
lhs
.
getZxy
()[
0
]
)
?
1
:
0
;
return
(
rhs
.
getZxy
()[
0
]
>
lhs
.
getZxy
()[
0
])
?
-
1
:
(
rhs
.
getZxy
()[
0
]
<
lhs
.
getZxy
()[
0
]
)
?
1
:
0
;
}
}
...
@@ -3458,297 +3456,352 @@ public class TilePlanes {
...
@@ -3458,297 +3456,352 @@ public class TilePlanes {
}
}
return
null
;
return
null
;
}
}
public
boolean
[][][]
refineDiscriminateTiles
(
final
PlaneData
[]
planes
,
final
int
stMeasSel
,
// = 1; // Select measurements for supertiles : +1 - combo, +2 - quad +4 - hor +8 - vert
}
final
double
plDispNorm
,
final
int
plMinPoints
,
// = 5; // Minimal number of points for plane detection
final
GeometryCorrection
geometryCorrection
,
final
boolean
correct_distortions
,
//TODO: Remove below methods and promote PlaneData (no TilePlanes) after tested
final
boolean
smplMode
,
// = true; // Use sample mode (false - regular tile mode)
final
int
smplSide
,
// = 2; // Sample size (side of a square)
/**
final
int
smplNum
,
// = 3; // Number after removing worst
* Calculate covariance matrix for a subset of tile data (disparities)
final
double
smplRms
,
// = 0.1; // Maximal RMS of the remaining tiles in a sample
* Subtract weight floor from weight
* @param data data array - square (2*stSize) * (2*stSize)
final
double
max_disp_diff
,
// maximal disparity difference from the plane to consider tile
* @param weight per sample weight (should have floor already subtracted)
final
double
disp_range
,
// parallel move known planes around original know value for the best overall fit
* @param select sample selection
final
int
amplitude_steps
,
// number of steps (each direction) for each plane to search for the best fit (0 - single, 1 - 1 each side)
* @return covariance (diagonal) matrix: [0]: disparity, [1]: d<disparity>/dx, [2]: d<disparity>/dy,
final
int
num_variants
,
// total number of variants to try (protect from too many planes)
*/
final
int
mode
,
// 0 - weighted, 1 - equalized, 2 - best, 3 - combined
public
double
[][][]
getCovar
(
final
int
debugLevel
)
double
[]
data
,
{
double
[]
weight
,
if
(
planes
==
null
)
return
null
;
boolean
[]
select
,
// create a list of usable planes according to the mode
double
plDispNorm
,
// Normalize disparities to the average if above
ArrayList
<
PlaneData
>
tilePlanes
=
new
ArrayList
<
PlaneData
>();
int
debugLevel
){
for
(
int
np
=
0
;
np
<
planes
.
length
;
np
++)
if
(
planes
[
np
]
!=
null
){
double
mindet
=
1
E
-
15
;
PlaneData
weighted_pd
=
planes
[
np
].
getNonexclusiveStar
();
int
stSize2
=
2
*
stSize
;
PlaneData
equal_pd
=
planes
[
np
].
getNonexclusiveStarEq
();
// Matrix covar = new Matrix(3,3);
switch
(
mode
){
double
[][]
acovar
=
new
double
[
3
][
3
];
case
0
:
int
numPoints
=
0
;
if
(
weighted_pd
==
null
)
throw
new
IllegalArgumentException
(
"refineDiscriminateTiles(): getNonexclusiveStar() retgurned null"
);
double
sw
=
0.0
,
swz
=
0.0
,
swx
=
0.0
,
swy
=
0.0
;
tilePlanes
.
add
(
weighted_pd
);
break
;
for
(
int
indx
=
0
;
indx
<
data
.
length
;
indx
++){
case
1
:
if
(
select
[
indx
]
&&
(
weight
[
indx
]
>
0
)){
if
(
equal_pd
==
null
)
throw
new
IllegalArgumentException
(
"refineDiscriminateTiles(): getNonexclusiveStarEq() retgurned null"
);
numPoints
++;
tilePlanes
.
add
(
equal_pd
);
double
w
=
weight
[
indx
];
break
;
double
d
=
data
[
indx
];
case
2
:
// referencing samples to centers of pixels
if
(
weighted_pd
==
null
)
throw
new
IllegalArgumentException
(
"refineDiscriminateTiles(): getNonexclusiveStar() retgurned null"
);
double
x
=
((
indx
%
stSize2
)
-
stSize
+
0.5
)
*
tileSize
+
0.5
;
// in pixels, not in tiles
if
(
equal_pd
==
null
)
throw
new
IllegalArgumentException
(
"refineDiscriminateTiles(): getNonexclusiveStarEq() retgurned null"
);
double
y
=
((
indx
/
stSize2
)
-
stSize
+
0.5
)
*
tileSize
+
0.5
;
if
(
weighted_pd
.
getWeight
()
>
equal_pd
.
getWeight
())
tilePlanes
.
add
(
weighted_pd
);
sw
+=
w
;
else
tilePlanes
.
add
(
equal_pd
);
swz
+=
w
*
d
;
break
;
swx
+=
w
*
x
;
case
3
:
swy
+=
w
*
y
;
if
(
weighted_pd
==
null
)
throw
new
IllegalArgumentException
(
"refineDiscriminateTiles(): getNonexclusiveStar() retgurned null"
);
}
if
(
equal_pd
==
null
)
throw
new
IllegalArgumentException
(
"refineDiscriminateTiles(): getNonexclusiveStarEq() retgurned null"
);
}
PlaneData
combo_pd
=
weighted_pd
.
mergePlaneToThis
(
if
(
sw
==
0.0
)
{
equal_pd
,
// PlaneData otherPd,
return
null
;
1.0
,
// double scale_other,
}
1.0
,
// double starWeightPwr, // Use this power of tile weight when calculating connection cost
swz
/=
sw
;
false
,
// boolean ignore_weights,
swx
/=
sw
;
true
,
// boolean sum_weights,
swy
/=
sw
;
preferDisparity
,
// boolean preferDisparity, // Always start with disparity-most axis (false - lowest eigenvalue)
debugLevel
-
2
);
// int debugLevel)
break
;
// TODO: scale disparity to make same scale for 3 axes?
default
:
throw
new
IllegalArgumentException
(
"refineDiscriminateTiles(): invalid mode="
+
mode
);
double
kz
=
((
plDispNorm
>
0.0
)
&&
(
swz
>
plDispNorm
))
?
(
plDispNorm
/
swz
)
:
1.0
;
if
(
debugLevel
>
0
){
System
.
out
.
println
(
"getCovar(): sw = "
+
sw
+
", swz = "
+
swz
+
", swx = "
+
swx
+
", swy = "
+
swy
+
" kz = "
+
kz
);
}
for
(
int
indx
=
0
;
indx
<
data
.
length
;
indx
++){
if
(
select
[
indx
]
&&
(
weight
[
indx
]
>
0
)){
double
w
=
weight
[
indx
]
/
sw
;
double
d
=
kz
*
(
data
[
indx
]
-
swz
);
double
wd
=
w
*
d
;
double
x
=
((
indx
%
stSize2
)
-
stSize
+
0.5
)
*
tileSize
+
0.5
-
swx
;
double
y
=
((
indx
/
stSize2
)
-
stSize
+
0.5
)
*
tileSize
+
0.5
-
swy
;
acovar
[
0
][
0
]
+=
wd
*
d
;
acovar
[
0
][
1
]
+=
wd
*
x
;
acovar
[
0
][
2
]
+=
wd
*
y
;
acovar
[
1
][
1
]
+=
w
*
x
*
x
;
acovar
[
1
][
2
]
+=
w
*
x
*
y
;
acovar
[
2
][
2
]
+=
w
*
y
*
y
;
}
}
acovar
[
1
][
0
]
=
acovar
[
0
][
1
];
acovar
[
2
][
0
]
=
acovar
[
0
][
2
];
acovar
[
2
][
1
]
=
acovar
[
1
][
2
];
Matrix
covar
=
new
Matrix
(
acovar
);
// if (Math.abs(covar.det()) < mindet){
// debugLevel = 5;
// }
EigenvalueDecomposition
eig
=
covar
.
eig
();
if
(
Double
.
isNaN
(
eig
.
getV
().
get
(
0
,
0
))){
System
.
out
.
println
(
"getCovar(): Double.isNaN(eig.getV().get(0, 0))"
);
debugLevel
=
20
;
}
if
(
debugLevel
>
3
){
System
.
out
.
println
(
"getCovar(): sw = "
+
sw
+
", swz = "
+
swz
+
", swx = "
+
swx
+
", swy = "
+
swy
+
", covar.det() = "
+
covar
.
det
());
System
.
out
.
println
(
"getCovar(): covarianvce matrix, number of used points:"
+
numPoints
);
covar
.
print
(
10
,
6
);
// w,d
System
.
out
.
println
(
"getCovar(): eigenvalues"
);
eig
.
getD
().
print
(
10
,
6
);
// w,d
System
.
out
.
println
(
"getCovar(): eigenvectors"
);
eig
.
getV
().
print
(
10
,
6
);
// w,d
}
if
((
eig
.
getD
().
get
(
0
,
0
)
==
0.0
)
||
(
Math
.
abs
(
covar
.
det
())
<
mindet
))
{
return
null
;
// testing with zero eigenvalue
// Problem with zero eigenvalue is with derivatives and coordinate conversion
}
double
[][][]
rslt
=
{
eig
.
getD
().
getArray
(),
eig
.
getV
().
getArray
(),
{
{
sw
,
kz
,
numPoints
},
{
swz
,
swx
,
swy
}}};
return
rslt
;
}
// TODO: obsolete - remove
public
PlaneData
getPlane
(
int
[]
sTileXY
,
double
[]
data
,
double
[]
weight
,
boolean
[]
select
,
// null OK, will enable all tiles
boolean
correctDistortions
,
boolean
preferDisparity
,
// Always start with disparity-most axis (false - lowest eigenvalue)
int
debugLevel
){
if
(
select
==
null
)
{
select
=
new
boolean
[
4
*
stSize
];
for
(
int
i
=
0
;
i
<
select
.
length
;
i
++)
select
[
i
]
=
true
;
}
if
(
debugLevel
>
0
){
System
.
out
.
println
(
"getPlane()"
);
}
double
[][][]
rslt
=
getCovar
(
data
,
weight
,
select
,
0.0
,
debugLevel
);
// debugLevel1); //0); // debugLevel);
if
(
rslt
==
null
)
return
null
;
int
numPoints
=
(
int
)
rslt
[
2
][
0
][
2
];
double
swc
=
rslt
[
2
][
0
][
0
];
double
[]
szxy
=
rslt
[
2
][
1
];
double
[][]
eig_val
=
rslt
[
0
];
double
[][]
eig_vect
=
rslt
[
1
];
// find vector most orthogonal to view // (anyway it all works with that assumption), make it first
// TODO normalize to local linear scales
int
oindx
=
0
;
if
(
preferDisparity
)
{
for
(
int
i
=
1
;
i
<
3
;
i
++){
if
(
Math
.
abs
(
eig_vect
[
0
][
i
])
>
Math
.
abs
(
eig_vect
[
0
][
oindx
])){
oindx
=
i
;
}
}
}
}
}
else
{
if
(
tilePlanes
.
isEmpty
()){
for
(
int
i
=
1
;
i
<
3
;
i
++){
return
null
;
if
(
eig_val
[
i
][
i
]
<
eig_val
[
oindx
][
oindx
]){
}
oindx
=
i
;
// get measured disparity/strength data, filtered, not tilted
double
[][][]
disp_strength
=
new
double
[
measuredLayers
.
getNumLayers
()][][];
for
(
int
ml
=
0
;
ml
<
disp_strength
.
length
;
ml
++)
if
((
stMeasSel
&
(
1
<<
ml
))
!=
0
){
if
(
smplMode
)
{
disp_strength
[
ml
]
=
measuredLayers
.
getDisparityStrength
(
// expensive to calculate (improve removing outlayers
ml
,
// int num_layer,
getSTileXY
()[
0
],
// int stX,
getSTileXY
()[
1
],
// int stY,
null
,
// boolean [] sel_in, - use all
strength_floor
,
measured_strength_pow
,
//
smplSide
,
// = 2; // Sample size (side of a square)
smplNum
,
// = 3; // Number after removing worst
smplRms
,
// = 0.1; // Maximal RMS of the remaining tiles in a sample
true
);
// boolean null_if_none)
}
else
{
disp_strength
[
ml
]
=
measuredLayers
.
getDisparityStrength
(
ml
,
// int num_layer,
getSTileXY
()[
0
],
// int stX,
getSTileXY
()[
1
],
// int stY,
null
,
// boolean [] sel_in, - use all
strength_floor
,
// double strength_floor,
measured_strength_pow
,
// double strength_pow,
true
);
// boolean null_if_none);
}
}
double
[]
window
=
getWindow
(
2
*
superTileSize
);
// get all original planes
int
num_planes
=
tilePlanes
.
size
();
double
[][][]
pds
=
new
double
[
num_planes
][][];
for
(
int
np
=
0
;
np
<
pds
.
length
;
np
++){
PlaneData
pd
=
tilePlanes
.
get
(
np
);
pds
[
np
]
=
pd
.
getDoublePlaneDisparityStrength
(
false
,
// boolean useWorld,
null
,
// double [] window,
-
1
,
// int dir,
false
,
// boolean use_sel,
false
,
// boolean divide_by_area,
1.0
,
// double scale_projection,
0.0
,
// double fraction_uni,
0
);
// int debugLevel)
}
// calculate number of the variants for each plane
int
extra_vars
=
(((
int
)
Math
.
pow
(
num_variants
,
1.0
/
num_planes
))
-
1
)
/
2
;
// 0 - single, 1 - 3 (1 each direction), ...
if
(
extra_vars
>
amplitude_steps
)
extra_vars
=
amplitude_steps
;
//
int
steps
=
2
*
extra_vars
+
1
;
double
[]
disps
=
new
double
[
steps
];
disps
[
0
]
=
0.0
;
// center
for
(
int
i
=
0
;
i
<
extra_vars
;
i
++){
disps
[
2
*
i
+
1
]
=
(
disp_range
*
(
i
+
1
))
/
extra_vars
;
disps
[
2
*
i
+
2
]
=
-
disps
[
2
*
i
+
1
];
}
int
[]
state
=
new
int
[
num_planes
];
// variants counter
// for (int variant = 0; i < num_variants; variant++ )
while
(
true
){
// evaluate current variant
double
[]
weights
=
new
double
[
num_planes
];
double
[]
err2
=
new
double
[
num_planes
];
boolean
// calculate next variant
boolean
all_done
=
true
;
for
(
int
i
=
0
;
i
<
num_planes
;
i
++){
if
(
state
[
i
]
<
(
steps
-
1
)){
state
[
i
]
++;
for
(
int
j
=
0
;
j
<
i
;
j
++){
state
[
j
]
=
0
;
}
all_done
=
false
;
break
;
}
}
if
(
all_done
){
break
;
}
}
}
}
}
if
(
eig_val
[
oindx
][
oindx
]
==
0.0
){
System
.
out
.
println
(
"getPlane(): zero eigenvalue!!"
);
}
/*
// Find two other axis - "mostly X" (horizontal) and "mostly Y" (vertical)
int vindx = (oindx == 0)? 1 : 0;
int hindx = (oindx == 0)? 2 : ((oindx == 1) ? 2 : 1);
if (Math.abs(eig_vect[2][vindx]) < Math.abs(Math.abs(eig_vect[2][hindx]))){
int tmp = vindx;
vindx = hindx;
hindx = tmp;
}
*/
// select 2 other axes for increasing eigenvalues (so v is short axis, h is the long one)
int
vindx
=
(
oindx
==
0
)?
1
:
0
;
int
hindx
=
(
oindx
==
0
)?
2
:
((
oindx
==
1
)
?
2
:
1
);
if
(
eig_val
[
vindx
][
vindx
]
>
eig_val
[
hindx
][
hindx
]){
int
tmp
=
vindx
;
vindx
=
hindx
;
hindx
=
tmp
;
}
PlaneData
pd
=
new
PlaneData
(
sTileXY
,
this
.
tileSize
,
this
.
stSize
,
this
.
geometryCorrection
,
correctDistortions
);
pd
.
setZxy
(
szxy
);
// pd.setValues(eig_val[oindx][oindx],eig_val[hindx][hindx],eig_val[vindx][vindx]); // eigenvalues [0] - thickness, 2 other to detect skinny (poles)
pd
.
setValues
(
eig_val
[
oindx
][
oindx
],
eig_val
[
vindx
][
vindx
],
eig_val
[
hindx
][
hindx
]);
// eigenvalues [0] - thickness, 2 other to detect skinny (poles)
double
[][]
plane
=
{
{
eig_vect
[
0
][
oindx
],
eig_vect
[
1
][
oindx
],
eig_vect
[
2
][
oindx
]},
// plane normal to camera
{
eig_vect
[
0
][
vindx
],
eig_vect
[
1
][
vindx
],
eig_vect
[
2
][
vindx
]},
// "horizontal" axis // to detect skinny planes and poles
{
eig_vect
[
0
][
hindx
],
eig_vect
[
1
][
hindx
],
eig_vect
[
2
][
hindx
]}};
// "vertical" axis // to detect skinny planes and poles
return
null
;
/*
// Make normal be towards camera (positive disparity), next vector - positive in X direction (right), last one - in positive Y (down)
for (int v = 0; v <3; v++) {
if (plane[v][v] < 0.0) for (int i = 0; i < 3; i ++) plane[v][i] = -plane[v][i];
}
*/
// Make normal be towards camera (positive disparity), next vector - positive in X direction (right)
for
(
int
v
=
0
;
v
<
2
;
v
++)
{
if
(
plane
[
v
][
v
]
<
0.0
)
for
(
int
i
=
0
;
i
<
3
;
i
++)
plane
[
v
][
i
]
=
-
plane
[
v
][
i
];
}
}
// make direction last vector so px (x) py (.) disp < 0 (left-hand coordinate system)
if
(
new
Matrix
(
plane
).
det
()
>
0
){
for
(
int
i
=
0
;
i
<
3
;
i
++)
plane
[
2
][
i
]
=
-
plane
[
2
][
i
];
}
pd
.
setVectors
(
plane
);
// detect and split/eliminate planes that are use disconnected tiles
pd
.
setNumPoints
(
numPoints
);
// and are not separated by higher disparity planes
pd
.
setWeight
(
swc
);
// return planes/selections (no remove outliers!)
pd
.
setPlaneSelection
(
select
);
boolean
[][][]
filterBridges
(
return
pd
;
ArrayList
<
PlaneData
>
tilePlanes
,
}
int
max_grow_these
,
int
max_grow_far
,
public
PlaneData
removePlaneOutliers
(
int
debugLevel
)
PlaneData
pd
,
// already found or null
{
int
[]
sTileXY
,
// may be null if pd is not null
double
[][]
pds
=
new
double
[
tilePlanes
.
size
()][];
double
[]
data
,
double
[]
max_disp
=
null
;
double
[]
weight
,
boolean
[][]
selections
=
new
boolean
[
pds
.
length
][];
boolean
[]
select
,
// will be modified
final
int
tsize
=
4
*
stSize
*
stSize
;
boolean
correctDistortions
,
for
(
int
np
=
0
;
np
<
pds
.
length
;
np
++){
double
targetEigen
,
// target eigenvalue for primary axis (is disparity-dependent, so is non-constant)
PlaneData
pd
=
tilePlanes
.
get
(
np
);
int
maxRemoved
,
// maximal number of tiles to remove (not a constant)
if
(
pd
!=
null
){
int
minLeft
,
// minimal number of tiles to keep
pds
[
np
]
=
pd
.
getDoublePlaneDisparityStrength
(
boolean
preferDisparity
,
// Always start with disparity-most axis (false - lowest eigenvalue)
false
,
// boolean useWorld,
int
debugLevel
){
null
,
// double [] window,
int
stSize2
=
2
*
stSize
;
-
1
,
// int dir,
if
(
pd
==
null
)
{
false
,
// boolean use_sel,
pd
=
getPlane
(
false
,
// boolean divide_by_area,
sTileXY
,
1.0
,
// double scale_projection,
data
,
0.0
,
// double fraction_uni,
weight
,
0
)[
0
];
// int debugLevel)
select
,
// null OK
if
(
max_disp
==
null
){
correctDistortions
,
max_disp
=
pds
[
np
].
clone
();
preferDisparity
,
}
else
{
debugLevel
);
for
(
int
i
=
0
;
i
<
max_disp
.
length
;
i
++){
}
else
if
(
select
!=
null
){
max_disp
[
i
]
=
Math
.
max
(
max_disp
[
i
],
pds
[
np
][
i
]);
pd
.
setPlaneSelection
(
select
);
}
}
}
if
(
pd
==
null
){
boolean
[][]
ms
=
pd
.
getMeasSelection
();
// should not be null
return
null
;
// zero eigenvalues
// combine selections from all measurement layers
}
for
(
int
ml
=
0
;
ml
<
ms
.
length
;
ml
++)
if
(
ms
[
ml
]
!=
null
){
if
(
maxRemoved
>
(
pd
.
getNumPoints
()
-
minLeft
))
maxRemoved
=
pd
.
getNumPoints
()
-
minLeft
;
if
(
selections
[
np
]
==
null
)
{
int
numRemoved
=
0
;
selections
[
np
]
=
ms
[
ml
].
clone
();
for
(;
(
pd
.
getValue
()
>
targetEigen
)
&&
(
numRemoved
<
maxRemoved
);
numRemoved
++){
}
else
{
if
(
debugLevel
>
2
){
for
(
int
i
=
0
;
i
<
ms
[
ml
].
length
;
i
++)
{
System
.
out
.
println
(
"removePlaneOutliers("
+
sTileXY
[
0
]+
":"
+
sTileXY
[
1
]+
"): numRemoved = "
+
numRemoved
+
" eigenValue = "
+
pd
.
getValue
()+
" target = "
+
targetEigen
);
selections
[
np
][
i
]
|=
ms
[
ml
][
i
];
}
}
// make a plane and find the worst (largest disparity difference) tile
}
// z = -(x*Vx + y*Vy)/Vz
double
worst_d2
=
0.0
;
int
worst_index
=
-
1
;
double
[]
v
=
pd
.
getVector
();
double
[]
zxy0
=
pd
.
getZxy
();
for
(
int
indx
=
0
;
indx
<
data
.
length
;
indx
++){
if
(
select
[
indx
]
&&
(
weight
[
indx
]
>
0
)){
// double w = weight[indx];
double
x
=
((
indx
%
stSize2
)
-
stSize
)
-
zxy0
[
1
];
double
y
=
((
indx
/
stSize2
)
-
stSize
)
-
zxy0
[
2
];
double
d
=
data
[
indx
];
d
-=
zxy0
[
0
];
d
+=
(
x
*
v
[
1
]+
y
*
v
[
2
])/
v
[
0
];
double
d2
=
d
*
d
;
if
(
d2
>
worst_d2
){
worst_d2
=
d2
;
worst_index
=
indx
;
}
}
}
}
}
}
if
(
worst_index
<
0
)
{
class
TileSelections
{
System
.
out
.
println
(
"This is a BUG in removePlaneOutliers()"
);
int
np
;
// number of original plane
break
;
boolean
[]
mask
;
// selection mask to apply to measurement layers
TileSelections
(
int
nl
,
boolean
[]
mask
){
this
.
np
=
nl
;
this
.
mask
=
mask
;
}
}
ArrayList
<
TileSelections
>
split_planes
=
new
ArrayList
<
TileSelections
>();
TileNeibs
tileNeibs
=
new
TileNeibs
(
2
*
stSize
,
2
*
stSize
);
HashSet
<
Integer
>
old_planes
=
new
HashSet
<
Integer
>();
for
(
int
np
=
0
;
np
<
pds
.
length
;
np
++){
PlaneData
pd
=
tilePlanes
.
get
(
np
);
if
(
pd
!=
null
){
old_planes
.
add
(
np
);
// see if all the plane tiles have other planes with higher disparity
boolean
all_far
=
true
;
for
(
int
i
=
0
;
i
<
max_disp
.
length
;
i
++)
if
(
selections
[
np
][
i
]){
if
(
pds
[
np
][
i
]
==
max_disp
[
i
]){
all_far
=
false
;
break
;
}
}
if
(!
all_far
){
boolean
[]
grown_sel
=
selections
[
np
].
clone
();
tileNeibs
.
growSelection
(
//
max_grow_these
,
// int grow, // grow tile selection by 1 over non-background tiles 1: 4 directions, 2 - 8 directions, 3 - 8 by 1, 4 by 1 more
grown_sel
,
// boolean [] tiles,
null
);
// boolean [] prohibit,
int
[]
clusters
=
tileNeibs
.
enumerateClusters
(
grown_sel
,
// boolean [] tiles,
false
);
// boolean ordered)
int
num_clusters
=
tileNeibs
.
getMax
(
clusters
);
// int [] data)
if
(
num_clusters
>
1
){
boolean
[]
dbg_grown_sel
=
grown_sel
.
clone
();
// determine area that should have connections between these clusters, not blocked by known
// tiles with lower disparity
boolean
[]
bound_octo
=
tileNeibs
.
boundShape
(
selections
[
np
],
// boolean [] selection,
true
);
// boolean octo)
// now combine all "offending" selections - known tiles belonging to farther planes
boolean
[]
sel_offend
=
new
boolean
[
tsize
];
for
(
int
np_other
=
0
;
np_other
<
pds
.
length
;
np_other
++)
if
((
selections
[
np_other
]
!=
null
)
&&
(
np_other
!=
np
)){
for
(
int
i
=
0
;
i
<
tsize
;
i
++)
if
(
selections
[
np_other
][
i
]){
sel_offend
[
i
]
|=
(
pds
[
np
][
i
]
>
pds
[
np_other
][
i
]);
}
}
// now grow offending selections to fill gaps
boolean
[]
dbg_sel_offend
=
sel_offend
.
clone
();
tileNeibs
.
growSelection
(
//
max_grow_far
,
// int grow, // grow tile selection by 1 over non-background tiles 1: 4 directions, 2 - 8 directions, 3 - 8 by 1, 4 by 1 more
sel_offend
,
// boolean [] tiles,
null
);
// boolean [] prohibit,
// create prohibited mask - all not in grown selection that are outside bounding octagon or belong to grown offenders
boolean
[]
prohibit
=
new
boolean
[
tsize
];
for
(
int
i
=
0
;
i
<
prohibit
.
length
;
i
++)
{
prohibit
[
i
]
=
!
grown_sel
[
i
]
&&
(!
bound_octo
[
i
]
||
sel_offend
[
i
]
);
// (pds[np][i] > max_disp[i]);
}
tileNeibs
.
growSelection
(
//
stSize
,
// int grow, // grow tile selection by 1 over non-background tiles 1: 4 directions, 2 - 8 directions, 3 - 8 by 1, 4 by 1 more
grown_sel
,
// boolean [] tiles,
prohibit
);
// boolean [] prohibit,
// re-clusterize what is remaining
int
[]
dbg_clusters
=
clusters
.
clone
();
clusters
=
tileNeibs
.
enumerateClusters
(
grown_sel
,
// boolean [] tiles,
false
);
// boolean ordered)
num_clusters
=
tileNeibs
.
getMax
(
clusters
);
if
(
num_clusters
>
1
){
boolean
[][]
cluster_sels
=
new
boolean
[
num_clusters
][
selections
[
np
].
length
];
for
(
int
i
=
0
;
i
<
selections
[
np
].
length
;
i
++)
if
(
selections
[
np
][
i
]){
cluster_sels
[
clusters
[
i
]-
1
][
i
]
=
true
;
}
for
(
int
nc
=
0
;
nc
<
num_clusters
;
nc
++){
split_planes
.
add
(
new
TileSelections
(
np
,
cluster_sels
[
nc
]));
}
old_planes
.
remove
(
np
);
}
if
(
debugLevel
>
2
)
{
String
[]
dbg_titles
=
{
"sel"
,
"grown"
,
"clust0"
,
"bound"
,
"offend"
,
"off_grown"
,
"prohibit"
,
"clusters"
,
"clus_masked"
};
double
[][]
dbg_img
=
new
double
[
dbg_titles
.
length
][
tsize
];
double
lon
=
3.0
;
for
(
int
i
=
0
;
i
<
tsize
;
i
++)
{
dbg_img
[
0
][
i
]
=
selections
[
np
][
i
]
?
lon:
0.0
;
dbg_img
[
1
][
i
]
=
dbg_grown_sel
[
i
]
?
lon:
0.0
;
dbg_img
[
2
][
i
]
=
dbg_clusters
[
i
];
dbg_img
[
3
][
i
]
=
bound_octo
[
i
]
?
lon:
0.0
;
dbg_img
[
4
][
i
]
=
dbg_sel_offend
[
i
]
?
lon:
0.0
;
dbg_img
[
5
][
i
]
=
sel_offend
[
i
]
?
lon:
0.0
;
dbg_img
[
6
][
i
]
=
prohibit
[
i
]
?
lon:
0.0
;
dbg_img
[
7
][
i
]
=
clusters
[
i
];
dbg_img
[
8
][
i
]
=
selections
[
np
][
i
]
?
clusters
[
i
]
:
0.0
;
}
showDoubleFloatArrays
sdfa_instance
=
new
showDoubleFloatArrays
();
sdfa_instance
.
showArrays
(
dbg_img
,
2
*
superTileSize
,
2
*
superTileSize
,
true
,
"bridges-"
+
np
+
"-"
+
debugLevel
,
dbg_titles
);
sdfa_instance
.
showArrays
(
pds
,
2
*
superTileSize
,
2
*
superTileSize
,
true
,
"pds-bridges-"
+
np
+
"-"
+
debugLevel
,
dbg_titles
);
}
}
}
}
}
}
select
[
worst_index
]
=
false
;
if
(!
split_planes
.
isEmpty
()){
if
(
debugLevel
>
2
){
boolean
[][][]
split_selections
=
new
boolean
[
old_planes
.
size
()
+
split_planes
.
size
()][][];
System
.
out
.
println
(
"removePlaneOutliers() worst_index = "
+
worst_index
);
int
ns
=
0
;
for
(
Integer
np:
old_planes
){
split_selections
[
ns
++]
=
tilePlanes
.
get
(
np
).
getMeasSelection
();
}
for
(
TileSelections
ts:
split_planes
){
PlaneData
pd
=
tilePlanes
.
get
(
ts
.
np
);
boolean
[][]
ms
=
tilePlanes
.
get
(
ts
.
np
).
getMeasSelection
().
clone
();
for
(
int
ml
=
0
;
ml
<
ms
.
length
;
ml
++)
if
(
ms
[
ml
]
!=
null
){
ms
[
ml
]
=
ms
[
ml
].
clone
();
for
(
int
i
=
0
;
i
<
ms
[
ml
].
length
;
i
++){
ms
[
ml
][
i
]
&=
ts
.
mask
[
i
];
}
}
split_selections
[
ns
++]
=
ms
;
}
return
split_selections
;
}
}
return
null
;
// no changes
pd
=
getPlane
(
// re-calculate with point removed
}
pd
.
getSTileXY
(),
data
,
public
double
[]
getWindow
(
weight
,
int
size
)
select
,
{
correctDistortions
,
double
[]
wnd1d
=
new
double
[
size
];
preferDisparity
,
for
(
int
i
=
0
;
i
<
size
/
2
;
i
++){
debugLevel
);
wnd1d
[
i
]
=
0.5
*
(
1.0
-
Math
.
cos
(
2
*
Math
.
PI
*(
i
+
0.5
)/
size
));
if
(
pd
==
null
)
{
wnd1d
[
size
-
i
-
1
]
=
wnd1d
[
i
];
return
null
;
}
double
[]
wnd
=
new
double
[
size
*
size
];
int
indx
=
0
;
for
(
int
i
=
0
;
i
<
size
;
i
++){
for
(
int
j
=
0
;
j
<
size
;
j
++){
wnd
[
indx
++]
=
wnd1d
[
i
]*
wnd1d
[
j
];
}
}
}
return
wnd
;
}
}
return
pd
;
}
}
}
}
src/main/java/TileProcessor.java
View file @
0ab422e2
...
@@ -3386,7 +3386,7 @@ public class TileProcessor {
...
@@ -3386,7 +3386,7 @@ public class TileProcessor {
LinkPlanes
lp
=
new
LinkPlanes
(
clt_parameters
,
st
);
LinkPlanes
lp
=
new
LinkPlanes
(
clt_parameters
,
st
);
// try to merge multiple times
// try to merge multiple times
int
max_num_merge_try
=
5
;
int
max_num_merge_try
=
8
;
TilePlanes
.
PlaneData
[][][]
dbg_orig_planes
=
new
TilePlanes
.
PlaneData
[
max_num_merge_try
][][];
TilePlanes
.
PlaneData
[][][]
dbg_orig_planes
=
new
TilePlanes
.
PlaneData
[
max_num_merge_try
][][];
for
(
int
num_merge_try
=
0
;
num_merge_try
<
max_num_merge_try
;
num_merge_try
++){
for
(
int
num_merge_try
=
0
;
num_merge_try
<
max_num_merge_try
;
num_merge_try
++){
...
@@ -3467,20 +3467,6 @@ public class TileProcessor {
...
@@ -3467,20 +3467,6 @@ public class TileProcessor {
clt_parameters
.
tileX
,
clt_parameters
.
tileX
,
clt_parameters
.
tileY
);
clt_parameters
.
tileY
);
// System.out.println("merge_cost_data.length = " + merge_cost_data.length);
// System.out.println("merge_cost_data.length = " + merge_cost_data.length);
/*
// double [][][][][][] merge_cost_data_eq =
lp.costSameTileConnections(
true, // final boolean ignore_weights,
1.8, // final double threshold_worst,
1000.0, //final double threshold_world_worst,
st.planes, // ffinal TilePlanes.PlaneData [][] planes,
merge_candidates, // final int [][][] merge_candidates,
plane_nooverlaps, // final boolean [][][] valid_candidates, // will be updated
2, // -1, // debugLevel, // final int debugLevel)
clt_parameters.tileX,
clt_parameters.tileY);
// System.out.println("merge_cost_data_eq.length = " + merge_cost_data_eq.length);
*/
int
[][][]
merge_groups
=
lp
.
extractMergeSameTileGroups
(
int
[][][]
merge_groups
=
lp
.
extractMergeSameTileGroups
(
st
.
planes
,
// final TilePlanes.PlaneData [][] planes,
st
.
planes
,
// final TilePlanes.PlaneData [][] planes,
merge_candidates
,
// final int [][][] merge_candidates,
merge_candidates
,
// final int [][][] merge_candidates,
...
...
src/main/java/TileSurface.java
View file @
0ab422e2
...
@@ -235,144 +235,6 @@ public class TileSurface {
...
@@ -235,144 +235,6 @@ public class TileSurface {
}
}
public
class
TileNeibs
{
int
sizeX
;
int
sizeY
;
public
int
dirs
=
8
;
public
TileNeibs
(
int
size
){
this
.
sizeX
=
size
;
this
.
sizeY
=
size
;
}
public
TileNeibs
(
int
sizeX
,
int
sizeY
){
this
.
sizeX
=
sizeX
;
this
.
sizeY
=
sizeY
;
}
public
int
numNeibs
()
// TODO: make configurable to
{
return
dirs
;
}
public
int
opposite
(
int
dir
){
return
(
dir
+
dirs
/
2
)
%
dirs
;
}
/**
* Get x,y pair from index
* @param indx element index
* @return array of {x,y}
*/
int
[]
getXY
(
int
indx
)
{
int
[]
xy
=
{
indx
%
sizeX
,
indx
/
sizeX
};
return
xy
;
}
/**
* Get element index from x and y
* @param x horizontal position
* @param y vertical position
* @return element linescan index
*/
int
getIndex
(
int
x
,
int
y
){
return
y
*
sizeX
+
x
;
}
/**
* Get 2d element index after step N, NE, ... NW. Returns -1 if leaving array
* @param indx start index
* @param dir step direction (CW from up)
* @return new index or -1 if leaving
*/
int
getNeibIndex
(
int
indx
,
int
dir
)
{
int
y
=
indx
/
sizeX
;
int
x
=
indx
%
sizeX
;
if
(
dir
<
0
)
return
indx
;
switch
(
dir
%
dirs
){
case
0
:
return
(
y
==
0
)
?
-
1
:
(
indx
-
sizeX
);
case
1
:
return
((
y
==
0
)
||
(
x
==
(
sizeX
-
1
)))
?
-
1
:
(
indx
-
sizeX
+
1
);
case
2
:
return
(
(
x
==
(
sizeX
-
1
)))
?
-
1
:
(
indx
+
1
);
case
3
:
return
((
y
==
(
sizeY
-
1
))
||
(
x
==
(
sizeX
-
1
)))
?
-
1
:
(
indx
+
sizeX
+
1
);
case
4
:
return
((
y
==
(
sizeY
-
1
))
)
?
-
1
:
(
indx
+
sizeX
);
case
5
:
return
((
y
==
(
sizeY
-
1
))
||
(
x
==
0
))
?
-
1
:
(
indx
+
sizeX
-
1
);
case
6
:
return
(
(
x
==
0
))
?
-
1
:
(
indx
-
1
);
case
7
:
return
((
y
==
0
)
||
(
x
==
0
))
?
-
1
:
(
indx
-
sizeX
-
1
);
default
:
return
indx
;
}
}
/**
* Return tile segment for 50% overlap. -1 - center, 0 N, 1 - NE,... 7 - NW
* @param indx element index
* @return which of the 9 areas this element belongs
*/
int
getSegment
(
int
indx
)
{
int
s1x
=
sizeX
/
4
;
int
s3x
=
3
*
sizeX
/
4
;
int
s1y
=
sizeY
/
4
;
int
s3y
=
3
*
sizeY
/
4
;
int
x
=
indx
%
sizeX
;
int
y
=
indx
/
sizeX
;
boolean
up
=
y
<
s1y
;
boolean
down
=
y
>=
s3y
;
boolean
left
=
x
<
s1x
;
boolean
right
=
x
>=
s3x
;
if
(
up
){
if
(
left
)
return
7
;
if
(
right
)
return
1
;
return
0
;
}
if
(
down
){
if
(
left
)
return
5
;
if
(
right
)
return
3
;
return
4
;
}
if
(
left
)
return
6
;
if
(
right
)
return
2
;
return
-
1
;
}
/**
* Find if the step leaves the center half of all area
* @param indx start point
* @param dir direction
* @return direction to the new tile (assuming 50% overlap) or -1 if did not cross the border
*/
int
leaveOvderlapedCenter
(
int
indx
,
int
dir
)
{
int
segm
=
getSegment
(
indx
);
int
indx1
=
getNeibIndex
(
indx
,
dir
);
if
(
indx1
<
0
)
{
return
-
1
;
// should not happen
}
int
segm1
=
getSegment
(
indx1
);
if
(
segm1
==
segm
)
return
-
1
;
if
(
segm
==
-
1
)
return
segm1
;
int
[][]
dxy
=
{
{
0
,
0
},
{-
1
,
0
},
{-
1
,
1
},
{
0
,
1
},
{
1
,
1
},
{
1
,
0
},
{
1
,-
1
},
{
0
,-
1
},
{-
1
,-
1
}};
int
dx
=
dxy
[
segm1
+
1
][
1
]
-
dxy
[
segm
+
1
][
1
];
int
dy
=
dxy
[
segm1
+
1
][
0
]
-
dxy
[
segm
+
1
][
0
];
for
(
int
dp1
=
0
;
dp1
<=
8
;
dp1
++)
{
int
sdx
=
(
dx
>
0
)
?
1
:
(
(
dx
<
0
)
?
-
1
:
0
);
int
sdy
=
(
dy
>
0
)
?
1
:
(
(
dy
<
0
)
?
-
1
:
0
);
if
((
dxy
[
dp1
][
0
]
==
sdy
)
&&
(
dxy
[
dp1
][
1
]
==
sdx
)){
return
dp1
-
1
;
}
}
return
-
1
;
// should not happen
}
}
public
int
getNStileDir
(
public
int
getNStileDir
(
int
nsTile
,
int
nsTile
,
int
dir
)
int
dir
)
...
...
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