Commit 869ec232 authored by Andrey Filippov's avatar Andrey Filippov

Implementing targets analysis

parent a4ec6dc5
package com.elphel.imagej.common;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import com.elphel.imagej.tileprocessor.QuadCLTCPU;
import ij.IJ;
import ij.ImagePlus;
import ij.ImageStack;
......@@ -1116,7 +1120,7 @@ G= Y +Pr*(- 2*Kr*(1-Kr))/Kg + Pb*(-2*Kb*(1-Kb))/Kg
System.out.println("readDoubleHyperstack(): reading "+path);
ImagePlus imp = new ImagePlus(path);
if (imp.getWidth() == 0) {
System.out.println("testSynthetic(): Failed reading Vector field from: " + path);
System.out.println("readDoubleHyperstack(): Failed reading [][][] from: " + path);
return null;
}
int num_slices = imp.getStackSize();
......@@ -1161,5 +1165,7 @@ G= Y +Pr*(- 2*Kr*(1-Kr))/Kg + Pb*(-2*Kb*(1-Kb))/Kg
}
return out_data;
}
}
}
\ No newline at end of file
......@@ -939,7 +939,8 @@ public class Eyesis_Correction implements PlugIn, ActionListener {
addJButton("Test LLT Cholesky", jpanelOrange, color_process);
addJButton("UAS log", jpanelOrange, color_process);
addJButton("DJI SRT", jpanelOrange, color_process);
addJButton("SRT to KML", jpanelOrange, color_process);
addJButton("SRT to KML", jpanelOrange, color_process);
addJButton("Target Analyze", jpanelOrange, color_process);
// addJButton("Motion_CUAS", jpanelOrange, color_stop);
// addJButton("Motion_scan", jpanelOrange, color_stop);
//
......@@ -6142,33 +6143,15 @@ public class Eyesis_Correction implements PlugIn, ActionListener {
}
}
testUasLog();
return;
} else if (label.equals("DJI SRT")) {
testDjiSrt();
} else if (label.equals("SRT to KML")) {
djiSrtToKml();
/*
} else if (label.equals("Motion_CUAS")) {
DEBUG_LEVEL = MASTER_DEBUG_LEVEL;
ImagePlus imp_sel = WindowManager.getCurrentImage();
if (imp_sel != null) {
motion_cuas(
imp_sel,
0); // int mode));
} else {
System.out.println("No image selected");
}
} else if (label.equals("Motion_scan")) {
DEBUG_LEVEL = MASTER_DEBUG_LEVEL;
ImagePlus imp_sel = WindowManager.getCurrentImage();
if (imp_sel != null) {
motion_cuas(
imp_sel,
1); // int mode));
} else {
System.out.println("No image selected");
}
*/
return;
} else if (label.equals("Target Analyze")) {
CuasMotion.targetsAnalyze();
return;
}
} finally {
MCP_COMMAND_CONTEXT = false;
......
......@@ -2,7 +2,6 @@ package com.elphel.imagej.cuas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.File;
import java.io.IOException;
......@@ -20,6 +19,7 @@ import java.net.URL;
import com.elphel.imagej.cameras.CLTParameters;
import com.elphel.imagej.common.DoubleGaussianBlur;
import com.elphel.imagej.common.GenericJTabbedDialog;
import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.gpu.GPUTileProcessor;
import com.elphel.imagej.gpu.GpuQuad;
......@@ -27,7 +27,6 @@ import com.elphel.imagej.gpu.TpTask;
import com.elphel.imagej.ims.UasLogReader;
import com.elphel.imagej.tileprocessor.Correlation2d;
import com.elphel.imagej.tileprocessor.ErsCorrection;
import com.elphel.imagej.tileprocessor.GeometryCorrection;
import com.elphel.imagej.tileprocessor.ImageDtt;
import com.elphel.imagej.tileprocessor.OpticalFlow;
import com.elphel.imagej.tileprocessor.QuadCLT;
......@@ -239,6 +238,7 @@ public class CuasMotion {
private final GPUTileProcessor gpuTileProcessor;
private CLTParameters clt_parameters=null;
private QuadCLT parentCLT = null;
private double [] noise_map = null;
private int debugLevel = 0;
private GpuQuad gpuQuad = null;
private ImageDtt image_dtt = null;
......@@ -255,6 +255,11 @@ public class CuasMotion {
private double [][][] targets = null;
private int start_frame = 0;
public double [] getNoiseMap () {
return noise_map;
}
public UasLogReader getUasLogReader() {
return uasLogReader;
}
......@@ -366,14 +371,20 @@ public class CuasMotion {
public int getTilesX() {
return tilesX;
}
public int getTilesY() {
return tilesY;
}
public CuasMotion (
CLTParameters clt_parameters,
String [] scene_titles,
QuadCLT parentCLT,
float [] fpixels_avg,
UasLogReader uasLogReader,
int debugLevel) {
// private double [] noise_map = null;
this.debugLevel = debugLevel;
this.clt_parameters = clt_parameters;
this.parentCLT = parentCLT;
......@@ -387,6 +398,7 @@ public class CuasMotion {
gpu_max_height = tilesY * GPUTileProcessor.DTT_SIZE;
corr_offset = clt_parameters.imp.cuas_corr_offset;
corr_pairs = clt_parameters.imp.cuas_corr_pairs;
double scale_window = clt_parameters.imp.cuas_scale_wnd = 2.0; //; When building noise map, scale search window range from original -8..+7 (2.0 -> -16..+15)
// int start_frame = 0;
int num_corr_samples = (scene_titles.length - getSeqLength() - start_frame) / getCorrInc();
......@@ -481,6 +493,9 @@ public class CuasMotion {
}
}
}
noise_map = getNoiseMap(
scale_window, // final double scale_window, // 1.0->8, 2.0 - 16.
fpixels_avg); // final float [] fpixels_avg)
return;
}
......@@ -555,6 +570,75 @@ public class CuasMotion {
return cloned;
}
public double [] getNoiseMap(
final double scale_window, // 1.0->8, 2.0 - 16.
final float [] fpixels_avg) {
final double [] noise_map = new double [tilesX*tilesY];
final int num_tiles = tilesX * tilesY; // 80 * 64 = 5120
// Find next power of 2 for bit reversal mapping
int max_power_of_two = 1;
int shift = 32;
while (max_power_of_two < num_tiles) {
max_power_of_two <<= 1;
shift--;
}
final int final_shift = shift;
final int limit_rtile = max_power_of_two;
final int tileSize = GPUTileProcessor.DTT_SIZE; // 8
final int width = tilesX * tileSize;
final int height = tilesY * tileSize;
final int scan_wnd = (int) (tileSize * scale_window);
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 nRtile = ai.getAndIncrement(); nRtile < limit_rtile; nRtile = ai.getAndIncrement()) {
// Bit reversal for cache-friendly access spread
int ntile = Integer.reverse(nRtile) >>> final_shift;
// Because max_power_of_two >= num_tiles, skip indices that map out of bounds
if (ntile >= num_tiles) {
continue;
}
int tileX = ntile % tilesX;
int tileY = ntile / tilesX;
// Define the 16x16 pixel window around tile centers at (4 + 8*tileX, 4 + 8*tileY)
// Scan from (center - 8) to (center + 7) inclusive
int px0 = Math.max(0, tileSize * tileX + tileSize / 2 - scan_wnd);
int px1 = Math.min(width, tileSize * tileX + tileSize / 2 + scan_wnd);
int py0 = Math.max(0, tileSize * tileY + tileSize / 2 - scan_wnd);
int py1 = Math.min(height, tileSize * tileY + tileSize / 2 + scan_wnd);
double min_val = Double.POSITIVE_INFINITY;
double max_val = Double.NEGATIVE_INFINITY;
// Scan the pixels in this window
for (int py = py0; py < py1; py++) {
int row_offset = py * width;
for (int px = px0; px < px1; px++) {
float val = fpixels_avg[row_offset + px];
if (val < min_val) min_val = val;
if (val > max_val) max_val = val;
}
}
noise_map[ntile] = max_val - min_val;
}
}
};
}
ImageDtt.startAndJoin(threads);
return noise_map;
}
public static int [] getRemain(
final double [][][] target_sequence,
int [] num_all_in,
......@@ -971,75 +1055,358 @@ public class CuasMotion {
}
return vf;
}
@Deprecated
public static double [][][] getTargetsFromHyper(String path){
int [] wh = new int [2];
public static void targetsAnalyze() { // not yet used
String [] modes = {"section","non-empty","non_NaN","==",">=","<="};
int mode = 0;
double par_val = 0.0;
int max_targets = 50;
GenericJTabbedDialog gd = new GenericJTabbedDialog("Set CLT parameters",1800,120);
String target_path = "/home/elphel/lwir16-proc/LV/models/models_1773135103-1773135664/1773135476_186641-CENTER/debug/v011-07/1773135476_186641-CENTER-OFFS5-PAIRS20-RSTR0.01-RMS5.0-SRMS0.4-RRMS0.35-AMP0.4-FZ50.0-PCRA4-PS2-TUM100-TT5.0-MF0.55-HR0.45-NL-0.3-FH1.5-FL0.8-FS5.0-CENT-FAST-ADDED_NEW_CENTERED_MULTI-n19.tiff";
gd.addStringField("Target path", target_path, 350, "Full target file path to analyze");
gd.showDialog();
if (gd.wasCanceled()) return;
target_path = gd.getNextString();
String [][] pvf_top_titles = new String[1][];
String [][] pvf_titles = new String[1][];
double [][][] targets_file = ShowDoubleFloatArrays.readDoubleHyperstack(
path, // String path,
wh, // int [] wh, // should be null or int[2]
pvf_top_titles, // String [][] ptop_titles, // should be null or String [1][]
pvf_titles); // String [][] pslice_titles){// should be null or String [1][]
if (targets_file == null) {
return null;
int [] err_num = new int [1];
int [] wh = new int[2];
double [][][][] multi_targets = readSingleMultiTargets( // slices should contain two ":"
target_path, // String path,
wh, // int [] wh, // should be null or int[2]
pvf_top_titles, // String [][] ptop_titles, // should be null or String [1][]
pvf_titles, // String [][] pslice_titles, // should be null or String [1][]
err_num); // int [] err_num)
if (multi_targets == null) {
System.out.println("targetsAnalyze() -> err="+err_num[0]);
return;
}
// int vect_len = INDX_SPEED; // vf_file.length;
int num_fields = targets_file.length;
int num_seq = targets_file[0].length;
int num_tiles = targets_file[0][0].length;
double [][][] vf = new double [num_seq][num_tiles][];
for (int nseq=0; nseq < num_seq; nseq++) {
for (int ntile = 0; ntile < num_tiles; ntile++) if (!Double.isNaN(targets_file[0][nseq][ntile])){
double [] v = new double[num_fields]; // cut to originally calculated fields
for (int i = 0; i < num_fields; i++) {
v[i] = targets_file[i][nseq][ntile];
boolean skip_empty = true;
int nseq0 = 0;
int nseq1 = multi_targets.length -1;
int tx = wh[0] / 2;
int ty = wh[1] / 2;
int num_pars = CuasMotionLMA.RSLT_LEN; // pvf_top_titles[0].length; // .RSLT_LEN;
int npar = CuasMotionLMA.RSLT_A;
int fw = 9;
String [] extra_choices = {"pX/pY"};
String [] choices = new String [num_pars+extra_choices.length];
for (int i = -extra_choices.length; i < 0; i++) {
choices[i + extra_choices.length] = String.format("%2d: %s", i, extra_choices[i+extra_choices.length]); // pvf_top_titles[0])
}
for (int i = 0; i < num_pars; i++) {
choices[i + extra_choices.length] = String.format("%2d: %s", i, CuasMotionLMA.LMA_TITLES[i]); // pvf_top_titles[0])
}
while (true) {
GenericJTabbedDialog gd1 = new GenericJTabbedDialog("Select Range",600,300);
gd1.addNumericField("tile X (0.."+(wh[0] -1)+")", tx, 0, 3, "",
"Select tile X");
gd1.addNumericField("tile Y (0.."+(wh[1] -1)+")", ty, 0, 3, "",
"Select tile Y");
gd1.addNumericField("Start sequence (0.."+(multi_targets.length -1)+")", nseq0, 0, 3, "",
"Select first scene to output");
gd1.addNumericField("End sequence (0.."+(multi_targets.length -1)+")", nseq1, 0, 3, "",
"Select last scene to output");
gd1.addChoice("Parameter", choices, choices[npar + extra_choices.length], "Parameter to display");
gd1.addNumericField("Format data width", fw, 0, 3, "",
"Parameter index to display");
gd1.addCheckbox("Skip empty", skip_empty, "Do not show tiles with no targets");
gd1.addChoice("Report mode", modes, modes[mode], "Select one of the report modes.");
gd1.addNumericField("Parameter value", par_val, 4, 10, "",
"Parameter value to compare");
gd1.addNumericField("Number of tiles to show", max_targets, 0, 3, "",
"Maximal number of tiles to show");
gd1.showDialog();
if (gd1.wasCanceled()) return;
final int tileSize = GPUTileProcessor.DTT_SIZE; // 8
tx = (int) gd1.getNextNumber();
ty = (int) gd1.getNextNumber();
nseq0 = (int) gd1.getNextNumber();
nseq1 = (int) gd1.getNextNumber();
npar = gd1.getNextChoiceIndex() - extra_choices.length;
fw = (int) gd1.getNextNumber();
skip_empty = gd1.getNextBoolean();
mode = gd1.getNextChoiceIndex();
par_val = gd1.getNextNumber();
max_targets = (int) gd1.getNextNumber();
tx = Math.max(Math.min(tx, wh[0] -1), 0);
ty = Math.max(Math.min(ty, wh[1] -1), 0);
nseq0 = Math.max(Math.min(nseq0, multi_targets.length -1), 0);
nseq1 = Math.max(Math.min(nseq1, multi_targets.length -1), nseq0);
npar = Math.max(Math.min(npar, num_pars -1), -extra_choices.length);
System.out.println("\nDisplaying scenes from "+nseq0+" to "+nseq1+", parameter: "+choices[npar+extra_choices.length]); // CuasMotionLMA.LMA_TITLES
System.out.println("tx="+tx+", ty="+ty);
int ntile = tx + ty * wh[0];
for (int nseq = nseq0; nseq <= nseq1; nseq++) {
boolean has_targets = (multi_targets[nseq] != null) && (multi_targets[nseq][ntile] != null) && (multi_targets[nseq][ntile].length > 0);
if (has_targets || !skip_empty) {
System.out.print(String.format("%17s, %4d, ",pvf_titles[0][nseq],nseq));
if (has_targets) {
int num_targ = multi_targets[nseq][ntile].length;
for (int ntarg = 0; ntarg < num_targ; ntarg++) {
if (npar == -1) {
double px = tileSize + tx + tileSize/2 + multi_targets[nseq][ntile][ntarg][CuasMotionLMA.RSLT_X];
double py = tileSize + ty + tileSize/2 + multi_targets[nseq][ntile][ntarg][CuasMotionLMA.RSLT_Y];
System.out.print(String.format("(%8.3f, %8.3f)",px,py));
} else {
System.out.print(String.format("%"+fw+"f",multi_targets[nseq][ntile][ntarg][npar]));
}
if (ntarg < (num_targ-1)) {
System.out.print(", ");
}
}
}
System.out.println();
}
vf[nseq][ntile] = v;
}
System.out.println();
}
return vf;
}
public static double [][][] getTargetsFromHyperAugment_old(
String path){ // add empty fields to the end of each target if shorter than CuasMotionLMA.RSLT_LEN
int [] wh = new int [2];
String [][] pvf_top_titles = new String[1][];
String [][] pvf_titles = new String[1][];
double [][][] targets_file = ShowDoubleFloatArrays.readDoubleHyperstack(
path, // String path,
wh, // int [] wh, // should be null or int[2]
pvf_top_titles, // String [][] ptop_titles, // should be null or String [1][]
pvf_titles); // String [][] pslice_titles){// should be null or String [1][]
if (targets_file == null) {
public static double [][][][] readSingleMultiTargets(
String path,
int [] wh, // should be null or int[2]
String [][] ptop_titles, // should be null or String [1][]
String [][] pslice_titles, // should be null or String [1][]
int [] err_num){
if (err_num == null) {
err_num = new int [1];
}
double [][][][] multi_targets = readDoubleHyperHyperstack( // slices should contain two ":"
path, // String path,
wh, // int [] wh, // should be null or int[2]
ptop_titles, // String [][] ptop_titles, // should be null or String [1][]
pslice_titles, // String [][] pslice_titles, // should be null or String [1][]
err_num); // int [] err_num)
if (multi_targets == null) {
System.out.println("readDoubleHyperHyperstack() -> err="+err_num[0]);
if ((err_num[0] == 2) || (err_num[0] == 3)) {
System.out.println("readDoubleHyperHyperstack(): trying to read a single-target array");
double [][][] targets = CuasMotion.getTargetsFromHyperAugment(
ptop_titles, // String [][] pvf_top_titles,
pslice_titles, // String [][] pvf_titles,
path);
if (targets != null) { // convert to multi-target
multi_targets = convertToMultiTarget(targets); // final double [][][] target_sequence) {
err_num[0] = -1; // got a single-target, converted to multi
}
}
}
return multi_targets;
}
public static double [][][][] readDoubleHyperHyperstack( // slices should contain two ":"
String path,
int [] wh, // should be null or int[2]
String [][] ptop_titles, // should be null or String [1][]
String [][] pslice_titles, // should be null or String [1][]
int [] err_num_ext){
final int [] err_num = (err_num_ext != null) ? err_num_ext : (new int[1]);
// will ignore last parameter "Targets" all above CuasMotionLMA.RSLT_LEN
// X-OFFS:1773135470_584775-74:6 : <target-parameter-name>:<file_name>-<file-index>:target_index
System.out.println("readDoubleHyperHyperstack(): reading "+path);
ImagePlus imp = new ImagePlus(path);
if (imp.getWidth() == 0) {
System.out.println("readDoubleHyperHyperstack(): Failed reading hyperstack data from: " + path);
err_num[0] = 1;
return null;
}
int num_fields = targets_file.length;
// fix - discarding last slice if it is called CuasMotionLMA.EXTRA_SLICE_DISCARD_ON_LOAD ("Targets")
if (pvf_top_titles[0][pvf_top_titles[0].length-1].equals(CuasMotionLMA.EXTRA_SLICE_DISCARD_ON_LOAD)) {
System.out.println("getTargetsFromHyperAugment(): removing last slice called "+ pvf_top_titles[0][pvf_top_titles[0].length-1]);
num_fields--;
if (wh!= null) {
wh[0] = imp.getWidth();
wh[1] = imp.getHeight();
}
int num_fields_augmented = Math.max(num_fields, CuasMotionLMA.RSLT_LEN);
int num_seq = targets_file[0].length;
int num_tiles = targets_file[0][0].length;
double [][][] target_sequence = new double [num_seq][num_tiles][];
for (int nseq=0; nseq < num_seq; nseq++) {
for (int ntile = 0; ntile < num_tiles; ntile++) if (!Double.isNaN(targets_file[0][nseq][ntile])){
double [] v = new double[num_fields_augmented]; // cut to originally calculated fields
for (int i = 0; i < num_fields; i++) {
v[i] = targets_file[i][nseq][ntile];
int num_slices = imp.getStackSize();
String [] slice_labels = imp.getStack().getSliceLabels();
ArrayList<String> top_titles = new ArrayList<String>(); // parameter names
final HashMap<Integer,String> ts_map = new HashMap<Integer,String>(); // to notice missing timestamps (no targets at all
final HashMap<Integer,Integer> offsets_map = new HashMap<Integer,Integer>(); // to notice missing timestamps (no targets at all
int last_index = 0;
for (int i = 0; i < num_slices; i++) {
String [] label = slice_labels[i].split(":");
if (label.length < 3) {
System.out.println("readDoubleHyperHyperstack(): Slices should have two ':' separators in : " + path);
err_num[0] = 2;
return null;
}
if (!top_titles.contains(label[0])) { // target parameter name
top_titles.add(label[0]);
}
String [] ts_indx = label[1].split("-");
if (label.length<2) {
System.out.println("readDoubleHyperHyperstack(): Slices should have '-' between the two ':' separators in : " + path);
err_num[0] = 3; // it may be [][][], not [][][][] array
return null;
}
int indx = Integer.parseInt(ts_indx[1]);
if (ts_map.get(indx) == null) {
ts_map.put(indx, ts_indx[0]);
offsets_map.put(indx, i);
last_index = Math.max(last_index, indx);
}
}
String [] top_l = top_titles.toArray(new String[0]);
int num_indices = num_slices/top_l.length; // number of slices per parameters
final int num_pars = Math.min(top_l.length, CuasMotionLMA.RSLT_LEN); // but preserve num_indices!
final int [] indices = new int [last_index+1];
Arrays.fill(indices, -1);
for (int indx = 0; indx < indices.length; indx++) {
Integer offs = offsets_map.get(indx);
if (offs != null) {
indices[indx] = offs;
}
}
double [][] file_data = ShowDoubleFloatArrays.readDoubleArray(
imp, // ImagePlus imp,
0, // int num_slices, // (0 - all)
wh); // int [] wh); // int [] wh)
int num_tiles = wh[0]*wh[1];
double [][][][] targets = new double [indices.length][num_tiles][][];
String [] scenes = new String [indices.length];
for (int nseq = 0; nseq < indices.length; nseq++) {
scenes[nseq] = ts_map.get(nseq);
}
int num_empty=0;
for (int nseq = 0; nseq < indices.length; nseq++) if (scenes[nseq] == null){
num_empty++;
if (nseq == 0) {
int nseq1 = nseq+1;
for (; (nseq1 < indices.length) && (scenes[nseq1] == null) ; nseq1++);
if (nseq1 >= indices.length) {
err_num[0] = 4;
return null;
}
for (int i = num_fields; i < num_fields_augmented; i++) {
v[i] = Double.NaN;
int nseq2 = indices.length-1;
for (; (nseq2 > nseq1) && (scenes[nseq2] == null) ; nseq2--);
if (nseq1 >= indices.length) {
err_num[0] = 5;
return null;
}
target_sequence[nseq][ntile] = v;
scenes[nseq]= missingTimestamp(
nseq, // int indx, // may be outside of the range
nseq1, // int indx0,
scenes[nseq1], // String ts0,
nseq2, // int indx1,
scenes[nseq2]); // String ts1)
} else { // nseq>0, all previous are defined
int nseq1 = nseq-1; // always defined already
int nseq2 = nseq+1;
for (; (nseq2 < indices.length) && (scenes[nseq2] == null) ; nseq2++);
if (nseq2 >= indices.length) { // nothing later defined - should not happen as the last index comes from existing.
System.out.println("readDoubleHyperHyperstack(): No timestamp after index " + nseq+ "(last is "+
(indices.length-1)+"). Should not happen!");
err_num[0] = 6; // should never happen
return null;
}
scenes[nseq]= missingTimestamp(
nseq, // int indx, // may be outside of the range
nseq1, // int indx0,
scenes[nseq1], // String ts0,
nseq2, // int indx1,
scenes[nseq2]); // String ts1)
}
}
return target_sequence;
if (num_empty > 0) {
System.out.println("readDoubleHyperHyperstack(): replaced "+ num_empty+" empty scene numes");
}
IJ.showStatus("Extracting multi-target data...");
IJ.showProgress(0.0);
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 nSeq = ai.getAndIncrement(); nSeq < indices.length; nSeq = ai.getAndIncrement())if (ts_map.get(nSeq) != null) { // if null - keep all tiles null
IJ.showProgress(1.0*(nSeq+1) / indices.length);
int indx0 = indices[nSeq];
if (indx0 < 0) {
System.out.println("readDoubleHyperHyperstack(): indices[" + nSeq+ "] < 0, should not happen as ts_map.get(nseq) != null");
err_num[0] = 7; // should never happen
continue;
}
int nseq1 = nSeq+1;
for (; (nseq1 < indices.length) && (indices[nseq1] < 0 ) ; nseq1++);
int indx1 = (nseq1 < indices.length) ? indices[nseq1] : num_indices; // file_data.length;
// indx0, indx1 are common for all tiles
if (nSeq == (indices.length-1)) {
System.out.println("readDoubleHyperHyperstack(): nseq=" + nSeq);
}
for (int ntile = 0; ntile < num_tiles; ntile++) {
int last_target = -1; // for this tile
boolean [] target_exists = new boolean [indx1-indx0]; // allowing missing targets (should not happen)
for (int ntarg = 0; ntarg < target_exists.length; ntarg++) {
int indx = indx0+ntarg;
for (int npar = 0; npar < num_pars; npar++) {
int nslice = npar * num_indices + indx;
if (!Double.isNaN(file_data[nslice][ntile])) {
target_exists[ntarg]=true;
last_target = ntarg;
break;
}
}
}
// truncate by the last non-null, if any exist (if none - keep null)
// find maximal number of target in this tile that has at least one non-null parameter
if (last_target >= 0) {
targets[nSeq][ntile] = new double [last_target+1][];
for (int ntarg = 0; ntarg <= last_target; ntarg++) {
if (target_exists[ntarg]) {
int indx = indx0+ntarg;
targets[nSeq][ntile][ntarg] = new double [num_pars];
for (int npar = 0; npar < num_pars; npar++) {
int nslice = npar * num_indices + indx;
targets[nSeq][ntile][ntarg][npar] = file_data[nslice][ntile];
}
}
}
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
IJ.showProgress(1.0);
if (ptop_titles != null) {
ptop_titles[0] = top_l;
}
if (pslice_titles != null) {
pslice_titles[0] = scenes;
}
return targets;
}
public static String missingTimestamp(
int indx, // may be outside of the range
int indx0,
String ts0,
int indx1,
String ts1) {
double dts0=Double.parseDouble(ts0.replace("_", "."));
double dts1=Double.parseDouble(ts1.replace("_", "."));
double dts = dts0+ (indx-indx0) * ((dts1-dts0)/(indx1-indx0));
int sec = (int) dts0;
int usec = (int) Math.round(1000000*(dts-sec));
String ts = String.format("%d_%06d", sec, usec);
return ts;
}
public static double [][][] getTargetsFromHyperAugment(
String path) {
return getTargetsFromHyperAugment(
......@@ -1393,6 +1760,7 @@ public class CuasMotion {
float [][] fpixels, // may be running average
int start_frame,
int corr_pairs,
double boost_pairs,
int corr_offset,
int corr_inc,
int corr_ra_step, // 5; // correlation step when using rolling average
......@@ -1406,6 +1774,10 @@ public class CuasMotion {
String title,
double [][][] corr2d, // null or [(fpixels.length - seq_length - start_frame) / corr_step)[][]
int debugLevel){
// int scale_pairs = 1; // temporarily for testing
// if ((slow_scale_samples >= 1) && (slow_scale_offset <= 1)) {
// scale_pairs = 4;
// }
int seq_length = corr_offset + corr_pairs;
int num_scenes = fpixels.length;
int num_corr_samples = (num_scenes - seq_length - start_frame) / corr_inc;
......@@ -1415,12 +1787,15 @@ public class CuasMotion {
IJ.showProgress(0.0);
for (int nscan = 0; nscan < targets.length; nscan++) {
int frame0 = start_frame + corr_inc * nscan;
int corr_pairs_scaled = (int) Math.round(corr_pairs*boost_pairs);
if (boost_pairs > 1) {
frame0 -= (int) Math.round((corr_pairs * (boost_pairs - 1))/ 2);
}
int frame1 = frame0 + corr_offset;
// int frame_cent = frame0 + seq_length/2; // debug only
int frame_cent = frame0 + corr_offset/2; // debug only
String suffix_param = "-"+frame_cent+"-"+corr_offset+"-"+corr_pairs;
String dbg_suffix = (title != null) ? (title+suffix_param) : null;
int corr_pairs_scaled = corr_pairs;
if ((slow_scale_samples > 1) || (slow_scale_offset > 1)) {
int frame_cent2 = 2 * frame0 + corr_offset;
int scan_center2 = frame_cent2 + corr_pairs; // twice index of scan center
......@@ -1430,6 +1805,7 @@ public class CuasMotion {
frame0 = (frame_cent2_scaled - corr_offset * slow_scale_offset)/2;
frame1 = frame0 + corr_offset * slow_scale_offset;
frame_cent = (frame0 + frame1)/2; // debug only
}
if (debugLevel > -4) {
System.out.print(frame0+":"+frame1+"-"+corr_pairs_scaled+" ");
......@@ -1513,8 +1889,8 @@ public class CuasMotion {
public TDCorrTile [] correlatePairs(
CLTParameters clt_parameters,
float [][] fpixels,
int frame0,
int frame1,
int frame0, // OK if <0
int frame1, // OK if >= fpixels.length
int frame_len,
int corr_ra_step,
boolean smooth, // use cosine mask
......@@ -1842,17 +2218,20 @@ public class CuasMotion {
final int frame0, // for vector_field[0]
final int frame_step,
final int half_range, // scale for slow
final double boost_pairs,
final boolean smooth,
final int corr_offset, // interframe distance for correlation
final boolean batch_mode) {
float [][] frames_accum = new float [target_sequence.length][];
final double [] window_full = new double [2*half_range+1];
final int half_range_boosted = (int) (half_range * boost_pairs);
final double [] window_full = new double [2 * half_range_boosted+1];
double s0 = 1.0;
window_full[half_range] = 1.0;
double k = Math.PI/2/(half_range +0.5);
for (int i = 1; i <= half_range; i ++) {
window_full[half_range+i] = smooth ? (Math.cos(i*k)):1.0;
s0+=2 * window_full[half_range+i];
window_full[half_range_boosted] = 1.0;
double k = Math.PI/2/(half_range_boosted + 0.5);
for (int i = 1; i <= half_range_boosted; i ++) {
window_full[half_range_boosted + i] = smooth ? (Math.cos(i*k)):1.0;
s0+=2 * window_full[half_range_boosted + i];
}
for (int i = 0; i < window_full.length; i ++) {
window_full[i] /= s0;
......@@ -1860,13 +2239,27 @@ public class CuasMotion {
// final int erase = 1; //NaN
for (int nseq = 0; nseq < target_sequence.length; nseq++) {
/*
// from getTargetsFromCorr2d()
int corr_pairs_scaled = (int) Math.round(corr_pairs*boost_pairs);
if (boost_pairs > 1) {
frame0 -= (int) Math.round((corr_pairs * (boost_pairs - 1))/ 2);
}
int frame1 = frame0 + corr_offset;
// int frame_cent = frame0 + seq_length/2; // debug only
int frame_cent = frame0 + corr_offset/2; // debug only
String suffix_param = "-"+frame_cent+"-"+corr_offset+"-"+corr_pairs;
String dbg_suffix = (title != null) ? (title+suffix_param) : null;
*/
int frame_center = frame0 + nseq * frame_step;
boolean fits = (frame_center >= half_range) && (frame_center < (fpixels.length-half_range));
boolean fits = (frame_center >= half_range_boosted) && (frame_center < (fpixels.length - half_range_boosted));
double [] window = fits? window_full: window_full.clone();
if (!fits) {
s0=0;
for (int i = 0; i < window.length; i++) {
int i1 = frame_center - half_range + i;
int i1 = frame_center - half_range_boosted + i;
if ((i1 >= 0) && (i1 < fpixels.length)) {
s0+= window[i];
}
......@@ -1876,8 +2269,8 @@ public class CuasMotion {
}
}
boolean first = true;
for (int dframe = -half_range; dframe < half_range; dframe++) {
double magnitude_scale = window [dframe + half_range];
for (int dframe = -half_range_boosted; dframe < half_range_boosted; dframe++) {
double magnitude_scale = window [dframe + half_range_boosted];
if (magnitude_scale > 0) { // to make sure <=0 did not get there accidentally
int frame = frame_center + dframe;
if ((frame >= 0) && (frame < fpixels.length) ) {
......@@ -4439,10 +4832,11 @@ public class CuasMotion {
center_targ, // false, // final boolean center,
true, // final boolean fill_zeros,
fpixels, // final float [][] fpixels,
extended_targets, // final double [][][] vector_field,
extended_targets, // final double [][][] vector_field,
frame0, // final int frame0, // for vector_field[0]
corr_inc, // final int frame_step,
half_accum_range, // final int half_range,
1.0, // final double boost_pairs,
smooth, // final boolean smooth,
corr_offset, // final int corr_offset, // interframe distance for correlation
true); // final boolean batch_mode) {
......@@ -6447,6 +6841,10 @@ public class CuasMotion {
final int debugLevel) {
int corr_offset = clt_parameters.imp.cuas_corr_offset; // 5 (20)
int corr_pairs = clt_parameters.imp.cuas_corr_pairs; // 20 (50)
double boost_pairs = slow_mode? 1.0: clt_parameters.imp.cuas_boost_slow; // 4.0; // if >1 and the motion vector is below tile_size/cuas_boost_slow, scale corr_pairs
double boost_mstr = clt_parameters.imp.cuas_boost_mstr; // 0.007; // scale corr_pairs if motion strength is below
// int precorr_ra = clt_parameters.imp.cuas_precorr_ra; // 4 (10)
int corr_ra_step = clt_parameters.imp.cuas_corr_step; // 2 ( 2)
double fat_zero = clt_parameters.imp.cuas_fat_zero;
......@@ -6531,6 +6929,7 @@ public class CuasMotion {
}
}
double [][][] corr2d = corr2d_save_show? new double [num_corr_samples][][] : null;
double [][][] corr2d_boosted = (corr2d_save_show && (boost_pairs > 1.0))? new double [num_corr_samples][][] : null;
double [][][] target_sequence = getTargetsFromCorr2d(
clt_parameters, // CLTParameters clt_parameters,
......@@ -6539,12 +6938,12 @@ public class CuasMotion {
fpixels_ra, // float [][] fpixels,
start_frame, // int start_frame,
corr_pairs, // int corr_pairs,
1.0, // double boost_pairs, // no boost
corr_offset, // int corr_offset,
corr_inc, // int corr_inc,
corr_ra_step, // int corr_ra_step, // 5; // correlation step when using rolling average
slow_scale_samples, // int slow_scale_samples, // multiply number of samples
slow_scale_offset, // int slow_scale_offset, // multiply offset
smooth, // boolean smooth,
fat_zero, // double fat_zero,
cent_radius, // double cent_radius,
......@@ -6553,6 +6952,75 @@ public class CuasMotion {
model_prefix, // String title,
corr2d, // double [][][] corr2d, // null or [(fpixels.length - seq_length - start_frame) / corr_inc)[][]
debugLevel); // int debugLevel) {
double [][][] target_sequence_boost = null;
// TODO: only boost tiles if they are week or slow, replace in-place
if (boost_pairs > 1.0) {
target_sequence_boost = getTargetsFromCorr2d(
clt_parameters, // CLTParameters clt_parameters,
batch_mode, // false, // boolean batch_mode,
cuasMotion, // CuasMotion cuasMotion,
fpixels_ra, // float [][] fpixels,
start_frame, // int start_frame,
corr_pairs, // int corr_pairs,
boost_pairs, // double boost_pairs, // no boost
corr_offset, // int corr_offset,
corr_inc, // int corr_inc,
corr_ra_step, // int corr_ra_step, // 5; // correlation step when using rolling average
slow_scale_samples, // int slow_scale_samples, // multiply number of samples
slow_scale_offset, // int slow_scale_offset, // multiply offset
smooth, // boolean smooth,
fat_zero, // double fat_zero,
cent_radius, // double cent_radius,
n_recenter, // int n_recenter,
-rstr, // double rstr,
model_prefix, // String title,
corr2d_boosted, // double [][][] corr2d, // null or [(fpixels.length - seq_length - start_frame) / corr_inc)[][]
debugLevel); // int debugLevel) {
if (intermed_low ) {
ImagePlus imp_initial = showTargetSequence(
target_sequence, // double [][][] vector_fields_sequence,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
model_prefix+"-INITIAL-MOTION-FAST",// String title,
!batch_mode, // boolean show,
cuasMotion.tilesX); // int tilesX) {
parentCLT.saveImagePlusInModelDirectory(imp_initial);
ImagePlus imp_initial_boosted = showTargetSequence(
target_sequence_boost, // double [][][] vector_fields_sequence,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
model_prefix+"-INITIAL-MOTION-BOOSTED",// String title,
!batch_mode, // boolean show,
cuasMotion.tilesX); // int tilesX) {
parentCLT.saveImagePlusInModelDirectory(imp_initial_boosted);
}
// combine motions
combineSlowBoosted(
target_sequence, // final double [][][] target_sequence,
target_sequence_boost, // final double [][][] target_boosted,
boost_pairs, // final double boost_slow, // 4.0;
boost_mstr, // final double boost_mstr,
debugLevel); // final int debugLevel)
if (corr2d_save_show) { // may be read to re-process with vector field
int corr_size = 2 * GPUTileProcessor.DTT_SIZE -1;
double [][] dbg_2d_corrs_boosted = ImageDtt.corr_partial_dbg( // not used in lwir
corr2d_boosted, // final double [][][] corr_data, // [layer][tile][(2*transform_size-1)*(2*transform_size-1)] // if null - will not calculate
cuasMotion.tilesX, // final int tilesX,
corr_size, //final int corr_size, // 15
clt_parameters.corr_border_contrast, // final double border_contrast,
debugLevel); // final int globalDebugLevel)
ImagePlus imp_corr2d = ShowDoubleFloatArrays.makeArrays(
dbg_2d_corrs_boosted, // double[][] pixels,
cuasMotion.tilesX * (corr_size + 1),
cuasMotion.tilesY * (corr_size + 1),
model_prefix+"-CORR2D-BOOSTED", // -OFFS"+corr_offset+"-PAIRS"+corr_pairs, // String title,
slice_titles);
if (!batch_mode) {
imp_corr2d.show();
}
parentCLT.saveImagePlusInModelDirectory(imp_corr2d); // ImagePlus imp)
}
}
setBadHorizon(
target_sequence, // final double [][][] target_sequence,
......@@ -6569,7 +7037,6 @@ public class CuasMotion {
cuasMotion.tilesX); // int tilesX) {
parentCLT.saveImagePlusInModelDirectory(imp_initial);
}
if (corr2d_save_show) { // may be read to re-process with vector field
int corr_size = 2 * GPUTileProcessor.DTT_SIZE -1;
......@@ -6613,6 +7080,73 @@ public class CuasMotion {
return target_sequence;
}
/**
* Combine motion vectors for fast targets calculated for the specified number of correlation pairs
* and "slow-boosted" - motion vectors calculated for scaled (>1) number of correlation pairs.
* TODO: boost on tile basis, only calculate boosted if tile matches offset and/or strength
* @param target_sequence target sequence with only motion vectors defined for specified number of correlation pairs
* @param target_boosted same for increased number of correlation
* @param boost_slow use boosted if motion vector is smaller than this
* @param boost_mstr use boosted if motion vector strength is smaller than this
* @param debugLevel debug level
*/
public static void combineSlowBoosted(
final double [][][] target_sequence,
final double [][][] target_boosted,
final double boost_slow, // 4.0;
final double boost_mstr,
final int debugLevel) {
if (boost_slow >1) {
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
final double max_v = 0.9 * GPUTileProcessor.DTT_SIZE / boost_slow;
final double max_v2 = max_v * max_v;
if (debugLevel > -4) {
System.out.println("combineSlowBoosted(): boost_slow="+boost_slow+", boost_mstr="+boost_mstr+", max_v2="+max_v2);
}
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nSeq = ai.getAndIncrement(); nSeq < target_sequence.length; nSeq = ai.getAndIncrement()){
double [][] target = target_sequence[nSeq];
double [][] target_b = target_boosted[nSeq];
if ((target != null) && (target_b != null)) {
for (int ntile=0; ntile < target.length; ntile++) if (target_b[ntile] != null) {
if (target[ntile] == null) {
target[ntile] = target_b[ntile];
} else {
boolean replace = false;
if (!(target[ntile][CuasMotionLMA.RSLT_VSTR] >= boost_mstr)) {
replace = true;
} else {
double vx = target[ntile][CuasMotionLMA.RSLT_VX];
double vy = target[ntile][CuasMotionLMA.RSLT_VY];
double vv = vx*vx+vy*vy;
if (!(vv > max_v2)) {
replace = true;
}
}
if (replace) {
target[ntile][CuasMotionLMA.RSLT_VX] = target_b[ntile][CuasMotionLMA.RSLT_VX];
target[ntile][CuasMotionLMA.RSLT_VY] = target_b[ntile][CuasMotionLMA.RSLT_VY];
target[ntile][CuasMotionLMA.RSLT_VSTR] = target_b[ntile][CuasMotionLMA.RSLT_VSTR];
target[ntile][CuasMotionLMA.RSLT_VFRAC] = target_b[ntile][CuasMotionLMA.RSLT_VFRAC];
}
}
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
}
return;
}
public double [][][][] locateAndFreezeTargetsMulti(
final boolean batch_mode,
float [][] fpixels_tum,
......@@ -6702,6 +7236,7 @@ public class CuasMotion {
double slow_fast_mismatch = clt_parameters.imp.cuas_slow_fast_mismatch; // 1.5; allow larger mismatch between slow and fast
boolean fail_mismatch = clt_parameters. imp.cuas_fail_mismatch; // Fail on high mismatch early (when calculating scores);
double offcenter = clt_parameters. imp.cuas_offcenter;
double noisemax = clt_parameters. imp.cuas_noisemax;
double target_horizon= clt_parameters.imp.cuas_horizon;
// Handling overall target scores
......@@ -6751,6 +7286,8 @@ public class CuasMotion {
final double [][][][] target_sequence_multi = new double [num_seq][num_tiles][][];
int niter=0;
// first pass, using non-centered targets
double boost_accum_pairs = slow_mode? 1.0:4.0; // just for testing, unconditionally boost tracking cameras exposure time
for (; niter < num_cycles; niter++) {
boolean save_filtered_low = intermed_low && (niter < iter_show);
boolean save_filtered_high = intermed_high && (niter < iter_show);
......@@ -6888,15 +7425,20 @@ public class CuasMotion {
frame0, // final int frame0, // for vector_field[0]
corr_inc, // final int frame_step,
half_accum_range, // final int half_range,
boost_accum_pairs,// final double boost_pairs,
smooth, // final boolean smooth,
corr_offset, // final int corr_offset, // interframe distance for correlation
true); // final boolean batch_mode) {
if (save_filtered_high) {
String title = model_prefix+"-ACCUMULATED-n"+niter;
if (boost_accum_pairs > 1.0) {
title+="-BOOST"+boost_accum_pairs;
}
ImagePlus imp_acc = ShowDoubleFloatArrays.makeArrays(
fpixels_accumulated, // double[][] pixels,
cuasMotion.gpu_max_width,
cuasMotion.gpu_max_height,
model_prefix+"-ACCUMULATED-n"+niter, // String title,
title, // model_prefix+"-ACCUMULATED-n"+niter, // String title,
slice_titles);
imp_acc.getProcessor().setMinAndMax(-input_range/2, input_range/2);
if (!batch_mode) {
......@@ -6965,11 +7507,15 @@ public class CuasMotion {
debugLevel); // final int debugLevel);
if (accum_debug != null) {
String title = model_prefix+"-ACCUMULATED_FILTERED-MULTI-n"+niter;
if (boost_accum_pairs > 1.0) {
title+="-BOOST"+boost_accum_pairs;
}
ImagePlus imp_acc = ShowDoubleFloatArrays.makeArrays(
accum_debug, // double[][] pixels,
cuasMotion.gpu_max_width,
cuasMotion.gpu_max_height,
model_prefix+"-ACCUMULATED_FILTERED-MULTI-n"+niter, // String title,
title, // model_prefix+"-ACCUMULATED_FILTERED-MULTI-n"+niter, // String title,
slice_titles);
imp_acc.getProcessor().setMinAndMax(-input_range/2, input_range/2);
if (!batch_mode) {
......@@ -6979,10 +7525,14 @@ public class CuasMotion {
}
if (save_filtered_low && debug_more) {
String title = model_prefix+"-NEW-TARGETS-MULTI-n"+niter;
if (boost_accum_pairs > 1.0) {
title+="-BOOST"+boost_accum_pairs;
}
ImagePlus imp_new = showTargetSequence(
targets_new_multi, // final double [][][][] targets_multi,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
model_prefix+"-NEW-TARGETS-MULTI-n"+niter,// String title,
title, // model_prefix+"-NEW-TARGETS-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,
......@@ -7008,6 +7558,8 @@ public class CuasMotion {
slow_fast_mismatch,// final double slow_fast_mismatch, // // 1.5; allow larger mismatch between slow and fast
fail_mismatch, // final boolean fail_mismatch,
offcenter, // final double offcenter,
cuasMotion.getNoiseMap(), // final double [] noise_map,
noisemax, // final double noise_max,
target_horizon, // final double lma_horizon, // horizon as maximal pixel Y
cuasMotion.tilesX); // final int tilesX,
getScore(
......@@ -7019,10 +7571,14 @@ public class CuasMotion {
cuasMotion.tilesX); // final int tilesX,
if (save_filtered_low) {
String title = model_prefix+"-NEW-TARGETS_SCORES_MULTI-n"+niter;
if (boost_accum_pairs > 1.0) {
title+="-BOOST"+boost_accum_pairs;
}
ImagePlus imp_new_scores = showTargetSequence(
targets_new_multi, // double [][][] vector_fields_sequence,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
model_prefix+"-NEW-TARGETS_SCORES_MULTI-n"+niter,// String title,
title, // model_prefix+"-NEW-TARGETS_SCORES_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,
......@@ -7041,10 +7597,14 @@ public class CuasMotion {
System.out.println("Added "+num_new+" new tiles as good/bad");
}
if (save_filtered_low) {
String title = model_prefix+"-ADDED_NEW_MULTI-n"+niter;
if (boost_accum_pairs > 1.0) {
title+="-BOOST"+boost_accum_pairs;
}
ImagePlus imp_new_scores = showTargetSequence(
target_sequence_multi, // double [][][] vector_fields_sequence,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
model_prefix+"-ADDED_NEW_MULTI-n"+niter,// String title,
title, // model_prefix+"-ADDED_NEW_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,
......@@ -7202,15 +7762,20 @@ public class CuasMotion {
frame0, // final int frame0, // for vector_field[0]
corr_inc, // final int frame_step, // keep for slow
half_accum_range, // final int half_range, // scale for slow
boost_accum_pairs,// final double boost_pairs,
smooth, // final boolean smooth,
corr_offset, // final int corr_offset, // interframe distance for correlation
true); // final boolean batch_mode) {
if (save_filtered_high) {
String title = model_prefix+"-ACCUMULATED-CENTERED-n"+niter;
if (boost_accum_pairs > 1.0) {
title+="-BOOST"+boost_accum_pairs;
}
ImagePlus imp_acc = ShowDoubleFloatArrays.makeArrays(
fpixels_accumulated, // double[][] pixels,
cuasMotion.gpu_max_width,
cuasMotion.gpu_max_height,
model_prefix+"-ACCUMULATED-CENTERED-n"+niter, // String title,
title, // model_prefix+"-ACCUMULATED-CENTERED-n"+niter, // String title,
slice_titles);
imp_acc.getProcessor().setMinAndMax(-input_range/2, input_range/2);
if (!batch_mode) {
......@@ -7279,11 +7844,15 @@ public class CuasMotion {
debugLevel); // final int debugLevel);
if (accum_debug != null) {
String title = model_prefix+"-ACCUMULATED_FILTERED-CENTERED-MULTI-n"+niter;
if (boost_accum_pairs > 1.0) {
title+="-BOOST"+boost_accum_pairs;
}
ImagePlus imp_acc = ShowDoubleFloatArrays.makeArrays(
accum_debug, // double[][] pixels,
cuasMotion.gpu_max_width,
cuasMotion.gpu_max_height,
model_prefix+"-ACCUMULATED_FILTERED-CENTERED-MULTI-n"+niter, // String title,
title, // model_prefix+"-ACCUMULATED_FILTERED-CENTERED-MULTI-n"+niter, // String title,
slice_titles);
imp_acc.getProcessor().setMinAndMax(-input_range/2, input_range/2);
if (!batch_mode) {
......@@ -7301,10 +7870,15 @@ public class CuasMotion {
if (save_filtered_low && debug_more) {
String title = model_prefix+"-NEW-TARGETS-CENTERED-MULTI-n"+niter;
if (boost_accum_pairs > 1.0) {
title+="-BOOST"+boost_accum_pairs;
}
ImagePlus imp_new = showTargetSequence(
targets_new_multi, // final double [][][][] targets_multi,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
model_prefix+"-NEW-TARGETS-CENTERED-MULTI-n"+niter,// String title,
title, // model_prefix+"-NEW-TARGETS-CENTERED-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,
......@@ -7327,9 +7901,11 @@ public class CuasMotion {
lma_maxk, // final double lma_maxk, // = 5.0; // Minimal K (overshoot) = 3.0// final double lma_a2a,
lma_a2a, // final double lma_a2a,
0, // max_mismatch, // final double max_mismatch, apply only during final, when mismatch scores are calculated
slow_fast_mismatch, // final double slow_fast_mismatch, // // 1.5; allow larger mismatch between slow and fast
slow_fast_mismatch,// final double slow_fast_mismatch, // // 1.5; allow larger mismatch between slow and fast
fail_mismatch, // final boolean fail_mismatch,
offcenter, // final double offcenter,
cuasMotion.getNoiseMap(), // final double [] noise_map,
noisemax, // final double noise_max,
target_horizon, // final double lma_horizon, // horizon as maximal pixel Y
cuasMotion.tilesX); // final int tilesX,
int [] remain_es_centered = getScore(
......@@ -7341,10 +7917,15 @@ public class CuasMotion {
cuasMotion.tilesX); // final int tilesX,
if (save_filtered_low) {
String title = model_prefix+"-NEW-TARGETS_CENTERED_SCORES_MULTI-n"+niter;
if (boost_accum_pairs > 1.0) {
title+="-BOOST"+boost_accum_pairs;
}
ImagePlus imp_new_scores = showTargetSequence(
targets_new_multi, // double [][][] vector_fields_sequence,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
model_prefix+"-NEW-TARGETS_CENTERED_SCORES_MULTI-n"+niter,// String title,
title, // model_prefix+"-NEW-TARGETS_CENTERED_SCORES_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,
......@@ -7364,10 +7945,14 @@ public class CuasMotion {
System.out.println("Added "+num_new+" new tiles as good/bad at iteration "+niter+".");
}
if (save_filtered_low) {
String title = model_prefix+"-ADDED_NEW_CENTERED_MULTI-n"+niter;
if (boost_accum_pairs > 1.0) {
title+="-BOOST"+boost_accum_pairs;
}
ImagePlus imp_new_scores = showTargetSequence(
target_sequence_multi, // double [][][] vector_fields_sequence,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
model_prefix+"-ADDED_NEW_CENTERED_MULTI-n"+niter,// String title,
title, // model_prefix+"-ADDED_NEW_CENTERED_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,
......@@ -7723,6 +8308,8 @@ public class CuasMotion {
final double slow_fast_mismatch,
final boolean fail_mismatch,
final double offcenter,
final double [] noise_map,
final double noise_max,
final double lma_horizon, // horizon as maximal pixel Y
final int tilesX ) {
// if centroid maximum is safely good, ignore lma_a2a ratio
......@@ -7764,6 +8351,14 @@ public class CuasMotion {
double x = lma_rslts[CuasMotionLMA.RSLT_X];
double y = lma_rslts[CuasMotionLMA.RSLT_Y];
double cxy = 1.0;
/*
* Filtering by "far" (center belongs to the neighbor tile, not this one) worked well
* except very low above the skyline. In that case the tile below resulted in gross wrong motion vector
* and then the target correlation. The low targets are important, so it will make sense for an exception:
* allowing "far" there (recognizing by some values), including preselecting "border tiles", or moving target
* with its parameters, including motion vectors to that other tile. Will first just try easing "far" limitations
* AF 04/25/2026
*/
// if ((Math.abs(x) > 0.5*GPUTileProcessor.DTT_SIZE) || (Math.abs(y) > 0.5*GPUTileProcessor.DTT_SIZE)) {
if ((Math.abs(x) > offcenter*GPUTileProcessor.DTT_SIZE) || (Math.abs(y) > offcenter*GPUTileProcessor.DTT_SIZE)) {
cxy = 0.0;
......@@ -7846,8 +8441,12 @@ public class CuasMotion {
break try_failures; // below horizon line
}
if (cxy==0) {
lma_rslts[CuasMotionLMA.RSLT_FAIL] = CuasMotionLMA.FAIL_FAR;
break try_failures; // below horizon line
// do not fail if average image has high variations for this tile
// near horizon allow targets far ftom the tile center. AF 04/26/2026
if ((noise_map == null) || (noise_map[ntile] < noise_max)) {
lma_rslts[CuasMotionLMA.RSLT_FAIL] = CuasMotionLMA.FAIL_FAR;
break try_failures; // below horizon line
}
}
failed = false; // all tests passed
}
......@@ -7986,10 +8585,10 @@ public class CuasMotion {
final int debugLevel) {
final int num_seq = target_sequence_multi.length;
final int num_tiles = target_sequence_multi[0].length;
boolean debug_now = (debugLevel > 5); // NEVER
final int dbg_tile = debug_now ?(12+23*80) : -1;
final int dbg_seq0 = debug_now ? 47: -1;
final int dbg_seq1 = debug_now ? 49: -1;
boolean debug_now = (debugLevel > -5); // NEVER
final int dbg_tile = debug_now ?(56+38*80) : -1;
final int dbg_seq0 = debug_now ? 197: -1;
final int dbg_seq1 = debug_now ? 197: -1;
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
final AtomicInteger anew = new AtomicInteger(0);
......@@ -8000,8 +8599,9 @@ public class CuasMotion {
for (int ntile = 0; ntile < num_tiles; ntile++) { // if (target_sequence[nSeq][ntile] != null) {
double [][] tg = target_sequence_multi[nSeq][ntile];
double [][] ns = new_sequence_multi[nSeq][ntile];
if ((ntile == dbg_tile) && (nSeq >= dbg_seq0) && (nSeq <= dbg_seq1)) {
System.out.println("addNewResults()): ntile="+ntile+", nSeq="+nSeq);
boolean debug_this = ((ntile == dbg_tile) && (nSeq >= dbg_seq0) && (nSeq <= dbg_seq1));
if (debug_this) {
System.out.println("\naddNewResults()): ntile="+ntile+", nSeq="+nSeq+", num_best="+num_best);
}
if ((tg != null) || (ns != null)) {
if (tg == null) tg = new double [0][];
......@@ -8011,6 +8611,10 @@ public class CuasMotion {
new_len = Math.min(new_len, num_best);
}
int ct_len = tg.length + new_len;
if (debug_this) {
System.out.println("addNewResults()): tg.length="+tg.length+", ns.length="+ns.length+", new_len="+new_len+", ct_len="+ct_len);
}
if (ct_len > 0) {
double [][] ct = new double [ct_len][];
for (int i = 0; i < tg.length; i++) {
......@@ -8025,9 +8629,20 @@ public class CuasMotion {
anew.getAndIncrement();
}
target_sequence_multi[nSeq][ntile] = ct;
} else { // need to put 0-length to mark tile as tested, not to retry again
target_sequence_multi[nSeq][ntile] = new double[0][];
}
if (debug_this) {
tg = target_sequence_multi[nSeq][ntile];
for (int ntg = 0; ntg < tg.length; ntg++) {
System.out.println("\ntg="+ntg+"("+tg.length+")");
for (int i = 0; i < 5; i++) {
System.out.print(tg[ntg][i]+", ");
}
System.out.println();
}
}
}
}
}
......@@ -8383,7 +8998,7 @@ public class CuasMotion {
0, // min_score_lma, // double min_confidence,
target_horizon, // final double lma_horizon, // target below horizon
cuasMotion.tilesX, // final int tilesX,
fin_range, // final int range, // 1 or 2
fin_range, // final int range, // 1 or 2
filter5_remain, // final int [] remain){
passes, // final int [] passes, // debugging - numer of passes required
1); // debugLevel); // final int debugLevel)
......@@ -8570,6 +9185,7 @@ public class CuasMotion {
public void processMovingTargetsMulti(
final boolean batch_mode,
final float [][] fpixels,
final float [] fpixels_avg,
final int debugLevel) {
int start_frame = 0;
boolean half_step = clt_parameters.imp.cuas_half_step; // true;
......
......@@ -57,6 +57,7 @@ public class CuasRanging {
boolean batch_mode){
boolean save_linear_cuas = true;
boolean save_um_cuas = true;
boolean save_noise_map = true;
double um_sigma = clt_parameters.imp.um_sigma;
double um_weight = clt_parameters.imp.um_weight;
boolean mono_fixed = clt_parameters.imp.mono_fixed;
......@@ -207,6 +208,9 @@ public class CuasRanging {
}
scene_titles[nscene] = s;// imp_targets.getStack().getSliceLabel(nscene+first_corr+1);
}
// get tile variations
float [] fpixels_avg = (float[]) imp_targets.getStack().getPixels(1); // here assuming first slice is average
boolean skip_targets = false;// true;
if (skip_targets) {
return null;
......@@ -218,9 +222,21 @@ public class CuasRanging {
clt_parameters, // CLTParameters clt_parameters,
scene_titles, // String [] scene_titles,
center_CLT, // QuadCLT parentCLT,
fpixels_avg, // float [] fpixels_avg,
uasLogReader, // UasLogReader uasLogReader,
debugLevel); // int debugLevel)
double[][][] targets; // = null;
if (save_noise_map) {
ImagePlus imp_noise_map = ShowDoubleFloatArrays.makeArrays(
cuasMotion.getNoiseMap(), // float[][] pixels,
cuasMotion.getTilesX(), // int width,
cuasMotion.getTilesY(), // int height,
center_CLT.getImageName()+"-NOISE-MAP"); //String [] titles)
center_CLT.saveImagePlusInModelDirectory(imp_noise_map); // ImagePlus imp)
}
double[][][] targets; // = null;
/*
cuasMotion.processMovingTargetsMulti( // will remove rendering
......@@ -251,6 +267,7 @@ public class CuasRanging {
cuasMotion.processMovingTargetsMulti( // will remove rendering
batch_mode, // final boolean batch_mode,
fpixels, // final float [][] fpixels,
fpixels_avg, // final float [] fpixels_avg,
debugLevel); // final int debugLevel) {
// double[][][]
targets = cuasMotion.getTargets();
......@@ -470,7 +487,6 @@ public class CuasRanging {
}
public double [][][] renderKeyFrames(
final double [][][] targets, // centers
final double [][][] targets5x5,
......
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