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
e496084a
Commit
e496084a
authored
Sep 27, 2024
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
minor bug fixes, verified jacobian
parent
dcec0ae3
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
267 additions
and
20 deletions
+267
-20
VegetationLMA.java
...main/java/com/elphel/imagej/vegetation/VegetationLMA.java
+246
-4
VegetationModel.java
...in/java/com/elphel/imagej/vegetation/VegetationModel.java
+21
-16
No files found.
src/main/java/com/elphel/imagej/vegetation/VegetationLMA.java
View file @
e496084a
...
@@ -52,11 +52,17 @@ public class VegetationLMA {
...
@@ -52,11 +52,17 @@ public class VegetationLMA {
private
double
[]
y_vector
=
null
;
private
double
[]
y_vector
=
null
;
private
double
weight_pure
=
0
;
private
double
weight_pure
=
0
;
private
double
[]
weights
;
// normalized so sum is 1.0 for all - samples and extra regularization
private
double
[]
weights
;
// normalized so sum is 1.0 for all - samples and extra regularization
public
double
alpha_loss
;
public
double
alpha_loss
=
0
;
// not used with cosine alpha
public
double
alpha_offset
=
0
;
// if >0, start losses above 0.0 and below 1.0;
public
double
alpha_offset
=
0
;
// if >0, start losses above 0.0 and below 1.0;
public
double
alpha_lpf
=
0
;
public
double
alpha_lpf
=
0
;
public
double
terr_lpf
=
0
;
public
double
terr_lpf
=
0
;
public
double
veget_lpf
=
0
;
public
double
veget_lpf
=
0
;
// when unsharp mask is applied , pulling to 0 (when alpha is 0 (for vegetation) or 1.0 (for terrain) makes sense
public
double
terr_pull0
=
0
;
public
double
veget_pull0
=
0
;
public
double
boost_parallax
=
1
;
public
double
boost_parallax
=
1
;
public
double
um_sigma
=
0
;
// just use in debug image names
public
double
um_sigma
=
0
;
// just use in debug image names
public
double
um_weight
=
0
;
public
double
um_weight
=
0
;
...
@@ -130,6 +136,8 @@ public class VegetationLMA {
...
@@ -130,6 +136,8 @@ public class VegetationLMA {
final
double
alpha_lpf
,
// pull vegetation alpha to average of 4 neighbors
final
double
alpha_lpf
,
// pull vegetation alpha to average of 4 neighbors
final
double
terr_lpf
,
// pull terrain to average of 4 neighbors (very small)
final
double
terr_lpf
,
// pull terrain to average of 4 neighbors (very small)
final
double
veget_lpf
,
// pull vegetation to average of 4 neighbors (very small - maybe not needed)
final
double
veget_lpf
,
// pull vegetation to average of 4 neighbors (very small - maybe not needed)
final
double
terr_pull0
,
// pull terrain to zero (makes sense with UM
final
double
veget_pull0
,
// pull vegetation to zero (makes sense with UM
final
double
boost_parallax
,
// increase weight of scene with maximal parallax relative to the reference scene
final
double
boost_parallax
,
// increase weight of scene with maximal parallax relative to the reference scene
final
double
um_sigma
,
// just use in debug image names
final
double
um_sigma
,
// just use in debug image names
final
double
um_weight
,
final
double
um_weight
,
...
@@ -831,11 +839,240 @@ public class VegetationLMA {
...
@@ -831,11 +839,240 @@ public class VegetationLMA {
ImageDtt
.
startAndJoin
(
threads
);
ImageDtt
.
startAndJoin
(
threads
);
// regularization weights and derivatives
// regularization weights and derivatives
return
terrain_weights
;
return
terrain_weights
;
}
}
private
double
[]
getFxDerivs
(
private
double
[]
getFxDerivs
(
final
double
[]
vector
,
final
double
[][]
jt
,
// should be null or initialized with [vector.length][]
final
int
debug_level
)
{
// using 0.5*(1-cos(alpha/2pi) instead of alpha. alpha < 0 -> 0, alpha > 1 -> 1. Depends on other terms for stability
double
[]
fX
=
new
double
[
weights
.
length
];
// num_pairs + vector.length];
if
(
jt
!=
null
)
{
for
(
int
i
=
0
;
i
<
jt
.
length
;
i
++)
{
jt
[
i
]
=
new
double
[
weights
.
length
];
// weights.length];
}
}
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
();
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
public
void
run
()
{
double
[]
vegetation
=
new
double
[
4
];
double
[]
alpha
=
new
double
[
4
];
for
(
int
n
=
ai
.
getAndIncrement
();
n
<
y_vector
.
length
;
n
=
ai
.
getAndIncrement
())
{
// int nscene = data_source[n][0][0];
// int indx = data_source[n][0][1];
double
terrain
=
vector
[
data_source
[
n
][
0
][
2
]];
double
[]
cw
=
corners_weights
[
n
];
double
d
;
int
[]
indx_vegetation
=
data_source
[
n
][
1
];
int
[]
indx_alpha
=
data_source
[
n
][
2
];
double
sum_v
=
0
,
sum_a
=
0
;
if
(
cw
!=
null
)
{
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
int
iv
=
indx_vegetation
[
i
],
ia
=
indx_alpha
[
i
];
vegetation
[
i
]
=
cw
[
i
]
*
((
iv
>=
0
)
?
vector
[
iv
]:
tvao
[
TVAO_VEGETATION
][-
1
-
iv
]);
alpha
[
i
]
=
cw
[
i
]
*
((
ia
>=
0
)
?
vector
[
ia
]:
tvao
[
TVAO_VEGETATION_ALPHA
][-
1
-
ia
]);
sum_v
+=
vegetation
[
i
];
sum_a
+=
alpha
[
i
];
}
double
k
=
(
sum_a
<
0
)?
0
:
(
(
sum_a
>
1
)
?
1.0
:
0.5
*
(
1.0
-
Math
.
cos
(
sum_a
*
Math
.
PI
)));
// d = terrain * (1.0 - sum_a) + sum_v * sum_a;
d
=
terrain
*
(
1.0
-
k
)
+
sum_v
*
k
;
if
(
jt
!=
null
)
{
jt
[
data_source
[
n
][
0
][
2
]][
n
]
=
1
-
k
;
// sum_a; // d/dterrain
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
if
(
indx_vegetation
[
i
]
>=
0
)
{
jt
[
data_source
[
n
][
1
][
i
]][
n
]
=
cw
[
i
]
*
k
;
// sum_a; // d/dvegetation[i]
}
if
((
indx_alpha
[
i
]
>=
0
)
&&
(
sum_a
>
0
)
&&
(
sum_a
<
1.0
))
{
// jt[data_source[n][2][i]][n] = cw[i] * (sum_v - terrain); // d/dalpha[i]
jt
[
data_source
[
n
][
2
][
i
]][
n
]
=
cw
[
i
]
*
(
sum_v
-
terrain
)
*
0.5
*
Math
.
PI
*
Math
.
sin
(
sum_a
*
Math
.
PI
);
// d/dalpha[i]
}
}
}
}
else
{
d
=
terrain
;
if
(
jt
!=
null
)
{
jt
[
data_source
[
n
][
0
][
2
]][
n
]
=
1
;
// d/dterrain
}
}
double
scene_offs
=
vector
[
data_source
[
n
][
0
][
3
]];
fX
[
n
]
=
d
+
scene_offs
;
if
(
jt
!=
null
)
{
jt
[
data_source
[
n
][
0
][
3
]][
n
]
=
1
;
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
// regularization weights and derivatives
int
ind_next
=
y_vector
.
length
;
if
((
alpha_lpf
>=
0
)
||
(
alpha_loss
>
0
))
{
final
int
ind_y_alpha
=
ind_next
;
ind_next
+=
num_pars_vegetation_alpha
;
ai
.
set
(
0
);
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
public
void
run
()
{
for
(
int
n
=
ai
.
getAndIncrement
();
n
<
num_pars_vegetation_alpha
;
n
=
ai
.
getAndIncrement
())
{
int
np
=
ind_pars_vegetation_alpha
+
n
;
// index of the alpha parameter
int
nx
=
n
+
ind_y_alpha
;
// y_vector.length; // x - index
double
d
=
0
;
fX
[
nx
]
=
0.0
;
if
(
alpha_loss
>
0
)
{
double
alpha
=
vector
[
np
];
if
(
alpha
<
alpha_offset
)
{
d
=
alpha
-
alpha_offset
;
}
else
if
(
alpha
>
(
1
-
alpha_offset
))
{
d
=
alpha
-
(
1.0
-
alpha_offset
);
}
if
(
d
!=
0
)
{
fX
[
nx
]
=
d
*
d
*
alpha_loss
;
if
(
jt
!=
null
)
{
jt
[
np
][
nx
]
=
2
*
alpha_loss
*
d
;
// d/dalpha[i]
}
}
}
// add cost for difference between this alpha and average of 4 neighbors (when they exist
// applies to alpha before cosine, so it will pull borders even when alpha<0 or alpha > 1 (zero derivatives)
if
(
alpha_lpf
>
0
)
{
// should always be > 0 to provide stability for out-of-range alpha
double
avg
=
0
;
int
nn
=
0
;
for
(
int
i
=
0
;
i
<
alpha_neibs
[
n
].
length
;
i
++)
{
// now 4, may be increased
int
di
=
alpha_neibs
[
n
][
i
];
d
=
0
;
if
(
di
>=
0
)
{
d
=
vector
[
di
];
// d - full parameter index
avg
+=
d
;
nn
++;
}
else
if
(
di
<
-
1
)
{
d
=
tvao
[
TVAO_VEGETATION_ALPHA
][-
di
-
2
];
avg
+=
d
;
nn
++;
}
}
avg
/=
nn
;
// average
fX
[
nx
]
+=
alpha_lpf
*
(
vector
[
np
]
-
avg
);
if
(
jt
!=
null
)
{
jt
[
np
][
nx
]
+=
alpha_lpf
;
for
(
int
i
=
0
;
i
<
alpha_neibs
[
n
].
length
;
i
++)
{
// now 4, may be increased
int
di
=
alpha_neibs
[
n
][
i
];
if
(
di
>=
0
)
{
jt
[
di
][
nx
]
-=
alpha_lpf
/
nn
;
}
}
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
}
// if (alpha_lpf >= 0) {
if
(
terr_lpf
>=
0
)
{
final
int
ind_y_terr
=
ind_next
;
ind_next
+=
num_pars_terrain
;
ai
.
set
(
0
);
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
public
void
run
()
{
for
(
int
n
=
ai
.
getAndIncrement
();
n
<
num_pars_terrain
;
n
=
ai
.
getAndIncrement
())
{
int
np
=
ind_pars_terrain
+
n
;
// index of the alpha parameter
int
nx
=
n
+
ind_y_terr
;
// y_vector.length; // x - index
double
d
=
0
;
if
(
terr_lpf
>
0
)
{
double
avg
=
0
;
int
nn
=
0
;
for
(
int
i
=
0
;
i
<
terr_neibs
[
n
].
length
;
i
++)
{
// now 4, may be increased
int
di
=
terr_neibs
[
n
][
i
];
d
=
0
;
if
(
di
>=
0
)
{
d
=
vector
[
di
];
// d - full parameter index
avg
+=
d
;
nn
++;
}
else
if
(
di
<
-
1
)
{
d
=
tvao
[
TVAO_TERRAIN
][-
di
-
2
];
avg
+=
d
;
nn
++;
}
}
avg
/=
nn
;
// average
fX
[
nx
]
+=
terr_lpf
*
(
vector
[
np
]
-
avg
)
+
terr_pull0
*
vector
[
np
];
if
(
jt
!=
null
)
{
jt
[
np
][
nx
]
+=
terr_lpf
+
terr_pull0
;
for
(
int
i
=
0
;
i
<
terr_neibs
[
n
].
length
;
i
++)
{
// now 4, may be increased
int
di
=
terr_neibs
[
n
][
i
];
if
(
di
>=
0
)
{
jt
[
di
][
nx
]
-=
terr_lpf
/
nn
;
}
}
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
}
if
(
veget_lpf
>=
0
)
{
final
int
ind_y_veget
=
ind_next
;
ind_next
+=
num_pars_vegetation
;
ai
.
set
(
0
);
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
public
void
run
()
{
for
(
int
n
=
ai
.
getAndIncrement
();
n
<
num_pars_vegetation
;
n
=
ai
.
getAndIncrement
())
{
int
np
=
ind_pars_vegetation
+
n
;
// index of the alpha parameter
int
nx
=
n
+
ind_y_veget
;
// y_vector.length; // x - index
double
d
=
0
;
if
(
veget_lpf
>
0
)
{
double
avg
=
0
;
int
nn
=
0
;
for
(
int
i
=
0
;
i
<
veget_neibs
[
n
].
length
;
i
++)
{
// now 4, may be increased
int
di
=
veget_neibs
[
n
][
i
];
d
=
0
;
if
(
di
>=
0
)
{
d
=
vector
[
di
];
// d - full parameter index
avg
+=
d
;
nn
++;
}
else
if
(
di
<
-
1
)
{
d
=
tvao
[
TVAO_VEGETATION
][-
di
-
2
];
avg
+=
d
;
nn
++;
}
}
avg
/=
nn
;
// average
fX
[
nx
]
+=
veget_lpf
*
(
vector
[
np
]
-
avg
)
+
veget_pull0
*
vector
[
np
];
if
(
jt
!=
null
)
{
jt
[
np
][
nx
]
+=
veget_lpf
+
veget_pull0
;
for
(
int
i
=
0
;
i
<
veget_neibs
[
n
].
length
;
i
++)
{
// now 4, may be increased
int
di
=
veget_neibs
[
n
][
i
];
if
(
di
>=
0
)
{
jt
[
di
][
nx
]
-=
veget_lpf
/
nn
;
}
}
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
}
return
fX
;
}
private
double
[]
getFxDerivs_precos
(
final
double
[]
vector
,
final
double
[]
vector
,
final
double
[][]
jt
,
// should be null or initialized with [vector.length][]
final
double
[][]
jt
,
// should be null or initialized with [vector.length][]
final
int
debug_level
)
final
int
debug_level
)
...
@@ -1058,6 +1295,8 @@ public class VegetationLMA {
...
@@ -1058,6 +1295,8 @@ public class VegetationLMA {
}
}
return
fX
;
return
fX
;
}
}
private
double
[][]
getFxDerivsDelta
(
private
double
[][]
getFxDerivsDelta
(
double
[]
vector
,
double
[]
vector
,
...
@@ -1255,17 +1494,20 @@ public class VegetationLMA {
...
@@ -1255,17 +1494,20 @@ public class VegetationLMA {
for
(
int
n
=
0
;
n
<
jt_diff
.
length
;
n
++)
{
for
(
int
n
=
0
;
n
<
jt_diff
.
length
;
n
++)
{
for
(
int
w
=
0
;
w
<
jt_diff
[
0
].
length
;
w
++)
{
for
(
int
w
=
0
;
w
<
jt_diff
[
0
].
length
;
w
++)
{
jt_diff
[
n
][
w
]
=
jt
[
n
][
w
]
-
jt_delta
[
n
][
w
];
jt_diff
[
n
][
w
]
=
jt
[
n
][
w
]
-
jt_delta
[
n
][
w
];
if
(
Math
.
abs
(
jt_diff
[
n
][
w
])
>
max_err
)
{
System
.
out
.
println
(
"debugDerivs(): n="
+
n
+
", w = "
+
w
+
", diff="
+
jt_diff
[
n
][
w
]);
}
max_err
=
Math
.
max
(
max_err
,
Math
.
abs
(
jt_diff
[
n
][
w
]));
max_err
=
Math
.
max
(
max_err
,
Math
.
abs
(
jt_diff
[
n
][
w
]));
}
}
}
}
System
.
out
.
println
(
"delta = "
+
delta
+
", max_err = "
+
max_err
);
System
.
out
.
println
(
"delta = "
+
delta
+
", max_err = "
+
max_err
);
// think of visualization
// think of visualization
/*
/*
*/
if
(
show_img
)
{
if
(
show_img
)
{
String
[]
frame_titles
=
{
"jt"
,
"jt_delta"
,
"jt_diff"
};
String
[]
frame_titles
=
{
"jt"
,
"jt_delta"
,
"jt_diff"
};
double
[][][]
debug_img
=
new
double
[
frame_titles
.
length
][][];
double
[][][]
debug_img
=
new
double
[
frame_titles
.
length
][][];
}
}
*/
/*
*/
return
max_err
;
return
max_err
;
}
}
...
...
src/main/java/com/elphel/imagej/vegetation/VegetationModel.java
View file @
e496084a
...
@@ -681,28 +681,31 @@ public class VegetationModel {
...
@@ -681,28 +681,31 @@ public class VegetationModel {
int
min_scenes
=
10
;
int
min_scenes
=
10
;
double
default_alpha
=
0.8
;
double
default_alpha
=
0.8
;
double
reg_weights
=
0.25
;
// fraction of the total weight used for regularization
double
reg_weights
=
0.25
;
// fraction of the total weight used for regularization
double
alpha_loss
=
10000.0
;
// 1000.0; // 100.; // 10.0; // quadratic loss when alpha reaches -1.0 or 2.0
double
alpha_loss
=
10.0
;
//
10000.0; // 1000.0; // 100.; // 10.0; // quadratic loss when alpha reaches -1.0 or 2.0
double
alpha_offset
=
0.02
;
// 0.03; // if >0, start losses above 0.0 and below 1.0;
double
alpha_offset
=
0.0
;
// 0.0
2; // 0.03; // if >0, start losses above 0.0 and below 1.0;
double
alpha_lpf
=
10
;
// 20; // 6.0; // 3.0; // 2.0; // 1.5; // 5.0; // 0.5; // pull to average of 4 neighbors
double
alpha_lpf
=
10
;
// 20; // 6.0; // 3.0; // 2.0; // 1.5; // 5.0; // 0.5; // pull to average of 4 neighbors
double
terr_lpf
=
0.1
;
// pull terrain to average of 4 neighbors (very small)
double
terr_lpf
=
0.1
;
// pull terrain to average of 4 neighbors (very small)
double
veget_lpf
=
0.1
;
// pull vegetation to average of 4 neighbors (very small - maybe not needed)
double
veget_lpf
=
0.1
;
// pull vegetation to average of 4 neighbors (very small - maybe not needed)
double
terr_pull0
=
0.1
;
//pull terrain to zero (makes sense with UM
double
veget_pull0
=
0.1
;
// pull vegetation to zero (makes sense with UM
double
boost_parallax
=
1.0
;
// 5;
double
boost_parallax
=
1.0
;
// 5;
boolean
exit_loop
=
debugLevel
<
1000
;
boolean
next_run
=
false
;
boolean
next_run
=
false
;
boolean
read_pars
=
true
;
// false; // true;
boolean
read_pars
=
false
;
// true; // false; // true;
double
threshold_terrain
=
0.05
;
double
threshold_terrain
=
0.05
;
double
min_max_terrain
=
0.1
;
double
min_max_terrain
=
0.1
;
double
min_terrain
=
0.001
;
double
min_terrain
=
0.001
;
double
min_vegetation
=
0.5
;
double
min_vegetation
=
0.5
;
boolean
um_en
=
true
;
double
um_sigma
=
1.0
;
double
um_weight
=
0.8
;
boolean
exit_loop
=
debugLevel
<
1000
;
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/lma/parameters_vector_data_1000-0.03.tiff";
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/lma/parameters_vector_data_1000-0.03.tiff";
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_1000-0.03.tiff";
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_1000-0.03.tiff";
String
parameters_path
=
"/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_x143-y317-w35-h35-live_10000_0.02_3.0.tiff"
;
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_x143-y317-w35-h35-live_10000_0.02_3.0.tiff";
// String parameters_path = "/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_x143-y317-w35-h35-al0.0-alo0.02-alp10.0-tl0.1-vl0.1-bp1.0-um1.0_0.8.tiff";
final
boolean
um_en
=
true
;
String
parameters_path
=
"/media/elphel/SSD3-4GB/lwir16-proc/berdich3/debug/vegetation/essential/parameters_vector_data_x143-y317-w35-h35-al10.0-alo0.0-alp10.0-tl0.1-vl0.1-bp1.0-um1.0_0.8-live.tiff"
;
final
double
um_sigma
=
1.0
;
final
double
um_weight
=
0.8
;
if
(
um_en
)
{
if
(
um_en
)
{
double
[][]
um_data
=
new
double
[
terrain_rendered
.
length
+
2
][];
double
[][]
um_data
=
new
double
[
terrain_rendered
.
length
+
2
][];
System
.
arraycopy
(
terrain_rendered
,
0
,
um_data
,
0
,
terrain_rendered
.
length
);
System
.
arraycopy
(
terrain_rendered
,
0
,
um_data
,
0
,
terrain_rendered
.
length
);
...
@@ -786,6 +789,8 @@ public class VegetationModel {
...
@@ -786,6 +789,8 @@ public class VegetationModel {
alpha_lpf
,
// final double alpha_lpf, // pull to average of 4 neighbors
alpha_lpf
,
// final double alpha_lpf, // pull to average of 4 neighbors
terr_lpf
,
// final double terr_lpf, // pull terrain to average of 4 neighbors (very small)
terr_lpf
,
// final double terr_lpf, // pull terrain to average of 4 neighbors (very small)
veget_lpf
,
// final double veget_lpf, // pull vegetation to average of 4 neighbors (very small - maybe not needed)
veget_lpf
,
// final double veget_lpf, // pull vegetation to average of 4 neighbors (very small - maybe not needed)
terr_pull0
,
// final double terr_pull0, // pull terrain to zero (makes sense with UM
veget_pull0
,
// final double veget_pull0, // pull vegetation to zero (makes sense with UM
boost_parallax
,
// final double boost_parallax, // increase weight of scene with maximal parallax relative to the reference scene
boost_parallax
,
// final double boost_parallax, // increase weight of scene with maximal parallax relative to the reference scene
um_sigma
,
// final double um_sigma, // just use in debug image names
um_sigma
,
// final double um_sigma, // just use in debug image names
(
um_en
?
um_weight:
0.0
),
// final double um_weight,
(
um_en
?
um_weight:
0.0
),
// final double um_weight,
...
...
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