Commit 6dd7be11 authored by Andrey Filippov's avatar Andrey Filippov

Implemented LMA-based filtering of the moving targets

parent 4342fd2a
......@@ -1067,7 +1067,7 @@ G= Y +Pr*(- 2*Kr*(1-Kr))/Kg + Pb*(-2*Kb*(1-Kb))/Kg
if (pslice_titles != null) {
pslice_titles[0] = slice_l;
}
double [][] file_data = ShowDoubleFloatArrays.readDoubleArray(
double [][] file_data = readDoubleArray(
imp, // ImagePlus imp,
0, // int num_slices, // (0 - all)
wh); // int [] wh); // int [] wh)
......
......@@ -95,15 +95,11 @@ public class CuasMotion {
int framecent = 180;
int corr_offset = clt_parameters.imp.cuas_corr_offset;
int corr_pairs = clt_parameters.imp.cuas_corr_pairs;
// int frame0cent = 210;
// int frame1cent = frame0cent + clt_parameters.imp.cuas_corr_offset;
// int frame_len = clt_parameters.imp.cuas_corr_pairs; // 40;
double cuas_fat_zero = clt_parameters.imp.cuas_fat_zero;
double cuas_cent_radius = clt_parameters.imp.cuas_cent_radius;
int cuas_n_recenter = clt_parameters.imp.cuas_n_recenter;
double cuas_rstr = clt_parameters.imp.cuas_rstr;// 0.003; // clt_parameters.imp.rln_sngl_rstr; // FIXME: ADD
boolean smooth = clt_parameters.imp.cuas_smooth; // true;
// double rln_neib_rstr = clt_parameters.imp.rln_neib_rstr;
GenericJTabbedDialog gd = new GenericJTabbedDialog("Motion detect parameters");
gd.addNumericField("Center frame", framecent, 0, 5, "frame", "Center frame");
......@@ -230,22 +226,47 @@ public class CuasMotion {
CLTParameters clt_parameters,
QuadCLT parentCLT,
int debugLevel) {
int corr_offset = clt_parameters.imp.cuas_corr_offset;
int corr_pairs = clt_parameters.imp.cuas_corr_pairs;
double fat_zero = clt_parameters.imp.cuas_fat_zero;
double cent_radius = clt_parameters.imp.cuas_cent_radius;
int n_recenter = clt_parameters.imp.cuas_n_recenter;
double rstr = clt_parameters.imp.cuas_rstr;// 0.003; // clt_parameters.imp.rln_sngl_rstr; // FIXME: ADD
double speed_min = clt_parameters.imp.cuas_speed_min;
double speed_pref = clt_parameters.imp.cuas_speed_pref;
double speed_boost = clt_parameters.imp.cuas_speed_boost;
boolean smooth = clt_parameters.imp.cuas_smooth; // true;
boolean half_step = clt_parameters.imp.cuas_half_step; // true;
int max_range = clt_parameters.imp.cuas_max_range;
int corr_offset = clt_parameters.imp.cuas_corr_offset;
int corr_pairs = clt_parameters.imp.cuas_corr_pairs;
double fat_zero = clt_parameters.imp.cuas_fat_zero;
double cent_radius = clt_parameters.imp.cuas_cent_radius;
int n_recenter = clt_parameters.imp.cuas_n_recenter;
double rstr = clt_parameters.imp.cuas_rstr;// 0.003; // clt_parameters.imp.rln_sngl_rstr; // FIXME: ADD
double speed_min = clt_parameters.imp.cuas_speed_min;
double speed_pref = clt_parameters.imp.cuas_speed_pref;
double speed_boost = clt_parameters.imp.cuas_speed_boost;
boolean smooth = clt_parameters.imp.cuas_smooth; // true;
boolean half_step = clt_parameters.imp.cuas_half_step; // true;
int max_range = clt_parameters.imp.cuas_max_range;
double target_radius = clt_parameters.imp.cuas_target_radius;
double target_strength = clt_parameters.imp.cuas_target_strength;
double [][] target_frac = new double [clt_parameters.imp.cuas_target_frac.length][2];
boolean no_border= clt_parameters.imp.cuas_no_border; // true;
// Moving target LMA
double lma_sigma = clt_parameters.imp.cuas_lma_sigma; // = 3.0;
double lma_r0 = clt_parameters.imp.cuas_lma_r0; // = 3.0; //maximum with with overshoot
double lma_ovrsht = clt_parameters.imp.cuas_lma_ovrsht; // = 2.0;
// CUAS Motion LMA parameters
boolean lma_fit_xy= clt_parameters.imp.cuas_lma_fit_xy; // true;
boolean lma_fit_a= clt_parameters.imp.cuas_lma_fit_a; // true;
boolean lma_fit_c= clt_parameters.imp.cuas_lma_fit_c; // true;
boolean lma_fit_r= clt_parameters.imp.cuas_lma_fit_r; // true;
boolean lma_fit_k= clt_parameters.imp.cuas_lma_fit_k; // true;
double lambda = clt_parameters.imp.cuas_lambda; // = 0.1;
double lambda_good = clt_parameters.imp.cuas_lambda_good; // = 0.5;
double lambda_bad = clt_parameters.imp.cuas_lambda_bad; // = 8;
double lambda_max = clt_parameters.imp.cuas_lambda_max; // = 100;
double rms_diff = clt_parameters.imp.cuas_rms_diff; // = 0.001; // relative RMS improvement
int num_iter = clt_parameters.imp.cuas_num_iter; // = 20;
// CUAS Motion LMA filter parameters
double lma_rms = clt_parameters.imp.cuas_lma_rms; // = 1.5; // Maximal RMS, regardless of amplitude
double lma_arms = clt_parameters.imp.cuas_lma_arms; // = 0.06; // Maximal absolute RMS, sufficient for any amplitude
double lma_rrms = clt_parameters.imp.cuas_lma_rrms; // = 0.15; // Maximal relative to A rms. OK is when (RMS < cuas_lma_arms) || (RMS < cuas_lma_rrms * A)
double lma_mina = clt_parameters.imp.cuas_lma_mina; // = 1.0; // Minimal A (amplitude)
double lma_maxr = clt_parameters.imp.cuas_lma_maxr; // = 5.0; // Maximal radius (>3.8)
double lma_mink = clt_parameters.imp.cuas_lma_mink; // = 0.0; // Minimal K (overshoot) <0.007
double lma_maxk = clt_parameters.imp.cuas_lma_maxk; // = 5.0; // Minimal K (overshoot) > 3.8
for (int i = 0; i < target_frac.length; i++) {
if (clt_parameters.imp.cuas_target_frac[i].length >= 2) {
target_frac[i][0] = clt_parameters.imp.cuas_target_frac[i][0];
......@@ -262,6 +283,8 @@ public class CuasMotion {
// srt_path = gd.getNextString();
boolean save_params = true;
boolean test_lma = false;
while (true) {
GenericJTabbedDialog gd = new GenericJTabbedDialog("Motion scan parameters");
// gd.addNumericField("Center frame", framecent, 0, 5, "frame", "Center frame");
......@@ -283,10 +306,57 @@ public class CuasMotion {
gd.addNumericField("Minimal target strength", target_strength, 5,8,"","Minimal value of the target image.");
gd.addStringField ("Fraction for strengths", IntersceneMatchParameters.double2dToString(target_frac), 100,
"Variable number of (strength, fraction) pairs separated by \":\". Each pair of strength, minimal fraction is separated by \",\".");
gd.addCheckbox ("Target not on the tile edge", no_border, "Exclude targets with centers on the edge of 16x16 tiles.");
gd.addMessage("=== Moving target LMA ===");
gd.addNumericField("Weight Gaussian sigma", lma_sigma, 5,8,"pix",
"Weights to emphasize maximum center area when fitting.");
gd.addNumericField("Target typical radius", lma_r0, 5,8,"pix",
"Typical target radius including negative overshoot (caused by UM filter).");
gd.addNumericField("Target maximum overshoot", lma_ovrsht, 5,8,"",
"Hos much smaller is the first zero than total maximum with overshoot (2.0 - first zero radius 1/2 of the full.");
gd.addMessage("--- Moving target LMA fitting parameters ---");
gd.addCheckbox ("LMA fit X,Y", lma_fit_xy, "Fit target center position.");
gd.addCheckbox ("LMA fit amplitude (strength)", lma_fit_a, "Fit maximum amplitude.");
gd.addCheckbox ("LMA fit offset", lma_fit_c, "Fit out-of-maximum level (offset).");
gd.addCheckbox ("LMA fit radius", lma_fit_r, "Fit target total radius - includes negative overshoot caused by UM filter.");
gd.addCheckbox ("LMA fit overshoot", lma_fit_k, "Fit target overshoot (2.0 - first zero crossing at half radius.");
gd.addNumericField("LMA lambda", lambda, 5,8,"",
"LMA initial lambda.");
gd.addNumericField("Scale lambda after success", lambda_good, 5,8,"",
"Multiply lambda if RMS decreaed.");
gd.addNumericField("Scale lambda after failure", lambda_bad, 5,8,"",
"Multiply lambda if RMS increaed.");
gd.addNumericField("Maximal lambda", lambda_max, 5,8,"",
"Give up if lambda gets higher value.");
gd.addNumericField("Relative RMS improvement", rms_diff, 5,8,"",
"Finish fitting when the relative RMS improvement drops below this value.");
gd.addNumericField("LMA iterations", num_iter, 0,3,"",
"Maximal number of the LMA iterations.");
gd.addMessage("--- Moving target discrimination parameters theresholds ---");
gd.addNumericField("Maximal RMS", lma_rms, 5,8,"",
"Maximal RMS for target that should match always, regardless of the amplitude.");
gd.addNumericField("Maximal sufficient RMS", lma_arms, 5,8,"",
"Maximal sufficient RMS for target. Satisfying any of the sufficient or relative is enough");
gd.addNumericField("Maximal relative RMS", lma_rrms, 5,8,"",
"Maximal relative (to amplitude) RMS for target. Satisfying any of the absolute and relative is sufficient");
gd.addNumericField("Minimal target amplitude", lma_mina, 5,8,"",
"Filter out weak targets.");
gd.addNumericField("Maximal radius", lma_maxr, 5,8,"",
"Maximal target radius including negative overshoot.");
gd.addNumericField("Minimal overshoot ratio", lma_mink, 5,8,"",
"Minimal ratio of the overshoot radius to the first 0 radius (typical 1.0).");
gd.addNumericField("Maximal overshoot ratio", lma_maxk, 5,8,"",
"Maximal ratio of the overshoot radius to the first 0 radius (typical 3.0).");
gd.addStringField("Data directory", data_dir,100,"Intermediate results directory (to bypass first stages during debugging).");
gd.addCheckbox ("Save_params", save_params, "Save edited parameters");
gd.addCheckbox ("Test LMA", test_lma, "Test LMA from known files instead of normal operation.");
gd.showDialog();
if (gd.wasCanceled()) {
......@@ -310,9 +380,32 @@ public class CuasMotion {
target_radius = gd.getNextNumber();
target_strength = gd.getNextNumber();
target_frac = IntersceneMatchParameters.stringToDouble2d(gd.getNextString());
no_border = gd.getNextBoolean();
lma_sigma = gd.getNextNumber();
lma_r0 = gd.getNextNumber();
lma_ovrsht = gd.getNextNumber();
lma_fit_xy = gd.getNextBoolean();
lma_fit_a = gd.getNextBoolean();
lma_fit_c = gd.getNextBoolean();
lma_fit_r = gd.getNextBoolean();
lma_fit_k = gd.getNextBoolean();
lambda = gd.getNextNumber();
lambda_good = gd.getNextNumber();
lambda_bad = gd.getNextNumber();
lambda_max = gd.getNextNumber();
rms_diff = gd.getNextNumber();
num_iter = (int) gd.getNextNumber();
lma_rms = gd.getNextNumber();
lma_arms = gd.getNextNumber();
lma_rrms = gd.getNextNumber();
lma_mina = gd.getNextNumber();
lma_maxr = gd.getNextNumber();
lma_mink = gd.getNextNumber();
lma_maxk = gd.getNextNumber();
data_dir = gd.getNextString();
save_params = gd.getNextBoolean();
test_lma = gd.getNextBoolean();
if (save_params) {
clt_parameters.imp.cuas_corr_offset = corr_offset;
......@@ -339,6 +432,28 @@ public class CuasMotion {
System.out.println("testCuasScanMotion(): 2.wrong format for a pair of strength, fraction values.");
}
}
clt_parameters.imp.cuas_no_border = no_border;
clt_parameters.imp.cuas_lma_sigma = lma_sigma;
clt_parameters.imp.cuas_lma_r0 = lma_r0;
clt_parameters.imp.cuas_lma_fit_xy= lma_fit_xy;
clt_parameters.imp.cuas_lma_fit_a= lma_fit_a;
clt_parameters.imp.cuas_lma_fit_c= lma_fit_c;
clt_parameters.imp.cuas_lma_fit_r= lma_fit_r;
clt_parameters.imp.cuas_lma_fit_k= lma_fit_k;
clt_parameters.imp.cuas_lma_ovrsht = lma_ovrsht;
clt_parameters.imp.cuas_lambda = lambda;
clt_parameters.imp.cuas_lambda_good = lambda_good;
clt_parameters.imp.cuas_lambda_bad = lambda_bad;
clt_parameters.imp.cuas_lambda_max = lambda_max;
clt_parameters.imp.cuas_rms_diff = rms_diff;
clt_parameters.imp.cuas_num_iter = num_iter;
clt_parameters.imp.cuas_lma_rms = lma_rms;
clt_parameters.imp.cuas_lma_arms = lma_arms;
clt_parameters.imp.cuas_lma_rrms = lma_rrms;
clt_parameters.imp.cuas_lma_mina = lma_mina;
clt_parameters.imp.cuas_lma_maxr = lma_maxr;
clt_parameters.imp.cuas_lma_mink = lma_mink;
clt_parameters.imp.cuas_lma_maxk = lma_maxk;
}
int start_frame = 0;
......@@ -370,6 +485,28 @@ public class CuasMotion {
System.out.println("target_radius= "+target_radius);
System.out.println("target_strength= "+target_strength);
System.out.println("target_frac= "+IntersceneMatchParameters.double2dToString(target_frac));
System.out.println("no_border= "+no_border);
System.out.println("lma_sigma= "+lma_sigma);
System.out.println("lma_r0= "+lma_r0);
System.out.println("lma_ovrsht= "+lma_ovrsht);
System.out.println("lma_fit_xy= "+lma_fit_xy);
System.out.println("lma_fit_a= "+lma_fit_a);
System.out.println("lma_fit_c= "+lma_fit_c);
System.out.println("lma_fit_r= "+lma_fit_r);
System.out.println("lma_fit_k= "+lma_fit_k);
System.out.println("lambda= "+lambda);
System.out.println("lambda_good= "+lambda_good);
System.out.println("lambda_bad= "+lambda_bad);
System.out.println("lambda_max= "+lambda_max);
System.out.println("rms_diff= "+rms_diff);
System.out.println("num_iter= "+num_iter);
System.out.println("lma_rms= "+lma_rms);
System.out.println("lma_arms= "+lma_arms);
System.out.println("lma_rrms= "+lma_rrms);
System.out.println("lma_mina= "+lma_mina);
System.out.println("lma_maxr= "+lma_maxr);
System.out.println("lma_mink= "+lma_mink);
System.out.println("lma_maxk= "+lma_maxk);
}
float [][] fpixels = new float[num_scenes][];
String [] scene_titles = new String [num_scenes];
......@@ -383,6 +520,7 @@ public class CuasMotion {
slice_titles[nscan] = imp_sel.getStack().getSliceLabel(frame_cent+1);
}
CuasMotion cuasMotion = new CuasMotion (
clt_parameters, // CLTParameters clt_parameters,
parentCLT, // QuadCLT parentCLT,
......@@ -404,6 +542,13 @@ public class CuasMotion {
String title_accumulated = imp_name+"-accumulated"+suffix_param;
String title_rendered_hyper=imp_name+"-rendered_hyper"+suffix_param; //
String title_acc_targets = imp_name+"-accumulated_targets"+suffix_param;
String title_vf_good = imp_name+"-vector_field_good"+suffix_param; //
String title_extended_good =imp_name+"-vector_field_extended_good"+suffix_param; //
String title_targets_good = imp_name+"-targets_good"+suffix_param; //
final int frame0 = start_frame + seq_length/2;
final int half_accum_range = corr_pairs/2;
final boolean smooth_accum = true;
double [][][] corr2d = null; // to read it if bypassing calculations
double [][][] motion_scan = null;
......@@ -413,8 +558,169 @@ public class CuasMotion {
int [] remain = new int [num_corr_samples];
data_dir= trimSuffix(data_dir,"/");
// String vf_extended_path = data_dir + "/" + vf_extended+".tiff";
String vf_filtered_path = data_dir + "/" + title_vf_filtered+".tiff";
motion_scan_filtered = getVectorFieldHyper(vf_filtered_path); // String path)
// String vf_filtered_path = data_dir + "/" + title_vf_filtered+".tiff";
String vf_path = data_dir + "/" + title_vf+".tiff";
// motion_scan_filtered = getVectorFieldHyper(vf_filtered_path); // String path)
if (test_lma) {
String path_vf = "/media/elphel/NVME/lwir16-proc/eagle_mountain/linked/movement/selected/25_r1.5/I-1747803449_165687-vector_field_good-offs20-pairs50-rstr0.01-fz300.0-cr3.0-mr1-ms0.0-sp0.0-sb1.0-tr2.0-ts0.8-tf0.0,0.12:2.5,0.15:5.0,0.25.tiff";
String path_acc = "/media/elphel/NVME/lwir16-proc/eagle_mountain/linked/movement/selected/25_r1.5/I-1747803449_165687-accumulated-offs20-pairs50-rstr0.01-fz300.0-cr3.0-mr1-ms0.0-sp0.0-sb1.0-tr2.0-ts0.8-tf0.0,0.12:2.5,0.15:5.0,0.25-n20.tiff";
double [][][] vf_sequence = getVectorFieldHyper(path_vf); // String path)
if (vf_sequence == null) {
System.out.println("Failed to motion vectors from "+path_vf);
continue;
}
ImagePlus imp_accum = new ImagePlus(path_acc);
if (imp_accum.getWidth()==0) {
System.out.println("Failed to read accum data from "+path_acc);
continue;
}
int [] wh = new int[2];
float [][] accum = ShowDoubleFloatArrays.readFloatArray(
imp_accum, // ImagePlus imp,
0, // int num_slices, // (0 - all)
wh); // int [] wh)
double [][][][] coord_data2 = getAccumulatedCoordinates(
vf_sequence, // final double [][][] vector_fields, // centers
accum, // final double [][] accum_data, // should be around 0, no low-freq
target_radius, // final double centroid_radius,
n_recenter, // final int n_recenter, // re-center window around new maximum. 0 -no refines (single-pass)
cuasMotion.tilesX, // final int tilesX){
no_border, // final boolean no_border,
// Moving target LMA
lma_sigma, // final double lma_sigma,
lma_r0, // final double lma_r0,
lma_ovrsht, // final double lma_ovrsht,
// CUAS Motion LMA parameters
lma_fit_xy, // final boolean lma_fit_xy,
lma_fit_a, // final boolean lma_fit_a,
lma_fit_c, // final boolean lma_fit_c,
lma_fit_r, // final boolean lma_fit_r,
lma_fit_k, // final boolean lma_fit_k,
lambda, // final double lambda,
lambda_good, // final double lambda_good,
lambda_bad, // final double lambda_bad,
lambda_max, // final double lambda_max,
rms_diff, // final double rms_diff,
num_iter, // final int num_iter,
debugLevel); // final int debugLevel);
double [][][] coord_data = coord_data2[0];
double [][][] coord_lma = coord_data2[1];
showVectorFieldsSequence(
coord_data, // double [][][] vector_fields_sequence,
0.0, // double speed_min,
0.0, // double speed_pref,
1.0, // double speed_boost,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_targets_all+"-VF-TEST", // String title,
false, // boolean nan_effective_strength,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
showVectorFieldsSequenceLMA(
coord_lma, // double [][][] target_scene_sequence, // rename
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_targets_all+"-LMA-TEST", // String title,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
// int [] targets_remain = new int [coord_data.length];
int [] targets_remain = new int [coord_data.length];
double [][][] coord_data_filtered = filterAndShowTargets(
coord_data, // double [][][] coord_data,
target_strength, // double target_strength,
target_frac, // double [][] target_frac,
slice_titles, // String [] slice_titles, //
title_targets_filt+"-VF-TEST-FILTERED", // String title_targets_filt,
targets_remain, // int [] targets_remain,
cuasMotion.tilesX, // int tilesX)
true); // show_vector_field); // boolean show)
int remained_total = printRemain(targets_remain, "Total good targets", true);
double [][][] coord_data_filtered_lma = filterAndShowTargetsLMA(
coord_lma,// double [][][] coord_data,
lma_rms, // double lma_rms, // = 1.5; // Maximal RMS (should always match, regardless if A)
lma_arms, // double lma_arms, // = 0.03; // Maximal absolutre RMS
lma_rrms, // double lma_rrms, // = 0.03; // Maximal relative to A rms. OK is when (RMS < cuas_lma_arms) || (RMS < cuas_lma_rrms * A)
lma_mina, // double lma_mina, // = 1.0; // Minimal A (amplitude)
lma_maxr, // double lma_maxr, // = 5.0; // Minimal K (overshoot) = 3.0
lma_mink, // double lma_mink, // = 1.0; // Minimal K (overshoot) = 1.0
lma_maxk, // double lma_maxk, // = 1.0; // Minimal K (overshoot) = 3.0
slice_titles, // String [] slice_titles, //
title_targets_filt+"-LMA-TEST-FILTERED", // String title_targets_filt,
targets_remain, // int [] targets_remain,
cuasMotion.tilesX, // int tilesX)
true); // show_vector_field); // boolean show)
remained_total = printRemain(targets_remain, "coord_data_filtered_lma: Total new targets LMA", true);
// remove tiles that did not pass old vf filter
double [][][] targets_lma_combo = filterMotionScans( // should keep LMA coordinates
coord_data_filtered_lma, // double [][][] scan0,
coord_data_filtered, // double [][][] scan1)
remain);
// create vector field sequence by masking after the last filter
double [][][] targets_vf_combo = filterMotionScans( // should keep LMA coordinates
vf_sequence, // double [][][] scan0,
targets_lma_combo, // double [][][] scan1)
remain);
printRemain(remain, "targets_lma_combo", true);
showVectorFieldsSequenceLMA(
targets_lma_combo, // double [][][] target_scene_sequence,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_targets_good+"-LMA-TEST-COMBO", // String title,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
// create larger, 5x5 vector field for accumulation
double [][][] extended_vf_sequence = extendMotionScan(
targets_vf_combo, // final double [][][] motion_scan,
null, // filter5, // final boolean [][] filtered, // centers, should be non-overlapped
cuasMotion.tilesX, // final int tilesX)
2, // final int range, // 1 or 2
remain); // final int [] remain)
printRemain(remain, "extended5x5_vf_sequence", true);
float [][] fpixels_accumulated5x5 = cuasMotion.shiftAndRenderAccumulate(
clt_parameters, // CLTParameters clt_parameters,
true, // final boolean fill_zeros,
fpixels, // final float [][] fpixels,
extended_vf_sequence, // final double [][][] vector_field,
frame0, // final int frame0, // for vector_field[0]
corr_step, // final int frame_step,
half_accum_range, // final int half_range,
smooth_accum, // final boolean smooth,
corr_offset, // final int corr_offset, // interframe distance for correlation
true); // final boolean batch_mode) {
// zero-fill undefined tiles
ShowDoubleFloatArrays.showArrays(
fpixels_accumulated5x5,
cuasMotion.gpu_max_width,
cuasMotion.gpu_max_height,
true,
title_accumulated+"-TARGETS5x5", // "-corr2d"+"-"+frame0+"-"+frame1+"-"+corr_pairs,
scene_titles); // titles_accum);
/*
float [][] fpixels_accumulated_filtered = getTargetImages(
targets_lma_combo, // final double [][][] vector_fields, // centers , just null/not null
accum, // final float [][] accum_data, // should be around 0, no low-freq
cuasMotion.tilesX); // final int tilesX)
ShowDoubleFloatArrays.showArrays(
fpixels_accumulated_filtered,
cuasMotion.gpu_max_width,
cuasMotion.gpu_max_height,
true,
title_acc_targets+"-LMA-TEST-COMBO", // "-corr2d"+"-"+frame0+"-"+frame1+"-"+corr_pairs,
scene_titles); // titles_accum);
*/
continue;
}
motion_scan = getVectorFieldHyper(vf_path); // title_vf); // String path)
/*
if (motion_scan_filtered != null) {
extended_scan = extendMotionScan(
motion_scan_filtered, // final double [][][] motion_scan,
......@@ -423,13 +729,15 @@ public class CuasMotion {
1, // final int range, // 1 or 2
remain); // final int [] remain)
}
*/
// extended_scan = getVectorFieldHyper(vf_extended_path); // String path)
if (extended_scan == null) {
// if (extended_scan == null) {
boolean show_vector_field = false; //true;
boolean show_2d_correlations = false; //true;
boolean show_full_images = false; //true;
if (motion_scan == null) {
System.out.println ("testCuasScanMotion(): Failed to read Vector Field from file, calculating");
// readVectorField(String path)
boolean show_vector_field = true;
boolean show_2d_correlations = true;
String dbg_title = imp_name;
// double [][][]
......@@ -451,6 +759,46 @@ public class CuasMotion {
dbg_title, // String title,
corr2d, // double [][][] corr2d, // null or [(fpixels.length - seq_length - start_frame) / corr_step)[][]
debugLevel); // int debugLevel) {
if (show_2d_correlations) { // may be read to re-process with vector field
int corr_size = 2 * GPUTileProcessor.DTT_SIZE -1;
double [][] dbg_2d_corrs = ImageDtt.corr_partial_dbg( // not used in lwir
corr2d, // 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)
ShowDoubleFloatArrays.showArrays(
dbg_2d_corrs,
cuasMotion.tilesX * (corr_size + 1),
cuasMotion.tilesY * (corr_size + 1),
true,
title_cor2d, // "-corr2d"+"-"+frame0+"-"+frame1+"-"+corr_pairs,
slice_titles);
}
if (debugLevel > -4) {
System.out.println("scan DONE");
}
}
// starting from the motion_scan[][][] - calculated or read from file. corr2d is curently unused, maybe we'll have to save restore
double [][][] motion_scan_original = cloneMotionScan(motion_scan, remain);
printRemain(remain, "motion_scan_original", true);
int niter;
int max_iter = 20; // 100;
double [][][] targets_good = new double [motion_scan.length][motion_scan[0].length][]; // will combine good targets
double [][][] targets_bad = new double [motion_scan.length][motion_scan[0].length][]; // will combine good targets
for (niter=0; niter < max_iter; niter++) {
// remove known bad targets. TODO: maybe will need to modify corr2d and recalculate, if the same tile is shared by a target and background
motion_scan = subtractMotionScans(
motion_scan, // double [][][] scan0, // all tried for targets
targets_bad, // double [][][] scan1) // good targets
remain);
printRemain(remain, "motion_scan wo bad", true);
// filter remaining (no known bad ones)
filter5 = filterMotionScan(
motion_scan, // final double [][][] motion_scan,
cuasMotion.tilesX, // final int tilesX)
......@@ -460,41 +808,35 @@ public class CuasMotion {
speed_min, // double speed_min,
speed_pref, // double speed_pref,
speed_boost); // double speed_boost);
printRemain(remain, "filter5", true);
motion_scan_filtered = applyFilter(
motion_scan, // double [][][] motion_scan,
filter5); // boolean [][] filter5)
// double [][][]
// remove know good (already processed)
motion_scan_filtered = subtractMotionScans(
motion_scan_filtered, // double [][][] scan0, // all tried for targets
targets_good, // double [][][] scan1) // good targets
remain);
printRemain(remain, "filtered wo good", true);
// Anything remains? we'll see agter extension
extended_scan = extendMotionScan(
motion_scan, // final double [][][] motion_scan,
filter5, // final boolean [][] filtered, // centers, should be non-overlapped
cuasMotion.tilesX, // final int tilesX)
1, // final int range, // 1 or 2
remain); // final int [] remain)
if ((debugLevel >-4) && (remain !=null)) {
motion_scan_filtered, // final double [][][] motion_scan,
null, // filter5, // final boolean [][] filtered, // centers, should be non-overlapped
cuasMotion.tilesX, // final int tilesX)
1, // final int range, // 1 or 2
remain); // final int [] remain)
int remained_total = printRemain(remain, "extended_scan", true);
if ((debugLevel >-4) && (remain !=null)) {
System.out.println("testCuasScanMotion() Total new tiles to process for "+remain.length+" scene sequences is "+remained_total);
for (int nscan = 0; nscan < remain.length; nscan++) {
System.out.print(nscan+":"+remain[nscan]+", ");
}
System.out.println();
}
if (show_2d_correlations) { // may be read to re-process with vector field
int corr_size = 2 * GPUTileProcessor.DTT_SIZE -1;
double [][] dbg_2d_corrs = ImageDtt.corr_partial_dbg( // not used in lwir
corr2d, // 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)
ShowDoubleFloatArrays.showArrays(
dbg_2d_corrs,
cuasMotion.tilesX * (corr_size + 1),
cuasMotion.tilesY * (corr_size + 1),
true,
title_cor2d, // "-corr2d"+"-"+frame0+"-"+frame1+"-"+corr_pairs,
slice_titles);
if (remained_total == 0) {
break;
}
// there are some tiles left to try
if (show_vector_field) {
//title_vf_all
......@@ -504,7 +846,7 @@ public class CuasMotion {
speed_pref, // double speed_pref,
speed_boost, // double speed_boost,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_vf_all, // String title,
title_vf_all+"-n"+niter,// String title,
false, // boolean nan_effective_strength,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
......@@ -514,8 +856,8 @@ public class CuasMotion {
speed_pref, // double speed_pref,
speed_boost, // double speed_boost,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_vf, // String title,
true, // boolean nan_effective_strength,
title_vf+"-n"+niter, // String title,
true, // boolean nan_effective_strength,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
showVectorFieldsSequence(
......@@ -524,7 +866,7 @@ public class CuasMotion {
speed_pref, // double speed_pref,
speed_boost, // double speed_boost,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_vf_filtered, // String title,
title_vf_filtered+"-n"+niter, // String title,
false, // boolean nan_effective_strength,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
......@@ -534,22 +876,251 @@ public class CuasMotion {
speed_pref, // double speed_pref,
speed_boost, // double speed_boost,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_vf_extended, // String title,
title_vf_extended+"-n"+niter, // String title,
false, // boolean nan_effective_strength,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
// show good and bad accumulated here too?
}
if (debugLevel > -4) {
System.out.println("scan DONE");
System.out.println("Starting render, iteration = "+niter);
}
}
if (debugLevel > -4) {
System.out.println("Starting render");
}
float [][] fpixels_rendered = cuasMotion.shiftAndRenderTest(
clt_parameters, // CLTParameters clt_parameters,
fpixels, // final float [][] fpixels,
extended_scan, // final double [][][] vector_field,
frame0, // final int frame0, // for vector_field[0]
corr_step, // final int frame_step,
corr_offset, // final int corr_offset, // interframe distance for correlation
true); // final boolean batch_mode) {
if (debugLevel > -4) {
System.out.println("Render DONE");
}
float [][] fpixels_accumulated = cuasMotion.shiftAndRenderAccumulate(
clt_parameters, // CLTParameters clt_parameters,
false, // final boolean fill_zeros,
fpixels, // final float [][] fpixels,
extended_scan, // final double [][][] vector_field,
frame0, // final int frame0, // for vector_field[0]
corr_step, // final int frame_step,
half_accum_range, // final int half_range,
smooth_accum, // final boolean smooth,
corr_offset, // final int corr_offset, // interframe distance for correlation
true); // final boolean batch_mode) {
// show just fpixels_accumulated
// move outside? compare to slice_titles known
if (show_full_images) {
ShowDoubleFloatArrays.showArrays(
fpixels_accumulated,
cuasMotion.gpu_max_width,
cuasMotion.gpu_max_height,
true,
title_accumulated+"-n"+niter, // "-corr2d"+"-"+frame0+"-"+frame1+"-"+corr_pairs,
scene_titles); // titles_accum);
}
// replace center frames with the accumulated ones
for (int nseq = 0; nseq < fpixels_accumulated.length; nseq++){
fpixels_rendered[frame0 + nseq * corr_step] = fpixels_accumulated[nseq];
}
if (debugLevel > -4) {
System.out.println("Accumulation DONE");
}
float [][][] fpixels_hyper = {fpixels,fpixels_rendered};
String [] hyper_titles_top = {"Source","Rendered"};
if (show_full_images) {
ImagePlus imp_hyper = ShowDoubleFloatArrays.showArraysHyperstack(
fpixels_hyper, // float[][][] pixels,
cuasMotion.gpu_max_width, // int width,
title_rendered_hyper+"-n"+niter, // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
scene_titles, // String [] titles, // all slices*frames titles or just slice titles or null
hyper_titles_top, // String [] frame_titles, // frame titles or null
true); // boolean show)
}
// double target_radius = cent_radius; // for now - make separate
// target_max
double [][][][] coord_data2 = getAccumulatedCoordinates(
motion_scan_filtered, // final double [][][] vector_fields, // centers
fpixels_accumulated, // final double [][] accum_data, // should be around 0, no low-freq
target_radius, // final double centroid_radius,
n_recenter, // final int n_recenter, // re-center window around new maximum. 0 -no refines (single-pass)
cuasMotion.tilesX, // final int tilesX){
no_border, // final boolean no_border,
// Moving target LMA
lma_sigma, // final double lma_sigma,
lma_r0, // final double lma_r0,
lma_ovrsht, // final double lma_ovrsht,
// CUAS Motion LMA parameters
lma_fit_xy, // final boolean lma_fit_xy,
lma_fit_a, // final boolean lma_fit_a,
lma_fit_c, // final boolean lma_fit_c,
lma_fit_r, // final boolean lma_fit_r,
lma_fit_k, // final boolean lma_fit_k,
lambda, // final double lambda,
lambda_good, // final double lambda_good,
lambda_bad, // final double lambda_bad,
lambda_max, // final double lambda_max,
rms_diff, // final double rms_diff,
num_iter, // final int num_iter,
debugLevel); // final int debugLevel);
double [][][] coord_data = coord_data2[0];
double [][][] coord_lma = coord_data2[1];
if (show_vector_field) {
showVectorFieldsSequence(
coord_data, // double [][][] vector_fields_sequence,
0.0, // double speed_min,
0.0, // double speed_pref,
1.0, // double speed_boost,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_targets_all+"-n"+niter, // String title,
false, // boolean nan_effective_strength,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
showVectorFieldsSequenceLMA(
coord_lma, // double [][][] target_scene_sequence, // rename
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_targets_all+"-LMA-n"+niter, // String title,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
}
int [] targets_remain = new int [coord_data.length];
double [][][] coord_data_filtered = filterAndShowTargets(
coord_data, // double [][][] coord_data,
target_strength, // double target_strength,
target_frac, // double [][] target_frac,
slice_titles, // String [] slice_titles, //
title_targets_filt+"-n"+niter, // String title_targets_filt,
targets_remain, // int [] targets_remain,
cuasMotion.tilesX, // int tilesX)
show_vector_field); // boolean show)
remained_total = printRemain(targets_remain, "coord_data_filtered: Total new targets", true);
if (remained_total == 0) {
break;
}
double [][][] coord_data_filtered_lma = filterAndShowTargetsLMA(
coord_lma, // double [][][] coord_data,
lma_rms, // double lma_rms, // = 1.5; // Maximal RMS (should always match, regardless if A)
lma_arms, // double lma_arms, // = 0.03; // Maximal absolutre RMS
lma_rrms, // double lma_rrms, // = 0.03; // Maximal relative to A rms. OK is when (RMS < cuas_lma_arms) || (RMS < cuas_lma_rrms * A)
lma_mina, // double lma_mina, // = 1.0; // Minimal A (amplitude)
lma_maxr, // double lma_maxr, // = 5.0; // Minimal K (overshoot) = 3.0
lma_mink, // double lma_mink, // = 1.0; // Minimal K (overshoot) = 1.0
lma_maxk, // double lma_maxk, // = 1.0; // Minimal K (overshoot) = 3.0
slice_titles, // String [] slice_titles, //
title_targets_filt+"-n"+niter, // String title_targets_filt,
targets_remain, // int [] targets_remain,
cuasMotion.tilesX, // int tilesX)
show_vector_field); // boolean show)
remained_total = printRemain(targets_remain, "coord_data_filtered: Total new targets", true);
// add good targets to targets_good
targets_good = combineMotionScans(
targets_good, // double [][][] scan0,
coord_data_filtered, // double [][][] scan1)
remain);
printRemain(remain, "targets_good", true);
if (show_vector_field) {
showVectorFieldsSequence(
targets_good, // double [][][] vector_fields_sequence,
speed_min, // double speed_min,
speed_pref, // double speed_pref,
speed_boost, // double speed_boost,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_targets_good+"-n"+niter,// String title,
false, // boolean nan_effective_strength,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
}
double [][][] targets_bad_last = subtractMotionScans(
motion_scan_filtered, // double [][][] scan0, // all tried for targets
coord_data_filtered, // double [][][] scan1) // good targets
remain);
printRemain(remain, "targets_bad_last", true);
// add bad targets to targets_bad
targets_bad = combineMotionScans(
targets_bad, // double [][][] scan0,
targets_bad_last, // double [][][] scan1)
remain); //
printRemain(remain, "targets_bad", true);
float [][] fpixels_accumulated_filtered = getTargetImages(
coord_data_filtered, // final double [][][] vector_fields, // centers , just null/not null
fpixels_accumulated, // final float [][] accum_data, // should be around 0, no low-freq
cuasMotion.tilesX); // final int tilesX)
if (show_full_images) {
ShowDoubleFloatArrays.showArrays(
fpixels_accumulated_filtered,
cuasMotion.gpu_max_width,
cuasMotion.gpu_max_height,
true,
title_acc_targets+"-n"+niter, // "-corr2d"+"-"+frame0+"-"+frame1+"-"+corr_pairs,
scene_titles); // titles_accum);
}
if (debugLevel > -4) {
System.out.println("Iteration "+niter+" DONE.");
}
} //for (niter=0; niter < max_iter; niter++)
show_vector_field = true;
show_full_images = true;
// make good motion vectors from good targets
double [][][] motion_good = filterMotionScans(
motion_scan_original, // double [][][] scan1 // or just use motion_scan - it has only bad removed
targets_good, // double [][][] scan1){ // keep scan0 that is in scan1
remain);
printRemain(remain, "All done: motion_good", true);
int frame0 = start_frame + seq_length/2;
// make extended from all good
extended_scan = extendMotionScan(
motion_good, // motion_scan_filtered, // final double [][][] motion_scan,
null, // filter5, // final boolean [][] filtered, // centers, should be non-overlapped
cuasMotion.tilesX, // final int tilesX)
1, // final int range, // 1 or 2
remain); // final int [] remain)
printRemain(remain, "targets_good", true);
if (show_vector_field) {
showVectorFieldsSequence(
motion_good, // double [][][] vector_fields_sequence,
speed_min, // double speed_min,
speed_pref, // double speed_pref,
speed_boost, // double speed_boost,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_vf_good,// String title,
false, // boolean nan_effective_strength,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
showVectorFieldsSequence(
targets_good, // double [][][] vector_fields_sequence,
speed_min, // double speed_min,
speed_pref, // double speed_pref,
speed_boost, // double speed_boost,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_targets_good,// String title,
false, // boolean nan_effective_strength,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
showVectorFieldsSequence(
extended_scan, // double [][][] vector_fields_sequence,
speed_min, // double speed_min,
speed_pref, // double speed_pref,
speed_boost, // double speed_boost,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_extended_good,// String title,
false, // boolean nan_effective_strength,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
}
// Render for all good
float [][] fpixels_rendered = cuasMotion.shiftAndRenderTest(
clt_parameters, // CLTParameters clt_parameters,
fpixels, // final float [][] fpixels,
......@@ -558,15 +1129,12 @@ public class CuasMotion {
corr_step, // final int frame_step,
corr_offset, // final int corr_offset, // interframe distance for correlation
true); // final boolean batch_mode) {
if (debugLevel > -4) {
System.out.println("Render DONE");
System.out.println("Render all good DONE");
}
final int half_accum_range = corr_pairs/2;
final boolean smooth_accum = true;
float [][] fpixels_accumulated = cuasMotion.shiftAndRenderAccumulate(
clt_parameters, // CLTParameters clt_parameters,
false, // final boolean fill_zeros,
fpixels, // final float [][] fpixels,
extended_scan, // final double [][][] vector_field,
frame0, // final int frame0, // for vector_field[0]
......@@ -575,105 +1143,214 @@ public class CuasMotion {
smooth_accum, // final boolean smooth,
corr_offset, // final int corr_offset, // interframe distance for correlation
true); // final boolean batch_mode) {
// show just fpixels_accumulated
String [] titles_accum = new String [fpixels_accumulated.length];
//scene_titles
for (int nseq = 0; nseq < fpixels_accumulated.length; nseq++){
titles_accum[nseq] = scene_titles[frame0 + nseq * corr_step];
if (show_full_images) {
ShowDoubleFloatArrays.showArrays( // good
fpixels_accumulated,
cuasMotion.gpu_max_width,
cuasMotion.gpu_max_height,
true,
title_accumulated+"-n"+niter, // "-corr2d"+"-"+frame0+"-"+frame1+"-"+corr_pairs,
scene_titles); // titles_accum);
}
ShowDoubleFloatArrays.showArrays(
fpixels_accumulated,
cuasMotion.gpu_max_width,
cuasMotion.gpu_max_height,
true,
title_accumulated, // "-corr2d"+"-"+frame0+"-"+frame1+"-"+corr_pairs,
titles_accum);
// replace center frames with the accumulated ones
for (int nseq = 0; nseq < fpixels_accumulated.length; nseq++){
fpixels_rendered[frame0 + nseq * corr_step] = fpixels_accumulated[nseq];
}
if (debugLevel > -4) {
System.out.println("Accumulation DONE");
System.out.println("Accumulation all good DONE");
}
float [][][] fpixels_hyper = {fpixels,fpixels_rendered};
String [] hyper_titles_top = {"Source","Rendered"};
ImagePlus imp_hyper = ShowDoubleFloatArrays.showArraysHyperstack(
fpixels_hyper, // float[][][] pixels,
cuasMotion.gpu_max_width, // int width,
title_rendered_hyper, // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
scene_titles, // String [] titles, // all slices*frames titles or just slice titles or null
hyper_titles_top, // String [] frame_titles, // frame titles or null
true); // boolean show)
// double target_radius = cent_radius; // for now - make separate
String [] hyper_titles_top = {"Source","Rendered"};
if (show_full_images) {
ImagePlus imp_hyper = ShowDoubleFloatArrays.showArraysHyperstack( // good
fpixels_hyper, // float[][][] pixels,
cuasMotion.gpu_max_width, // int width,
title_rendered_hyper+"-n"+niter, // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
scene_titles, // String [] titles, // all slices*frames titles or just slice titles or null
hyper_titles_top, // String [] frame_titles, // frame titles or null
true); // boolean show)
}
// double target_radius = cent_radius; // for now - make separate
// target_max
double [][][] coord_data = getAccumulatedCoordinates(
motion_scan_filtered, // final double [][][] vector_fields, // centers
fpixels_accumulated, // final double [][] accum_data, // should be around 0, no low-freq
target_radius, // final double centroid_radius,
n_recenter, // final int n_recenter, // re-center window around new maximum. 0 -no refines (single-pass)
cuasMotion.tilesX); // final int tilesX){
// update parameters
showVectorFieldsSequence(
coord_data, // double [][][] vector_fields_sequence,
0.0, // double speed_min,
0.0, // double speed_pref,
1.0, // double speed_boost,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_targets_all, // String title,
false, // boolean nan_effective_strength,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
double [][][][] coord_data2 = getAccumulatedCoordinates(
motion_good, // final double [][][] vector_fields, // centers
fpixels_accumulated, // final double [][] accum_data, // should be around 0, no low-freq
target_radius, // final double centroid_radius,
n_recenter, // final int n_recenter, // re-center window around new maximum. 0 -no refines (single-pass)
cuasMotion.tilesX, // final int tilesX){
no_border, // final boolean no_border,
// Moving target LMA
lma_sigma, // final double lma_sigma,
lma_r0, // final double lma_r0,
lma_ovrsht, // final double lma_ovrsht,
// CUAS Motion LMA parameters
lma_fit_xy, // final boolean lma_fit_xy,
lma_fit_a, // final boolean lma_fit_a,
lma_fit_c, // final boolean lma_fit_c,
lma_fit_r, // final boolean lma_fit_r,
lma_fit_k, // final boolean lma_fit_k,
lambda, // final double lambda,
lambda_good, // final double lambda_good,
lambda_bad, // final double lambda_bad,
lambda_max, // final double lambda_max,
rms_diff, // final double rms_diff,
num_iter, // final int num_iter,
debugLevel); // final int debugLevel);
double [][][] coord_data = coord_data2[0];
double [][][] coord_lma = coord_data2[1];
if (show_vector_field) {
showVectorFieldsSequence(
coord_data, // double [][][] vector_fields_sequence,
0.0, // double speed_min,
0.0, // double speed_pref,
1.0, // double speed_boost,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_targets_all+"-COMBO", // String title,
false, // boolean nan_effective_strength,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
showVectorFieldsSequenceLMA(
coord_lma, // double [][][] target_scene_sequence, // rename
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_targets_all+"-LMA-COMBO", // String title,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
}
int [] targets_remain = new int [coord_data.length];
double [][][] coord_data_filtered = filterAndShowTargets(
coord_data, // double [][][] coord_data,
target_strength, // double target_strength,
target_frac, // double [][] target_frac,
slice_titles, // String [] slice_titles, //
title_targets_filt, // String title_targets_filt,
title_targets_filt+"-n"+niter, // String title_targets_filt,
targets_remain, // int [] targets_remain,
cuasMotion.tilesX, // int tilesX)
show_vector_field); // boolean show)
int remained_total = printRemain(targets_remain, "Total good targets", true);
double [][][] coord_data_filtered_lma = filterAndShowTargetsLMA(
coord_lma,// double [][][] coord_data,
lma_rms, // double lma_rms, // = 1.5; // Maximal RMS (should always match, regardless if A)
lma_arms, // double lma_arms, // = 0.03; // Maximal absolutre RMS
lma_rrms, // double lma_rrms, // = 0.03; // Maximal relative to A rms. OK is when (RMS < cuas_lma_arms) || (RMS < cuas_lma_rrms * A)
lma_mina, // double lma_mina, // = 1.0; // Minimal A (amplitude)
lma_maxr, // double lma_maxr, // = 5.0; // Minimal K (overshoot) = 3.0
lma_mink, // double lma_mink, // = 1.0; // Minimal K (overshoot) = 1.0
lma_maxk, // double lma_maxk, // = 1.0; // Minimal K (overshoot) = 3.0
slice_titles, // String [] slice_titles, //
title_targets_filt+"-n"+niter, // String title_targets_filt,
targets_remain, // int [] targets_remain,
cuasMotion.tilesX); // int tilesX)
cuasMotion.tilesX, // int tilesX)
show_vector_field); // boolean show)
remained_total = printRemain(targets_remain, "coord_data_filtered: Total new targets LMA", true);
float [][] fpixels_accumulated_filtered = getTargetImages(
coord_data_filtered, // final double [][][] vector_fields, // centers , just null/not null
fpixels_accumulated, // final float [][] accum_data, // should be around 0, no low-freq
cuasMotion.tilesX); // final int tilesX)
ShowDoubleFloatArrays.showArrays(
fpixels_accumulated_filtered,
cuasMotion.gpu_max_width,
cuasMotion.gpu_max_height,
true,
title_acc_targets, // "-corr2d"+"-"+frame0+"-"+frame1+"-"+corr_pairs,
titles_accum);
/*
boolean [][] good_targets = filterTargets(
coord_data, // final double [][][] target_coords,
target_strength, // final double target_strength,
target_frac, // final double [][] target_frac, // pairs - strength, minimal fraction for that strength
cuasMotion.tilesX, // final int tilesX,
targets_remain); // final int [] remain) {
double [][][] coord_data_filtered = applyFilter(
coord_data, // double [][][] motion_scan,
good_targets); // boolean [][] filter5)
showVectorFieldsSequence(
coord_data_filtered, // double [][][] vector_fields_sequence,
0.0, // double speed_min,
0.0, // double speed_pref,
1.0, // double speed_boost,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_targets_filt, // String title,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
*/
if (debugLevel > -4) {
System.out.println("testCuasScanMotion() Total good targets for "+targets_remain.length+" scene sequences is "+remained_total);
}
if (debugLevel > -4) {
System.out.println("All DONE");
}
} // while (true) {
}
public static int printRemain(int [] remain, String s, boolean all) {
int remained_total = 0;
for (int nseq = 0; nseq < remain.length; nseq++) {
remained_total += remain[nseq];
}
System.out.println(s+": total tiles for "+remain.length+" scene sequences is "+remained_total);
if (all) {
for (int nscan = 0; nscan < remain.length; nscan++) {
System.out.print(nscan+":"+remain[nscan]+", ");
}
System.out.println();
}
return remained_total;
}
public static double [][][] cloneMotionScan(
double [][][] motionScan,
int [] remain){
double [][][] cloned = new double[motionScan.length][motionScan[0].length][];
for (int nseq = 0; nseq<cloned.length; nseq++) {
int n = 0;
for (int ntile = 0; ntile < cloned[nseq].length; ntile++) {
if (motionScan[nseq][ntile] != null) {
cloned[nseq][ntile] = motionScan[nseq][ntile].clone();
n++;
}
}
if (remain != null) remain[nseq] = n;
}
return cloned;
}
public static double [][][] combineMotionScans(
double [][][] scan0,
double [][][] scan1,
int [] remain){ // preference
double [][][] comboScan = new double[scan0.length][scan0[0].length][];
for (int nseq = 0; nseq < comboScan.length; nseq++) {
int n = 0;
for (int ntile = 0; ntile < comboScan[nseq].length; ntile++) {
if (scan1[nseq][ntile] != null) {
comboScan[nseq][ntile] = scan1[nseq][ntile].clone();
n++;
} else if (scan0[nseq][ntile] != null) {
comboScan[nseq][ntile] = scan0[nseq][ntile].clone();
n++;
}
}
if (remain != null) remain[nseq] = n;
}
return comboScan;
}
public static double [][][] subtractMotionScans(
double [][][] scan0,
double [][][] scan1,
int [] remain){ // keep scan0 that is not in scan1
double [][][] comboScan = new double[scan0.length][scan0[0].length][];
for (int nseq = 0; nseq < comboScan.length; nseq++) {
int n = 0;
for (int ntile = 0; ntile < comboScan[nseq].length; ntile++) {
if ((scan0[nseq][ntile] != null) && (scan1[nseq][ntile] == null)) {
comboScan[nseq][ntile] = scan0[nseq][ntile].clone();
n++;
}
}
if (remain != null) remain[nseq] = n;
}
return comboScan;
}
public static double [][][] filterMotionScans(
double [][][] scan0,
double [][][] scan1,
int [] remain){ // keep scan0 that is in scan1
double [][][] comboScan = new double[scan0.length][scan0[0].length][];
for (int nseq = 0; nseq < comboScan.length; nseq++) {
int n = 0;
for (int ntile = 0; ntile < comboScan[nseq].length; ntile++) {
if ((scan0[nseq][ntile] != null) && (scan1[nseq][ntile] != null)) {
comboScan[nseq][ntile] = scan0[nseq][ntile].clone();
n++;
}
}
if (remain != null) remain[nseq] = n;
}
return comboScan;
}
public static double[][][] filterAndShowTargets(
double [][][] coord_data,
double target_strength,
......@@ -681,38 +1358,78 @@ public class CuasMotion {
String [] slice_titles, //
String title_targets_filt,
int [] targets_remain,
int tilesX) {
// int [] targets_remain = new int [coord_data.length];
int tilesX,
boolean show) {
boolean [][] good_targets = filterTargets(
coord_data, // final double [][][] target_coords,
target_strength, // final double target_strength,
target_frac, // final double [][] target_frac, // pairs - strength, minimal fraction for that strength
tilesX, // final int tilesX,
targets_remain); // final int [] remain) {
if (targets_remain !=null) {
for (int nscan = 0; nscan < targets_remain.length; nscan++) {
System.out.print(nscan+":"+targets_remain[nscan]+", ");
}
System.out.println();
double [][][] coord_data_filtered = applyFilter(
coord_data, // double [][][] motion_scan,
good_targets); // boolean [][] filter5)
if (show) {
///ImagePlus imp =
showVectorFieldsSequence(
coord_data_filtered, // double [][][] vector_fields_sequence,
0.0, // double speed_min,
0.0, // double speed_pref,
1.0, // double speed_boost,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_targets_filt, // String title,
false, // boolean nan_effective_strength,
true, // boolean show,
tilesX); // int tilesX) {
}
return coord_data_filtered; // manually restart with different parameters
}
public static double[][][] filterAndShowTargetsLMA(
double [][][] coord_data,
double lma_rms, // = 1.5; // Maximal RMS (should always match, regardless if A)
double lma_arms, // = 0.06; // Maximal absolute RMS (should match one of cuas_lma_arms OR cuas_lma_rrms (0.484)
double lma_rrms, // = 0.15; // Maximal relative to A rms. OK is when (RMS < cuas_lma_arms) || (RMS < cuas_lma_rrms * A)
double lma_mina, // = 1.0; // Minimal A (amplitude)
double lma_maxr, // = 5.0; // Minimal K (overshoot) = 3.0
double lma_mink, // = 0.0; // Minimal K (overshoot) = 1.0
double lma_maxk, // = 5.0; // Minimal K (overshoot) = 3.0
String [] slice_titles, //
String title_targets_filt,
int [] targets_remain,
int tilesX,
boolean show) {
double lma_minxy = 0.8;
boolean [][] good_targets = filterTargetsLMA(
coord_data, // final double [][][] target_coords,
lma_rms, // double lma_rms, // = 1.5; // Maximal RMS (should always match, regardless if A)
lma_arms, // double lma_arms, // = 0.03; // Maximal absolutre RMS
lma_rrms, // double lma_rrms, // = 0.03; // Maximal relative to A rms. OK is when (RMS < cuas_lma_arms) || (RMS < cuas_lma_rrms * A)
lma_mina, // double lma_mina, // = 1.0; // Minimal A (amplitude)
lma_maxr, // double lma_maxr, // = 5.0; // Minimal K (overshoot) = 3.0
lma_mink, // double lma_mink, // = 1.0; // Minimal K (overshoot) = 1.0
lma_maxk, // double lma_maxk, // = 1.0; // Minimal K (overshoot) = 3.0
lma_minxy, // final double lma_minxy, // 0.8
tilesX, // final int tilesX,
targets_remain); // final int [] remain) {
double [][][] coord_data_filtered = applyFilter(
coord_data, // double [][][] motion_scan,
good_targets); // boolean [][] filter5)
if (show) {
///ImagePlus imp =
showVectorFieldsSequence(
coord_data_filtered, // double [][][] vector_fields_sequence,
0.0, // double speed_min,
0.0, // double speed_pref,
1.0, // double speed_boost,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_targets_filt, // String title,
false, // boolean nan_effective_strength,
true, // boolean show,
tilesX); // int tilesX) {
return coord_data_filtered; // manually restart with different parameters
showVectorFieldsSequenceLMA(
coord_data_filtered, // double [][][] target_scene_sequence,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
title_targets_filt, // String title,
true, // boolean show,
tilesX); // int tilesX) {
}
return coord_data_filtered; // manually restart with different parameters
}
......@@ -773,12 +1490,30 @@ public class CuasMotion {
return acc_coord;
}
public static double [][][] getAccumulatedCoordinates(
public static double [][][][] getAccumulatedCoordinates(
final double [][][] vector_fields, // centers
final float [][] accum_data, // should be around 0, no low-freq
final float [][] accum_data, // should be around 0, no low-freq
final double centroid_radius,
final int n_recenter, // re-center window around new maximum. 0 -no refines (single-pass)
final int tilesX){
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 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 int debugLevel){
final int tile2 = 2 * GPUTileProcessor.DTT_SIZE;
final int num_seq = vector_fields.length; // same as accum_data.length
final int num_tiles = vector_fields[0].length;
......@@ -787,12 +1522,26 @@ public class CuasMotion {
final int width = GPUTileProcessor.DTT_SIZE * tilesX;
// final int height = num_pix/width;
final double [][][] acc_coord = new double[num_seq][num_tiles][];
final double [][][] lma_coord = 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 boolean[] fpn_mask= no_border? (new boolean[0]) : null;
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
double [] pix_tile = new double [tile2 * tile2];
CuasMotionLMA cuasMotionLMA = new CuasMotionLMA(
tile2, // int width,
lma_sigma); // double sigma);
// 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()) {
for (int ntile = 0; ntile < num_tiles; ntile++) {
......@@ -815,10 +1564,31 @@ public class CuasMotion {
-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, // boolean [] fpn_mask,
fpn_mask, // boolean [] fpn_mask,
false, // boolean ignore_border, // only if fpn_mask != null - ignore tile if maximum touches fpn_mask
false); // boolean debug)
acc_coord[nSeq][ntile] = mv; // no filtering here
if (mv != null) {
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,
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
debugLevel); // int debug_level)
if (rslt >= 0) {
lma_coord[nSeq][ntile] = cuasMotionLMA.getResult();
}
}
}
}
}
......@@ -826,7 +1596,7 @@ public class CuasMotion {
};
}
ImageDtt.startAndJoin(threads);
return acc_coord;
return new double [][][][] {acc_coord, lma_coord};
}
public static float [][] getTargetImages(
......@@ -935,9 +1705,43 @@ public class CuasMotion {
VF_TOP_TITLES, // String [] frame_titles, // frame titles or null
show); // boolean show)
return imp;
}
public static ImagePlus showVectorFieldsSequenceLMA(
double [][][] target_scene_sequence, // rename
String [] titles, // all slices*frames titles or just slice titles or null
String title,
boolean show,
int tilesX) {
int num_fileds = CuasMotionLMA.LMA_TITLES.length;
int num_scenes = target_scene_sequence.length;
int num_tiles = target_scene_sequence[0].length;
double [][][] img_data = new double [num_fileds][num_scenes][num_tiles];
for (int nscene = 0; nscene < num_scenes; nscene++) {
for (int nfiled = 0; nfiled < num_fileds; nfiled++) {
Arrays.fill(img_data[nfiled][nscene], Double.NaN);
}
for (int ntile=0; ntile<target_scene_sequence[nscene].length; ntile++) {
if (target_scene_sequence[nscene][ntile] != null) {
for (int nfield = 0; nfield < CuasMotionLMA.RSLT_LEN; nfield++) {
img_data[nfield][nscene][ntile] = target_scene_sequence[nscene][ntile][nfield];
}
}
}
}
ImagePlus imp = ShowDoubleFloatArrays.showArraysHyperstack(
img_data, // double[][][] pixels,
tilesX, // int width,
title, // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
titles, // String [] titles, // all slices*frames titles or just slice titles or null
CuasMotionLMA.LMA_TITLES, // String [] frame_titles, // frame titles or null
show); // boolean show)
return imp;
}
public static double [][][] getVectorFieldHyper(String path){
int [] wh = new int [2];
......@@ -1025,6 +1829,83 @@ public class CuasMotion {
ImageDtt.startAndJoin(threads);
return filter_target;
}
public static boolean [][] filterTargetsLMA(
final double [][][] target_coords,
double lma_rms, // = 1.5; // Maximal RMS (should always match, regardless if A)
double lma_arms, // = 0.06; // Maximal absolute RMS (should match one of cuas_lma_arms OR cuas_lma_rrms (0.484)
double lma_rrms, // = 0.15; // Maximal relative to A rms. OK is when (RMS < cuas_lma_arms) || (RMS < cuas_lma_rrms * A)
double lma_mina, // = 1.0; // Minimal A (amplitude)
double lma_maxr, // = 5.0; // Minimal K (overshoot) = 3.0
double lma_mink, // = 0.0; // Minimal K (overshoot) = 1.0
double lma_maxk, // = 5.0; // Minimal K (overshoot) = 3.0
final double lma_minxy, // 0.8
final int tilesX,
final int [] remain) {
final int num_seq = target_coords.length;
final int num_tiles = target_coords[0].length;
final int tilesY = num_tiles/ tilesX;
final boolean [][] filter_target = new boolean [num_seq][num_tiles];
final double maxxy = GPUTileProcessor.DTT_SIZE - 1 -lma_minxy; // lma_minxy=1 - prevent bottom row/righth column
final double minxy = -GPUTileProcessor.DTT_SIZE +lma_minxy; // lma_minxy=1 - prevent top row/left column
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 < num_seq; nSeq = ai.getAndIncrement()) {
int num = 0;
for (int tileY = 0; tileY < tilesY; tileY++) {
for (int tileX = 0; tileX < tilesX; tileX++) {
int ntile = tileX + tilesX * tileY;
double [] lma_rslts = target_coords[nSeq][ntile];
if (lma_rslts != null) {
if (lma_rslts[CuasMotionLMA.RSLT_ITERS] < 0) { // fitting has not failed
continue; // LMA failed
}
double A = lma_rslts[CuasMotionLMA.RSLT_A];
if (A < lma_mina) {
continue; // too weak
}
if (lma_rslts[CuasMotionLMA.RSLT_RMS] > lma_rms) {
continue; // too high RMSE regardless of A
}
double max_RMS = Math.max(lma_arms, A * lma_rrms);
if (lma_rslts[CuasMotionLMA.RSLT_RMS] > max_RMS) {
continue; // too high RMSE
}
if (lma_rslts[CuasMotionLMA.RSLT_R0] > lma_maxr) {
continue; // Radius is too high
}
if (lma_rslts[CuasMotionLMA.RSLT_K] < lma_mink) {
continue; // K is too low
}
if (lma_rslts[CuasMotionLMA.RSLT_K] > lma_maxk) {
continue; // K is too high
}
double x = lma_rslts[CuasMotionLMA.RSLT_X];
double y = lma_rslts[CuasMotionLMA.RSLT_Y];
if ((x < minxy) || (y < minxy) || (x > maxxy) || (y > maxxy)) {
continue; // center outside of allowed range (on the very edges)
}
filter_target[nSeq][ntile] = true;
num++;
}
}
}
if (remain != null) {
remain[nSeq] = num;
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return filter_target;
}
public static boolean [][] filterMotionScan(
final double [][][] motion_scan,
......@@ -1137,7 +2018,7 @@ public class CuasMotion {
final boolean [][] filtered, // centers, should be non-overlapped . May be [motion_scan.length][] - will be calculated and returned
final int tilesX,
final int range, // 1 or 2
final int [] remain){
final int [] remain){ // number of center tiles (3x3 groups in the output)
final int num_seq = motion_scan.length;
final int num_tiles = motion_scan[0].length;
final int tilesY = num_tiles/ tilesX;
......@@ -1522,6 +2403,7 @@ public class CuasMotion {
public float [][] shiftAndRenderAccumulate(
CLTParameters clt_parameters,
final boolean zero_fill,
final float [][] fpixels,
final double [][][] vector_field,
final int frame0, // for vector_field[0]
......@@ -1530,15 +2412,7 @@ public class CuasMotion {
final boolean smooth,
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][];
float [][] frames_accum = new float [vector_field.length][];
Arrays.fill(nan_frame, Float.NaN);
// Arrays.fill(result_frames, nan_frame);
Arrays.fill(frames_accum, nan_frame);
// int half_step = frame_step/2;
final double [] window_full = new double [2*half_range+1];
double s0 = 1.0;
window_full[half_range] = 1.0;
......@@ -1625,6 +2499,9 @@ public class CuasMotion {
for (int nSeq = ai.getAndIncrement(); nSeq < frames_accum.length; nSeq = ai.getAndIncrement()) {
for (int i = 0; i < frames_accum[nSeq].length; i++) {
frames_accum[nSeq][i] *=-1;
if (zero_fill && Double.isNaN(frames_accum[nSeq][i])){
frames_accum[nSeq][i] = 0f;
}
}
}
}
......
package com.elphel.imagej.cuas;
import java.util.concurrent.atomic.AtomicInteger;
import com.elphel.imagej.tileprocessor.ImageDtt;
import com.elphel.imagej.tileprocessor.QuadCLT;
import Jama.Matrix;
/*
* Use fixed-position relative to initial max gaussian window weight
* fx = A*cos2(r/R0*pi/2)*cos(K*r/R0*pi/2)+C
* K<1, K~=2
* A,K,R0,C
* RR0= pi/(R0*2)
* r=sqrt((x-X0)^2+(y-Y0)^2)
*
* fx = A*cos2(r*RR0)*cos(K*RR0*r)+C
*
*
*
*
*/
public class CuasMotionLMA {
private static final double R_OFFS = 1e-6;
public static final int INDX_A = 0;
public static final int INDX_C = 1;
public static final int INDX_RR0 = 2;
public static final int INDX_K = 3;
public static final int INDX_X0 = 4; // relative to left
public static final int INDX_Y0 = 5; // relative to top
public static final int INDX_LEN = INDX_Y0+1;
// result vector indices
public static final int RSLT_X = 0;
public static final int RSLT_Y = 1;
public static final int RSLT_A = 2;
public static final int RSLT_R0 = 3;
public static final int RSLT_K = 4;
public static final int RSLT_C = 5;
public static final int RSLT_RMS = 6;
public static final int RSLT_ITERS = 7;
public static final int RSLT_LEN = RSLT_ITERS+1;
public static final String [] LMA_TITLES = {"X-OFFS","Y-OFFS", "AMPLITUDE","RADIUS","OVERSHOOT","OFFSET","RMSE","ITERATIONS"};
private int width;
private double [][] window;
private double [] y_vector;
private double [] weights;
private double [] full_vector = new double[INDX_LEN];
private int [] pindx; // full parameter index for vector
private int [] rindx; // vector index or -1
private double [] last_rms = null; // {rms, rms_pure}, matching this.vector
private double [] good_or_bad_rms = null; // just for diagnostics, to read last (failed) rms
private double [] initial_rms = null; // {rms, rms_pure}, first-calcualted rms
private double [] last_ymfx = null;
private double [][] last_jt = null;
private int iters = -2; // never ran
public CuasMotionLMA(
int width,
double sigma) {
this.width = width;
window = new double [width][width];
double k = -0.5/(sigma*sigma);
for (int i = 0; i < width; i++) {
for (int j = 0; j < width; j++) {
window[i][j] = Math.exp(k*(i*i+j*j));
}
}
}
public int prepareLMA(
boolean [] param_select,
double [] tile_data,
double xc, // relative to center =width/2
double yc, // relative to center =width/2
double r0,
double k,
int debugLevel) {
y_vector = tile_data;
double x0 = Math.min(Math.max(xc + width/2, 0), width-1);
double y0 = Math.min(Math.max(yc + width/2, 0), width-1);
int ix0 = (int) Math.round(x0);
int iy0 = (int) Math.round(y0);
full_vector[INDX_A] = tile_data[ix0+iy0*width];
full_vector[INDX_C] = 0;
full_vector[INDX_RR0] = Math.PI/(2* r0);
full_vector[INDX_K] = k; // > 1 (~2.0)
full_vector[INDX_X0] = x0;
full_vector[INDX_Y0] = y0;
weights = new double [width*width];
double sw = 0;
for (int y = 0; y < width; y++) {
int ay = Math.abs(y-iy0);
for (int x = 0; x < width; x++) {
int ax = Math.abs(x-ix0);
double w = window[ay][ax]; // window to the nearest integer x,y
weights[x + y*width] = w;
sw += w;
}
}
for (int i = 0; i < weights.length; i++) {
weights[i] /= sw;
}
int indx = 0;
for (int i = 0; i < INDX_LEN; i++) if (param_select[i]){
indx++;
}
rindx = new int [INDX_LEN];
pindx = new int [indx];
indx= 0;
for (int i = 0; i < INDX_LEN; i++) {
if (param_select[i]) {
pindx[indx] = i;
rindx[i] = indx++;
} else {
rindx[i] = -1;
}
}
last_jt = new double [pindx.length][];
double [] fx = getFxDerivs(
getParametersVector(), // double [] vector,
last_jt, // final double [][] jt, // should be null or initialized with [vector.length][]
debugLevel); // final int debug_level)
last_rms = new double [2];
last_ymfx = getYminusFxWeighted(
fx, // final double [] fx,
last_rms); // final double [] rms_fp // null or [2]
initial_rms = last_rms.clone();
good_or_bad_rms = last_rms.clone();
return 0;
}
public double getRMS() {
return last_rms[0];
}
public double getInitialRMS() {
return initial_rms[0];
}
public double [] getResult() {
double rslt[] = new double [RSLT_LEN];
rslt[RSLT_X] = getCenter()[0];
rslt[RSLT_Y] = getCenter()[1];
rslt[RSLT_A] = getA();
rslt[RSLT_R0] = getR0();
rslt[RSLT_K] = getK();
rslt[RSLT_C] = getC();
rslt[RSLT_RMS] = getRMS();
rslt[RSLT_ITERS] = getIters();
return rslt;
}
public double [] getCenter(){
return new double [] {full_vector[INDX_X0] - width/2, full_vector[INDX_Y0]-width/2};
}
public double getRR0() {
return full_vector[INDX_RR0];
}
public double getR0() {
return Math.PI/(2 * full_vector[INDX_RR0]);
}
public double getA() {
return full_vector[INDX_A];
}
public double getC() {
return full_vector[INDX_C];
}
public double getK() {
return full_vector[INDX_K];
}
public int getIters() {
return iters;
}
public double [] getFullParametersVector() {
return full_vector;
}
public double [] getParametersVector() {
double [] vector = new double [pindx.length];
for (int i = 0; i < vector.length; i++) {
vector[i] = full_vector[pindx[i]];
}
return vector;
}
public void setParametersVector(double [] vector) {
for (int i = 0; i < vector.length; i++) {
full_vector[pindx[i]] = vector[i];
}
}
public int runLma( // <0 - failed, >=0 iteration number (1 - immediately)
double lambda, // 0.1
double lambda_scale_good,// 0.5
double lambda_scale_bad, // 8.0
double lambda_max, // 100
double rms_diff, // 0.001
int num_iter, // 20
int debug_level)
{
boolean last_run = true;
boolean [] rslt = {false,false};
this.last_rms = null; // remove?
int iter = 0;
for (iter = 0; iter < num_iter; iter++) {
rslt = lmaStep(
lambda,
rms_diff,
debug_level);
if (rslt == null) {
iters = -1;
return iters;
}
if (debug_level > 1) {
System.out.println("LMA step "+iter+": {"+rslt[0]+","+rslt[1]+"} full RMS= "+good_or_bad_rms[0]+
" ("+initial_rms[0]+"), pure RMS="+good_or_bad_rms[1]+" ("+initial_rms[1]+") + lambda="+lambda);
}
if (rslt[1]) {
break;
}
if (rslt[0]) { // good
lambda *= lambda_scale_good;
} else {
lambda *= lambda_scale_bad;
if (lambda > lambda_max) {
break; // not used in lwir
}
}
// if (dbg_prefix != null) {
// showDebugImage(dbg_prefix+"-"+iter+(rslt[0]?"-GOOD":"-BAD"));
// }
}
if (rslt[0]) { // better
if (iter >= num_iter) { // better, but num tries exceeded
if (debug_level > 1) System.out.println("Step "+iter+": Improved, but number of steps exceeded maximal");
} else {
if (debug_level > 1) System.out.println("Step "+iter+": LMA: Success");
}
} else { // improved over initial ?
if (last_rms[0] < initial_rms[0]) { // NaN
rslt[0] = true;
if (debug_level > 1) System.out.println("Step "+iter+": Failed to converge, but result improved over initial");
} else {
if (debug_level > 1) System.out.println("Step "+iter+": Failed to converge");
}
}
// if (dbg_prefix != null) {
// showDebugImage(dbg_prefix+"-FINAL");
// }
boolean show_intermediate = true;
if (show_intermediate && (debug_level > 0)) {
System.out.println("LMA: full RMS="+last_rms[0]+" ("+initial_rms[0]+"), pure RMS="+last_rms[1]+" ("+initial_rms[1]+") + lambda="+lambda);
}
if (debug_level > 2){
// String [] lines1 = printOldNew(false); // boolean allvectors)
// System.out.println("iteration="+iter);
// for (String line : lines1) {
// System.out.println(line);
// }
}
if (debug_level > 0) {
if ((debug_level > 1) || last_run) { // (iter == 1) || last_run) {
if (!show_intermediate) {
System.out.println("LMA: iter="+iter+", full RMS="+last_rms[0]+" ("+initial_rms[0]+"), pure RMS="+last_rms[1]+" ("+initial_rms[1]+") + lambda="+lambda);
}
// String [] lines = printOldNew(false); // boolean allvectors)
// for (String line : lines) {
// System.out.println(line);
// }
}
}
if ((debug_level > -2) && !rslt[0]) { // failed
if ((debug_level > 1) || (iter == 1) || last_run) {
System.out.println("LMA failed on iteration = "+iter);
// String [] lines = printOldNew(true); // boolean allvectors)
// for (String line : lines) {
// System.out.println(line);
// }
}
System.out.println();
}
// No need to updateFullParameters() in this implementation - they are already updated
/*
if (rslt[0]) {
updateFullParameters();
}
*/
iters = rslt[0]? iter : -1;
return iters;
}
private boolean [] lmaStep(
double lambda,
double rms_diff,
int debug_level) {
boolean [] rslt = {false,false};
double [] parameters_vector = getParametersVector();
// maybe the following if() branch is not needed - already done in prepareLMA !
if (this.last_rms == null) { //first time, need to calculate all (vector is valid)
last_rms = new double[2];
if (debug_level > 1) {
System.out.println("lmaStep(): first step");
}
double [] fx = getFxDerivs(
parameters_vector, // parameters_vector, // double [] vector,
last_jt, // final double [][] jt, // should be null or initialized with [vector.length][]
debug_level); // final int debug_level)
last_ymfx = getYminusFxWeighted(
fx, // final double [] fx,
last_rms); // final double [] rms_fp // null or [2]
this.initial_rms = this.last_rms.clone();
this.good_or_bad_rms = this.last_rms.clone();
if (last_ymfx == null) {
return null; // need to re-init/restart LMA
}
// TODO: Restore/implement
if (debug_level > 3) {
double delta = 1E-5;
double delta_err=compareJT(
parameters_vector, // double [] vector,
delta, // double delta,
false); // last3only); // boolean last3only); // do not process samples - they are tested before
System.out.println("\nMaximal error = "+delta_err);
/*
dbgJacobians(
corr_vector, // GeometryCorrection.CorrVector corr_vector,
1E-5, // double delta,
true); //boolean graphic)
*/
}
}
if (debug_level > 3) {
double delta = 1E-5;
double delta_err=compareJT(
parameters_vector, // double [] vector,
delta, // double delta,
false); // last3only); // boolean last3only); // do not process samples - they are tested before
System.out.println("\nMaximal error = "+delta_err);
/*
dbgJacobians(
corr_vector, // GeometryCorrection.CorrVector corr_vector,
1E-5, // double delta,
true); //boolean graphic)
*/
}
Matrix y_minus_fx_weighted = new Matrix(this.last_ymfx, this.last_ymfx.length);
Matrix wjtjlambda = new Matrix(getWJtJlambda(
lambda, // *10, // temporary
this.last_jt)); // double [][] jt)
if (debug_level>2) {
System.out.println("JtJ + lambda*diag(JtJ");
wjtjlambda.print(18, 6);
}
Matrix jtjl_inv = null;
try {
jtjl_inv = wjtjlambda.inverse(); // check for errors
} catch (RuntimeException e) {
rslt[1] = true;
if (debug_level > 0) {
System.out.println("Singular Matrix!");
}
return rslt;
}
if (debug_level>2) {
System.out.println("(JtJ + lambda*diag(JtJ).inv()");
jtjl_inv.print(18, 6);
}
//last_jt has NaNs
Matrix jty = (new Matrix(this.last_jt)).times(y_minus_fx_weighted);
if (debug_level>2) {
System.out.println("Jt * (y-fx)");
jty.print(18, 6);
}
Matrix mdelta = jtjl_inv.times(jty);
if (debug_level>2) {
System.out.println("mdelta");
mdelta.print(18, 10);
}
double scale = 1.0;
double [] delta = mdelta.getColumnPackedCopy();
double [] new_vector = parameters_vector.clone();
for (int i = 0; i < parameters_vector.length; i++) {
new_vector[i] += scale * delta[i];
}
double [] fx = getFxDerivs(
new_vector, // double [] vector,
last_jt, // final double [][] jt, // should be null or initialized with [vector.length][]
debug_level); // final int debug_level)
double [] rms = new double[2];
last_ymfx = getYminusFxWeighted(
fx, // final double [] fx,
rms); // final double [] rms_fp // null or [2]
if (debug_level > 2) {
/*
dbgYminusFx(this.last_ymfx, "next y-fX");
dbgXY(new_vector, "XY-correction");
*/
}
if (last_ymfx == null) {
return null; // need to re-init/restart LMA
}
this.good_or_bad_rms = rms.clone();
if (rms[0] < this.last_rms[0]) { // improved
rslt[0] = true;
rslt[1] = rms[0] >=(this.last_rms[0] * (1.0 - rms_diff));
this.last_rms = rms.clone();
parameters_vector = new_vector.clone();
setParametersVector(new_vector);
if (debug_level > 2) {
// print vectors in some format
/*
System.out.print("delta: "+corr_delta.toString()+"\n");
System.out.print("New vector: "+new_vector.toString()+"\n");
System.out.println();
*/
}
} else { // worsened
rslt[0] = false;
rslt[1] = false; // do not know, caller will decide
// restore state
fx = getFxDerivs(
parameters_vector, // double [] vector,
last_jt, // final double [][] jt, // should be null or initialized with [vector.length][]
debug_level); // final int debug_level)
last_ymfx = getYminusFxWeighted(
fx, // final double [] fx,
this.last_rms); // final double [] rms_fp // null or [2]
if (last_ymfx == null) {
return null; // need to re-init/restart LMA
}
if (debug_level > 2) {
/*
dbgJacobians(
corr_vector, // GeometryCorrection.CorrVector corr_vector,
1E-5, // double delta,
true); //boolean graphic)
*/
}
}
return rslt;
}
private double [][] getWJtJlambda( // USED in lwir
final double lambda,
final double [][] jt)
{
final int num_pars = jt.length;
final int nup_points = jt[0].length;
final double [][] wjtjl = new double [num_pars][num_pars];
for (int i = 0; i < num_pars; i++) {
for (int j = i; j < num_pars; j++) {
double d = 0.0;
for (int k = 0; k < nup_points; k++) {
// if (jt[i][k] != 0) {
// d+=0; // ???
// }
d += weights[k]*jt[i][k]*jt[j][k];
if (Double.isNaN(d)) {
System.out.println("CuasMotionLMA.getWJtJlambda(): NAN i="+i+", j="+j+", k="+k);
}
}
wjtjl[i][j] = d;
if (i == j) {
wjtjl[i][j] += d * lambda;
} else {
wjtjl[j][i] = d;
}
}
}
return wjtjl;
}
private double [] getYminusFxWeighted( // problems. at least with eigen?
final double [] fx,
final double [] rms_fp) { // null or [2]
final double [] wymfw = new double [fx.length];
double s_rms = 0.0;
for (int i = 0; i < fx.length; i++) {
double d = y_vector[i] - fx[i];
double wd = d * weights[i];
wymfw[i] = wd;
s_rms += d * wd;
}
double rms = Math.sqrt(s_rms); // assuming sum_weights == 1.0; /pure_weight); they should be re-normalized after adding regularization
if (rms_fp != null) {
rms_fp[0] = rms;
if (rms_fp.length > 1) {
rms_fp[1] = rms; // _pure;
}
}
return wymfw;
}
private double compareJT(
double [] vector,
double delta,
boolean last3only) { // do not process samples - they are tested before
double [] errors=new double [vector.length];
double [][] jt = new double [vector.length][];
System.out.print("Parameters vector = [");
for (int i = 0; i < vector.length; i++) {
System.out.print(vector[i]);
if (i < (vector.length -1)) System.out.print(", ");
}
System.out.println("]");
getFxDerivs(
vector,
jt, // final double [][] jt, // should be null or initialized with [vector.length][]
1); // debug_level);
double [][] jt_delta = getFxDerivsDelta(
vector, // double [] vector,
delta, // final double delta,
-1); // final int debug_level)
int start_index = last3only? (weights.length-3) : 0;
for (int n = start_index; n < weights.length; n++) if (weights[n] > 0) {
System.out.print(String.format("%3d",n));
for (int i = 0; i < vector.length; i++) {
System.out.print(String.format("\t%12.9f",jt[i][n]));
}
for (int i = 0; i < vector.length; i++) {
System.out.print(String.format("\t%12.9f",jt_delta[i][n]));
}
for (int i = 0; i < vector.length; i++) {
System.out.print(String.format("\t%12.9f",jt[i][n]-jt_delta[i][n]));
}
System.out.println();
/*
System.out.println(String.format(
"%3d\t%12.9f\t%12.9f\t%12.9f\t%12.9f\t%12.9f\t%12.9f\t%12.9f\t%12.9f\t%12.9f\t%12.9f\t%12.9f\t%12.9f",
n, jt[0][n], jt[1][n], jt[2][n], jt[3][n],
jt_delta[0][n], jt_delta[1][n], jt_delta[2][n], jt_delta[3][n],
jt[0][n]-jt_delta[0][n],jt[1][n]-jt_delta[1][n],jt[2][n]-jt_delta[2][n],jt[3][n]-jt_delta[3][n]));
*/
for (int i = 0; i < vector.length; i++) {
errors[i] = Math.max(errors[i], jt[i][n]-jt_delta[i][n]);
}
}
for (int i = 0; i < vector.length; i++) {
System.out.print("\t\t");
}
for (int i = 0; i < vector.length; i++) {
System.out.print(String.format("\t%12.9f",errors[i]));
}
/*
System.out.println(String.format(
"-\t-\t-\t-\t-\t-\t-\t-\t-\t%12.9f\t%12.9f\t%12.9f\t%12.9f",
errors[0], errors[1], errors[2], errors[3]));
*/
double err=0;
for (int i = 0; i < vector.length; i++) {
err = Math.max(errors[i], err);
}
return err;
}
private double [][] getFxDerivsDelta(
double [] vector,
final double delta,
final int debug_level) {
double [][] jt = new double [vector.length][weights.length];
for (int nv = 0; nv < vector.length; nv++) {
double [] vpm = vector.clone();
vpm[nv]+= 0.5*delta;
double [] fx_p = getFxDerivs(
vpm,
null, // final double [][] jt, // should be null or initialized with [vector.length][]
debug_level);
vpm[nv]-= delta;
double [] fx_m = getFxDerivs(
vpm,
null, // final double [][] jt, // should be null or initialized with [vector.length][]
debug_level);
for (int i = 0; i < weights.length; i++) if (weights[i] > 0) {
jt[nv][i] = (fx_p[i]-fx_m[i])/delta;
}
}
return jt;
}
private double [] getFxDerivs(
final double [] vector,
final double [][] jt, // should be null or initialized with [vector.length][]
final int debug_level) {
int height = y_vector.length/width;
final double [] fx = new double [y_vector.length];
if (jt != null) {
for (int i = 0; i < jt.length; i++) {
jt[i] = new double [y_vector.length]; // weights.length];
}
}
double A= (rindx[INDX_A] >=0)? vector[rindx[INDX_A]] : full_vector[INDX_A] ;
double C= (rindx[INDX_C] >=0)? vector[rindx[INDX_C]] : full_vector[INDX_C] ;
double RR0 = (rindx[INDX_RR0] >=0)? vector[rindx[INDX_RR0]] : full_vector[INDX_RR0] ;
double K = (rindx[INDX_K] >=0)? vector[rindx[INDX_K]] : full_vector[INDX_K] ; // >1.0
double X0 = (rindx[INDX_X0] >=0)? vector[rindx[INDX_X0]] : full_vector[INDX_X0] ;
double Y0 = (rindx[INDX_Y0] >=0)? vector[rindx[INDX_Y0]] : full_vector[INDX_Y0] ;
for (int y = 0; y < height; y++) {
double dy = y-Y0;
double dy2 = dy*dy;
for (int x = 0; x < width; x++) {
int indx = y*width+x;
double dx = x-X0;
double dx2 = dx*dx;
double r2 = dx2+dy2+R_OFFS;
double r = Math.sqrt(r2);
if (r*RR0 > Math.PI/2) { // outside circle where function is defined
fx[indx] = C;
if (jt != null) {
double df_dC = 1;
if (rindx[INDX_C] >=0) {
jt[rindx[INDX_C]][indx] = df_dC;
}
}
} else {
double W1 = Math.cos(r*RR0);
double W2 = Math.cos(r*RR0*K);
fx[indx] = A * (W1 * W1 * W2) + C;
if (jt != null) {
double dr2_dX0 = -2 * dx;
double dr2_dY0 = -2 * dy;
double dr_dr2 = 0.5 / r; // r !=0
double sin_rRR0 = Math.sin(r * RR0);
double dW1_dRR0 = -r * sin_rRR0; //
double dW1_dr = -RR0 *sin_rRR0;
double sin_rKRR0 = Math.sin(r * RR0 * K);
double dW2_dRR0 = -K * r * sin_rKRR0;
double dW2_dK = -r * RR0 * sin_rKRR0;
double dW2_dr = -K * RR0 * sin_rKRR0;
double df_dA = W1*W1*W2; // +
double df_dC = 1; // +
double df_dW1 = 2 * A* W1 * W2;
double df_dW2 = A * W1 * W1;
double df_dK = df_dW2 * dW2_dK;
double df_dRR0 = df_dW1*dW1_dRR0+df_dW2*dW2_dRR0;
double df_dr = df_dW1 * dW1_dr + df_dW2 * dW2_dr;
double df_dr2 = df_dr * dr_dr2;
double df_dX0 = df_dr2 * dr2_dX0;
double df_dY0 = df_dr2 * dr2_dY0;
double [] df_dfp = {df_dA,df_dC,df_dRR0, df_dK, df_dX0, df_dY0};
for (int i = 0; i < vector.length; i++) {
jt[i][indx] = df_dfp[pindx[i]];
}
}
}
}
}
return fx;
}
}
......@@ -2422,12 +2422,18 @@ public class Correlation2d {
boolean ignore_border, // only if fpn_mask != null - ignore tile if maximum touches fpn_mask
boolean debug)
{
boolean exclude_margins = false;
if ((fpn_mask!=null) && (fpn_mask.length==0)) {
exclude_margins = true;
fpn_mask = null;
}
boolean calc_fraction = data_width < 0;
if (calc_fraction) {
data_width = -data_width;
}
int data_height = data.length/data_width;
int center_xy = (data_width - 1)/2; // = transform_size - 1;
// int center_xy = (data_width - 1)/2; // = transform_size - 1;
int center_xy = data_width / 2; // = transform_size - 1;
double x0 = center_xy, y0 = center_xy;
int imax= 0;
for (int i= 1; i < data.length;i++) {
......@@ -2438,6 +2444,12 @@ public class Correlation2d {
double mx = data[imax];
int ix0 = imax % data_width;
int iy0 = imax / data_width;
if (exclude_margins) {
if ((ix0 == 0) || (iy0== 0) || (ix0 == (data_width-1)) || (iy0 == (data_height-1))) {
return null; // maximum is on the tile border.
}
}
x0 = ix0;
y0 = iy0;
// if (fpn_mask != null
......
......@@ -716,8 +716,33 @@ min_str_neib_fpn 0.35
public double cuas_target_radius = 3.0; // target centroids center radius
public double cuas_target_strength =0.8; // target centroids center radius
public double [][] cuas_target_frac = {{0,0.15},{2,0.3},{5,0.4}};
public boolean cuas_no_border = true; // exclude targets with centers on the 16x16 tile edges
// CUAS Motion LMA parameters
public double cuas_lma_sigma = 3.0;
public double cuas_lma_r0 = 3.0; //maximum with with overshoot
public double cuas_lma_ovrsht = 2.0;
public boolean cuas_lma_fit_xy = true;
public boolean cuas_lma_fit_a = true;
public boolean cuas_lma_fit_c = true;
public boolean cuas_lma_fit_r = true;
public boolean cuas_lma_fit_k = true;
public double cuas_lambda = 0.1;
public double cuas_lambda_good = 0.5;
public double cuas_lambda_bad = 8;
public double cuas_lambda_max = 100;
public double cuas_rms_diff = 0.001; // relative RMS improvement
public int cuas_num_iter = 20;
// CUAS Motion LMA filter parameters
public double cuas_lma_rms = 1.5; // Maximal RMS (should always match, regardless if A)
public double cuas_lma_arms = 0.06; // Maximal absolute RMS (should match one of cuas_lma_arms OR cuas_lma_rrms (0.484)
public double cuas_lma_rrms = 0.15; // Maximal relative to A rms. OK is when (RMS < cuas_lma_arms) || (RMS < cuas_lma_rrms * A)
public double cuas_lma_mina = 1.0; // Minimal A (amplitude) = 1.0 (< 2.0)
public double cuas_lma_maxr = 5.0; // Maximal R (radius) =5.0 (> 3.8)
public double cuas_lma_mink = 0.0; // Minimal K (overshoot) = 0.0 (<0.007)
public double cuas_lma_maxk = 5.0; // Maximal K (overshoot) = 5.0 (>3.8)
public boolean cuas_debug = false; // save debug images (and show them if not in batch mode)
public boolean cuas_step_debug = false; // save debug images during per-step cuas recalculation (and show them if not in batch mode)
......@@ -2157,6 +2182,61 @@ min_str_neib_fpn 0.35
"Minimal value of the target image.");
gd.addStringField ("Fraction for strengths", double2dToString(this.cuas_target_frac), 100,
"Variable number of (strength, fraction) pairs separated by \":\". Each pair of strength, minimal fraction is separated by \",\".");
gd.addCheckbox ("Target not on the tile edge", this.cuas_no_border,
"Exclude targets with centers on the edge of 16x16 tiles.");
gd.addMessage("=== Moving target LMA ===");
gd.addNumericField("Weight Gaussian sigma", this.cuas_lma_sigma, 5,8,"pix",
"Weights to emphasize maximum center area when fitting.");
gd.addNumericField("Target typical radius", this.cuas_lma_r0, 5,8,"pix",
"Typical target radius including negative overshoot (caused by UM filter).");
gd.addNumericField("Target maximum overshoot", this.cuas_lma_ovrsht, 5,8,"",
"Hos much smaller is the first zero than total maximum with overshoot (2.0 - first zero radius 1/2 of the full.");
gd.addCheckbox ("LMA fit X,Y", this.cuas_lma_fit_xy,
"Fit target center position.");
gd.addCheckbox ("LMA fit amplitude (strength)", this.cuas_lma_fit_a,
"Fit maximum amplitude.");
gd.addCheckbox ("LMA fit offset", this.cuas_lma_fit_c,
"Fit out-of-maximum level (offset).");
gd.addCheckbox ("LMA fit radius", this.cuas_lma_fit_r,
"Fit target total radius - includes negative overshoot caused by UM filter.");
gd.addCheckbox ("LMA fit overshoot", this.cuas_lma_fit_k,
"Fit target overshoot (2.0 - first zero crossing at half radius.");
gd.addMessage("--- Moving target LMA fitting parameters ---");
gd.addNumericField("LMA lambda", this.cuas_lambda, 5,8,"",
"LMA initial lambda.");
gd.addNumericField("Scale lambda after success", this.cuas_lambda_good, 5,8,"",
"Multiply lambda if RMS decreaed.");
gd.addNumericField("Scale lambda after failure", this.cuas_lambda_bad, 5,8,"",
"Multiply lambda if RMS increaed.");
gd.addNumericField("Maximal lambda", this.cuas_lambda_max, 5,8,"",
"Give up if lambda gets higher value.");
gd.addNumericField("Relative RMS improvement", this.cuas_rms_diff, 5,8,"",
"Finish fitting when the relative RMS improvement drops below this value.");
gd.addNumericField("LMA iterations", this.cuas_num_iter, 0,3,"",
"Maximal number of the LMA iterations.");
gd.addMessage("--- Moving target discrimination parameters theresholds ---");
gd.addNumericField("Maximal RMS", this.cuas_lma_rms, 5,8,"",
"Maximal RMS for target that should match always, regardless of the amplitude.");
gd.addNumericField("Maximal sufficient RMS", this.cuas_lma_arms, 5,8,"",
"Maximal sufficient RMS for target. Satisfying any of the sufficient or relative is enough");
gd.addNumericField("Maximal relative RMS", this.cuas_lma_rrms, 5,8,"",
"Maximal relative (to amplitude) RMS for target. Satisfying any of the absolute and relative is sufficient");
gd.addNumericField("Minimal target amplitude", this.cuas_lma_mina, 5,8,"",
"Filter out weak targets.");
gd.addNumericField("Maximal radius", this.cuas_lma_maxr, 5,8,"pix",
"Maximal target radius including negative overshoot.");
gd.addNumericField("Minimal overshoot ratio", this.cuas_lma_mink, 5,8,"",
"Minimal ratio of the overshoot radius to the first 0 radius (typical 1.0).");
gd.addNumericField("Maximal overshoot ratio", this.cuas_lma_maxk, 5,8,"",
"Maximal ratio of the overshoot radius to the first 0 radius (typical 3.0).");
gd.addMessage("=== Debug ===");
gd.addCheckbox ("Save/show debug images", this.cuas_debug,
......@@ -2170,8 +2250,6 @@ min_str_neib_fpn 0.35
"Overwrite value (when Overwrite... is checked).");
gd.addNumericField("Value to overwrote num_accum", this.cuas_num_accum, 0,3,"",
"Overwrite value (when Overwrite... is checked).");
gd.addTab("LMA sequence","Interscene LMA sequence control");
gd.addMessage("Parameters for control of the LMA pose adjustment sequence");
......@@ -3125,6 +3203,29 @@ min_str_neib_fpn 0.35
this.cuas_target_radius = gd.getNextNumber();
this.cuas_target_strength = gd.getNextNumber();
this.cuas_target_frac = stringToDouble2d(gd.getNextString());
this.cuas_no_border = gd.getNextBoolean();
this.cuas_lma_sigma = gd.getNextNumber();
this.cuas_lma_r0 = gd.getNextNumber();
this.cuas_lma_ovrsht = gd.getNextNumber();
this.cuas_lma_fit_xy = gd.getNextBoolean();
this.cuas_lma_fit_a = gd.getNextBoolean();
this.cuas_lma_fit_c = gd.getNextBoolean();
this.cuas_lma_fit_r = gd.getNextBoolean();
this.cuas_lma_fit_k = gd.getNextBoolean();
this.cuas_lambda = gd.getNextNumber();
this.cuas_lambda_good = gd.getNextNumber();
this.cuas_lambda_bad = gd.getNextNumber();
this.cuas_lambda_max = gd.getNextNumber();
this.cuas_rms_diff = gd.getNextNumber();
this.cuas_num_iter = (int) gd.getNextNumber();
this.cuas_lma_rms = gd.getNextNumber();
this.cuas_lma_arms = gd.getNextNumber();
this.cuas_lma_rrms = gd.getNextNumber();
this.cuas_lma_mina = gd.getNextNumber();
this.cuas_lma_maxr = gd.getNextNumber();
this.cuas_lma_mink = gd.getNextNumber();
this.cuas_lma_maxk = gd.getNextNumber();
this.cuas_debug = gd.getNextBoolean();
this.cuas_step_debug = gd.getNextBoolean();
......@@ -4018,6 +4119,29 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"cuas_target_radius", this.cuas_target_radius+""); // double
properties.setProperty(prefix+"cuas_target_strength", this.cuas_target_strength+"");// double
properties.setProperty(prefix+"cuas_target_frac", double2dToString(cuas_target_frac)+""); // double[][]
properties.setProperty(prefix+"cuas_no_border", this.cuas_no_border+""); // boolean
properties.setProperty(prefix+"cuas_lma_sigma", this.cuas_lma_sigma+""); // double
properties.setProperty(prefix+"cuas_lma_r0", this.cuas_lma_r0+""); // double
properties.setProperty(prefix+"cuas_lma_ovrsht", this.cuas_lma_ovrsht+""); // double
properties.setProperty(prefix+"cuas_lma_fit_xy", this.cuas_lma_fit_xy+""); // boolean
properties.setProperty(prefix+"cuas_lma_fit_a", this.cuas_lma_fit_a+""); // boolean
properties.setProperty(prefix+"cuas_lma_fit_c", this.cuas_lma_fit_c+""); // boolean
properties.setProperty(prefix+"cuas_lma_fit_r", this.cuas_lma_fit_r+""); // boolean
properties.setProperty(prefix+"cuas_lma_fit_k", this.cuas_lma_fit_k+""); // boolean
properties.setProperty(prefix+"cuas_lambda", this.cuas_lambda+""); // double
properties.setProperty(prefix+"cuas_lambda_good", this.cuas_lambda_good+""); // double
properties.setProperty(prefix+"cuas_lambda_bad", this.cuas_lambda_bad+""); // double
properties.setProperty(prefix+"cuas_lambda_max", this.cuas_lambda_max+""); // double
properties.setProperty(prefix+"cuas_rms_diff", this.cuas_rms_diff+""); // double
properties.setProperty(prefix+"cuas_num_iter", this.cuas_num_iter+""); // int
properties.setProperty(prefix+"cuas_lma_rms", this.cuas_lma_rms+""); // double
properties.setProperty(prefix+"cuas_lma_arms", this.cuas_lma_arms+""); // double
properties.setProperty(prefix+"cuas_lma_rrms", this.cuas_lma_rrms+""); // double
properties.setProperty(prefix+"cuas_lma_mina", this.cuas_lma_mina+""); // double
properties.setProperty(prefix+"cuas_lma_maxr", this.cuas_lma_maxr+""); // double
properties.setProperty(prefix+"cuas_lma_mink", this.cuas_lma_mink+""); // double
properties.setProperty(prefix+"cuas_lma_maxk", this.cuas_lma_maxk+""); // double
properties.setProperty(prefix+"cuas_debug", this.cuas_debug+""); // boolean
properties.setProperty(prefix+"cuas_step_debug", this.cuas_step_debug+""); // boolean
......@@ -4883,6 +5007,30 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"cuas_target_radius")!=null) this.cuas_target_radius=Double.parseDouble(properties.getProperty(prefix+"cuas_target_radius"));
if (properties.getProperty(prefix+"cuas_target_strength")!=null) this.cuas_target_strength=Double.parseDouble(properties.getProperty(prefix+"cuas_target_strength"));
if (properties.getProperty(prefix+"cuas_target_frac")!= null) cuas_target_frac=stringToDouble2d((String) properties.getProperty(prefix+"cuas_target_frac"));
if (properties.getProperty(prefix+"cuas_no_border")!=null) this.cuas_no_border=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_no_border"));
if (properties.getProperty(prefix+"cuas_lma_sigma")!=null) this.cuas_lma_sigma=Double.parseDouble(properties.getProperty(prefix+"cuas_lma_sigma"));
if (properties.getProperty(prefix+"cuas_lma_r0")!=null) this.cuas_lma_r0=Double.parseDouble(properties.getProperty(prefix+"cuas_lma_r0"));
if (properties.getProperty(prefix+"cuas_lma_ovrsht")!=null) this.cuas_lma_ovrsht=Double.parseDouble(properties.getProperty(prefix+"cuas_lma_ovrsht"));
if (properties.getProperty(prefix+"cuas_lma_fit_xy")!=null) this.cuas_lma_fit_xy=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_lma_fit_xy"));
if (properties.getProperty(prefix+"cuas_lma_fit_a")!=null) this.cuas_lma_fit_a=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_lma_fit_a"));
if (properties.getProperty(prefix+"cuas_lma_fit_c")!=null) this.cuas_lma_fit_c=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_lma_fit_c"));
if (properties.getProperty(prefix+"cuas_lma_fit_r")!=null) this.cuas_lma_fit_r=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_lma_fit_r"));
if (properties.getProperty(prefix+"cuas_lma_fit_k")!=null) this.cuas_lma_fit_k=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_lma_fit_k"));
if (properties.getProperty(prefix+"cuas_lambda")!=null) this.cuas_lambda=Double.parseDouble(properties.getProperty(prefix+"cuas_lambda"));
if (properties.getProperty(prefix+"cuas_lambda_good")!=null) this.cuas_lambda_good=Double.parseDouble(properties.getProperty(prefix+"cuas_lambda_good"));
if (properties.getProperty(prefix+"cuas_lambda_bad")!=null) this.cuas_lambda_bad=Double.parseDouble(properties.getProperty(prefix+"cuas_lambda_bad"));
if (properties.getProperty(prefix+"cuas_lambda_max")!=null) this.cuas_lambda_max=Double.parseDouble(properties.getProperty(prefix+"cuas_lambda_max"));
if (properties.getProperty(prefix+"cuas_rms_diff")!=null) this.cuas_rms_diff=Double.parseDouble(properties.getProperty(prefix+"cuas_rms_diff"));
if (properties.getProperty(prefix+"cuas_num_iter")!=null) this.cuas_num_iter=Integer.parseInt(properties.getProperty(prefix+ "cuas_num_iter"));
if (properties.getProperty(prefix+"cuas_lma_rms")!=null) this.cuas_lma_rms=Double.parseDouble(properties.getProperty(prefix+"cuas_lma_rms"));
if (properties.getProperty(prefix+"cuas_lma_arms")!=null) this.cuas_lma_arms=Double.parseDouble(properties.getProperty(prefix+"cuas_lma_arms"));
if (properties.getProperty(prefix+"cuas_lma_rrms")!=null) this.cuas_lma_rrms=Double.parseDouble(properties.getProperty(prefix+"cuas_lma_rrms"));
if (properties.getProperty(prefix+"cuas_lma_mina")!=null) this.cuas_lma_mina=Double.parseDouble(properties.getProperty(prefix+"cuas_lma_mina"));
if (properties.getProperty(prefix+"cuas_lma_maxr")!=null) this.cuas_lma_maxr=Double.parseDouble(properties.getProperty(prefix+"cuas_lma_maxr"));
if (properties.getProperty(prefix+"cuas_lma_mink")!=null) this.cuas_lma_mink=Double.parseDouble(properties.getProperty(prefix+"cuas_lma_mink"));
if (properties.getProperty(prefix+"cuas_lma_maxk")!=null) this.cuas_lma_maxk=Double.parseDouble(properties.getProperty(prefix+"cuas_lma_maxk"));
if (properties.getProperty(prefix+"cuas_debug")!=null) this.cuas_debug=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_debug"));
if (properties.getProperty(prefix+"cuas_step_debug")!=null) this.cuas_step_debug=Boolean.parseBoolean(properties.getProperty(prefix+"cuas_step_debug"));
......@@ -5748,6 +5896,29 @@ min_str_neib_fpn 0.35
for (int i = 0; i < this.cuas_target_frac.length; i++) {
imp.cuas_target_frac[i] = this.cuas_target_frac[i].clone();
}
imp.cuas_no_border = this.cuas_no_border;
imp.cuas_lma_sigma = this.cuas_lma_sigma;
imp.cuas_lma_r0 = this.cuas_lma_r0;
imp.cuas_lma_ovrsht = this.cuas_lma_ovrsht;
imp.cuas_lma_fit_xy = this.cuas_lma_fit_xy;
imp.cuas_lma_fit_a = this.cuas_lma_fit_a;
imp.cuas_lma_fit_c = this.cuas_lma_fit_c;
imp.cuas_lma_fit_r = this.cuas_lma_fit_r;
imp.cuas_lma_fit_k = this.cuas_lma_fit_k;
imp.cuas_lambda = this.cuas_lambda;
imp.cuas_lambda_good = this.cuas_lambda_good;
imp.cuas_lambda_bad = this.cuas_lambda_bad;
imp.cuas_lambda_max = this.cuas_lambda_max;
imp.cuas_rms_diff = this.cuas_rms_diff;
imp.cuas_num_iter = this.cuas_num_iter;
imp.cuas_lma_rms = this.cuas_lma_rms;
imp.cuas_lma_arms = this.cuas_lma_arms;
imp.cuas_lma_rrms = this.cuas_lma_rrms;
imp.cuas_lma_mina = this.cuas_lma_mina;
imp.cuas_lma_maxr = this.cuas_lma_maxr;
imp.cuas_lma_mink = this.cuas_lma_mink;
imp.cuas_lma_maxk = this.cuas_lma_maxk;
imp.cuas_debug = this.cuas_debug;
imp.cuas_step_debug = this.cuas_step_debug;
......
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