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
41d614cb
Commit
41d614cb
authored
Apr 15, 2017
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
handling zero eigenvalues
parent
b267218c
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
154 additions
and
61 deletions
+154
-61
EyesisCorrectionParameters.java
src/main/java/EyesisCorrectionParameters.java
+12
-2
SuperTiles.java
src/main/java/SuperTiles.java
+50
-39
TilePlanes.java
src/main/java/TilePlanes.java
+72
-12
TileProcessor.java
src/main/java/TileProcessor.java
+20
-8
No files found.
src/main/java/EyesisCorrectionParameters.java
View file @
41d614cb
...
@@ -2142,6 +2142,7 @@ public class EyesisCorrectionParameters {
...
@@ -2142,6 +2142,7 @@ public class EyesisCorrectionParameters {
public
double
grow_disp_step
=
6.0
;
// Increase disparity (from maximal tried) if nothing found in that tile // TODO: handle enclosed dips?
public
double
grow_disp_step
=
6.0
;
// Increase disparity (from maximal tried) if nothing found in that tile // TODO: handle enclosed dips?
public
double
grow_min_diff
=
0.5
;
// Grow more only if at least one channel has higher variance from others for the tile
public
double
grow_min_diff
=
0.5
;
// Grow more only if at least one channel has higher variance from others for the tile
public
boolean
plPreferDisparity
=
false
;
// Always start with disparity-most axis (false - lowest eigenvalue)
public
double
plDispNorm
=
3.0
;
// Normalize disparities to the average if above (now only for eigenvalue comparison)
public
double
plDispNorm
=
3.0
;
// Normalize disparities to the average if above (now only for eigenvalue comparison)
public
int
plMinPoints
=
5
;
// Minimal number of points for plane detection
public
int
plMinPoints
=
5
;
// Minimal number of points for plane detection
public
double
plTargetEigen
=
0.1
;
// Remove outliers until main axis eigenvalue (possibly scaled by plDispNorm) gets below
public
double
plTargetEigen
=
0.1
;
// Remove outliers until main axis eigenvalue (possibly scaled by plDispNorm) gets below
...
@@ -2150,7 +2151,8 @@ public class EyesisCorrectionParameters {
...
@@ -2150,7 +2151,8 @@ public class EyesisCorrectionParameters {
public
double
plMinStrength
=
0.1
;
// Minimal total strength of a plane
public
double
plMinStrength
=
0.1
;
// Minimal total strength of a plane
public
double
plMaxEigen
=
0.3
;
// Maximal eigenvalue of a plane
public
double
plMaxEigen
=
0.3
;
// Maximal eigenvalue of a plane
public
boolean
plDbgMerge
=
true
;
// Combine 'other' plane with current
public
boolean
plDbgMerge
=
true
;
// Combine 'other' plane with current
public
double
plWorstWorsening
=
1.0
;
// Worst case worsening after merge
public
double
plWorstWorsening
=
3.0
;
// Worst case worsening after merge
public
double
plWeakWorsening
=
1.0
;
// Relax merge requirements for weaker planes
public
boolean
plMutualOnly
=
true
;
// keep only mutual links, remove weakest if conflict
public
boolean
plMutualOnly
=
true
;
// keep only mutual links, remove weakest if conflict
public
boolean
plFillSquares
=
true
;
// Add diagonals to full squares
public
boolean
plFillSquares
=
true
;
// Add diagonals to full squares
public
boolean
plCutCorners
=
true
;
// Add ortho to 45-degree corners
public
boolean
plCutCorners
=
true
;
// Add ortho to 45-degree corners
...
@@ -2406,6 +2408,7 @@ public class EyesisCorrectionParameters {
...
@@ -2406,6 +2408,7 @@ public class EyesisCorrectionParameters {
properties
.
setProperty
(
prefix
+
"grow_disp_step"
,
this
.
grow_disp_step
+
""
);
properties
.
setProperty
(
prefix
+
"grow_disp_step"
,
this
.
grow_disp_step
+
""
);
properties
.
setProperty
(
prefix
+
"grow_min_diff"
,
this
.
grow_min_diff
+
""
);
properties
.
setProperty
(
prefix
+
"grow_min_diff"
,
this
.
grow_min_diff
+
""
);
properties
.
setProperty
(
prefix
+
"plPreferDisparity"
,
this
.
plPreferDisparity
+
""
);
properties
.
setProperty
(
prefix
+
"plDispNorm"
,
this
.
plDispNorm
+
""
);
properties
.
setProperty
(
prefix
+
"plDispNorm"
,
this
.
plDispNorm
+
""
);
properties
.
setProperty
(
prefix
+
"plMinPoints"
,
this
.
plMinPoints
+
""
);
properties
.
setProperty
(
prefix
+
"plMinPoints"
,
this
.
plMinPoints
+
""
);
properties
.
setProperty
(
prefix
+
"plTargetEigen"
,
this
.
plTargetEigen
+
""
);
properties
.
setProperty
(
prefix
+
"plTargetEigen"
,
this
.
plTargetEigen
+
""
);
...
@@ -2415,6 +2418,7 @@ public class EyesisCorrectionParameters {
...
@@ -2415,6 +2418,7 @@ public class EyesisCorrectionParameters {
properties
.
setProperty
(
prefix
+
"plMaxEigen"
,
this
.
plMaxEigen
+
""
);
properties
.
setProperty
(
prefix
+
"plMaxEigen"
,
this
.
plMaxEigen
+
""
);
properties
.
setProperty
(
prefix
+
"plDbgMerge"
,
this
.
plDbgMerge
+
""
);
properties
.
setProperty
(
prefix
+
"plDbgMerge"
,
this
.
plDbgMerge
+
""
);
properties
.
setProperty
(
prefix
+
"plWorstWorsening"
,
this
.
plWorstWorsening
+
""
);
properties
.
setProperty
(
prefix
+
"plWorstWorsening"
,
this
.
plWorstWorsening
+
""
);
properties
.
setProperty
(
prefix
+
"plWeakWorsening"
,
this
.
plWeakWorsening
+
""
);
properties
.
setProperty
(
prefix
+
"plMutualOnly"
,
this
.
plMutualOnly
+
""
);
properties
.
setProperty
(
prefix
+
"plMutualOnly"
,
this
.
plMutualOnly
+
""
);
properties
.
setProperty
(
prefix
+
"plFillSquares"
,
this
.
plFillSquares
+
""
);
properties
.
setProperty
(
prefix
+
"plFillSquares"
,
this
.
plFillSquares
+
""
);
...
@@ -2657,6 +2661,7 @@ public class EyesisCorrectionParameters {
...
@@ -2657,6 +2661,7 @@ public class EyesisCorrectionParameters {
if
(
properties
.
getProperty
(
prefix
+
"grow_disp_step"
)!=
null
)
this
.
grow_disp_step
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"grow_disp_step"
));
if
(
properties
.
getProperty
(
prefix
+
"grow_disp_step"
)!=
null
)
this
.
grow_disp_step
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"grow_disp_step"
));
if
(
properties
.
getProperty
(
prefix
+
"grow_min_diff"
)!=
null
)
this
.
grow_min_diff
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"grow_min_diff"
));
if
(
properties
.
getProperty
(
prefix
+
"grow_min_diff"
)!=
null
)
this
.
grow_min_diff
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"grow_min_diff"
));
if
(
properties
.
getProperty
(
prefix
+
"plPreferDisparity"
)!=
null
)
this
.
plPreferDisparity
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"plPreferDisparity"
));
if
(
properties
.
getProperty
(
prefix
+
"plDispNorm"
)!=
null
)
this
.
plDispNorm
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"plDispNorm"
));
if
(
properties
.
getProperty
(
prefix
+
"plDispNorm"
)!=
null
)
this
.
plDispNorm
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"plDispNorm"
));
if
(
properties
.
getProperty
(
prefix
+
"plMinPoints"
)!=
null
)
this
.
plMinPoints
=
Integer
.
parseInt
(
properties
.
getProperty
(
prefix
+
"plMinPoints"
));
if
(
properties
.
getProperty
(
prefix
+
"plMinPoints"
)!=
null
)
this
.
plMinPoints
=
Integer
.
parseInt
(
properties
.
getProperty
(
prefix
+
"plMinPoints"
));
if
(
properties
.
getProperty
(
prefix
+
"plTargetEigen"
)!=
null
)
this
.
plTargetEigen
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"plTargetEigen"
));
if
(
properties
.
getProperty
(
prefix
+
"plTargetEigen"
)!=
null
)
this
.
plTargetEigen
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"plTargetEigen"
));
...
@@ -2666,6 +2671,7 @@ public class EyesisCorrectionParameters {
...
@@ -2666,6 +2671,7 @@ public class EyesisCorrectionParameters {
if
(
properties
.
getProperty
(
prefix
+
"plMaxEigen"
)!=
null
)
this
.
plMaxEigen
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"plMaxEigen"
));
if
(
properties
.
getProperty
(
prefix
+
"plMaxEigen"
)!=
null
)
this
.
plMaxEigen
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"plMaxEigen"
));
if
(
properties
.
getProperty
(
prefix
+
"plDbgMerge"
)!=
null
)
this
.
plDbgMerge
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"plDbgMerge"
));
if
(
properties
.
getProperty
(
prefix
+
"plDbgMerge"
)!=
null
)
this
.
plDbgMerge
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"plDbgMerge"
));
if
(
properties
.
getProperty
(
prefix
+
"plWorstWorsening"
)!=
null
)
this
.
plWorstWorsening
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"plWorstWorsening"
));
if
(
properties
.
getProperty
(
prefix
+
"plWorstWorsening"
)!=
null
)
this
.
plWorstWorsening
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"plWorstWorsening"
));
if
(
properties
.
getProperty
(
prefix
+
"plWeakWorsening"
)!=
null
)
this
.
plWeakWorsening
=
Double
.
parseDouble
(
properties
.
getProperty
(
prefix
+
"plWeakWorsening"
));
if
(
properties
.
getProperty
(
prefix
+
"plMutualOnly"
)!=
null
)
this
.
plMutualOnly
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"plMutualOnly"
));
if
(
properties
.
getProperty
(
prefix
+
"plMutualOnly"
)!=
null
)
this
.
plMutualOnly
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"plMutualOnly"
));
if
(
properties
.
getProperty
(
prefix
+
"plFillSquares"
)!=
null
)
this
.
plFillSquares
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"plFillSquares"
));
if
(
properties
.
getProperty
(
prefix
+
"plFillSquares"
)!=
null
)
this
.
plFillSquares
=
Boolean
.
parseBoolean
(
properties
.
getProperty
(
prefix
+
"plFillSquares"
));
...
@@ -2930,6 +2936,7 @@ public class EyesisCorrectionParameters {
...
@@ -2930,6 +2936,7 @@ public class EyesisCorrectionParameters {
gd
.
addNumericField
(
"Increase disparity (from maximal tried) if nothing found in that tile"
,
this
.
grow_disp_step
,
6
);
gd
.
addNumericField
(
"Increase disparity (from maximal tried) if nothing found in that tile"
,
this
.
grow_disp_step
,
6
);
gd
.
addNumericField
(
"Grow more only if at least one channel has higher variance from others for the tile"
,
this
.
grow_min_diff
,
6
);
gd
.
addNumericField
(
"Grow more only if at least one channel has higher variance from others for the tile"
,
this
.
grow_min_diff
,
6
);
gd
.
addMessage
(
"--- Planes detection ---"
);
gd
.
addMessage
(
"--- Planes detection ---"
);
gd
.
addCheckbox
(
"Always start with disparity-most axis (false - lowest eigenvalue)"
,
this
.
plPreferDisparity
);
gd
.
addNumericField
(
"Normalize disparities to the average if above"
,
this
.
plDispNorm
,
6
);
gd
.
addNumericField
(
"Normalize disparities to the average if above"
,
this
.
plDispNorm
,
6
);
gd
.
addNumericField
(
"Minimal number of points for plane detection"
,
this
.
plMinPoints
,
0
);
gd
.
addNumericField
(
"Minimal number of points for plane detection"
,
this
.
plMinPoints
,
0
);
gd
.
addNumericField
(
"Remove outliers until main axis eigenvalue (possibly scaled by plDispNorm) gets below"
,
this
.
plTargetEigen
,
6
);
gd
.
addNumericField
(
"Remove outliers until main axis eigenvalue (possibly scaled by plDispNorm) gets below"
,
this
.
plTargetEigen
,
6
);
...
@@ -2937,8 +2944,9 @@ public class EyesisCorrectionParameters {
...
@@ -2937,8 +2944,9 @@ public class EyesisCorrectionParameters {
gd
.
addNumericField
(
"Maximal number of outliers to remove"
,
this
.
plMaxOutliers
,
0
);
gd
.
addNumericField
(
"Maximal number of outliers to remove"
,
this
.
plMaxOutliers
,
0
);
gd
.
addNumericField
(
"Minimal total strength of a plane"
,
this
.
plMinStrength
,
6
);
gd
.
addNumericField
(
"Minimal total strength of a plane"
,
this
.
plMinStrength
,
6
);
gd
.
addNumericField
(
"Maximal eigenvalue of a plane"
,
this
.
plMaxEigen
,
6
);
gd
.
addNumericField
(
"Maximal eigenvalue of a plane"
,
this
.
plMaxEigen
,
6
);
gd
.
addCheckbox
(
"Combine 'other' plane with the current
"
,
this
.
plDbgMerge
);
gd
.
addCheckbox
(
"Combine 'other' plane with the current
(unused)"
,
this
.
plDbgMerge
);
gd
.
addNumericField
(
"Worst case worsening after merge"
,
this
.
plWorstWorsening
,
6
);
gd
.
addNumericField
(
"Worst case worsening after merge"
,
this
.
plWorstWorsening
,
6
);
gd
.
addNumericField
(
"Relax merge requirements for weaker planes"
,
this
.
plWeakWorsening
,
6
);
gd
.
addCheckbox
(
"Keep only mutual links, remove weakest if conflict"
,
this
.
plMutualOnly
);
gd
.
addCheckbox
(
"Keep only mutual links, remove weakest if conflict"
,
this
.
plMutualOnly
);
gd
.
addCheckbox
(
"Add diagonals to full squares"
,
this
.
plFillSquares
);
gd
.
addCheckbox
(
"Add diagonals to full squares"
,
this
.
plFillSquares
);
...
@@ -3191,6 +3199,7 @@ public class EyesisCorrectionParameters {
...
@@ -3191,6 +3199,7 @@ public class EyesisCorrectionParameters {
this
.
grow_disp_step
=
gd
.
getNextNumber
();
this
.
grow_disp_step
=
gd
.
getNextNumber
();
this
.
grow_min_diff
=
gd
.
getNextNumber
();
this
.
grow_min_diff
=
gd
.
getNextNumber
();
this
.
plPreferDisparity
=
gd
.
getNextBoolean
();
this
.
plDispNorm
=
gd
.
getNextNumber
();
this
.
plDispNorm
=
gd
.
getNextNumber
();
this
.
plMinPoints
=
(
int
)
gd
.
getNextNumber
();
this
.
plMinPoints
=
(
int
)
gd
.
getNextNumber
();
this
.
plTargetEigen
=
gd
.
getNextNumber
();
this
.
plTargetEigen
=
gd
.
getNextNumber
();
...
@@ -3200,6 +3209,7 @@ public class EyesisCorrectionParameters {
...
@@ -3200,6 +3209,7 @@ public class EyesisCorrectionParameters {
this
.
plMaxEigen
=
gd
.
getNextNumber
();
this
.
plMaxEigen
=
gd
.
getNextNumber
();
this
.
plDbgMerge
=
gd
.
getNextBoolean
();
this
.
plDbgMerge
=
gd
.
getNextBoolean
();
this
.
plWorstWorsening
=
gd
.
getNextNumber
();
this
.
plWorstWorsening
=
gd
.
getNextNumber
();
this
.
plWeakWorsening
=
gd
.
getNextNumber
();
this
.
plMutualOnly
=
gd
.
getNextBoolean
();
this
.
plMutualOnly
=
gd
.
getNextBoolean
();
this
.
plFillSquares
=
gd
.
getNextBoolean
();
this
.
plFillSquares
=
gd
.
getNextBoolean
();
...
...
src/main/java/SuperTiles.java
View file @
41d614cb
...
@@ -1168,7 +1168,6 @@ public class SuperTiles{
...
@@ -1168,7 +1168,6 @@ public class SuperTiles{
public
void
processPlanes2
(
public
void
processPlanes2
(
final
boolean
[]
selected
,
// or null
final
boolean
[]
selected
,
// or null
final
double
min_disp
,
final
double
min_disp
,
final
boolean
invert_disp
,
// use 1/disparity
final
boolean
invert_disp
,
// use 1/disparity
...
@@ -1177,8 +1176,9 @@ public class SuperTiles{
...
@@ -1177,8 +1176,9 @@ public class SuperTiles{
final
double
plTargetEigen
,
// = 0.1; // Remove outliers until main axis eigenvalue (possibly scaled by plDispNorm) gets below
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
double
plFractOutliers
,
// = 0.3; // Maximal fraction of outliers to remove
final
int
plMaxOutliers
,
// = 20; // Maximal number of outliers to remove
final
int
plMaxOutliers
,
// = 20; // Maximal number of outliers to remove
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
,
final
int
debugLevel
,
final
int
debugLevel
,
final
int
dbg_X
,
final
int
dbg_X
,
final
int
dbg_Y
)
final
int
dbg_Y
)
...
@@ -1262,27 +1262,19 @@ public class SuperTiles{
...
@@ -1262,27 +1262,19 @@ public class SuperTiles{
}
}
}
}
planes
[
nsTile
]
=
null
;
planes
[
nsTile
]
=
null
;
if
(
sw
>
0
){
if
(
sw
>
0
){
// there are some non-zero tiles, process them (all points, not clustered by disparity value)
ArrayList
<
TilePlanes
.
PlaneData
>
st_planes
=
new
ArrayList
<
TilePlanes
.
PlaneData
>();
ArrayList
<
TilePlanes
.
PlaneData
>
st_planes
=
new
ArrayList
<
TilePlanes
.
PlaneData
>();
// int dl = ((nsTile >= debug_stile-1) && (nsTile <= debug_stile+1) ) ? 1 : 0;
// int dl = ((stileY == 17) && (stileX > 4)) ? 1 : 0;
// int dl = (stileY >= 0) ? 1 : 0;
int
dl1
=
(
nsTile
==
debug_stile
)
?
3
:
0
;
int
dl1
=
(
nsTile
==
debug_stile
)
?
3
:
0
;
// int dl = (nsTile == debug_stile) ? 3 : 0;
// int dl = ((stileY >= 15) && (stileY <= 18) && (stileX >= 5) && (stileX <= 31)) ? 1 : 0;
// int dl = ((stileY == 16) && (stileX == 27) ) ? 3 : 0;
int
dl
=
(
nsTile
==
debug_stile
)
?
3
:
0
;
int
dl
=
(
nsTile
==
debug_stile
)
?
3
:
0
;
// int debugLevel1 = ((sTileXY[0] == 27) && (sTileXY[1] == 16))? 1: 0; // check why v[0][0] <0
boolean
[]
sel_all
=
stSel
.
clone
();
boolean
[]
sel_all
=
stSel
.
clone
();
TilePlanes
.
PlaneData
pd
=
tpl
.
getPlane
(
TilePlanes
.
PlaneData
pd
=
tpl
.
getPlane
(
sTiles
,
sTiles
,
stDisparity
,
stDisparity
,
stStrength
,
stStrength
,
sel_all
,
sel_all
,
plPreferDisparity
,
0
);
// debugLevel);
0
);
// debugLevel);
if
(
pd
!=
null
)
{
if
(
pd
!=
null
)
{
// not too few points, probably
//correct_distortions
//correct_distortions
double
swc_common
=
pd
.
getWeight
();
double
swc_common
=
pd
.
getWeight
();
if
(
dl
>
0
)
{
if
(
dl
>
0
)
{
...
@@ -1301,19 +1293,11 @@ public class SuperTiles{
...
@@ -1301,19 +1293,11 @@ public class SuperTiles{
// now try to remove outliers
// now try to remove outliers
int
max_outliers
=
(
int
)
Math
.
round
(
pd
.
getNumPoints
()
*
plFractOutliers
);
int
max_outliers
=
(
int
)
Math
.
round
(
pd
.
getNumPoints
()
*
plFractOutliers
);
if
(
max_outliers
>
plMaxOutliers
)
max_outliers
=
plMaxOutliers
;
if
(
max_outliers
>
plMaxOutliers
)
max_outliers
=
plMaxOutliers
;
/*
double targetV = plTargetEigen;
double z0 = pd.getZxy()[0];
if ((plTargetEigen > 0.0) && (z0 > plDispNorm)) {
double dd = (plDispNorm + z0)/ plDispNorm; // > 1
targetV *= dd * dd; // > original
}
*/
double
targetV
=
corrMaxEigen
(
double
targetV
=
corrMaxEigen
(
plTargetEigen
,
plTargetEigen
,
plDispNorm
,
plDispNorm
,
pd
);
pd
);
if
(
pd
.
getValue
s
()[
0
]
>
targetV
)
{
if
(
pd
.
getValue
()
>
targetV
)
{
pd
=
tpl
.
removePlaneOutliers
(
pd
=
tpl
.
removePlaneOutliers
(
pd
,
pd
,
sTiles
,
sTiles
,
...
@@ -1323,7 +1307,9 @@ public class SuperTiles{
...
@@ -1323,7 +1307,9 @@ public class SuperTiles{
targetV
,
// double targetEigen, // target eigenvalue for primary axis (is disparity-dependent, so is non-constant)
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)
max_outliers
,
// int maxRemoved, // maximal number of tiles to remove (not a constant)
plMinPoints
,
// int minLeft, // minimal number of tiles to keep
plMinPoints
,
// int minLeft, // minimal number of tiles to keep
plPreferDisparity
,
dl1
);
// 0); // debugLevel);
dl1
);
// 0); // debugLevel);
if
(
pd
==
null
)
continue
;
if
(
dl
>
0
)
{
if
(
dl
>
0
)
{
if
(
swc_common
>
0.3
)
{
// 1.0) {
if
(
swc_common
>
0.3
)
{
// 1.0) {
System
.
out
.
println
(
"Removed outliers["
+
nsTile
+
"]"
+
System
.
out
.
println
(
"Removed outliers["
+
nsTile
+
"]"
+
...
@@ -1350,9 +1336,9 @@ public class SuperTiles{
...
@@ -1350,9 +1336,9 @@ public class SuperTiles{
norm_xyz
[
0
]+
", "
+
norm_xyz
[
1
]+
", "
+
norm_xyz
[
2
]+
"}"
);
norm_xyz
[
0
]+
", "
+
norm_xyz
[
1
]+
", "
+
norm_xyz
[
2
]+
"}"
);
}
}
st_planes
.
add
(
pd
);
st_planes
.
add
(
pd
);
// adding [0] - all supertile tiles, not clustered by disparity value
// now try for each of the disparity-separated clusters
// now try for each of the disparity-separated clusters
(only for multi-peak histograms)
double
[][]
mm
=
maxMinMax
[
nsTile
];
double
[][]
mm
=
maxMinMax
[
nsTile
];
...
@@ -1392,6 +1378,7 @@ public class SuperTiles{
...
@@ -1392,6 +1378,7 @@ public class SuperTiles{
stDisparity
,
stDisparity
,
stStrength
,
stStrength
,
stSels
[
m
],
stSels
[
m
],
plPreferDisparity
,
0
);
// debugLevel);
0
);
// debugLevel);
if
(
pd
!=
null
)
{
if
(
pd
!=
null
)
{
if
(
dl
>
0
)
{
if
(
dl
>
0
)
{
...
@@ -1426,7 +1413,11 @@ public class SuperTiles{
...
@@ -1426,7 +1413,11 @@ public class SuperTiles{
targetV
,
// double targetEigen, // target eigenvalue for primary axis (is disparity-dependent, so is non-constant)
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)
max_outliers
,
// int maxRemoved, // maximal number of tiles to remove (not a constant)
plMinPoints
,
// int minLeft, // minimal number of tiles to keep
plMinPoints
,
// int minLeft, // minimal number of tiles to keep
plPreferDisparity
,
dl1
);
// 0); // debugLevel);
dl1
);
// 0); // debugLevel);
if
(
pd
==
null
)
{
continue
;
}
if
(
dl
>
0
)
{
if
(
dl
>
0
)
{
if
(
swc_common
>
1.0
)
{
if
(
swc_common
>
1.0
)
{
System
.
out
.
println
(
"Removed outliers["
+
nsTile
+
"]["
+
m
+
"]"
+
System
.
out
.
println
(
"Removed outliers["
+
nsTile
+
"]["
+
m
+
"]"
+
...
@@ -1485,6 +1476,7 @@ public class SuperTiles{
...
@@ -1485,6 +1476,7 @@ public class SuperTiles{
TilePlanes
.
PlaneData
[][]
getNeibPlanes
(
TilePlanes
.
PlaneData
[][]
getNeibPlanes
(
final
int
dir
,
// 0: get from up (N), 1:from NE, ... 7 - from NW
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
boolean
dbgMerge
,
// Combine 'other' plane with current
final
int
dbg_X
,
final
int
dbg_X
,
final
int
dbg_Y
final
int
dbg_Y
...
@@ -1548,12 +1540,14 @@ public class SuperTiles{
...
@@ -1548,12 +1540,14 @@ public class SuperTiles{
planes
[
nsTile0
][
indx
],
// PlaneData otherPd,
planes
[
nsTile0
][
indx
],
// PlaneData otherPd,
1.0
,
// double scale_other,
1.0
,
// double scale_other,
true
,
// boolean ignore_weights,
true
,
// boolean ignore_weights,
preferDisparity
,
(
nsTile0
==
debug_stile
)?
1
:
0
);
// int debugLevel)
(
nsTile0
==
debug_stile
)?
1
:
0
);
// int debugLevel)
System
.
out
.
println
(
"other with other, same weight:"
);
System
.
out
.
println
(
"other with other, same weight:"
);
TilePlanes
.
PlaneData
other_other_pd
=
other_pd
.
mergePlaneToThis
(
TilePlanes
.
PlaneData
other_other_pd
=
other_pd
.
mergePlaneToThis
(
other_pd
,
// PlaneData otherPd,
other_pd
,
// PlaneData otherPd,
1.0
,
// double scale_other,
1.0
,
// double scale_other,
true
,
// boolean ignore_weights,
true
,
// boolean ignore_weights,
preferDisparity
,
(
nsTile0
==
debug_stile
)?
1
:
0
);
// int debugLevel)
(
nsTile0
==
debug_stile
)?
1
:
0
);
// int debugLevel)
System
.
out
.
println
(
"other with this, same weight:"
);
System
.
out
.
println
(
"other with this, same weight:"
);
}
}
...
@@ -1561,6 +1555,7 @@ public class SuperTiles{
...
@@ -1561,6 +1555,7 @@ public class SuperTiles{
other_pd
,
// PlaneData otherPd,
other_pd
,
// PlaneData otherPd,
1.0
,
// double scale_other,
1.0
,
// double scale_other,
true
,
// boolean ignore_weights,
true
,
// boolean ignore_weights,
preferDisparity
,
(
nsTile0
==
debug_stile
)?
1
:
0
);
// int debugLevel)
(
nsTile0
==
debug_stile
)?
1
:
0
);
// int debugLevel)
if
(!(
merged_pd
.
getValue
()
>
best_value
))
{
// Double.isNaN(best_value) will work too
if
(!(
merged_pd
.
getValue
()
>
best_value
))
{
// Double.isNaN(best_value) will work too
best_value
=
merged_pd
.
getValue
();
best_value
=
merged_pd
.
getValue
();
...
@@ -1576,6 +1571,7 @@ public class SuperTiles{
...
@@ -1576,6 +1571,7 @@ public class SuperTiles{
other_pd
,
// PlaneData otherPd,
other_pd
,
// PlaneData otherPd,
1.0
,
// double scale_other,
1.0
,
// double scale_other,
false
,
// boolean ignore_weights,
false
,
// boolean ignore_weights,
preferDisparity
,
(
nsTile0
==
debug_stile
)?
1
:
0
);
// int debugLevel)
(
nsTile0
==
debug_stile
)?
1
:
0
);
// int debugLevel)
neib_planes
[
nsTile0
][
np
]
=
merged_pd
;
neib_planes
[
nsTile0
][
np
]
=
merged_pd
;
}
else
{
}
else
{
...
@@ -1618,6 +1614,7 @@ public class SuperTiles{
...
@@ -1618,6 +1614,7 @@ public class SuperTiles{
}
}
public
void
matchPlanes
(
public
void
matchPlanes
(
final
boolean
preferDisparity
,
// Always start with disparity-most axis (false - lowest eigenvalue)
final
int
dbg_X
,
final
int
dbg_X
,
final
int
dbg_Y
)
final
int
dbg_Y
)
{
{
...
@@ -1636,6 +1633,7 @@ public class SuperTiles{
...
@@ -1636,6 +1633,7 @@ public class SuperTiles{
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
);
// Select best symmetrical match, consider only N, NE, E, SE - later opposite ones will be copied
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
threads
[
ithread
]
=
new
Thread
()
{
public
void
run
()
{
public
void
run
()
{
...
@@ -1673,6 +1671,7 @@ public class SuperTiles{
...
@@ -1673,6 +1671,7 @@ public class SuperTiles{
other_plane
,
// PlaneData otherPd,
other_plane
,
// PlaneData otherPd,
1.0
,
// double scale_other,
1.0
,
// double scale_other,
false
,
// boolean ignore_weights,
false
,
// boolean ignore_weights,
preferDisparity
,
dl
);
// int debugLevel)
dl
);
// int debugLevel)
if
(
merged_pd
!=
null
)
{
// now always, but may add later
if
(
merged_pd
!=
null
)
{
// now always, but may add later
this_plane
.
setNeibMatch
(
dir
,
np
,
merged_pd
.
getValue
());
// smallest eigenValue
this_plane
.
setNeibMatch
(
dir
,
np
,
merged_pd
.
getValue
());
// smallest eigenValue
...
@@ -1706,28 +1705,18 @@ public class SuperTiles{
...
@@ -1706,28 +1705,18 @@ public class SuperTiles{
if
(
planes
[
nsTile0
]
!=
null
)
{
if
(
planes
[
nsTile0
]
!=
null
)
{
for
(
int
np0
=
0
;
np0
<
planes
[
nsTile0
].
length
;
np0
++){
// nu
for
(
int
np0
=
0
;
np0
<
planes
[
nsTile0
].
length
;
np0
++){
// nu
TilePlanes
.
PlaneData
this_plane
=
planes
[
nsTile0
][
np0
];
TilePlanes
.
PlaneData
this_plane
=
planes
[
nsTile0
][
np0
];
// this_plane.initMergedValue();
for
(
int
dir
=
4
;
dir
<
8
;
dir
++){
// other half - copy from opposite
for
(
int
dir
=
4
;
dir
<
8
;
dir
++){
// other half - copy from opposite
int
stx
=
stx0
+
dirsYX
[
dir
][
1
];
int
stx
=
stx0
+
dirsYX
[
dir
][
1
];
int
sty
=
sty0
+
dirsYX
[
dir
][
0
];
int
sty
=
sty0
+
dirsYX
[
dir
][
0
];
// if ((stx < stilesX) && (sty < stilesY) && (sty > 0)) {
if
((
sty
<
stilesY
)
&&
(
sty
>
0
)
&&
(
stx
>
0
))
{
if
((
sty
<
stilesY
)
&&
(
sty
>
0
)
&&
(
stx
>
0
))
{
int
nsTile
=
sty
*
stilesX
+
stx
;
// from where to get
int
nsTile
=
sty
*
stilesX
+
stx
;
// from where to get
TilePlanes
.
PlaneData
[]
other_planes
=
planes
[
nsTile
];
TilePlanes
.
PlaneData
[]
other_planes
=
planes
[
nsTile
];
if
(
other_planes
!=
null
)
{
if
(
other_planes
!=
null
)
{
this_plane
.
initMergedValue
(
dir
,
other_planes
.
length
);
// filled with NaN
this_plane
.
initMergedValue
(
dir
,
other_planes
.
length
);
// filled with NaN
for
(
int
np
=
0
;
np
<
other_planes
.
length
;
np
++){
for
(
int
np
=
0
;
np
<
other_planes
.
length
;
np
++){
/*
if ((other_planes[np] != null) && (other_planes[np].getMergedValue(dir-4) != null)) {
double [] dbg_nm = other_planes[np].getMergedValue(dir-4);
this_plane.setNeibMatch(dir,np, other_planes[np].getMergedValue(dir-4, np0)); //
}
*/
if
(
other_planes
[
np
]
!=
null
)
{
// && (other_planes[np].getMergedValue(dir-4) != null)) {
if
(
other_planes
[
np
]
!=
null
)
{
// && (other_planes[np].getMergedValue(dir-4) != null)) {
double
[]
nm
=
other_planes
[
np
].
getMergedValue
(
dir
-
4
);
double
[]
nm
=
other_planes
[
np
].
getMergedValue
(
dir
-
4
);
if
(
nm
!=
null
)
{
if
(
nm
!=
null
)
{
// this_plane.setNeibMatch(dir,np, other_planes[np].getMergedValue(dir-4, np0)); //
this_plane
.
setNeibMatch
(
dir
,
np
,
nm
[
np0
]);
//
this_plane
.
setNeibMatch
(
dir
,
np
,
nm
[
np0
]);
//
}
}
}
}
...
@@ -1859,7 +1848,7 @@ public class SuperTiles{
...
@@ -1859,7 +1848,7 @@ public class SuperTiles{
ImageDtt
.
startAndJoin
(
threads
);
ImageDtt
.
startAndJoin
(
threads
);
}
}
}
}
public
void
fillSquares
()
public
int
fillSquares
()
{
{
final
int
tilesX
=
tileProcessor
.
getTilesX
();
final
int
tilesX
=
tileProcessor
.
getTilesX
();
final
int
tilesY
=
tileProcessor
.
getTilesY
();
final
int
tilesY
=
tileProcessor
.
getTilesY
();
...
@@ -1868,6 +1857,7 @@ public class SuperTiles{
...
@@ -1868,6 +1857,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
;
int
num_added
=
0
;
for
(
int
stY
=
0
;
stY
<
(
stilesY
-
1
);
stY
++
)
{
for
(
int
stY
=
0
;
stY
<
(
stilesY
-
1
);
stY
++
)
{
for
(
int
stX
=
0
;
stX
<
(
stilesX
-
1
);
stX
++
)
{
for
(
int
stX
=
0
;
stX
<
(
stilesX
-
1
);
stX
++
)
{
int
nsTile
=
stY
*
stilesX
+
stX
;
int
nsTile
=
stY
*
stilesX
+
stX
;
...
@@ -1891,18 +1881,21 @@ public class SuperTiles{
...
@@ -1891,18 +1881,21 @@ public class SuperTiles{
if
(
neibs0
[
3
]
<
0
)
{
if
(
neibs0
[
3
]
<
0
)
{
neibs0
[
3
]
=
neibs1
[
4
];
neibs0
[
3
]
=
neibs1
[
4
];
neibs3
[
7
]
=
np
;
neibs3
[
7
]
=
np
;
num_added
++;
}
}
if
(
neibs1
[
5
]
<
0
){
if
(
neibs1
[
5
]
<
0
){
neibs1
[
5
]
=
neibs0
[
4
];
neibs1
[
5
]
=
neibs0
[
4
];
neibs2
[
1
]
=
neibs0
[
2
];
neibs2
[
1
]
=
neibs0
[
2
];
num_added
++;
}
}
}
}
}
}
}
}
}
}
return
num_added
;
}
}
public
void
cutCorners
()
public
int
cutCorners
()
{
{
final
int
tilesX
=
tileProcessor
.
getTilesX
();
final
int
tilesX
=
tileProcessor
.
getTilesX
();
final
int
tilesY
=
tileProcessor
.
getTilesY
();
final
int
tilesY
=
tileProcessor
.
getTilesY
();
...
@@ -1910,7 +1903,8 @@ public class SuperTiles{
...
@@ -1910,7 +1903,8 @@ 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
int
nStiles
=
stilesX
*
stilesY
;
// final int nStiles = stilesX * stilesY;
int
num_added
=
0
;
for
(
int
stY
=
0
;
stY
<
(
stilesY
-
1
);
stY
++
)
{
for
(
int
stY
=
0
;
stY
<
(
stilesY
-
1
);
stY
++
)
{
for
(
int
stX
=
0
;
stX
<
(
stilesX
-
1
);
stX
++
)
{
for
(
int
stX
=
0
;
stX
<
(
stilesX
-
1
);
stX
++
)
{
int
nsTile
=
stY
*
stilesX
+
stX
;
int
nsTile
=
stY
*
stilesX
+
stX
;
...
@@ -1931,6 +1925,7 @@ public class SuperTiles{
...
@@ -1931,6 +1925,7 @@ public class SuperTiles{
neibs0
[
4
]
=
neibs1
[
5
];
neibs0
[
4
]
=
neibs1
[
5
];
int
[]
neibs2
=
planes4
[
2
][
neibs1
[
5
]].
getNeibBest
();
int
[]
neibs2
=
planes4
[
2
][
neibs1
[
5
]].
getNeibBest
();
neibs2
[
0
]
=
np
;
//?
neibs2
[
0
]
=
np
;
//?
num_added
++;
}
}
}
}
}
}
...
@@ -1942,6 +1937,7 @@ public class SuperTiles{
...
@@ -1942,6 +1937,7 @@ public class SuperTiles{
neibs0
[
2
]
=
neibs2
[
1
];
neibs0
[
2
]
=
neibs2
[
1
];
int
[]
neibs1
=
planes4
[
1
][
neibs2
[
1
]].
getNeibBest
();
int
[]
neibs1
=
planes4
[
1
][
neibs2
[
1
]].
getNeibBest
();
neibs1
[
6
]
=
np
;
neibs1
[
6
]
=
np
;
num_added
++;
}
}
}
}
}
}
...
@@ -1951,6 +1947,7 @@ public class SuperTiles{
...
@@ -1951,6 +1947,7 @@ public class SuperTiles{
if
(
neibs1
[
4
]
<
0
)
{
if
(
neibs1
[
4
]
<
0
)
{
neibs1
[
4
]
=
neibs0
[
3
];
neibs1
[
4
]
=
neibs0
[
3
];
neibs3
[
0
]
=
neibs0
[
2
];
//?
neibs3
[
0
]
=
neibs0
[
2
];
//?
num_added
++;
}
}
}
}
if
((
neibs0
[
3
]
>=
0
)
&&
(
neibs0
[
4
]
>=
0
)){
if
((
neibs0
[
3
]
>=
0
)
&&
(
neibs0
[
4
]
>=
0
)){
...
@@ -1959,6 +1956,7 @@ public class SuperTiles{
...
@@ -1959,6 +1956,7 @@ public class SuperTiles{
if
(
neibs2
[
2
]
<
0
)
{
if
(
neibs2
[
2
]
<
0
)
{
neibs2
[
2
]
=
neibs0
[
3
];
neibs2
[
2
]
=
neibs0
[
3
];
neibs3
[
6
]
=
neibs0
[
4
];
neibs3
[
6
]
=
neibs0
[
4
];
num_added
++;
}
}
}
}
}
}
...
@@ -1975,6 +1973,7 @@ public class SuperTiles{
...
@@ -1975,6 +1973,7 @@ public class SuperTiles{
if
(
neibs0
[
2
]
<
0
)
{
if
(
neibs0
[
2
]
<
0
)
{
neibs0
[
2
]
=
neibs3
[
0
];
neibs0
[
2
]
=
neibs3
[
0
];
neibs1
[
6
]
=
neibs3
[
7
];
neibs1
[
6
]
=
neibs3
[
7
];
num_added
++;
}
}
}
}
...
@@ -1985,6 +1984,7 @@ public class SuperTiles{
...
@@ -1985,6 +1984,7 @@ public class SuperTiles{
if
(
neibs0
[
4
]
<
0
)
{
if
(
neibs0
[
4
]
<
0
)
{
neibs0
[
4
]
=
neibs3
[
6
];
neibs0
[
4
]
=
neibs3
[
6
];
neibs2
[
0
]
=
neibs3
[
7
];
//?
neibs2
[
0
]
=
neibs3
[
7
];
//?
num_added
++;
}
}
}
}
...
@@ -1996,6 +1996,7 @@ public class SuperTiles{
...
@@ -1996,6 +1996,7 @@ public class SuperTiles{
int
[]
neibs2
=
planes4
[
2
][
neibs0
[
4
]].
getNeibBest
();
int
[]
neibs2
=
planes4
[
2
][
neibs0
[
4
]].
getNeibBest
();
neibs3
[
6
]
=
neibs0
[
4
];
neibs3
[
6
]
=
neibs0
[
4
];
neibs2
[
2
]
=
np
;
//?
neibs2
[
2
]
=
np
;
//?
num_added
++;
}
}
}
}
...
@@ -2006,6 +2007,7 @@ public class SuperTiles{
...
@@ -2006,6 +2007,7 @@ public class SuperTiles{
int
[]
neibs1
=
planes4
[
1
][
neibs2
[
1
]].
getNeibBest
();
int
[]
neibs1
=
planes4
[
1
][
neibs2
[
1
]].
getNeibBest
();
neibs3
[
0
]
=
neibs2
[
1
];
//?
neibs3
[
0
]
=
neibs2
[
1
];
//?
neibs1
[
4
]
=
np
;
neibs1
[
4
]
=
np
;
num_added
++;
}
}
}
}
}
}
...
@@ -2013,6 +2015,8 @@ public class SuperTiles{
...
@@ -2013,6 +2015,8 @@ public class SuperTiles{
}
}
}
}
}
}
return
num_added
;
}
}
/**
/**
...
@@ -2027,6 +2031,7 @@ public class SuperTiles{
...
@@ -2027,6 +2031,7 @@ public class SuperTiles{
*/
*/
public
void
selectNeighborPlanesMutual
(
public
void
selectNeighborPlanesMutual
(
final
double
rquality
,
final
double
rquality
,
final
double
weakWorsening
,
final
double
dispNorm
,
final
double
dispNorm
,
final
double
maxEigen
,
// maximal eigenvalue of planes to consider
final
double
maxEigen
,
// maximal eigenvalue of planes to consider
final
double
minWeight
,
// minimal pain weight to consider
final
double
minWeight
,
// minimal pain weight to consider
...
@@ -2130,8 +2135,9 @@ public class SuperTiles{
...
@@ -2130,8 +2135,9 @@ public class SuperTiles{
merge_ev
[
np
],
// double L,
merge_ev
[
np
],
// double L,
w1
,
// double w1,
w1
,
// double w1,
w2
);
// double w2)
w2
);
// double w2)
// if (this_rq <= rquality) { // compare with the threshold before applying strengths
double
this_rq_norm
=
this_rq
;
if
((
w1
+
w2
)
*
this_rq
<=
rquality
)
{
// forgive more for weak planes
if
((
w1
+
w2
)
<
weakWorsening
)
this_rq_norm
*=
(
w1
+
w2
)
/
weakWorsening
;
// forgive more for weak planes
if
(
this_rq_norm
<=
rquality
)
{
this_rq
/=
(
w1
+
w2
);
// for comparision reduce this value for stronger planes
this_rq
/=
(
w1
+
w2
);
// for comparision reduce this value for stronger planes
if
(
Double
.
isNaN
(
best_rqual
)
||
(
this_rq
<
best_rqual
)){
// OK if Double.isNaN(this_rq[np])
if
(
Double
.
isNaN
(
best_rqual
)
||
(
this_rq
<
best_rqual
)){
// OK if Double.isNaN(this_rq[np])
best_rqual
=
this_rq
;
best_rqual
=
this_rq
;
...
@@ -2504,6 +2510,7 @@ public class SuperTiles{
...
@@ -2504,6 +2510,7 @@ public class SuperTiles{
final
double
meas_pull
,
// relative pull of the original (measured) plane with respect to the average of the neighbors
final
double
meas_pull
,
// relative pull of the original (measured) plane with respect to the average of the neighbors
final
int
num_passes
,
final
int
num_passes
,
final
double
maxDiff
,
// maximal change in any of the disparity values
final
double
maxDiff
,
// maximal change in any of the disparity values
final
boolean
preferDisparity
,
// Always start with disparity-most axis (false - lowest eigenvalue)
final
int
debugLevel
,
final
int
debugLevel
,
final
int
dbg_X
,
final
int
dbg_X
,
final
int
dbg_Y
)
final
int
dbg_Y
)
...
@@ -2517,6 +2524,7 @@ public class SuperTiles{
...
@@ -2517,6 +2524,7 @@ public class SuperTiles{
this
.
planes
,
// final TilePlanes.PlaneData[][] measured_planes,
this
.
planes
,
// final TilePlanes.PlaneData[][] measured_planes,
this
.
planes_mod
,
// final TilePlanes.PlaneData[][] mod_planes,
this
.
planes_mod
,
// final TilePlanes.PlaneData[][] mod_planes,
true
,
// final boolean calc_diff,
true
,
// final boolean calc_diff,
preferDisparity
,
(
pass
<
10
)?
debugLevel:
0
,
(
pass
<
10
)?
debugLevel:
0
,
dbg_X
,
dbg_X
,
dbg_Y
);
dbg_Y
);
...
@@ -2539,6 +2547,7 @@ public class SuperTiles{
...
@@ -2539,6 +2547,7 @@ public class SuperTiles{
final
TilePlanes
.
PlaneData
[][]
measured_planes
,
final
TilePlanes
.
PlaneData
[][]
measured_planes
,
final
TilePlanes
.
PlaneData
[][]
mod_planes
,
final
TilePlanes
.
PlaneData
[][]
mod_planes
,
final
boolean
calc_diff
,
final
boolean
calc_diff
,
final
boolean
preferDisparity
,
// Always start with disparity-most axis (false - lowest eigenvalue)
final
int
debugLevel
,
final
int
debugLevel
,
final
int
dbg_X
,
final
int
dbg_X
,
final
int
dbg_Y
)
final
int
dbg_Y
)
...
@@ -2600,6 +2609,7 @@ public class SuperTiles{
...
@@ -2600,6 +2609,7 @@ public class SuperTiles{
other_plane
,
// PlaneData otherPd,
other_plane
,
// PlaneData otherPd,
1.0
,
// double scale_other,
1.0
,
// double scale_other,
false
,
// boolean ignore_weights,
false
,
// boolean ignore_weights,
preferDisparity
,
dl
);
// int debugLevel)
dl
);
// int debugLevel)
}
else
{
}
else
{
this_new_plane
=
other_plane
;
this_new_plane
=
other_plane
;
...
@@ -2619,6 +2629,7 @@ public class SuperTiles{
...
@@ -2619,6 +2629,7 @@ public class SuperTiles{
measured_planes
[
nsTile0
][
np0
],
// PlaneData otherPd,
measured_planes
[
nsTile0
][
np0
],
// PlaneData otherPd,
meas_pull
,
// double scale_other,
meas_pull
,
// double scale_other,
false
,
// boolean ignore_weights,
false
,
// boolean ignore_weights,
preferDisparity
,
dl
);
// int debugLevel)
dl
);
// int debugLevel)
}
else
{
}
else
{
this_new_plane
=
measured_planes
[
nsTile0
][
np0
].
clone
();
this_new_plane
=
measured_planes
[
nsTile0
][
np0
].
clone
();
...
...
src/main/java/TilePlanes.java
View file @
41d614cb
...
@@ -452,6 +452,7 @@ public class TilePlanes {
...
@@ -452,6 +452,7 @@ public class TilePlanes {
PlaneData
otherPd
,
PlaneData
otherPd
,
double
scale_other
,
double
scale_other
,
boolean
ignore_weights
,
boolean
ignore_weights
,
boolean
preferDisparity
,
// Always start with disparity-most axis (false - lowest eigenvalue)
int
debugLevel
)
int
debugLevel
)
{
{
if
(
debugLevel
>
0
)
{
if
(
debugLevel
>
0
)
{
...
@@ -474,7 +475,11 @@ public class TilePlanes {
...
@@ -474,7 +475,11 @@ public class TilePlanes {
double
sum_weight
=
scale_other
*
otherPd
.
weight
+
this
.
weight
;
double
sum_weight
=
scale_other
*
otherPd
.
weight
+
this
.
weight
;
double
other_fraction
=
ignore_weights
?
(
scale_other
/(
scale_other
+
1.0
)):
((
scale_other
*
otherPd
.
weight
)
/
sum_weight
);
double
other_fraction
=
ignore_weights
?
(
scale_other
/(
scale_other
+
1.0
)):
((
scale_other
*
otherPd
.
weight
)
/
sum_weight
);
Matrix
common_center
=
this_center
.
times
(
1.0
-
other_fraction
).
plus
(
other_center
.
times
(
other_fraction
));
Matrix
common_center
=
this_center
.
times
(
1.0
-
other_fraction
).
plus
(
other_center
.
times
(
other_fraction
));
Matrix
other_offset
=
other_center
.
minus
(
this_center
);
// other center from this center
Matrix
other_offset
=
other_center
.
minus
(
this_center
);
// other center from this center
if
((
this
.
values
[
0
]
==
0.0
)
||
(
otherPd
.
values
[
0
]
==
0.0
))
{
System
.
out
.
println
(
"Zero eigenvalue"
);
debugLevel
=
10
;
}
if
(
debugLevel
>
0
)
{
if
(
debugLevel
>
0
)
{
System
.
out
.
println
(
"other_eig_vals"
);
System
.
out
.
println
(
"other_eig_vals"
);
other_eig_vals
.
print
(
8
,
6
);
other_eig_vals
.
print
(
8
,
6
);
...
@@ -495,9 +500,6 @@ public class TilePlanes {
...
@@ -495,9 +500,6 @@ public class TilePlanes {
System
.
out
.
println
(
"other_fraction="
+
other_fraction
);
System
.
out
.
println
(
"other_fraction="
+
other_fraction
);
}
}
double
[][]
acovar
=
{
// covariance matrix of center masses (not yet scaled by weight)
double
[][]
acovar
=
{
// covariance matrix of center masses (not yet scaled by weight)
{
other_offset
.
get
(
0
,
0
)*
other_offset
.
get
(
0
,
0
),
other_offset
.
get
(
0
,
0
)*
other_offset
.
get
(
1
,
0
),
other_offset
.
get
(
0
,
0
)*
other_offset
.
get
(
2
,
0
)},
{
other_offset
.
get
(
0
,
0
)*
other_offset
.
get
(
0
,
0
),
other_offset
.
get
(
0
,
0
)*
other_offset
.
get
(
1
,
0
),
other_offset
.
get
(
0
,
0
)*
other_offset
.
get
(
2
,
0
)},
{
other_offset
.
get
(
1
,
0
)*
other_offset
.
get
(
0
,
0
),
other_offset
.
get
(
1
,
0
)*
other_offset
.
get
(
1
,
0
),
other_offset
.
get
(
1
,
0
)*
other_offset
.
get
(
2
,
0
)},
{
other_offset
.
get
(
1
,
0
)*
other_offset
.
get
(
0
,
0
),
other_offset
.
get
(
1
,
0
)*
other_offset
.
get
(
1
,
0
),
other_offset
.
get
(
1
,
0
)*
other_offset
.
get
(
2
,
0
)},
...
@@ -525,9 +527,12 @@ public class TilePlanes {
...
@@ -525,9 +527,12 @@ public class TilePlanes {
System
.
out
.
println
(
"covar with other_covar and this_covar"
);
System
.
out
.
println
(
"covar with other_covar and this_covar"
);
covar
.
print
(
8
,
6
);
covar
.
print
(
8
,
6
);
}
}
if
(
Double
.
isNaN
(
covar
.
get
(
0
,
0
))){
System
.
out
.
println
(
"covar is NaN !"
);
covar
.
print
(
8
,
6
);
}
// extract new eigenvalues, eigenvectors
// extract new eigenvalues, eigenvectors
EigenvalueDecomposition
eig
=
covar
.
eig
();
EigenvalueDecomposition
eig
=
covar
.
eig
();
// verify NaN - it gets stuck
// eig.getD().getArray(),
// eig.getD().getArray(),
// eig.getV().getArray(),
// eig.getV().getArray(),
if
(
debugLevel
>
0
)
{
if
(
debugLevel
>
0
)
{
...
@@ -542,12 +547,30 @@ public class TilePlanes {
...
@@ -542,12 +547,30 @@ public class TilePlanes {
double
[][]
eig_vect
=
eig
.
getV
().
getArray
();
double
[][]
eig_vect
=
eig
.
getV
().
getArray
();
double
[][]
eig_val
=
eig
.
getD
().
getArray
();
double
[][]
eig_val
=
eig
.
getD
().
getArray
();
// make towards camera, left coordinate system
// make towards camera, left coordinate system
/*
int oindx = 0;
int oindx = 0;
for (int i = 1; i <3; i++){
for (int i = 1; i <3; i++){
if (Math.abs(eig_vect[0][i]) > Math.abs(eig_vect[0][oindx])){
if (Math.abs(eig_vect[0][i]) > Math.abs(eig_vect[0][oindx])){
oindx = i;
oindx = i;
}
}
}
}
*/
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
{
for
(
int
i
=
1
;
i
<
3
;
i
++){
if
(
eig_val
[
i
][
i
]
<
eig_val
[
oindx
][
oindx
]){
oindx
=
i
;
}
}
}
// select 2 other axes for increasing eigenvalues (so v is short axis, h is the long one)
// select 2 other axes for increasing eigenvalues (so v is short axis, h is the long one)
int
vindx
=
(
oindx
==
0
)?
1
:
0
;
int
vindx
=
(
oindx
==
0
)?
1
:
0
;
int
hindx
=
(
oindx
==
0
)?
2
:
((
oindx
==
1
)
?
2
:
1
);
int
hindx
=
(
oindx
==
0
)?
2
:
((
oindx
==
1
)
?
2
:
1
);
...
@@ -886,6 +909,7 @@ public class TilePlanes {
...
@@ -886,6 +909,7 @@ public class TilePlanes {
boolean
[]
select
,
boolean
[]
select
,
double
plDispNorm
,
// Normalize disparities to the average if above
double
plDispNorm
,
// Normalize disparities to the average if above
int
debugLevel
){
int
debugLevel
){
double
mindet
=
1
E
-
15
;
int
stSize2
=
2
*
stSize
;
int
stSize2
=
2
*
stSize
;
// Matrix covar = new Matrix(3,3);
// Matrix covar = new Matrix(3,3);
double
[][]
acovar
=
new
double
[
3
][
3
];
double
[][]
acovar
=
new
double
[
3
][
3
];
...
@@ -939,8 +963,21 @@ public class TilePlanes {
...
@@ -939,8 +963,21 @@ public class TilePlanes {
acovar
[
2
][
0
]
=
acovar
[
0
][
2
];
acovar
[
2
][
0
]
=
acovar
[
0
][
2
];
acovar
[
2
][
1
]
=
acovar
[
1
][
2
];
acovar
[
2
][
1
]
=
acovar
[
1
][
2
];
Matrix
covar
=
new
Matrix
(
acovar
);
Matrix
covar
=
new
Matrix
(
acovar
);
if
(
Math
.
abs
(
covar
.
det
())
<
mindet
){
debugLevel
=
5
;
}
EigenvalueDecomposition
eig
=
covar
.
eig
();
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
(
eig
.
getD
().
get
(
0
,
0
)
==
0.0
){
debugLevel
=
10
;
}
if
(
debugLevel
>
0
){
if
(
debugLevel
>
0
){
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
);
System
.
out
.
println
(
"getCovar(): covarianvce matrix, number of used points:"
+
numPoints
);
covar
.
print
(
10
,
6
);
// w,d
covar
.
print
(
10
,
6
);
// w,d
System
.
out
.
println
(
"getCovar(): eigenvalues"
);
System
.
out
.
println
(
"getCovar(): eigenvalues"
);
...
@@ -948,6 +985,10 @@ public class TilePlanes {
...
@@ -948,6 +985,10 @@ public class TilePlanes {
System
.
out
.
println
(
"getCovar(): eigenvectors"
);
System
.
out
.
println
(
"getCovar(): eigenvectors"
);
eig
.
getV
().
print
(
10
,
6
);
// w,d
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
=
{
double
[][][]
rslt
=
{
eig
.
getD
().
getArray
(),
eig
.
getD
().
getArray
(),
eig
.
getV
().
getArray
(),
eig
.
getV
().
getArray
(),
...
@@ -962,13 +1003,12 @@ public class TilePlanes {
...
@@ -962,13 +1003,12 @@ public class TilePlanes {
double
[]
data
,
double
[]
data
,
double
[]
weight
,
double
[]
weight
,
boolean
[]
select
,
// null OK, will enable all tiles
boolean
[]
select
,
// null OK, will enable all tiles
boolean
preferDisparity
,
// Always start with disparity-most axis (false - lowest eigenvalue)
int
debugLevel
){
int
debugLevel
){
if
(
select
==
null
)
{
if
(
select
==
null
)
{
select
=
new
boolean
[
4
*
stSize
];
select
=
new
boolean
[
4
*
stSize
];
for
(
int
i
=
0
;
i
<
select
.
length
;
i
++)
select
[
i
]
=
true
;
for
(
int
i
=
0
;
i
<
select
.
length
;
i
++)
select
[
i
]
=
true
;
}
}
// int debugLevel1 = ((sTileXY[0] == 27) && (sTileXY[1] == 20))? 1: 0;
// int debugLevel1 = ((sTileXY[0] == 27) && (sTileXY[1] == 17))? 1: 0;
int
debugLevel1
=
((
sTileXY
[
0
]
==
27
)
&&
(
sTileXY
[
1
]
==
16
))?
1
:
0
;
// check why v[0][0] <0
int
debugLevel1
=
((
sTileXY
[
0
]
==
27
)
&&
(
sTileXY
[
1
]
==
16
))?
1
:
0
;
// check why v[0][0] <0
...
@@ -980,7 +1020,6 @@ public class TilePlanes {
...
@@ -980,7 +1020,6 @@ public class TilePlanes {
debugLevel1
);
//0); // debugLevel);
debugLevel1
);
//0); // debugLevel);
if
(
rslt
==
null
)
return
null
;
if
(
rslt
==
null
)
return
null
;
int
numPoints
=
(
int
)
rslt
[
2
][
0
][
2
];
int
numPoints
=
(
int
)
rslt
[
2
][
0
][
2
];
// double kz = rslt[2][0][1]; // == 1.0
double
swc
=
rslt
[
2
][
0
][
0
];
double
swc
=
rslt
[
2
][
0
][
0
];
double
[]
szxy
=
rslt
[
2
][
1
];
double
[]
szxy
=
rslt
[
2
][
1
];
double
[][]
eig_val
=
rslt
[
0
];
double
[][]
eig_val
=
rslt
[
0
];
...
@@ -988,11 +1027,23 @@ public class TilePlanes {
...
@@ -988,11 +1027,23 @@ public class TilePlanes {
// find vector most orthogonal to view // (anyway it all works with that assumption), make it first
// find vector most orthogonal to view // (anyway it all works with that assumption), make it first
// TODO normalize to local linear scales
// TODO normalize to local linear scales
int
oindx
=
0
;
int
oindx
=
0
;
for
(
int
i
=
1
;
i
<
3
;
i
++){
if
(
preferDisparity
)
{
if
(
Math
.
abs
(
eig_vect
[
0
][
i
])
>
Math
.
abs
(
eig_vect
[
0
][
oindx
])){
for
(
int
i
=
1
;
i
<
3
;
i
++){
oindx
=
i
;
if
(
Math
.
abs
(
eig_vect
[
0
][
i
])
>
Math
.
abs
(
eig_vect
[
0
][
oindx
])){
oindx
=
i
;
}
}
}
}
else
{
for
(
int
i
=
1
;
i
<
3
;
i
++){
if
(
eig_val
[
i
][
i
]
<
eig_val
[
oindx
][
oindx
]){
oindx
=
i
;
}
}
}
if
(
eig_val
[
oindx
][
oindx
]
==
0.0
){
System
.
out
.
println
(
"getPlane(): zero eigenvalue!!"
);
}
}
/*
/*
// Find two other axis - "mostly X" (horizontal) and "mostly Y" (vertical)
// Find two other axis - "mostly X" (horizontal) and "mostly Y" (vertical)
int vindx = (oindx == 0)? 1 : 0;
int vindx = (oindx == 0)? 1 : 0;
...
@@ -1058,6 +1109,7 @@ public class TilePlanes {
...
@@ -1058,6 +1109,7 @@ public class TilePlanes {
double
targetEigen
,
// target eigenvalue for primary axis (is disparity-dependent, so is non-constant)
double
targetEigen
,
// target eigenvalue for primary axis (is disparity-dependent, so is non-constant)
int
maxRemoved
,
// maximal number of tiles to remove (not a constant)
int
maxRemoved
,
// maximal number of tiles to remove (not a constant)
int
minLeft
,
// minimal number of tiles to keep
int
minLeft
,
// minimal number of tiles to keep
boolean
preferDisparity
,
// Always start with disparity-most axis (false - lowest eigenvalue)
int
debugLevel
){
int
debugLevel
){
int
stSize2
=
2
*
stSize
;
int
stSize2
=
2
*
stSize
;
if
(
pd
==
null
)
{
if
(
pd
==
null
)
{
...
@@ -1066,10 +1118,14 @@ public class TilePlanes {
...
@@ -1066,10 +1118,14 @@ public class TilePlanes {
data
,
data
,
weight
,
weight
,
select
,
// null OK
select
,
// null OK
preferDisparity
,
debugLevel
);
debugLevel
);
}
else
if
(
select
!=
null
){
}
else
if
(
select
!=
null
){
pd
.
setPlaneSelection
(
select
);
pd
.
setPlaneSelection
(
select
);
}
}
if
(
pd
==
null
){
return
null
;
// zero eigenvalues
}
if
(
maxRemoved
>
(
pd
.
getNumPoints
()
-
minLeft
))
maxRemoved
=
pd
.
getNumPoints
()
-
minLeft
;
if
(
maxRemoved
>
(
pd
.
getNumPoints
()
-
minLeft
))
maxRemoved
=
pd
.
getNumPoints
()
-
minLeft
;
int
numRemoved
=
0
;
int
numRemoved
=
0
;
for
(;
(
pd
.
getValue
()
>
targetEigen
)
&&
(
numRemoved
<
maxRemoved
);
numRemoved
++){
for
(;
(
pd
.
getValue
()
>
targetEigen
)
&&
(
numRemoved
<
maxRemoved
);
numRemoved
++){
...
@@ -1107,7 +1163,11 @@ public class TilePlanes {
...
@@ -1107,7 +1163,11 @@ public class TilePlanes {
data
,
data
,
weight
,
weight
,
select
,
select
,
preferDisparity
,
debugLevel
);
debugLevel
);
if
(
pd
==
null
)
{
return
null
;
}
}
}
return
pd
;
return
pd
;
}
}
...
...
src/main/java/TileProcessor.java
View file @
41d614cb
...
@@ -2952,7 +2952,8 @@ public class TileProcessor {
...
@@ -2952,7 +2952,8 @@ public class TileProcessor {
clt_parameters
.
plMinPoints
,
// = 5; // Minimal number of points for plane detection
clt_parameters
.
plMinPoints
,
// = 5; // Minimal number of points for plane detection
clt_parameters
.
plTargetEigen
,
// = 0.1; // Remove outliers until main axis eigenvalue (possibly scaled by plDispNorm) gets below
clt_parameters
.
plTargetEigen
,
// = 0.1; // Remove outliers until main axis eigenvalue (possibly scaled by plDispNorm) gets below
clt_parameters
.
plFractOutliers
,
// = 0.3; // Maximal fraction of outliers to remove
clt_parameters
.
plFractOutliers
,
// = 0.3; // Maximal fraction of outliers to remove
clt_parameters
.
plMaxOutliers
,
// = 20; // Maximal number of outliers to remove
clt_parameters
.
plMaxOutliers
,
// = 20; // Maximal number of outliers to remove\
clt_parameters
.
plPreferDisparity
,
geometryCorrection
,
geometryCorrection
,
clt_parameters
.
correct_distortions
,
clt_parameters
.
correct_distortions
,
0
,
// -1, // debugLevel, // final int debugLevel)
0
,
// -1, // debugLevel, // final int debugLevel)
...
@@ -2964,26 +2965,36 @@ public class TileProcessor {
...
@@ -2964,26 +2965,36 @@ public class TileProcessor {
if
(
debugLevel
>
-
1
)
sdfa_instance
=
new
showDoubleFloatArrays
();
// just for debugging?
if
(
debugLevel
>
-
1
)
sdfa_instance
=
new
showDoubleFloatArrays
();
// just for debugging?
st
.
matchPlanes
(
st
.
matchPlanes
(
clt_parameters
.
plPreferDisparity
,
clt_parameters
.
tileX
,
clt_parameters
.
tileX
,
clt_parameters
.
tileY
);
clt_parameters
.
tileY
);
st
.
selectNeighborPlanesMutual
(
st
.
selectNeighborPlanesMutual
(
clt_parameters
.
plWorstWorsening
,
// final double worst_worsening,
clt_parameters
.
plWorstWorsening
,
// final double worst_worsening,
clt_parameters
.
plWeakWorsening
,
// final double worst_worsening,
clt_parameters
.
plDispNorm
,
clt_parameters
.
plDispNorm
,
clt_parameters
.
plMaxEigen
,
clt_parameters
.
plMaxEigen
,
clt_parameters
.
plMinStrength
,
clt_parameters
.
plMinStrength
,
0
,
// final int debugLevel)
0
,
// final int debugLevel)
clt_parameters
.
tileX
,
clt_parameters
.
tileX
,
clt_parameters
.
tileY
);
clt_parameters
.
tileY
);
while
(
true
)
{
if
(
clt_parameters
.
plFillSquares
){
int
num_added
=
0
;
st
.
fillSquares
();
if
(
clt_parameters
.
plFillSquares
){
}
num_added
+=
st
.
fillSquares
();
if
(
clt_parameters
.
plCutCorners
){
}
st
.
cutCorners
();
if
(
debugLevel
>
-
1
)
{
System
.
out
.
println
(
"after fillSquares() added "
+
num_added
);
}
if
(
clt_parameters
.
plCutCorners
){
num_added
+=
st
.
cutCorners
();
}
if
(
debugLevel
>
-
1
)
{
System
.
out
.
println
(
"after plCutCorners() added (cumulative) "
+
num_added
);
}
if
(
num_added
==
0
)
break
;
}
}
TilePlanes
.
PlaneData
[][]
planes_mod
=
null
;
TilePlanes
.
PlaneData
[][]
planes_mod
=
null
;
// smooth planes (by averaging with neighbors and the "measured" one with variable "pull")
// smooth planes (by averaging with neighbors and the "measured" one with variable "pull")
...
@@ -2993,6 +3004,7 @@ public class TileProcessor {
...
@@ -2993,6 +3004,7 @@ public class TileProcessor {
clt_parameters
.
plPull
,
// final double meas_pull,// relative pull of the original (measured) plane with respect to the average of the neighbors
clt_parameters
.
plPull
,
// final double meas_pull,// relative pull of the original (measured) plane with respect to the average of the neighbors
clt_parameters
.
plIterations
,
// final int num_passes,
clt_parameters
.
plIterations
,
// final int num_passes,
Math
.
pow
(
10.0
,
-
clt_parameters
.
plPrecision
),
// final double maxDiff, // maximal change in any of the disparity values
Math
.
pow
(
10.0
,
-
clt_parameters
.
plPrecision
),
// final double maxDiff, // maximal change in any of the disparity values
clt_parameters
.
plPreferDisparity
,
0
,
// final int debugLevel)
0
,
// final int debugLevel)
clt_parameters
.
tileX
,
clt_parameters
.
tileX
,
clt_parameters
.
tileY
);
clt_parameters
.
tileY
);
...
...
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