Commit 7bc39323 authored by Andrey Filippov's avatar Andrey Filippov

Removed some stale code,fixed centered mode

parent 04b52a7f
......@@ -218,6 +218,124 @@ Rotation introduces faster target/background variation in image coordinates whil
- CUAS-focused work was parked around commit `8946631f767ddda77365ebc32d45eef1e3d21936` (October 27, 2025).
- Since then, development emphasis shifted to foliage/global-LMA paths; CUAS branches may require restoration and re-validation for bit-rot before new-data testing.
### Current CUAS target-detection flow (March 2026 LV data)
For the March 2026 LV runs, the current working input list is:
```
/home/elphel/lwir16-proc/LV/lists/lv_site_05.list
```
Per-sequence outputs are created under linked center directories such as:
```
/home/elphel/lwir16-proc/LV/linked/centeres_1773389747-1773390382/1773389818_152542-CENTER/v07
```
The first restored CUAS stage currently produces merged LWIR stacks after FPN and row/column mitigation. A typical file is:
```
1773389818_152542-CENTER-CUAS-MERGED-CUAS.tiff
```
In this stack:
- the first slice is the sequence average,
- the remaining slices are individual scenes with that average subtracted.
The corresponding unsharp-masked version, for example:
```
1773389818_152542-CENTER-CUAS-MERGED-CUAS-UM2.0_1.000_250.tiff
```
is the same merged sequence after unsharp masking (for the example above: sigma 2.0 px, amount 1.0).
The next CUAS stage is the moving-target stage:
- estimate a prevailing per-tile motion vector using 2D phase correlation on the merged/unsharp sequence,
- use those vectors as a "virtual moving camera",
- shift each contributing frame according to that motion vector,
- accumulate the shifted frames as a long exposure to improve SNR of dim moving targets,
- then locate/freeze targets on the accumulated data and render target overlays/video products.
This stage is where the sky mask matters operationally: terrain-rich areas are suppressed before accepting local maxima, so target search is effectively constrained to the allowed sky region.
#### CUAS motion-scan details: keyframes, pair geometry, and FAST/SLOW split
The per-tile motion vectors are not estimated from a single frame pair. For each keyframe index, the code builds a short temporal block and accumulates multiple pairwise correlations that all correspond to nearly the same constant-velocity target motion.
The main scan geometry is controlled by:
- `cuas_corr_offset`: separation between the two halves of each pair set
- `cuas_corr_pairs`: number of correlation pairs accumulated inside one keyframe block
- `cuas_half_step`: if `true`, adjacent keyframes advance by `cuas_corr_offset/2`; otherwise by `cuas_corr_offset`
- `cuas_precorr_ra` and `cuas_corr_step`: optional temporal smoothing/decimation before correlation
For one keyframe:
- `seq_length = cuas_corr_offset + cuas_corr_pairs`
- `corr_inc = cuas_half_step ? (cuas_corr_offset / 2) : cuas_corr_offset`
- for keyframe `n`, `frame0 = start_frame + n * corr_inc`
- `frame1 = frame0 + cuas_corr_offset`
Inside that keyframe, the code correlates multiple temporally aligned pairs:
- `(frame0 + dframe)` against `(frame1 + dframe)`
- where `dframe` runs from `corr_ra_step/2` to `< cuas_corr_pairs`, stepping by `corr_ra_step`
So with the common mental model of `offset = 8` and `pairs = 8`, the effective pairs are approximately:
- `0 vs 8`
- `1 vs 9`
- ...
- `7 vs 15`
or the decimated equivalent if `cuas_corr_step > 1`.
Each pair is correlated tile-by-tile in transform domain (`TDCorrTile`). The pair results are accumulated before conversion back to pixel-domain correlation. If `cuas_smooth` is enabled, the individual pair contributions are weighted by a sine window across the temporal block. After accumulation:
- TD correlations are normalized and converted to pixel-domain using `cuas_fat_zero`
- per-tile local maxima are extracted
- centroid recentering (`cuas_cent_radius`, `cuas_n_recenter`) estimates `vx`, `vy`, peak strength, and in-center fraction
The `*-CORR2D.tiff` files visualize these per-tile 15x15 correlation maps, one keyframe per slice.
FAST and SLOW currently share this same motion-scan geometry. The difference is only in the temporal prefiltering of the input sequence:
- FAST: `temporalUnsharpMask()` using `cuas_temporal_um`
- SLOW: `runningGaussian()` using `cuas_slow_ra`
Both then call the same `prepareMotionBasedSequence()` path and therefore use the same `cuas_corr_offset`, `cuas_corr_pairs`, `cuas_half_step`, `cuas_precorr_ra`, and `cuas_corr_step`.
Practical consequence: if targets are too fast and the peaks in `*-FAST-CORR2D.tiff` hit the `+-7` tile borders, reducing `cuas_corr_offset` will reduce the apparent motion in both FAST and SLOW modes. There is currently no separate fast-only correlation offset parameter; adding one would require a code change.
### Where the current code does this
- `CuasRanging.processMovingTargetsMulti()` renders the per-sequence `...-CUAS...` stack and applies the unsharp mask before creating `fpixels`.
- `CuasMotion.processMovingTargetsMulti()` runs the fast/slow motion-target preparation and resolves non-conflicting motion candidates.
- `CuasMotion.generateExtractFilterMovingTargets()` expands the target field, performs the motion-compensated accumulation, and renders target/background outputs.
- `CuasMotion.shiftAndRenderAccumulate()` is the "virtual moving camera / long exposure" step.
- `CuasMotion.getAccumulatedCoordinates()` searches the accumulated tiles for isolated local maxima, applies the sky mask, and refines target coordinates with the CUAS LMA fit.
### Top-level trigger path
The March 2026 CUAS workflow order is:
1. Normal per-sequence CUAS scene processing (`cuas_proc_mode = 0`) produces the merged/unsharp stacks, motion vectors, accumulated target frames, and per-sequence CUAS outputs.
2. `CUAS Combine` runs later on the already generated linked centers (`CuasMultiSeries.processGlobals()`).
3. `CUAS Video` runs after that to combine/package already produced CUAS video outputs.
So the motion-vector and long-exposure stage belongs to the first, per-sequence CUAS processing pass, while `CUAS Combine` and `CUAS Video` are later-stage steps.
The direct gate for producing the accumulated target outputs is:
```
IntersceneMatchParameters.cuas_generate
```
shown in the UI as:
```
Generate and save detected targets
```
If that checkbox is off, the code will still do earlier target/ranging work but will skip the accumulated target TIFF/video generation stage.
## Latest Additions
### Segment freezing with `keep_segments`
Index scenes (`*-index`) contain `*-INTERFRAME.corr-xml` with keys like:
......
......@@ -595,7 +595,8 @@ import ij.process.ImageProcessor;
not_empty = true;
fpixels=new float[pixels[i].length];
for (j=0;j<fpixels.length;j++) fpixels[j]=(float)pixels[i][j];
array_stack.addSlice(titles[i], fpixels);
String titlesi=(i < titles.length) ? titles[i] : ("st"+i); // when debugging, titles may to match pixels
array_stack.addSlice(titlesi, fpixels);
}
if (not_empty) {
ImagePlus imp_stack = new ImagePlus(title, array_stack);
......
......@@ -1397,399 +1397,6 @@ public class CuasMotion {
}
public static double [][][] getAccumulatedCoordinates(
final boolean centered, // accum_data was centered, use target_sequence[][][CuasMotionLMA.RSLT_X], target_sequence[][][CuasMotionLMA.RSLT_Y] (if not NaN)
final double [][][] target_sequence, // contains vector_fields data, // centers
final float [][] accum_data, // should be around 0, no low-freq
final double lmax_fraction, // 0.7; // Check if local maximum is separated from the surrounding by this fraction of the maximum value
final double lmax_flt_neglim, // -0.3; // limit negative data to reduce ridge influence (>= to disable)
final double lmax_flt_hsigma, // 1.0 // HPF (~UM) subtract GB with this sigma from the data tile
final double lmax_flt_lsigma, // 1.0 // LPF - GB result of the previous subtraction
final double lmax_flt_scale, // 5.0 // scale filtering result
final double [] sky_mask,
final double sky_threshold, // 0.9 // minimal value of the sky mask where target is possible
final double lma_horizon,
final double lmax_hack_ridge, // 0.45; // Hack for ridges: remove horizontal streaks, where average(abs()) for the line exceeds fraction of abs max 0.32-good, 0.55 - bad
final double lmax_radius, // 3; // look inside cuas_lmax_radius* 2 + 1 square for the local maximum isolation
final boolean lmax_zero, // true; // zero all data outside this radius from the maximum
final double centroid_radius,
final int n_recenter, // re-center window around new maximum. 0 -no refines (single-pass)
final int tilesX,
final boolean no_border,
// Moving target LMA
final double lma_sigma,
final double wnd_pedestal,
final double lma_r0,
final double lma_ovrsht,
// CUAS Motion LMA parameters
final boolean lma_fit_xy,
final boolean lma_fit_a,
final boolean lma_fit_c,
final boolean lma_fit_r,
final boolean lma_fit_k,
final double lambda,
final double lambda_good,
final double lambda_bad,
final double lambda_max,
final double rms_diff,
final int num_iter,
final float [][] accum_debug,
final int debugLevel){
if (debugLevel > 0 ) {
System.out.println("getAccumulatedCoordinates(): "+((sky_mask == null)? "NOT ":"")+"using sky_mask");
}
final boolean dbg_hack_ridge = (debugLevel > 0); // true;
final int tile2 = 2 * GPUTileProcessor.DTT_SIZE;
final int lmax_iradius = (int) Math.floor(lmax_radius);
final int num_seq = target_sequence.length; // same as accum_data.length
final int num_tiles = target_sequence[0].length;
final int num_pixels = accum_data[0].length;
final int width = GPUTileProcessor.DTT_SIZE * tilesX;
final int height = num_pixels / width;
final double [][][] targets_out = new double[num_seq][num_tiles][];
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
final boolean [] param_select = new boolean [CuasMotionLMA.INDX_LEN];
param_select[CuasMotionLMA.INDX_X0] = lma_fit_xy;
param_select[CuasMotionLMA.INDX_Y0] = lma_fit_xy;
param_select[CuasMotionLMA.INDX_A] = lma_fit_a;
param_select[CuasMotionLMA.INDX_C] = lma_fit_c;
param_select[CuasMotionLMA.INDX_RR0] = lma_fit_r;
param_select[CuasMotionLMA.INDX_K] = lma_fit_k;
final int dbg_tile = -(31 + 45 * 80); //(38 + 45 * 80);
final int dbg_seq = 13;
final boolean use_filters = (lmax_flt_hsigma > 0) && (lmax_flt_lsigma > 0) && (lmax_flt_scale > 0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
double [] pix_tile = new double [tile2 * tile2];
double [] pix_tile_filtered0 = use_filters ? new double [tile2 * tile2]:null;
double [] pix_tile_filtered = use_filters ? new double [tile2 * tile2]:null;
boolean [] disabled = new boolean[pix_tile.length];
TileNeibs tn = new TileNeibs(tile2,tile2);
DoubleGaussianBlur gb = new DoubleGaussianBlur();
CuasMotionLMA cuasMotionLMA = new CuasMotionLMA(
tile2, // int width,
lma_sigma, // double sigma);
wnd_pedestal);
// may be faster if process only where vector_field[nseq][ntile] is not null
for (int nSeq = ai.getAndIncrement(); nSeq < num_seq; nSeq = ai.getAndIncrement()) {
if (accum_debug != null) {
accum_debug[nSeq] = new float [num_pixels];
Arrays.fill(accum_debug[nSeq], Float.NaN);
}
for (int ntile = 0; ntile < num_tiles; ntile++) {
if (target_sequence[nSeq][ntile] != null) {
double [] target = target_sequence[nSeq][ntile].clone();
if ((nSeq==dbg_seq) && (ntile == dbg_tile)) {
System.out.println("getAccumulatedCoordinates(): nSeq="+nSeq+", ntile="+ntile);
}
int tileX = ntile % tilesX;
int tileY = ntile / tilesX;
int px0 = tileX * GPUTileProcessor.DTT_SIZE - GPUTileProcessor.DTT_SIZE/2; // top-left of 16x16 tile
int py0 = tileY * GPUTileProcessor.DTT_SIZE - GPUTileProcessor.DTT_SIZE/2; // top-left of 16x16 tile
int horizon_y = (int) Math.ceil (lma_horizon)-py0;
if (centered && !Double.isNaN(target[CuasMotionLMA.RSLT_Y])) {
horizon_y = (int) Math.ceil (lma_horizon - target[CuasMotionLMA.RSLT_Y])-py0;
}
int y_mask_offs = (centered && !Double.isNaN(target[CuasMotionLMA.RSLT_Y])) ? ((int) Math.round(target[CuasMotionLMA.RSLT_Y])):0;
int x_mask_offs = (centered && !Double.isNaN(target[CuasMotionLMA.RSLT_X])) ? ((int) Math.round(target[CuasMotionLMA.RSLT_X])):0;
// copy 16x16 tile
{
int indx_dst = 0;
for (int y = 0; y < tile2; y++) {
int indx_src = px0 + (py0 +y) * width;
if (y >= horizon_y) {
for (int x = 0; x < tile2; x++) {
pix_tile[indx_dst++] = 0;
indx_src++; // float-> double
}
} else {
for (int x = 0; x < tile2; x++) {
pix_tile[indx_dst++] = accum_data[nSeq][indx_src++]; // float-> double
}
}
}
}
// find absolute maximum (before hacking and masking)
int ntile_amax0 = TileNeibs.getAmaxTile(
pix_tile); //double [] data)
if (lmax_hack_ridge > 0) {
Arrays.fill(disabled,false);
// disabled = new boolean[pix_tile.length];
double thresh = pix_tile[ntile_amax0] * lmax_hack_ridge;
for (int row=0; row < tile2; row++) {
double s = 0;
int n = 0;
for (int col = 0; col < tile2; col++) {
double d = Math.abs(pix_tile[row*tile2+col]);
if (!Double.isNaN(d)) {
s += d;
n++;
}
}
s/= n;
if (s > thresh) {
for (int col = 0; col < tile2; col++) {
int pindx = row*tile2+col;
disabled[pindx] = true;
pix_tile[pindx] = 0.0;
}
}
}
}
if (sky_mask != null) {
for (int row = 0; row < tile2; row++) {
int mask_y = Math.min(height-1, Math.max(0, py0 + y_mask_offs + row));
for (int col = 0; col < tile2; col++) {
int mask_x = Math.min(width-1, Math.max(0, px0 + x_mask_offs + col));
int pindx = col+row*tile2;
double mask_val = sky_mask[mask_x + mask_y * width];
pix_tile[pindx] *= mask_val;
if (mask_val < sky_threshold) {
disabled[pindx] = true; // disallow maximums in this area
}
}
}
if ((nSeq==dbg_seq) && (ntile == dbg_tile)) {
System.out.println("getAccumulatedCoordinates(): nSeq="+nSeq+", ntile="+ntile+
" py0="+py0+" px0="+px0+", y_mask_offs="+y_mask_offs+", x_mask_offs="+x_mask_offs);
for (int row = 0; row < tile2; row++) {
int mask_y = Math.min(height-1, Math.max(0, py0 + y_mask_offs + row));
for (int col = 0; col < tile2; col++) {
int mask_x = Math.min(width-1, Math.max(0, px0 + x_mask_offs + col));
int pindx = col+row*tile2;
double mask_val = sky_mask[mask_x + mask_y * width];
if (col == 0) {
System.out.println("row="+row+", mask_y="+mask_y+"col="+col+", mask_x="+mask_x+", mask_val="+mask_val+", pindx="+pindx);
}
}
}
}
}
// find absolute maximum (after "hacking" and masking
int ntile_amax = TileNeibs.getAmaxTile(
pix_tile); //double [] data)
// filtering tile for better maximum selection
if (pix_tile_filtered != null) {
System.arraycopy(pix_tile, 0, pix_tile_filtered, 0, pix_tile_filtered.length);
if (lmax_flt_neglim <0) {
for (int i = 0; i < pix_tile_filtered.length; i++) {
pix_tile_filtered[i] = Math.max(lmax_flt_neglim, pix_tile_filtered[i]);
}
}
System.arraycopy(pix_tile_filtered, 0, pix_tile_filtered0, 0, pix_tile_filtered.length);
gb.blurDouble(
pix_tile_filtered, //
tile2,
tile2,
lmax_flt_hsigma, // double sigmaX,
lmax_flt_hsigma, // double sigmaY,
0.01); // double accuracy)
for (int i = 0; i < pix_tile_filtered.length; i++) {
pix_tile_filtered[i] = pix_tile_filtered0[i] - pix_tile_filtered[i];
}
gb.blurDouble(
pix_tile_filtered, //
tile2,
tile2,
lmax_flt_lsigma, // double sigmaX,
lmax_flt_lsigma, // double sigmaY,
0.01); // double accuracy)
for (int i = 0; i < pix_tile_filtered.length; i++) {
pix_tile_filtered[i] *= lmax_flt_scale;
}
ntile_amax = TileNeibs.getAmaxTile(
pix_tile_filtered); //double [] data)
}
double [] pix_tile_centroid = (pix_tile_filtered != null) ? pix_tile_filtered : pix_tile;
double amax_val = pix_tile_centroid[ntile_amax];
double lmax_val = amax_val;
int use_max = -1;
if (!tn.isEdge(ntile_amax)) {
boolean isolated = tn.isMaxIsolated(
pix_tile_centroid, // double [] data,
ntile_amax, // int ntile,
lmax_fraction, // double fraction,
lmax_iradius); //int radius)) {
if (disabled[ntile_amax]) {
if (dbg_hack_ridge && isolated) {
System.out.println ("getAccumulatedCoordinates(): Removing ridge max for nSeq="+nSeq+", ntile="+ntile+", ntile_amax="+ntile_amax);
}
isolated = false;
}
if (isolated) {
use_max = ntile_amax;
}
}
boolean max_abs = (use_max >= 0); // maximum is absolute maximum
if (use_max < 0) { // find alternative maximum
int [] max_indices = tn.getLocalMaxes(
pix_tile_centroid, //double [] data,
true); // boolean exclude_margins)
double best_val = Double.NaN;
for (int indx:max_indices) {
boolean isolated = tn.isMaxIsolated(
pix_tile_centroid, // double [] data,
indx, // int ntile,
lmax_fraction, // double fraction,
lmax_iradius); //int radius)) {
if (disabled[indx]) {
if (dbg_hack_ridge && isolated) {
System.out.println ("getAccumulatedCoordinates(): Removing ridge max for nSeq="+nSeq+", ntile="+ntile+", indx="+indx);
}
isolated = false;
}
if (isolated) {
double max_val = pix_tile_centroid[indx];
if (!(best_val >= max_val)) {
best_val = max_val;
use_max = indx;
}
}
}
lmax_val = best_val;
}
// zero out outside the circle if maximum is not the absolute maximum or
if ((use_max >= 0) && (lmax_zero || !max_abs)) {
double lmax_iradius2 = (int) Math.ceil(lmax_radius * lmax_radius);
int x0 = use_max % tile2;
int y0 = use_max / tile2;
for (int y = 0; y < tile2; y++) {
int dy = y-y0;
int dy2 = dy*dy;
for (int x = 0; x < tile2; x++) {
int dx = x - x0;
int r2 = dy2+dx*dx;
int pindx = x + tile2 * y;
if (r2 > lmax_iradius2) {
pix_tile[pindx] = 0.0;
} else {
double rratio = Math.sqrt(r2)/lmax_iradius;
pix_tile[pindx] *= Math.cos(0.5*Math.PI*rratio);
}
}
}
}
// accum_debug will apply circular mask only if no filtering. With filtering it will contain filtered (HPF+LPF) data
if (accum_debug != null) {
int indx_src = 0;
for (int y = 0; y < tile2; y++) {
int indx_dst = px0 + (py0 +y) * width;
for (int x = 0; x < tile2; x++) {
accum_debug[nSeq][indx_dst++] = (float) pix_tile_centroid[indx_src++]; // double -> float
}
}
}
target[CuasMotionLMA.RSLT_CENT_MX] = 0.0;
if (use_max >= 0){ // at least one candidate found
double [] mv = Correlation2d.getMaxXYCm( // last, average (Will be relative to the center of the tile)
pix_tile, // corrs.length-1], // double [] data,
tile2, // int data_width, // = 2 * transform_size - 1; // negative - will return center fraction
centroid_radius, // double radius, // 0 - all same weight, > 0 cosine(PI/2*sqrt(dx^2+dy^2)/rad)
n_recenter, // int refine, // re-center window around new maximum. 0 -no refines (single-pass)
null, // fpn_mask, // boolean [] fpn_mask,
false, // boolean ignore_border, // only if fpn_mask != null - ignore tile if maximum touches fpn_mask
no_border, // boolean exclude_margins,
true, // boolean calc_fraction,
use_max, // int imax, // index of the maximum in data[]
false); // boolean debug)
if (mv != null) {
target[CuasMotionLMA.RSLT_CENT_X] = mv[0];
target[CuasMotionLMA.RSLT_CENT_Y] = mv[1];
target[CuasMotionLMA.RSLT_CENT_MX] = mv[2];
if (mv.length > 3) {
target[CuasMotionLMA.RSLT_CENT_F] = mv[3];
}
cuasMotionLMA.prepareLMA(
param_select, // boolean [] param_select,
pix_tile, // double [] tile_data,
mv[0], // double xc, // relative to center =width/2
mv[1], // double yc, // relative to center =width/2
lma_r0, // double r0,
lma_ovrsht, // double k,
lmax_val, // double lmax_val,
debugLevel); // int debugLevel)
int rslt = cuasMotionLMA.runLma( // <0 - failed, >=0 iteration number (1 - immediately)
lambda, // double lambda, // 0.1
lambda_good, // double lambda_scale_good,// 0.5
lambda_bad, // double lambda_scale_bad, // 8.0
lambda_max, // double lambda_max, // 100
rms_diff, // double rms_diff, // 0.001
num_iter, // int num_iter, // 20
nSeq, // int dbg_seq,
ntile, // int dbg_tile,
-1, // int dbg_index,
debugLevel); // int debug_level)
target[CuasMotionLMA.RSLT_ITERS] = rslt; // will save -1 (failure) also
if (rslt >= 0) {
cuasMotionLMA.setResult(target);
int col = GPUTileProcessor.DTT_SIZE + (int) Math.round(target[CuasMotionLMA.RSLT_X]);
int row = GPUTileProcessor.DTT_SIZE + (int) Math.round(target[CuasMotionLMA.RSLT_Y]);
int pindx = col+row*tile2;
if (!tn.isInside(pindx)) {
target[CuasMotionLMA.RSLT_ITERS] = -2; // outside of the 16x16 tiles -> LMA failed to converge
} else if (disabled[pindx]) {
target[CuasMotionLMA.RSLT_FAIL] = CuasMotionLMA.FAIL_HORIZON;
}
if (centered && !Double.isNaN(target_sequence[nSeq][ntile][CuasMotionLMA.RSLT_X])) {
double x0 = target_sequence[nSeq][ntile][CuasMotionLMA.RSLT_X];
double y0 = target_sequence[nSeq][ntile][CuasMotionLMA.RSLT_Y];
target[CuasMotionLMA.RSLT_CENT_X] += x0;
target[CuasMotionLMA.RSLT_CENT_Y] += y0;
target[CuasMotionLMA.RSLT_X] += x0;
target[CuasMotionLMA.RSLT_Y] += y0;
}
if ((ntile == dbg_tile) && (nSeq == dbg_seq)) { // if ((nSeq==dbg_seq) && (ntile == dbg_tile)) {
// px0, py0 - top/left corner of 16x16
int ipx = (int) (px0 + GPUTileProcessor.DTT_SIZE + target[CuasMotionLMA.RSLT_X]);
int ipy = (int) (py0 + GPUTileProcessor.DTT_SIZE + target[CuasMotionLMA.RSLT_Y]);
int mask_x = Math.min(width-1, Math.max(0, ipx));
int mask_y = Math.min(height-1, Math.max(0, ipy));
double mask_val = sky_mask[mask_x + mask_y * width];
System.out.println("getAccumulatedCoordinates(): nSeq="+nSeq+", ntile="+ntile+
", centered="+centered+", pindx="+pindx+
", ipx="+ipx+", ipy="+ipy+
", mask_x="+mask_x + ", mask_y="+mask_y+", mask_val = "+mask_val);
System.out.println();
for (int prow = 0; prow < tile2; prow++) {
for (int pcol=0; pcol<tile2; pcol++) {
System.out.print(disabled[pcol+prow*tile2]?".":"+");
}
System.out.println();
}
}
}
}
}
targets_out[nSeq][ntile] = target;
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return targets_out;
}
public static float [][] getTargetImages(
final double [][][] vector_fields, // centers , just null/not null
final float [][] accum_data, // should be around 0, no low-freq
......@@ -1833,18 +1440,20 @@ public class CuasMotion {
return taret_images;
}
/**
* Probably obsolete, was used with single-target target_sequence (motion sequence)
* @param target_sequence
* @param filter5
* @return
*/
public static double [][][] applyFilter(
double [][][] target_sequence,
boolean [][] filter5){
int [][] filter5){
double [][][] filtered_scan = new double [target_sequence.length][target_sequence[0].length][];
for (int nscan = 0; nscan < target_sequence.length; nscan++) {
for (int t=0; t<target_sequence[nscan].length; t++) {
if ((target_sequence[nscan][t] != null) && filter5[nscan][t]) {
// if ((target_sequence[nscan][t] != null) && (filter5[nscan][t] >=0)) {
if (filter5[nscan][t] >=0) {
filtered_scan[nscan][t] = target_sequence[nscan][t].clone();
}
}
......@@ -1852,20 +1461,29 @@ public class CuasMotion {
return filtered_scan;
}
/**
* Trying to fix centered mode probably broken when switching to multi-varian targets.
* It uses data from the selected target variant, including RSLT_X, RSLT_Y data
* @param target_sequence_multi
* @param filter5
* @return
*/
public static double [][][] applyFilter(
double [][][] target_sequence,
double [][][][] target_sequence_multi,
int [][] filter5){
double [][][] filtered_scan = new double [target_sequence.length][target_sequence[0].length][];
for (int nscan = 0; nscan < target_sequence.length; nscan++) {
for (int t=0; t<target_sequence[nscan].length; t++) {
if ((target_sequence[nscan][t] != null) && (filter5[nscan][t] >=0)) {
filtered_scan[nscan][t] = target_sequence[nscan][t].clone();
double [][][] filtered_scan = new double [target_sequence_multi.length][target_sequence_multi[0].length][];
for (int nscan = 0; nscan < target_sequence_multi.length; nscan++) {
for (int t=0; t<target_sequence_multi[nscan].length; t++) {
if ((target_sequence_multi[nscan][t] != null) && (filter5[nscan][t] >=0)) {
filtered_scan[nscan][t] = target_sequence_multi[nscan][t][filter5[nscan][t]].clone();
}
}
}
return filtered_scan;
}
public static void findStrongerNeighbor(// does not modify "when"
final double [][][] target_sequence,
final boolean [][] filter5,
......@@ -2881,46 +2499,6 @@ public class CuasMotion {
* @param targets - targets for a single keyframe
* @return
*/
public double [][][] targetPxPyD_old(
final double [][] targets) {
final int half_accum_range = getSeqLength()/2;
final int num_tiles = tilesX * tilesY;
final int tileSize = GPUTileProcessor.DTT_SIZE;
final double [][][] pXpYDs = new double [2* half_accum_range +1][num_tiles][];
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 [] pXpYD = new double [3];
for (int nTile = ai.getAndIncrement(); nTile < num_tiles; nTile = ai.getAndIncrement()) if (targets[nTile] != null) {
double [] target = targets[nTile];
int tileY = nTile / tilesX;
int tileX = nTile % tilesX;
double xc = tileSize * tileX + tileSize/2;
double yc = tileSize * tileY + tileSize/2;
double xtk = xc + target[CuasMotionLMA.RSLT_X];
double ytk = yc + target[CuasMotionLMA.RSLT_Y];
double vx = target[CuasMotionLMA.RSLT_VX]/corr_offset;
double vy = target[CuasMotionLMA.RSLT_VY]/corr_offset;
double disp = target[CuasMotionLMA.RSLT_DISPARITY];
if (Double.isNaN(disp)) {
disp = 0.0;
}
pXpYD[2] = disp;
for (int dseq = -half_accum_range; dseq <= half_accum_range; dseq++) {
pXpYD[0] = xtk + vx * dseq;
pXpYD[1] = ytk + vy * dseq;
pXpYDs[dseq + half_accum_range][nTile] = pXpYD.clone();
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return pXpYDs;
}
public double [][][] targetPxPyD( // original
final double [][] targets) {
......@@ -3162,50 +2740,6 @@ public class CuasMotion {
return tdCorrTiles;
}
public float [][] shiftAndRenderTest(
CLTParameters clt_parameters,
final float [][] fpixels,
final double [][][] vector_field,
final int frame0, // for vector_field[0]
final int frame_step,
final int corr_offset, // interframe distance for correlation
final boolean batch_mode) {
double magnitude_scale = -1.0; // /(2 * half_step); // here just 1.0 - will use cosine window when accumulating
float [] nan_frame = new float [fpixels[0].length];
float [][] result_frames = new float [fpixels.length][];
Arrays.fill(nan_frame, Float.NaN);
Arrays.fill(result_frames, nan_frame);
int half_step = frame_step/2;
final int erase = 1; //NaN
for (int nseq = 0; nseq < vector_field.length; nseq++) {
int frame_center = frame0 + nseq * frame_step;
for (int dframe = -half_step; dframe < half_step; dframe++) {
int frame = frame_center + dframe;
if ((frame >=0) && (frame < result_frames.length)) {
double offset_scale = (1.0 * dframe) / corr_offset;
accumulateMotionScene(
clt_parameters, // CLTParameters clt_parameters,
false, // final boolean center,
fpixels[frame], // float [] fpixels,
vector_field[nseq], // final double [][] vector_field,
erase, // final int erase,
batch_mode, // final boolean batch_mode,
offset_scale, // final double offset_scale,
magnitude_scale, // final double magnitude_scale,
tilesX) ; // final int tilesX) {
result_frames[frame] = floatFromTD(false); // boolean use_reference)
boolean frame_debug = false;
if (frame_debug) {
renderFromTD (
false, // boolean use_reference,
"render-from-TD"); // String suffix)
}
}
}
}
return result_frames;
}
public float [][] shiftAndRenderAccumulate(
CLTParameters clt_parameters,
final boolean center,
......@@ -4074,8 +3608,8 @@ public class CuasMotion {
System.out.println("uas_log_path="+uas_log_path);
}
*/
final double [] camera_atr = uasLogReader.getCameraATR();
final ErsCorrection ersCorrection = parentCLT.getErsCorrection();
final double [] camera_atr = (uasLogReader != null) ? uasLogReader.getCameraATR() : ersCorrection.getCameraATR();
// prepare UAS log icon (blue circle)
ColorProcessor uaslog_cp = annotate_uas? getUasLogIconColorProcessor():null;
......@@ -4089,10 +3623,10 @@ public class CuasMotion {
final int uaslog_width = (uaslog_cp != null) ? uaslog_cp.getWidth() : 0;
final int target_icon_width = cp_target_icon.getWidth();
final int uas_icon_width = cp_uas_icon.getWidth();
final int [] uaslog_pixels = (int[]) uaslog_cp.getPixels();
final int [] uaslog_pixels = (uaslog_cp != null) ? (int[]) uaslog_cp.getPixels() : null;
final int [] target_icon_pixels = (int[]) cp_target_icon.getPixels();
final int [] uas_icon_pixels = (int[]) cp_uas_icon.getPixels();
final int [][] uaslog_rgba = splitColorIcon(uaslog_pixels);
final int [][] uaslog_rgba = (uaslog_pixels != null) ? splitColorIcon(uaslog_pixels) : null;
final int [][] target_icon_rgba = splitColorIcon(target_icon_pixels);
final int [][] uas_icon_rgba = splitColorIcon(uas_icon_pixels);
......@@ -4697,8 +4231,8 @@ public class CuasMotion {
stack.addSlice(scene_titles[nscene], color_processors[nscene]);
}
// final double camera_az = uasLogReader.getCameraATR()[0];
final double [] camera_atr = uasLogReader.getCameraATR();
final ErsCorrection ersCorrection = scene.getErsCorrection();
final double [] camera_atr = (uasLogReader != null) ? uasLogReader.getCameraATR() : ersCorrection.getCameraATR();
// prepare target icons
ColorProcessor cp_target_icon = getIconColorProcessor(
......@@ -5383,7 +4917,7 @@ public class CuasMotion {
if (Double.isNaN(fps)) {
fps = 60.0;
}
double [] camera_atr = uasLogReader.getCameraATR();
double [] camera_atr = (uasLogReader != null) ? uasLogReader.getCameraATR() : ersCorrection.getCameraATR();
double ifov = ersCorrection.getIFOV();
int sensor_width = ersCorrection.getSensorWH()[0];
int sensor_height = ersCorrection.getSensorWH()[1];
......@@ -5815,7 +5349,9 @@ public class CuasMotion {
final int frame0 = start_frame + seq_length/2;
// create larger, 5x5 vector field for accumulation -> 3x3
// Expand the sparse target field, then use the motion vectors as a virtual moving camera
// to build long-exposure target frames before rendering target/background composites.
// The accumulation itself is done by shiftAndRenderAccumulate().
double [][][] extended_targets = extendMotionScan(
target_sequence, // final double [][][] motion_scan,
null, // filter5, // final boolean [][] filtered, // centers, should be non-overlapped
......@@ -6833,7 +6369,8 @@ public class CuasMotion {
double [][] targets = target_multi[nSeq][ntile];
if ((targets != null) && (targets.length > 0)) {
if (targets[0][CuasMotionLMA.RSLT_FAIL] == CuasMotionLMA.FAIL_NONE) {
if ((targets[0][CuasMotionLMA.RSLT_MATCH_LENGTH] >=(enough_seq-1)) && targets[0][CuasMotionLMA.RSLT_SEQ_TRAVEL] >= seq_travel) {
if (targets[0][CuasMotionLMA.RSLT_SEQ_TRAVEL] >= seq_travel) {
if (targets[0][CuasMotionLMA.RSLT_MATCH_LENGTH] >=(enough_seq-1)) {
target_sequence[nSeq][ntile] = targets[0];
if (remain != null) {
remain[nSeq]++;
......@@ -6849,6 +6386,7 @@ public class CuasMotion {
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
......@@ -8117,7 +7655,8 @@ public class CuasMotion {
filter5_remain, // final int [] remain){
passes, // final int [] passes, // debugging - numer of passes required
debugLevel); // final int debugLevel)
boolean good_only= false;
boolean show_empty = true; // false; // show scenes with no (valid) targets
if (save_filtered_low) {
ImagePlus imp_filter5 = ShowDoubleFloatArrays.makeArrays(
filter5,
......@@ -8129,6 +7668,17 @@ public class CuasMotion {
imp_filter5.show();
}
parentCLT.saveImagePlusInModelDirectory(imp_filter5); // ImagePlus imp)
/*
ImagePlus imp_target_sequence_multi = showTargetSequence(
target_sequence_multi, // final double [][][][] targets_multi,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
model_prefix+"-TARGET-SEQUENCE-MULTI-n"+niter,// String title,
good_only, // final boolean good_only,
show_empty, // final boolean show_empty, // show scenes with no (valid) targets
!batch_mode, // boolean show,
cuasMotion.tilesX); // int tilesX) {
parentCLT.saveImagePlusInModelDirectory(imp_target_sequence_multi);
*/
}
......@@ -8143,6 +7693,12 @@ public class CuasMotion {
double [][][] targets_nonoverlap = applyFilter( // motion vectors // will have nulls not top try
motion_sequence, // double [][][] motion_scan,
filter5); // boolean [][] filter5)
// Here target_sequence_multi is yet empty
/*
double [][][] targets_nonoverlap = applyFilter( // motion vectors // will have nulls not top try
target_sequence_multi, // double [][][][] target_sequence_multi
filter5); // boolean [][] filter5)
*/
// Anything remains? we'll see after extension
double [][][] extended_scan = extendMotionScan(
targets_nonoverlap, // final double [][][] motion_scan,
......@@ -8172,7 +7728,7 @@ public class CuasMotion {
// show good and bad accumulated here too?
}
// perform new accumulations of shifted non-confliocting tiles
// perform new accumulations of shifted non-conflicting tiles
float [][] fpixels_accumulated = cuasMotion.shiftAndRenderAccumulate(
clt_parameters, // CLTParameters clt_parameters,
false, // final boolean center,
......@@ -8271,8 +7827,6 @@ public class CuasMotion {
parentCLT.saveImagePlusInModelDirectory(imp_acc); // ImagePlus imp)
}
boolean good_only= false;
boolean show_empty = true; // false; // show scenes with no (valid) targets
if (save_filtered_low && debug_more) {
ImagePlus imp_new = showTargetSequence(
targets_new_multi, // final double [][][][] targets_multi,
......@@ -8381,6 +7935,16 @@ public class CuasMotion {
// second pass, using non-centered targets
int niter_lim = niter+ num_cycles;
int iter_show1 = iter_show + niter;
if (intermed_low && debug_more) {
ImagePlus imp_mv_strength = showTargetSequence(
motion_sequence, // double [][][] vector_fields_sequence,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
model_prefix+"-MOTION_SEQUENCE-PRE-CENT",// String title,
!batch_mode, // boolean show,
cuasMotion.tilesX); // int tilesX) {
parentCLT.saveImagePlusInModelDirectory(imp_mv_strength);
}
for (; niter < niter_lim; niter++) {
boolean good_only= false;
boolean show_empty = true; // false; // show scenes with no (valid) targets
......@@ -8396,7 +7960,7 @@ public class CuasMotion {
int [][] filter5 = filter5Targets( // will ignore failed tiles
motion_sequence, // final double [][][] target_sequence,
target_sequence_multi, // final double [][][][] target_sequence_multi,
target_sequence_multi, // final double [][][][] target_sequence_multi,non-centered marked as "used"
// if use motion and select_new will only consider tiles (and compare motion scores in motion_sequence) that have nulls in target_sequence_multi[nseq][ntile]
// if not use motion and select_new will only consider (and compare scores) tiles that have [RSLT_CENTERED] = 0.0
// if not select_new (assumes not use motion) will return best (and good) target indices
......@@ -8443,9 +8007,14 @@ public class CuasMotion {
break;
}
// render and process in centered mode
// double [][][] targets_nonoverlap = applyFilter( // motion vectors // will have nulls not top try
// motion_sequence, // double [][][] motion_scan,
// filter5); // boolean [][] filter5)
double [][][] targets_nonoverlap = applyFilter( // motion vectors // will have nulls not top try
motion_sequence, // double [][][] motion_scan,
target_sequence_multi, // double [][][][] target_sequence_multi
filter5); // boolean [][] filter5)
// Anything remains? we'll see after extension
double [][][] extended_scan = extendMotionScan(
targets_nonoverlap, // final double [][][] motion_scan,
......@@ -8474,10 +8043,10 @@ public class CuasMotion {
// show good and bad accumulated here too?
}
// perform new accumulations of shifted non-confliocting tiles
// perform new accumulations of shifted non-conflicting tiles
float [][] fpixels_accumulated = cuasMotion.shiftAndRenderAccumulate(
clt_parameters, // CLTParameters clt_parameters,
false, // final boolean center,
true, // false, // final boolean center, // why is it false here?
false, // final boolean fill_zeros,
fpixels_tum, // final float [][] fpixels,
extended_scan, // final double [][][] vector_field,
......@@ -8711,8 +8280,8 @@ public class CuasMotion {
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
final int dbg_tile = (debugLevel >0) ?(38+45*80) : -1;
final int dbg_seq0 = -13;
final int dbg_seq1 = -14;
final int dbg_seq0 = (debugLevel >0) ? -13: -1;
final int dbg_seq1 = (debugLevel >0) ? -14: -1;
final int ihorizon = (lma_horizon > 0) ?( (int) Math.ceil(lma_horizon/GPUTileProcessor.DTT_SIZE)) : -1; // tiles with tileY >= ihorizon are removed
if (dbg_tile >=0) {
System.out.println("filter5Targets()):00: use_motion="+use_motion+", select_new="+select_new+", ihorizon="+ihorizon);
......@@ -8771,6 +8340,9 @@ public class CuasMotion {
if ((ihorizon > 0) && (ihorizon < tilesY)) {
Arrays.fill(prohibit, ihorizon*tilesX, num_tiles, true);
}
if ((nSeq >= dbg_seq0) && (nSeq <= dbg_seq1)) {
System.out.println("filter5Targets()):2: nSeq="+nSeq);
}
int num_this_pass = 0;
int npass = 0;
do {
......@@ -8831,12 +8403,13 @@ public class CuasMotion {
for (int dx = -range; dx <= range; dx++) {
int ntile1 = tn.getNeibIndex(ntile, dx, dy);
if ((ntile1 >= 0) && !prohibit[ntile1]) {
targets = target_sequence_multi[nSeq][ntile]; // other targets
if (targets != null) {
for (int ntarg = 0; ntarg < targets.length; ntarg++) if ((targets[ntarg] != null) &&
(targets[ntarg][CuasMotionLMA.RSLT_FAIL] == CuasMotionLMA.FAIL_NONE) &&
(targets[ntarg][CuasMotionLMA.RSLT_CENTERED] == CuasMotionLMA.CENTERED_NO)) {
double val = targets[ntarg][CuasMotionLMA.RSLT_QSCORE];
// targets = target_sequence_multi[nSeq][ntile]; // other targets
double [][] other_targets = target_sequence_multi[nSeq][ntile1]; // other targets
if (other_targets != null) {
for (int ntarg = 0; ntarg < other_targets.length; ntarg++) if ((other_targets[ntarg] != null) &&
(other_targets[ntarg][CuasMotionLMA.RSLT_FAIL] == CuasMotionLMA.FAIL_NONE) &&
(other_targets[ntarg][CuasMotionLMA.RSLT_CENTERED] == CuasMotionLMA.CENTERED_NO)) {
double val = other_targets[ntarg][CuasMotionLMA.RSLT_QSCORE];
if (val > cval) {
ismax = false;
break check_max_target;
......@@ -8877,12 +8450,13 @@ public class CuasMotion {
for (int dx = -range; dx <= range; dx++) {
int ntile1 = tn.getNeibIndex(ntile, dx, dy);
if ((ntile1 >= 0) && !prohibit[ntile1]) {
targets = target_sequence_multi[nSeq][ntile1]; // other targets
if (targets != null) {
for (int ntarg = 0; ntarg < targets.length; ntarg++) if ((targets[ntarg] != null) &&
(targets[ntarg][CuasMotionLMA.RSLT_FAIL] == CuasMotionLMA.FAIL_NONE) &&
(targets[ntarg][CuasMotionLMA.RSLT_CENTERED] != CuasMotionLMA.CENTERED_USED)) {
double val = targets[ntarg][CuasMotionLMA.RSLT_QSCORE];
// targets = target_sequence_multi[nSeq][ntile1]; // other targets
double [][] other_targets = target_sequence_multi[nSeq][ntile1]; // other targets
if (other_targets != null) {
for (int ntarg = 0; ntarg < other_targets.length; ntarg++) if ((other_targets[ntarg] != null) &&
(other_targets[ntarg][CuasMotionLMA.RSLT_FAIL] == CuasMotionLMA.FAIL_NONE) &&
(other_targets[ntarg][CuasMotionLMA.RSLT_CENTERED] != CuasMotionLMA.CENTERED_USED)) {
double val = other_targets[ntarg][CuasMotionLMA.RSLT_QSCORE];
if (val > cval) {
ismax = false;
break check_max_target_any;
......@@ -9874,6 +9448,10 @@ public class CuasMotion {
}
if (targets_nonconflict == null){
// Detect motion candidates on two temporal views of the same merged sequence:
// a temporal-unsharp path for faster targets and a slow running-average path
// for dim/slow targets, then merge and de-conflict the two result sets.
// The selected motion field is later consumed by generateExtractFilterMovingTargets().
// process fast targets
slow_targets = false; // just for filenames
float [][] fpixels_fast = temporalUnsharpMask( // all good targets
......
......@@ -584,12 +584,18 @@ public class CuasMultiSeries {
public void processGlobals() {
int debugLevel = 0;
if (uasLogReader != null) {
int setup_uas = setupUasTiles();
System.out.println("processGlobals(): setupUasTiles() -> "+setup_uas);
int assign_uas_target = assignUasTarget();
System.out.println("processGlobals(): assignUasTarget() -> "+assign_uas_target);
} else {
System.out.println("processGlobals(): no UAS flight log, skipping UAS-specific assignment");
}
printAssignmentStats();
if (uasLogReader != null) {
printUasStats();
}
printAssignments();
combineLocalTargets(
true, // boolean skip_assigned, // if global ID is assigned, do not mess with that pair
......@@ -608,7 +614,9 @@ public class CuasMultiSeries {
min_disparity_velocity); // double min_disparit_velocity);
linearRangeInterpolation();
printAverageRanges(avg_range_ts);
if (uasLogReader != null) {
printAverageVsUASRanges(avg_range_ts);
}
saveUpdatedTargets();
//
ImagePlus imp_radar = testGenerateRadarImage(
......@@ -692,6 +700,10 @@ public class CuasMultiSeries {
}
public void printAverageVsUASRanges(double [][][] avg_range_ts) {
if (uasLogReader == null) {
System.out.println("printAverageVsUASRanges(): skipping, no UAS flight log");
return;
}
System.out.println("printAverageVsUASRanges(): Compare average UAS range with flight log");
int ngtarg = 0;
System.out.println("name, timestamp,scene,range,fl_range,axial_velocity,disparity");
......@@ -733,6 +745,9 @@ public class CuasMultiSeries {
* @return number of keyframes with missing UAS log (should be 0)
*/
public int setupUasTiles() {
if (uasLogReader == null) {
return 0;
}
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
final AtomicInteger amiss = new AtomicInteger(0);
......@@ -771,6 +786,9 @@ public class CuasMultiSeries {
* @return number of assigned local targets
*/
public int assignUasTarget() {
if (uasLogReader == null) {
return 0;
}
final double tmtch_pix= clt_parameters.imp.cuas_tmtch_pix;
final double tmtch_frac = clt_parameters.imp.cuas_tmtch_frac;
final int tileSize = GPUTileProcessor.DTT_SIZE;
......
......@@ -211,8 +211,7 @@ public class CuasRanging {
return null;
}
if (uasLogReader == null) {
System.out.println("uasLogReader == null, it is needed");
return null;
System.out.println("processMovingTargetsMulti(): proceeding without UAS flight log");
}
this.cuasMotion = new CuasMotion (
clt_parameters, // CLTParameters clt_parameters,
......@@ -347,7 +346,9 @@ public class CuasRanging {
{ // always save after calculating ranges and adding UAS data. Later may be moved to after rangeTargets() above, only when calculated
getRangeFromDisparity(targets); // adds RSLT_INFINITY field
// generate results video (move from earlier)
if (uasLogReader != null) {
addUasData(targets); // add flight log data to the nearest tiles, either existing or new
}
// re-saving data with flight log (ground truth) additions
ImagePlus imp_with_range = CuasMotion.showTargetSequence(
targets, // double [][][] vector_fields_sequence,
......@@ -357,7 +358,7 @@ public class CuasRanging {
cuasMotion.getTilesX()); // int tilesX) {
center_CLT.saveImagePlusInModelDirectory(imp_with_range); // ImagePlus imp)
}
if (generate_csv) {
if (generate_csv && (uasLogReader != null)) {
saveTargetStats(targets); // final double [][][] targets_single) {
}
}
......@@ -1017,8 +1018,19 @@ public class CuasRanging {
System.out.println("rangeTargets()): disparity_map==null on nrefine="+nrefine);
break;
}
/*
double disp_diff = disparity_map[ImageDtt.DISPARITY_INDEX_POLY][ref_tile]; // null
double str = disparity_map[ImageDtt.DISPARITY_INDEX_POLY+1][ref_tile];
*/
double disp_diff = Double.NaN;
double str = 0;
if ((disparity_map[ImageDtt.DISPARITY_INDEX_POLY] == null) || (disparity_map[ImageDtt.DISPARITY_INDEX_POLY] == null)) {
System.out.println("rangeTargets()): disparity_map[ImageDtt.DISPARITY_INDEX_POLY]==null, nrefine="+nrefine);
} else {
disp_diff = disparity_map[ImageDtt.DISPARITY_INDEX_POLY][ref_tile]; // null
str = disparity_map[ImageDtt.DISPARITY_INDEX_POLY+1][ref_tile];
}
if (Double.isNaN(disp_diff)) {
if (use_non_lma) {
disp_diff = disparity_map[ImageDtt.DISPARITY_INDEX_CM][ref_tile];
......@@ -2699,6 +2711,9 @@ public class CuasRanging {
final double [][][] targets_single) {
int num_seq = targets_single.length;
UasLogReader uasLogReader = cuasMotion.getUasLogReader();
if (uasLogReader == null) {
return;
}
String [] slice_titles = cuasMotion.getSliceTitles(); // timestamps
int tilesX = cuasMotion.getTilesX();
int tilesY = targets_single[0].length / tilesX;
......@@ -2731,6 +2746,11 @@ public class CuasRanging {
// relies on calcMatchingTargetsLengths(.., true,...) called from recalcOmegas() to set [RSLT_GLOBAL]
public void saveTargetStats(
final double [][][] targets_single) {
UasLogReader uasLogReader = cuasMotion.getUasLogReader();
if (uasLogReader == null) {
System.out.println("saveTargetStats(): skipping target-vs-flight-log CSV, no UAS flight log provided");
return;
}
final int tilesX = cuasMotion.getTilesX();
final GeometryCorrection gc = center_CLT.getGeometryCorrection();
final int tileSize = GPUTileProcessor.DTT_SIZE;
......@@ -2767,7 +2787,6 @@ public class CuasRanging {
}
sb.append("\n"); // there will be 1 extra blank column
String [] slice_titles = cuasMotion.getSliceTitles(); // timestamps
UasLogReader uasLogReader = cuasMotion.getUasLogReader();
ErsCorrection ersCorrection = center_CLT.getErsCorrection();
for (int nseq = 0; nseq < num_seq; nseq++) {
String timestamp = slice_titles[nseq];
......
......@@ -7234,7 +7234,9 @@ java.lang.NullPointerException
// boolean test_vegetation = true;
if (master_CLT.hasCenterClt()) { // cuas mode
if (debugLevel >-3) {
System.out.println("===== Running CUAS ranging. =====");
}
CuasRanging cuasRanging = new CuasRanging (
clt_parameters, // CLTParameters clt_parameters,
master_CLT, // QuadCLT center_CLT,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment