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
86e73701
Commit
86e73701
authored
Jun 11, 2025
by
Andrey Filippov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Trying row/col FPN correction
parent
c3f2181a
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
487 additions
and
263 deletions
+487
-263
CorrectionFPN.java
src/main/java/com/elphel/imagej/cuas/CorrectionFPN.java
+425
-0
OpticalFlow.java
...ain/java/com/elphel/imagej/tileprocessor/OpticalFlow.java
+29
-7
QuadCLTCPU.java
...main/java/com/elphel/imagej/tileprocessor/QuadCLTCPU.java
+33
-256
No files found.
src/main/java/com/elphel/imagej/cuas/CorrectionFPN.java
0 → 100644
View file @
86e73701
package
com
.
elphel
.
imagej
.
cuas
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
com.elphel.imagej.common.ShowDoubleFloatArrays
;
import
com.elphel.imagej.tileprocessor.ImageDtt
;
import
com.elphel.imagej.tileprocessor.OpticalFlow
;
import
com.elphel.imagej.tileprocessor.QuadCLT
;
import
com.elphel.imagej.tileprocessor.QuadCLTCPU
;
import
ij.ImagePlus
;
public
class
CorrectionFPN
{
final
QuadCLT
quadCLT
;
public
CorrectionFPN
(
QuadCLTCPU
quadCLT
)
{
this
.
quadCLT
=
(
QuadCLT
)
quadCLT
;
}
public
void
setApplyFPN
(
QuadCLT
[]
quadCLTs
,
double
[][][]
fpn
)
{
// can be null to reset
quadCLT
.
setImageData
(
fpn
);
quadCLT
.
setFPN
(
fpn
);
for
(
int
nscene
=
0
;
nscene
<
quadCLTs
.
length
;
nscene
++)
if
(
quadCLTs
[
nscene
]
!=
null
){
quadCLTs
[
nscene
].
setFPN
(
fpn
);
quadCLTs
[
nscene
].
applyFPN
();
}
return
;
}
public
void
applyFPN
(
double
[][][]
fpn
)
{
if
(
quadCLT
.
getImageFpnApplied
()
!=
fpn
)
{
if
(
quadCLT
.
getImageData
()
==
null
)
{
System
.
out
.
println
(
"applyFPN (): image_data==null"
);
return
;
}
final
double
[][][]
image_data
=
quadCLT
.
getImageData
();
final
double
[][][]
image_fpn_applied
=
quadCLT
.
getImageFpnApplied
();
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
ImageDtt
.
THREADS_MAX
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
public
void
run
()
{
for
(
int
nChn
=
ai
.
getAndIncrement
();
nChn
<
image_data
.
length
;
nChn
=
ai
.
getAndIncrement
())
{
for
(
int
ncol
=
0
;
ncol
<
image_data
[
nChn
].
length
;
ncol
++)
{
for
(
int
npix
=
0
;
npix
<
image_data
[
nChn
][
ncol
].
length
;
npix
++)
{
if
(
image_fpn_applied
!=
null
)
{
image_data
[
nChn
][
ncol
][
npix
]
+=
image_fpn_applied
[
nChn
][
ncol
][
npix
];
}
if
(
fpn
!=
null
)
{
image_data
[
nChn
][
ncol
][
npix
]
-=
fpn
[
nChn
][
ncol
][
npix
];
}
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
quadCLT
.
setFpnApplied
(
fpn
);
quadCLT
.
setHasNewImageData
(
true
);
}
return
;
}
public
ImagePlus
saveShowFPN
(
double
[][][]
fpn
,
int
width
,
boolean
save
,
boolean
show
)
{
ImagePlus
imp
=
CorrectionFPN
.
showFPN
(
fpn
,
// double [][][] fpn,
width
,
// int width,
show
);
// boolean show)
if
(
save
&&
(
imp
!=
null
))
{
quadCLT
.
saveImagePlusInModelDirectory
(
QuadCLT
.
CENTER_FPN_SUFFIX
,
// String suffix, // null - use title from the imp
imp
);
// ImagePlus imp)
}
return
imp
;
}
public
double
[][][]
readImageFPN
(
int
sens_mask
){
int
[]
wh
=
new
int
[
2
];
double
[][]
fpn_data2
=
quadCLT
.
readDoubleArrayFromModelDirectory
(
QuadCLT
.
CENTER_FPN_SUFFIX
,
// String suffix,
0
,
// int num_slices, // (0 - all)
wh
);
// int [] wh)
if
(
fpn_data2
==
null
)
{
return
null
;
}
int
num_sensors
=
quadCLT
.
getNumSensors
();
int
used_sensors
=
0
;
for
(
int
nsens
=
0
;
nsens
<
num_sensors
;
nsens
++)
if
(
(
sens_mask
&
(
1
<<
nsens
))
!=
0
)
{
used_sensors
++;
}
int
num_colors
=
fpn_data2
.
length
/
used_sensors
;
double
[][][]
fpn
=
new
double
[
num_sensors
][
num_colors
][];
int
isens
=
0
;
for
(
int
nsens
=
0
;
nsens
<
num_sensors
;
nsens
++)
if
(
(
sens_mask
&
(
1
<<
nsens
))
!=
0
)
{
for
(
int
ncol
=
0
;
ncol
<
num_colors
;
ncol
++)
{
fpn
[
nsens
][
ncol
]
=
fpn_data2
[
ncol
*
used_sensors
+
isens
];
}
isens
++;
}
return
fpn
;
}
public
ImagePlus
debugFPN
(
QuadCLT
[]
quadCLTs
,
double
[][][]
fpn
,
int
[]
range
,
int
nsens
,
double
um_sigma
,
boolean
show
)
{
int
fpn_width
=
quadCLT
.
getTilesX
()*
quadCLT
.
getTileSize
();
// see if center_CLT can be used
String
dbg_title
=
quadCLT
.
getImageName
()+
"-DEBUG_FPN_ROWCOL_SENS_"
+
nsens
;
ImagePlus
imp
=
debugFPN
(
quadCLTs
,
// final QuadCLT [] quadCLTs,
fpn
,
// final double [][][] fpn,
range
,
// final int [] range, // required
nsens
,
// final int nsens,
fpn_width
,
// final int width,
um_sigma
,
// final double um_sigma,
1.0
,
// final double um_weight,
dbg_title
);
// final String title)
if
(
imp
!=
null
)
{
quadCLT
.
saveImagePlusInModelDirectory
(
dbg_title
,
// String suffix, // null - use title from the imp
imp
);
// ImagePlus imp)
if
(
show
)
{
imp
.
show
();
}
}
return
imp
;
// ************** restart from here!
}
public
static
ImagePlus
showFPN
(
double
[][][]
fpn
,
int
width
,
boolean
show
)
{
int
num_sens
=
fpn
.
length
;
int
num_colors
=
-
1
;
// fpn[0].length;
for
(
int
i
=
0
;
i
<
num_sens
;
i
++)
{
if
(
fpn
[
i
]
!=
null
)
{
num_colors
=
fpn
[
i
].
length
;
break
;
}
}
String
[]
titles
=
new
String
[
num_sens
];
String
[]
top_titles
=
new
String
[
num_colors
];
for
(
int
ncol
=
0
;
ncol
<
num_colors
;
ncol
++)
{
top_titles
[
ncol
]
=
"Color-"
+
ncol
;
}
double
[][][]
img_data
=
new
double
[
num_colors
][
num_sens
][];
for
(
int
nsens
=
0
;
nsens
<
num_sens
;
nsens
++)
if
(
fpn
[
nsens
]
!=
null
)
{
titles
[
nsens
]=
"Sens-"
+
nsens
;
for
(
int
ncol
=
0
;
ncol
<
num_colors
;
ncol
++)
{
img_data
[
ncol
][
nsens
]
=
fpn
[
nsens
][
ncol
];
}
}
String
fpn_title
=
"FPN_data"
;
ImagePlus
imp
=
ShowDoubleFloatArrays
.
showArraysHyperstack
(
img_data
,
// double[][][] pixels,
width
,
// int width,
fpn_title
,
// String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles
,
// String [] titles, // all slices*frames titles or just slice titles or null
top_titles
,
// String [] frame_titles, // frame titles or null
show
);
// boolean show)
return
imp
;
}
/**
* Calculate sensors FPN in a simple way average each channel/color for a scene sequence. Intended to be
* used in CUAS mode averaging several (normally 2 full periods of rotation.
* TODO: make more accurate and universal by back-propagating the corrected image and subtracting per-sensor
* versions before averaging.
* @param quadCLTs sequence of scenes with conditioned images (getImageData() != null), without FPN applied
* @param range a first_last scene index pair. May be adjusted to include an integer number of rotations.
* @param sensor_mask bitmask which sensors to process (normally -1 - all)
* @param debugLevel debug level
* @return [sensor][color][pixel] average FPN image. May be saved as image_data to a virtual (center) scene
* (a QuadCLT instance).
*/
public
static
double
[][][]
calculateFPN
(
final
QuadCLT
[]
quadCLTs
,
final
int
[]
range
,
// required
final
int
sensor_mask
,
final
int
debugLevel
){
QuadCLT
first_scene
=
quadCLTs
[
range
[
0
]];
final
int
num_sens
=
first_scene
.
getNumSensors
();
final
int
num_colors
=
first_scene
.
getNumColors
();
final
int
width
=
first_scene
.
getTilesX
()*
first_scene
.
getTileSize
();
final
int
height
=
first_scene
.
getTilesY
()*
first_scene
.
getTileSize
();
final
int
num_pix
=
width
*
height
;
final
int
num_scenes
=
range
[
1
]-
range
[
0
]+
1
;
final
double
[][][]
fpn
=
new
double
[
num_sens
][
num_colors
][
num_pix
];
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
()
{
for
(
int
nChn
=
ai
.
getAndIncrement
();
nChn
<
num_sens
;
nChn
=
ai
.
getAndIncrement
())
if
(((
sensor_mask
>>
nChn
)
&
1
)
!=
0
)
{
for
(
int
nscene
=
range
[
0
];
nscene
<=
range
[
1
];
nscene
++)
{
for
(
int
ncol
=
0
;
ncol
<
num_colors
;
ncol
++)
{
double
[]
img_slice
=
quadCLTs
[
nscene
].
getImageData
()[
nChn
][
ncol
];
for
(
int
npix
=
0
;
npix
<
num_pix
;
npix
++)
{
fpn
[
nChn
][
ncol
][
npix
]
+=
img_slice
[
npix
];
}
}
}
double
scale
=
1.0
/
num_scenes
;
for
(
int
ncol
=
0
;
ncol
<
num_colors
;
ncol
++)
{
for
(
int
npix
=
0
;
npix
<
num_pix
;
npix
++)
{
fpn
[
nChn
][
ncol
][
npix
]
*=
scale
;
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
return
fpn
;
}
public
static
int
getImageHeight
(
double
[][][]
image_data
,
int
width
)
{
for
(
int
nChn
=
0
;
nChn
<
image_data
.
length
;
nChn
++)
{
if
(
image_data
[
nChn
]
!=
null
)
{
return
image_data
[
nChn
][
0
].
length
/
width
;
}
}
return
0
;
}
public
static
double
[][]
getRowAvg
(
final
double
[][][]
image_data
,
final
int
width
,
final
double
max_abs
,
// only average within +/- max_abs
final
double
weight_outlier
){
// small weight of outliers to avoid instability
final
int
num_sens
=
image_data
.
length
;
final
int
height
=
getImageHeight
(
image_data
,
// final double [][][] image_data,
width
);
// final int width){
final
double
[][]
image_row_avg
=
new
double
[
num_sens
][
width
];
final
double
[][]
weight_row_avg
=
new
double
[
num_sens
][
width
];
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
()
{
for
(
int
nChn
=
ai
.
getAndIncrement
();
nChn
<
num_sens
;
nChn
=
ai
.
getAndIncrement
())
if
(
image_data
[
nChn
]
!=
null
){
int
indx
=
0
;
for
(
int
y
=
0
;
y
<
height
;
y
++)
{
for
(
int
x
=
0
;
x
<
width
;
x
++)
{
double
d
=
image_data
[
nChn
][
0
][
indx
++];
double
w
=
(
Math
.
abs
(
d
)
<=
max_abs
)
?
1.0
:
weight_outlier
;
image_row_avg
[
nChn
][
x
]
+=
w
*
d
;
weight_row_avg
[
nChn
][
x
]
+=
w
;
}
}
for
(
int
x
=
0
;
x
<
width
;
x
++)
{
image_row_avg
[
nChn
][
x
]
/=
weight_row_avg
[
nChn
][
x
];
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
return
image_row_avg
;
}
public
static
double
[][]
getColAvg
(
final
double
[][][]
image_data
,
final
int
width
,
final
double
max_abs
,
// only average within +/- max_abs
final
double
weight_outlier
){
// small weight of outliers to avoid instability
final
int
num_sens
=
image_data
.
length
;
final
int
height
=
getImageHeight
(
image_data
,
// final double [][][] image_data,
width
);
// final int width){
final
double
[][]
image_col_avg
=
new
double
[
num_sens
][
height
];
final
double
[][]
weight_col_avg
=
new
double
[
num_sens
][
height
];
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
()
{
for
(
int
nChn
=
ai
.
getAndIncrement
();
nChn
<
num_sens
;
nChn
=
ai
.
getAndIncrement
())
if
(
image_data
[
nChn
]
!=
null
){
int
indx
=
0
;
for
(
int
y
=
0
;
y
<
height
;
y
++)
{
for
(
int
x
=
0
;
x
<
width
;
x
++)
{
double
d
=
image_data
[
nChn
][
0
][
indx
++];
double
w
=
(
Math
.
abs
(
d
)
<=
max_abs
)
?
1.0
:
weight_outlier
;
image_col_avg
[
nChn
][
y
]
+=
w
*
d
;
weight_col_avg
[
nChn
][
y
]
+=
w
;
}
}
for
(
int
y
=
0
;
y
<
height
;
y
++)
{
image_col_avg
[
nChn
][
y
]
/=
weight_col_avg
[
nChn
][
y
];
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
return
image_col_avg
;
}
public
static
double
[][][]
applyRowCol
(
final
double
[][][]
image_data
,
final
double
[][]
image_row_avg
,
final
double
[][]
image_col_avg
,
final
boolean
inplace
){
final
int
num_sens
=
image_data
.
length
;
final
double
[][][]
out_data
=
new
double
[
num_sens
][
1
][];
int
w
=
0
,
h
=
0
;
for
(
int
nchn
=
0
;
nchn
<
num_sens
;
nchn
++)
if
(
image_data
[
nchn
]
!=
null
)
{
out_data
[
nchn
][
0
]
=
inplace
?
image_data
[
nchn
][
0
]
:
image_data
[
nchn
][
0
].
clone
();
w
=
image_row_avg
[
nchn
].
length
;
h
=
image_col_avg
[
nchn
].
length
;
}
final
int
width
=
w
;
final
int
height
=
h
;
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
()
{
for
(
int
nChn
=
ai
.
getAndIncrement
();
nChn
<
num_sens
;
nChn
=
ai
.
getAndIncrement
())
if
(
image_data
[
nChn
]
!=
null
){
int
indx
=
0
;
for
(
int
y
=
0
;
y
<
height
;
y
++)
{
for
(
int
x
=
0
;
x
<
width
;
x
++)
{
out_data
[
nChn
][
0
][
indx
++]
-=
image_row_avg
[
nChn
][
x
]
+
image_col_avg
[
nChn
][
y
];
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
return
out_data
;
}
public
static
ImagePlus
debugFPN
(
final
QuadCLT
[]
quadCLTs
,
final
double
[][][]
fpn
,
final
int
[]
range
,
// required
final
int
nsens
,
final
int
width
,
final
double
um_sigma
,
final
double
um_weight
,
final
String
title
){
int
ncol
=
0
;
int
num_sens
=
quadCLTs
[
range
[
0
]].
getNumSensors
();
double
max_abs
=
100.0
;
double
weight_outlier
=
0.001
;
int
num_pix
=
quadCLTs
[
range
[
0
]].
getImageData
()[
nsens
][
ncol
].
length
;
String
[]
titles_top
=
{
"src"
,
"src-fpn"
,
"UM"
+
um_sigma
,
"row_col"
};
double
[][][]
data
=
new
double
[
titles_top
.
length
][
range
[
1
]-
range
[
0
]+
1
][
num_pix
];
String
[]
titles
=
new
String
[
range
[
1
]-
range
[
0
]+
1
];
for
(
int
nscene
=
range
[
0
];
nscene
<=
range
[
1
];
nscene
++)
{
int
iscene
=
nscene
-
range
[
0
];
titles
[
iscene
]
=
quadCLTs
[
nscene
].
getImageName
();
data
[
0
][
iscene
]
=
quadCLTs
[
nscene
].
getImageData
()[
nsens
][
ncol
].
clone
();
data
[
1
][
iscene
]
=
data
[
0
][
iscene
].
clone
();
for
(
int
i
=
0
;
i
<
num_pix
;
i
++)
{
data
[
1
][
iscene
][
i
]
-=
fpn
[
nsens
][
ncol
][
i
];
}
data
[
2
][
iscene
]
=
data
[
1
][
iscene
].
clone
();
OpticalFlow
.
applyUMDouble
(
data
[
2
][
iscene
],
// final double [] data,
width
,
// final int width,
um_sigma
,
// final double um_sigma,
um_weight
);
// final double um_weight)
double
[][][]
data_chn
=
new
double
[
num_sens
][][];
data_chn
[
nsens
]
=
new
double
[][]
{
data
[
2
][
iscene
]};
double
[][]
image_row_avg
=
getRowAvg
(
data_chn
,
// final double [][][] image_data,
width
,
// final int width,
max_abs
,
// final double max_abs, // only average within +/- max_abs
weight_outlier
);
// final double weight_outlier)
double
[][]
image_col_avg
=
getColAvg
(
data_chn
,
// final double [][][] image_data,
width
,
// final int width,
max_abs
,
// final double max_abs, // only average within +/- max_abs
weight_outlier
);
// final double weight_outlier)
double
[][][]
data_out
=
applyRowCol
(
data_chn
,
// final double [][][] image_data,
image_row_avg
,
// final double [][] image_row_avg,
image_col_avg
,
// final double [][] image_col_avg,
false
);
// final boolean inplace )
data
[
3
][
iscene
]
=
data_out
[
nsens
][
0
];
}
ImagePlus
imp
=
ShowDoubleFloatArrays
.
showArraysHyperstack
(
data
,
// double[][][] pixels,
width
,
// int width,
title
,
// String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles
,
// String [] titles, // all slices*frames titles or just slice titles or null
titles_top
,
// String [] frame_titles, // frame titles or null
false
);
// boolean show)
return
imp
;
}
}
src/main/java/com/elphel/imagej/tileprocessor/OpticalFlow.java
View file @
86e73701
...
@@ -54,6 +54,7 @@ import com.elphel.imagej.common.DoubleGaussianBlur;
...
@@ -54,6 +54,7 @@ import com.elphel.imagej.common.DoubleGaussianBlur;
import
com.elphel.imagej.common.PolynomialApproximation
;
import
com.elphel.imagej.common.PolynomialApproximation
;
import
com.elphel.imagej.common.ShowDoubleFloatArrays
;
import
com.elphel.imagej.common.ShowDoubleFloatArrays
;
import
com.elphel.imagej.correction.CorrectionColorProc
;
import
com.elphel.imagej.correction.CorrectionColorProc
;
import
com.elphel.imagej.cuas.CorrectionFPN
;
import
com.elphel.imagej.cuas.Cuas
;
import
com.elphel.imagej.cuas.Cuas
;
import
com.elphel.imagej.cuas.CuasCenterLma
;
import
com.elphel.imagej.cuas.CuasCenterLma
;
import
com.elphel.imagej.gpu.GPUTileProcessor
;
import
com.elphel.imagej.gpu.GPUTileProcessor
;
...
@@ -5184,7 +5185,7 @@ public class OpticalFlow {
...
@@ -5184,7 +5185,7 @@ public class OpticalFlow {
}
}
}
}
double
[][][]
fpn
=
center_CLT
.
readImageFPN
(
-
1
);
// int sens_mask);
double
[][][]
fpn
=
center_CLT
.
getCorrectionFPN
().
readImageFPN
(
-
1
);
// int sens_mask);
if
((
fpn
==
null
)
||
cuas_calc_fpn
)
{
if
((
fpn
==
null
)
||
cuas_calc_fpn
)
{
if
(
debugLevel
>-
3
)
{
if
(
debugLevel
>-
3
)
{
System
.
out
.
println
(
"Calculating FPN."
);
System
.
out
.
println
(
"Calculating FPN."
);
...
@@ -5193,7 +5194,7 @@ public class OpticalFlow {
...
@@ -5193,7 +5194,7 @@ public class OpticalFlow {
int
rot_periods
=
(
int
)
Math
.
floor
(
num_scenes
/
cuas_rot_period
);
int
rot_periods
=
(
int
)
Math
.
floor
(
num_scenes
/
cuas_rot_period
);
int
rot_scenes
=
(
int
)
Math
.
floor
(
rot_periods
*
cuas_rot_period
);
int
rot_scenes
=
(
int
)
Math
.
floor
(
rot_periods
*
cuas_rot_period
);
int
[]
rot_range
=
{
0
,
rot_scenes
-
1
};
int
[]
rot_range
=
{
0
,
rot_scenes
-
1
};
fpn
=
QuadCLT
.
calculateFPN
(
fpn
=
CorrectionFPN
.
calculateFPN
(
quadCLTs
,
// final QuadCLT [] quadCLTs,
quadCLTs
,
// final QuadCLT [] quadCLTs,
rot_range
,
// final int [] range, // required
rot_range
,
// final int [] range, // required
-
1
,
// final int sensor_mask,
-
1
,
// final int sensor_mask,
...
@@ -5201,11 +5202,13 @@ public class OpticalFlow {
...
@@ -5201,11 +5202,13 @@ public class OpticalFlow {
int
dbg_sens
=
12
;
int
dbg_sens
=
12
;
if
(
cuas_debug
&&
(
dbg_sens
>=
0
))
{
if
(
cuas_debug
&&
(
dbg_sens
>=
0
))
{
center_CLT
.
debugFPN
(
double
um_sigma_fpn
=
10.0
;
center_CLT
.
getCorrectionFPN
().
debugFPN
(
quadCLTs
,
// QuadCLT [] quadCLTs,
quadCLTs
,
// QuadCLT [] quadCLTs,
fpn
,
// double [][][] fpn,
fpn
,
// double [][][] fpn,
rot_range
,
// int [] range,
rot_range
,
// int [] range,
dbg_sens
,
// int nsens,
dbg_sens
,
// int nsens,
um_sigma_fpn
,
// double um_sigma = 10.0;
show_fpn
);
// boolean show) {
show_fpn
);
// boolean show) {
}
}
...
@@ -5215,12 +5218,12 @@ public class OpticalFlow {
...
@@ -5215,12 +5218,12 @@ public class OpticalFlow {
}
}
}
}
// center_CLT.setImageData(fpn); // included in center_CLT.setApplyFPN(). // setting FPN images to the virtual (center) scene
// center_CLT.setImageData(fpn); // included in center_CLT.setApplyFPN(). // setting FPN images to the virtual (center) scene
center_CLT
.
saveShowFPN
(
center_CLT
.
getCorrectionFPN
().
saveShowFPN
(
fpn
,
// double [][][] fpn,
fpn
,
// double [][][] fpn,
fpn_width
,
// int width,
fpn_width
,
// int width,
true
,
// boolean save,
true
,
// boolean save,
show_fpn
);
// boolean show) {
show_fpn
);
// boolean show) {
center_CLT
.
setApplyFPN
(
center_CLT
.
getCorrectionFPN
().
setApplyFPN
(
quadCLTs
,
// QuadCLT [] quadCLTs,
quadCLTs
,
// QuadCLT [] quadCLTs,
fpn
);
// double [][][] fpn)
fpn
);
// double [][][] fpn)
}
else
{
}
else
{
...
@@ -5228,7 +5231,7 @@ public class OpticalFlow {
...
@@ -5228,7 +5231,7 @@ public class OpticalFlow {
System
.
out
.
println
(
"Skipping FPN."
);
System
.
out
.
println
(
"Skipping FPN."
);
}
}
// center_CLT.setImageData(null);
// center_CLT.setImageData(null);
center_CLT
.
setApplyFPN
(
center_CLT
.
getCorrectionFPN
().
setApplyFPN
(
quadCLTs
,
// QuadCLT [] quadCLTs,
quadCLTs
,
// QuadCLT [] quadCLTs,
null
);
// double [][][] fpn)
null
);
// double [][][] fpn)
}
}
...
@@ -8621,8 +8624,27 @@ public class OpticalFlow {
...
@@ -8621,8 +8624,27 @@ public class OpticalFlow {
imp_scenes
.
getProcessor
().
resetMinAndMax
();
imp_scenes
.
getProcessor
().
resetMinAndMax
();
return
imp_scenes
;
return
imp_scenes
;
}
}
public
static
void
applyUMDouble
(
final
double
[]
data
,
final
int
width
,
final
double
um_sigma
,
final
double
um_weight
)
{
double
[]
blurred
=
data
.
clone
();
(
new
DoubleGaussianBlur
()).
blurDouble
(
blurred
,
// double[] pixels,
width
,
// int width,
blurred
.
length
/
width
,
// int height,
um_sigma
,
// double sigmaX,
um_sigma
,
// double sigmaY,
0.01
);
// double accuracy)
for
(
int
i
=
0
;
i
<
data
.
length
;
i
++)
{
data
[
i
]
-=
blurred
[
i
]*
um_weight
;
}
}
public
static
double
[][]
getSceneSZXY
(
public
static
double
[][]
getSceneSZXY
(
QuadCLT
scene
,
QuadCLT
scene
,
...
...
src/main/java/com/elphel/imagej/tileprocessor/QuadCLTCPU.java
View file @
86e73701
...
@@ -67,6 +67,7 @@ import com.elphel.imagej.common.ShowDoubleFloatArrays;
...
@@ -67,6 +67,7 @@ import com.elphel.imagej.common.ShowDoubleFloatArrays;
import
com.elphel.imagej.correction.CorrectionColorProc
;
import
com.elphel.imagej.correction.CorrectionColorProc
;
import
com.elphel.imagej.correction.EyesisCorrections
;
import
com.elphel.imagej.correction.EyesisCorrections
;
import
com.elphel.imagej.correction.Eyesis_Correction
;
import
com.elphel.imagej.correction.Eyesis_Correction
;
import
com.elphel.imagej.cuas.CorrectionFPN
;
import
com.elphel.imagej.cuas.Cuas
;
import
com.elphel.imagej.cuas.Cuas
;
import
com.elphel.imagej.cuas.CuasData
;
import
com.elphel.imagej.cuas.CuasData
;
import
com.elphel.imagej.gpu.GpuQuad
;
import
com.elphel.imagej.gpu.GpuQuad
;
...
@@ -171,7 +172,9 @@ public class QuadCLTCPU {
...
@@ -171,7 +172,9 @@ public class QuadCLTCPU {
public
double
[][][]
image_fpn
=
null
;
// [channel][color][pixel] Shared by images in a series, subtracted during conditioning
public
double
[][][]
image_fpn
=
null
;
// [channel][color][pixel] Shared by images in a series, subtracted during conditioning
// and applied to image_data;
// and applied to image_data;
public
double
[][][]
image_fpn_applied
=
null
;
// [channel][color][pixel] // when applying different instance, the old will be unapplied
public
double
[][][]
image_fpn_applied
=
null
;
// [channel][color][pixel] // when applying different instance, the old will be unapplied
boolean
new_image_data
=
false
;
public
double
[][]
image_row_avg
=
null
;
//[nsens][width] integrated by columns, lwir-only (single-color)
public
double
[][]
image_col_avg
=
null
;
//[nsens][height] integrated by rows, lwir-only (single-color)
boolean
new_image_data
=
false
;
boolean
[][]
saturation_imp
=
null
;
// (near) saturated pixels or null
boolean
[][]
saturation_imp
=
null
;
// (near) saturated pixels or null
boolean
is_aux
=
false
;
boolean
is_aux
=
false
;
String
photometric_scene
=
null
;
String
photometric_scene
=
null
;
...
@@ -228,6 +231,19 @@ public class QuadCLTCPU {
...
@@ -228,6 +231,19 @@ public class QuadCLTCPU {
public
boolean
center_is_parent
=
false
;
// when true - use image_path that discards current version
public
boolean
center_is_parent
=
false
;
// when true - use image_path that discards current version
public
String
center_parent_dir
=
null
;
public
String
center_parent_dir
=
null
;
public
ImagePlus
imp_center_average
=
null
;
public
ImagePlus
imp_center_average
=
null
;
public
CorrectionFPN
correctionFPN
=
null
;
public
void
setCorrectionFPN
()
{
correctionFPN
=
new
CorrectionFPN
(
this
);
}
public
CorrectionFPN
getCorrectionFPN
()
{
if
(
correctionFPN
==
null
)
{
correctionFPN
=
new
CorrectionFPN
(
this
);
}
return
correctionFPN
;
}
public
ImagePlus
getCenterAverage
()
{
public
ImagePlus
getCenterAverage
()
{
...
@@ -6458,6 +6474,11 @@ public class QuadCLTCPU {
...
@@ -6458,6 +6474,11 @@ public class QuadCLTCPU {
public
boolean
hasNewImageData
()
{
public
boolean
hasNewImageData
()
{
return
new_image_data
;
return
new_image_data
;
}
}
public
void
setHasNewImageData
(
boolean
has_data
)
{
new_image_data
=
has_data
;
}
public
double
[][][]
getResetImageData
(){
public
double
[][][]
getResetImageData
(){
new_image_data
=
false
;
new_image_data
=
false
;
return
image_data
;
return
image_data
;
...
@@ -6466,6 +6487,10 @@ public class QuadCLTCPU {
...
@@ -6466,6 +6487,10 @@ public class QuadCLTCPU {
return
image_data
;
return
image_data
;
}
}
public
double
[][][]
getImageFpnApplied
(){
return
image_fpn_applied
;
}
public
void
setImageData
(
double
[][][]
data
)
{
public
void
setImageData
(
double
[][][]
data
)
{
image_data
=
data
;
image_data
=
data
;
new_image_data
=
true
;
new_image_data
=
true
;
...
@@ -6473,6 +6498,10 @@ public class QuadCLTCPU {
...
@@ -6473,6 +6498,10 @@ public class QuadCLTCPU {
image_fpn
=
null
;
image_fpn
=
null
;
}
}
public
void
setFpnApplied
(
double
[][][]
data
)
{
image_fpn_applied
=
data
;
}
// magic scale should be set before using TileProcessor (calculated disparities depend on it)
// magic scale should be set before using TileProcessor (calculated disparities depend on it)
public
boolean
isAux
()
{
return
is_aux
;}
// USED in lwir
public
boolean
isAux
()
{
return
is_aux
;}
// USED in lwir
...
@@ -9891,261 +9920,6 @@ public class QuadCLTCPU {
...
@@ -9891,261 +9920,6 @@ public class QuadCLTCPU {
this
.
image_fpn
=
fpn
;
this
.
image_fpn
=
fpn
;
}
}
public
void
setApplyFPN
(
QuadCLT
[]
quadCLTs
,
double
[][][]
fpn
)
{
// can be null to reset
setImageData
(
fpn
);
setFPN
(
fpn
);
for
(
int
nscene
=
0
;
nscene
<
quadCLTs
.
length
;
nscene
++)
if
(
quadCLTs
[
nscene
]
!=
null
){
quadCLTs
[
nscene
].
setFPN
(
fpn
);
quadCLTs
[
nscene
].
applyFPN
();
}
return
;
}
public
void
applyFPN
()
{
applyFPN
(
this
.
image_fpn
);
}
public
void
applyFPN
(
double
[][][]
fpn
)
{
if
(
image_fpn_applied
!=
fpn
)
{
if
(
image_data
==
null
)
{
System
.
out
.
println
(
"applyFPN (): image_data==null"
);
return
;
}
final
Thread
[]
threads
=
ImageDtt
.
newThreadArray
(
ImageDtt
.
THREADS_MAX
);
final
AtomicInteger
ai
=
new
AtomicInteger
(
0
);
for
(
int
ithread
=
0
;
ithread
<
threads
.
length
;
ithread
++)
{
threads
[
ithread
]
=
new
Thread
()
{
public
void
run
()
{
for
(
int
nChn
=
ai
.
getAndIncrement
();
nChn
<
image_data
.
length
;
nChn
=
ai
.
getAndIncrement
())
{
for
(
int
ncol
=
0
;
ncol
<
image_data
[
nChn
].
length
;
ncol
++)
{
for
(
int
npix
=
0
;
npix
<
image_data
[
nChn
][
ncol
].
length
;
npix
++)
{
if
(
image_fpn_applied
!=
null
)
{
image_data
[
nChn
][
ncol
][
npix
]
+=
image_fpn_applied
[
nChn
][
ncol
][
npix
];
}
if
(
fpn
!=
null
)
{
image_data
[
nChn
][
ncol
][
npix
]
-=
fpn
[
nChn
][
ncol
][
npix
];
}
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
image_fpn_applied
=
fpn
;
this
.
new_image_data
=
true
;
}
return
;
}
public
ImagePlus
saveShowFPN
(
double
[][][]
fpn
,
int
width
,
boolean
save
,
boolean
show
)
{
ImagePlus
imp
=
showFPN
(
fpn
,
// double [][][] fpn,
width
,
// int width,
show
);
// boolean show)
if
(
save
&&
(
imp
!=
null
))
{
saveImagePlusInModelDirectory
(
CENTER_FPN_SUFFIX
,
// String suffix, // null - use title from the imp
imp
);
// ImagePlus imp)
}
return
imp
;
}
public
static
ImagePlus
showFPN
(
double
[][][]
fpn
,
int
width
,
boolean
show
)
{
int
num_sens
=
fpn
.
length
;
int
num_colors
=
-
1
;
// fpn[0].length;
for
(
int
i
=
0
;
i
<
num_sens
;
i
++)
{
if
(
fpn
[
i
]
!=
null
)
{
num_colors
=
fpn
[
i
].
length
;
break
;
}
}
String
[]
titles
=
new
String
[
num_sens
];
String
[]
top_titles
=
new
String
[
num_colors
];
for
(
int
ncol
=
0
;
ncol
<
num_colors
;
ncol
++)
{
top_titles
[
ncol
]
=
"Color-"
+
ncol
;
}
double
[][][]
img_data
=
new
double
[
num_colors
][
num_sens
][];
for
(
int
nsens
=
0
;
nsens
<
num_sens
;
nsens
++)
if
(
fpn
[
nsens
]
!=
null
)
{
titles
[
nsens
]=
"Sens-"
+
nsens
;
for
(
int
ncol
=
0
;
ncol
<
num_colors
;
ncol
++)
{
img_data
[
ncol
][
nsens
]
=
fpn
[
nsens
][
ncol
];
}
}
String
fpn_title
=
"FPN_data"
;
ImagePlus
imp
=
ShowDoubleFloatArrays
.
showArraysHyperstack
(
img_data
,
// double[][][] pixels,
width
,
// int width,
fpn_title
,
// String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles
,
// String [] titles, // all slices*frames titles or just slice titles or null
top_titles
,
// String [] frame_titles, // frame titles or null
show
);
// boolean show)
return
imp
;
}
public
double
[][][]
readImageFPN
(
int
sens_mask
){
int
[]
wh
=
new
int
[
2
];
double
[][]
fpn_data2
=
readDoubleArrayFromModelDirectory
(
CENTER_FPN_SUFFIX
,
// String suffix,
0
,
// int num_slices, // (0 - all)
wh
);
// int [] wh)
if
(
fpn_data2
==
null
)
{
return
null
;
}
int
num_sensors
=
getNumSensors
();
int
used_sensors
=
0
;
for
(
int
nsens
=
0
;
nsens
<
num_sensors
;
nsens
++)
if
(
(
sens_mask
&
(
1
<<
nsens
))
!=
0
)
{
used_sensors
++;
}
int
num_colors
=
fpn_data2
.
length
/
used_sensors
;
double
[][][]
fpn
=
new
double
[
num_sensors
][
num_colors
][];
int
isens
=
0
;
for
(
int
nsens
=
0
;
nsens
<
num_sensors
;
nsens
++)
if
(
(
sens_mask
&
(
1
<<
nsens
))
!=
0
)
{
for
(
int
ncol
=
0
;
ncol
<
num_colors
;
ncol
++)
{
fpn
[
nsens
][
ncol
]
=
fpn_data2
[
ncol
*
used_sensors
+
isens
];
}
isens
++;
}
return
fpn
;
}
/**
* Calculate sensors FPN in a simple way average each channel/color for a scene sequence. Intended to be
* used in CUAS mode averaging several (normally 2 full periods of rotation.
* TODO: make more accurate and universal by back-propagating the corrected image and subtracting per-sensor
* versions before averaging.
* @param quadCLTs sequence of scenes with conditioned images (getImageData() != null), without FPN applied
* @param range a first_last scene index pair. May be adjusted to include an integer number of rotations.
* @param sensor_mask bitmask which sensors to process (normally -1 - all)
* @param debugLevel debug level
* @return [sensor][color][pixel] average FPN image. May be saved as image_data to a virtual (center) scene
* (a QuadCLT instance).
*/
public
static
double
[][][]
calculateFPN
(
final
QuadCLT
[]
quadCLTs
,
final
int
[]
range
,
// required
final
int
sensor_mask
,
final
int
debugLevel
){
QuadCLT
first_scene
=
quadCLTs
[
range
[
0
]];
final
int
num_sens
=
first_scene
.
getNumSensors
();
final
int
num_colors
=
first_scene
.
getNumColors
();
final
int
width
=
first_scene
.
getTilesX
()*
first_scene
.
getTileSize
();
final
int
height
=
first_scene
.
getTilesY
()*
first_scene
.
getTileSize
();
final
int
num_pix
=
width
*
height
;
final
int
num_scenes
=
range
[
1
]-
range
[
0
]+
1
;
final
double
[][][]
fpn
=
new
double
[
num_sens
][
num_colors
][
num_pix
];
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
()
{
for
(
int
nChn
=
ai
.
getAndIncrement
();
nChn
<
num_sens
;
nChn
=
ai
.
getAndIncrement
())
if
(((
sensor_mask
>>
nChn
)
&
1
)
!=
0
)
{
for
(
int
nscene
=
range
[
0
];
nscene
<=
range
[
1
];
nscene
++)
{
for
(
int
ncol
=
0
;
ncol
<
num_colors
;
ncol
++)
{
double
[]
img_slice
=
quadCLTs
[
nscene
].
getImageData
()[
nChn
][
ncol
];
for
(
int
npix
=
0
;
npix
<
num_pix
;
npix
++)
{
fpn
[
nChn
][
ncol
][
npix
]
+=
img_slice
[
npix
];
}
}
}
double
scale
=
1.0
/
num_scenes
;
for
(
int
ncol
=
0
;
ncol
<
num_colors
;
ncol
++)
{
for
(
int
npix
=
0
;
npix
<
num_pix
;
npix
++)
{
fpn
[
nChn
][
ncol
][
npix
]
*=
scale
;
}
}
}
}
};
}
ImageDtt
.
startAndJoin
(
threads
);
return
fpn
;
}
public
ImagePlus
debugFPN
(
QuadCLT
[]
quadCLTs
,
double
[][][]
fpn
,
int
[]
range
,
int
nsens
,
boolean
show
)
{
int
fpn_width
=
getTilesX
()*
getTileSize
();
// see if center_CLT can be used
String
dbg_title
=
getImageName
()+
"-DEBUG_FPN_SENS_"
+
nsens
;
ImagePlus
imp
=
QuadCLT
.
debugFPN
(
quadCLTs
,
// final QuadCLT [] quadCLTs,
fpn
,
// final double [][][] fpn,
range
,
// final int [] range, // required
nsens
,
// final int nsens,
fpn_width
,
// final int width,
dbg_title
);
// final String title)
if
(
imp
!=
null
)
{
saveImagePlusInModelDirectory
(
dbg_title
,
// String suffix, // null - use title from the imp
imp
);
// ImagePlus imp)
if
(
show
)
{
imp
.
show
();
}
}
return
imp
;
}
public
static
ImagePlus
debugFPN
(
final
QuadCLT
[]
quadCLTs
,
final
double
[][][]
fpn
,
final
int
[]
range
,
// required
final
int
nsens
,
final
int
width
,
final
String
title
){
int
ncol
=
0
;
int
num_pix
=
quadCLTs
[
range
[
0
]].
getImageData
()[
nsens
][
ncol
].
length
;
double
[][][]
data
=
new
double
[
2
][
range
[
1
]-
range
[
0
]+
1
][
num_pix
];
String
[]
titles_top
=
{
"src"
,
"src-fpn"
};
String
[]
titles
=
new
String
[
range
[
1
]-
range
[
0
]+
1
];
for
(
int
nscene
=
range
[
0
];
nscene
<=
range
[
1
];
nscene
++)
{
int
iscene
=
nscene
-
range
[
0
];
titles
[
iscene
]
=
quadCLTs
[
nscene
].
getImageName
();
data
[
0
][
iscene
]
=
quadCLTs
[
nscene
].
getImageData
()[
nsens
][
ncol
].
clone
();
data
[
1
][
iscene
]
=
data
[
0
][
iscene
].
clone
();
for
(
int
i
=
0
;
i
<
num_pix
;
i
++)
{
data
[
1
][
iscene
][
i
]
-=
fpn
[
nsens
][
ncol
][
i
];
}
}
ImagePlus
imp
=
ShowDoubleFloatArrays
.
showArraysHyperstack
(
data
,
// double[][][] pixels,
width
,
// int width,
title
,
// String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles
,
// String [] titles, // all slices*frames titles or just slice titles or null
titles_top
,
// String [] frame_titles, // frame titles or null
false
);
// boolean show)
return
imp
;
}
public
void
processCLTQuadCorrs
(
// not used in lwir
public
void
processCLTQuadCorrs
(
// not used in lwir
CLTParameters
clt_parameters
,
CLTParameters
clt_parameters
,
...
@@ -10228,6 +10002,9 @@ public class QuadCLTCPU {
...
@@ -10228,6 +10002,9 @@ public class QuadCLTCPU {
IJ
.
d2s
(
0.000000001
*(
System
.
nanoTime
()-
this
.
startTime
),
3
)+
" sec, --- Free memory11="
+
Runtime
.
getRuntime
().
freeMemory
()+
" (of "
+
Runtime
.
getRuntime
().
totalMemory
()+
")"
);
IJ
.
d2s
(
0.000000001
*(
System
.
nanoTime
()-
this
.
startTime
),
3
)+
" sec, --- Free memory11="
+
Runtime
.
getRuntime
().
freeMemory
()+
" (of "
+
Runtime
.
getRuntime
().
totalMemory
()+
")"
);
}
}
public
void
applyFPN
()
{
getCorrectionFPN
().
applyFPN
(
this
.
image_fpn
);
}
public
void
processCLTQuadCorrsTestERS
(
public
void
processCLTQuadCorrsTestERS
(
...
...
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