Commit 4342fd2a authored by Andrey Filippov's avatar Andrey Filippov

more working code for moving targets

parent da579ebb
......@@ -10,7 +10,9 @@ import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.gpu.GPUTileProcessor;
import com.elphel.imagej.gpu.GpuQuad;
import com.elphel.imagej.gpu.TpTask;
import com.elphel.imagej.tileprocessor.Correlation2d;
import com.elphel.imagej.tileprocessor.ImageDtt;
import com.elphel.imagej.tileprocessor.IntersceneMatchParameters;
import com.elphel.imagej.tileprocessor.QuadCLT;
import com.elphel.imagej.tileprocessor.TDCorrTile;
import com.elphel.imagej.tileprocessor.TileNeibs;
......@@ -18,10 +20,15 @@ import com.elphel.imagej.tileprocessor.TileNeibs;
import ij.ImagePlus;
public class CuasMotion {
final static private int INDX_VX = 0;
final static private int INDX_VY = 1;
final static private int INDX_STRENGTH = 2;
final static private int INDX_FRAC = 3;
final static private int INDX_VX = 0;
final static private int INDX_VY = 1;
final static private int INDX_STRENGTH = 2;
final static private int INDX_FRAC = 3;
final static private int INDX_SPEED = 4; // calculated separately
final static private int INDX_CONFIDENCE = 5; // calculated separately
final static String [] VF_TOP_TITLES = {"vX","vY","strength","fraction","speed", "confidence"};
private final GPUTileProcessor gpuTileProcessor;
private CLTParameters clt_parameters=null;
......@@ -235,7 +242,21 @@ public class CuasMotion {
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;
String vf_extended_dir = "/media/elphel/NVME/lwir16-proc/eagle_mountain/linked/movement/selected/13";
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];
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];
target_frac[i][1] = clt_parameters.imp.cuas_target_frac[i][1];
} else {
System.out.println("testCuasScanMotion(): wrong format for a pair of strength, fraction values.");
}
}
String data_dir = "/media/elphel/NVME/lwir16-proc/eagle_mountain/linked/movement/selected/13";
//file:///media/elphel/NVME/lwir16-proc/eagle_mountain/linked/movement/selected/12/INPUT-1747803449_165687.tiff-vector_extended-offs20-pairs50-rstr0.01-fz300.0-cr3.0-mr2-ms0.3-sp1.0-2.5.tiff
// gd.addStringField("KML document title", name, 100, "Provide title of the KML file");
// srt_path = gd.getNextString();
......@@ -256,9 +277,14 @@ public class CuasMotion {
gd.addNumericField("Minimal speed", speed_min, 5,8,"ppr", "Minimal target speed in pixels per range (per cuas_corr_offset).");
gd.addNumericField("Preferable speed", speed_pref, 5,8,"ppr", "Boost effective strength when speed is above this.");
gd.addNumericField("Maximal speed boost", speed_boost, 5,8,"", "Maximal speed-caused effective strength boost.");
gd.addNumericField("Local max range", max_range, 0,3,"", "While filtering local correlation maximums: 1 - 3x3 neighbors, 2 - 5x5 ones.");
gd.addStringField("vf_extended_dir",vf_extended_dir,100,"directory to read vf_extended file");
gd.addNumericField("Target radius", target_radius, 5,8,"pix","Target radius, also used to calculate fraction of totals inside (windowed) to all positive values.");
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.addStringField("Data directory", data_dir,100,"Intermediate results directory (to bypass first stages during debugging).");
gd.addCheckbox ("Save_params", save_params, "Save edited parameters");
......@@ -280,8 +306,12 @@ public class CuasMotion {
speed_boost = gd.getNextNumber();
max_range = (int) gd.getNextNumber();
vf_extended_dir = gd.getNextString();
target_radius = gd.getNextNumber();
target_strength = gd.getNextNumber();
target_frac = IntersceneMatchParameters.stringToDouble2d(gd.getNextString());
data_dir = gd.getNextString();
save_params = gd.getNextBoolean();
if (save_params) {
......@@ -297,6 +327,18 @@ public class CuasMotion {
clt_parameters.imp.cuas_smooth = smooth;
clt_parameters.imp.cuas_max_range = max_range;
clt_parameters.imp.cuas_half_step = half_step;
clt_parameters.imp.cuas_target_radius = target_radius;
clt_parameters.imp.cuas_target_strength = target_strength;
clt_parameters.imp.cuas_target_frac = new double [target_frac.length][2];
for (int i = 0; i < target_frac.length; i++) {
if (target_frac[i].length >= 2) {
clt_parameters.imp.cuas_target_frac[i][0] = target_frac[i][0];
clt_parameters.imp.cuas_target_frac[i][1] = target_frac[i][1];
} else {
System.out.println("testCuasScanMotion(): 2.wrong format for a pair of strength, fraction values.");
}
}
}
int start_frame = 0;
......@@ -325,6 +367,9 @@ public class CuasMotion {
System.out.println("speed_boost= "+speed_boost);
System.out.println("fat_zero= "+fat_zero);
System.out.println("max_range= "+max_range);
System.out.println("target_radius= "+target_radius);
System.out.println("target_strength= "+target_strength);
System.out.println("target_frac= "+IntersceneMatchParameters.double2dToString(target_frac));
}
float [][] fpixels = new float[num_scenes][];
String [] scene_titles = new String [num_scenes];
......@@ -332,32 +377,64 @@ public class CuasMotion {
fpixels[nscene] = (float[]) imp_sel.getStack().getPixels(nscene+first_corr+1);
scene_titles[nscene] = imp_sel.getStack().getSliceLabel(nscene+first_corr+1);
}
String [] slice_titles= new String [num_corr_samples];
for (int nscan = 0; nscan < num_corr_samples; nscan++) {
int frame_cent = start_frame + corr_step * nscan + seq_length/2; // debug only
slice_titles[nscan] = imp_sel.getStack().getSliceLabel(frame_cent+1);
}
CuasMotion cuasMotion = new CuasMotion (
clt_parameters, // CLTParameters clt_parameters,
parentCLT, // QuadCLT parentCLT,
debugLevel); // int debugLevel)
String suffix_param = "-offs"+corr_offset+"-pairs"+corr_pairs+"-rstr"+rstr+"-fz"+fat_zero+"-cr"+cent_radius+"-mr"+max_range +
"-ms"+speed_min+"-sp"+speed_pref+"-"+speed_boost;
"-ms"+speed_min+"-sp"+speed_pref+"-sb"+speed_boost+"-tr"+target_radius+"-ts"+target_strength+
"-tf"+IntersceneMatchParameters.double2dToString(target_frac);
String imp_name = imp_sel.getTitle();
imp_name = trimSuffix(imp_name,".tif");
imp_name = trimSuffix(imp_name,".tiff");
String vf_extended = imp_name+"-vector_extended"+suffix_param; //
vf_extended_dir= trimSuffix(vf_extended_dir,"/");
String vf_extended_path = vf_extended_dir + "/" + vf_extended+".tiff";
double [][][] extended_scan = getVectorFieldHyper(vf_extended_path); // String path)
// String [] vf_top_titles = {"vX","vY","strength","fraction","speed", "confidence"};
String title_cor2d = imp_name+"-corr2d"+suffix_param; // "-corr2d"+"-"+frame0+"-"+frame1+"-"+corr_pairs,
String title_vf_all = imp_name+"-vector_field_all"+suffix_param; //
String title_vf = imp_name+"-vector_field"+suffix_param; //
String title_vf_filtered = imp_name+"-vector_field_filtered"+suffix_param; //
String title_vf_extended = imp_name+"-vector_extended"+suffix_param; //
String title_targets_all = imp_name+"-targets_all"+suffix_param; //
String title_targets_filt = imp_name+"-targets_filt"+suffix_param; //
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;
double [][][] corr2d = null; // to read it if bypassing calculations
double [][][] motion_scan = null;
boolean [][] filter5 = new boolean [num_corr_samples][]; // may be calculated in extendMotionScan when read from file
double [][][] motion_scan_filtered = null;
double [][][] extended_scan = null;
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)
if (motion_scan_filtered != null) {
extended_scan = extendMotionScan(
motion_scan_filtered, // 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)
}
// extended_scan = getVectorFieldHyper(vf_extended_path); // String path)
if (extended_scan == null) {
System.out.println ("testCuasScanMotion(): Failed to read Vector Field from file, calculatring");
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 [][][] corr2d = show_2d_correlations? new double [num_corr_samples][][] : null;
double [][][] motion_scan = getMotionScan(
// double [][][]
corr2d = show_2d_correlations? new double [num_corr_samples][][] : null;
motion_scan = getMotionScan(
false, // batch_mode, // boolean batch_mode,
clt_parameters, // CLTParameters clt_parameters,
cuasMotion, // CuasMotion cuasMotion,
......@@ -374,8 +451,7 @@ public class CuasMotion {
dbg_title, // String title,
corr2d, // double [][][] corr2d, // null or [(fpixels.length - seq_length - start_frame) / corr_step)[][]
debugLevel); // int debugLevel) {
int [] remain = new int [num_corr_samples];
boolean [][] filter5 = filterMotionScan(
filter5 = filterMotionScan(
motion_scan, // final double [][][] motion_scan,
cuasMotion.tilesX, // final int tilesX)
max_range, // final int range, // 1 or 2
......@@ -384,6 +460,9 @@ public class CuasMotion {
speed_min, // double speed_min,
speed_pref, // double speed_pref,
speed_boost); // double speed_boost);
motion_scan_filtered = applyFilter(
motion_scan, // double [][][] motion_scan,
filter5); // boolean [][] filter5)
// double [][][]
extended_scan = extendMotionScan(
......@@ -398,13 +477,8 @@ public class CuasMotion {
}
System.out.println();
}
String [] slice_titles= new String [num_corr_samples];
for (int nscan = 0; nscan < num_corr_samples; nscan++) {
int frame_cent = start_frame + corr_step * nscan + seq_length/2; // debug only
slice_titles[nscan] = imp_sel.getStack().getSliceLabel(frame_cent+1);
}
if (show_2d_correlations) {
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
......@@ -417,97 +491,53 @@ public class CuasMotion {
cuasMotion.tilesX * (corr_size + 1),
cuasMotion.tilesY * (corr_size + 1),
true,
imp_name+"-corr2d"+suffix_param, // "-corr2d"+"-"+frame0+"-"+frame1+"-"+corr_pairs,
title_cor2d, // "-corr2d"+"-"+frame0+"-"+frame1+"-"+corr_pairs,
slice_titles);
}
if (show_vector_field) {
String [] top_titles = {"vX","vY","strength","fraction","speed", "confidence"};
double [][][] dbg_vf = new double [top_titles.length][num_corr_samples][cuasMotion.tilesX * cuasMotion.tilesY];
for (int nscan = 0; nscan < motion_scan.length; nscan++) {
for (int k = 0; k < top_titles.length; k++) {
Arrays.fill(dbg_vf[k][nscan], Double.NaN);
}
for (int t=0; t<motion_scan[nscan].length; t++) {
if (motion_scan[nscan][t] != null) {
double es = getEffectiveStrength(
motion_scan[nscan][t], // double [] mv_tile, // 4
speed_min, // double speed_min,
speed_pref, // double speed_pref,
speed_boost); //double speed_boost)
if (es > 0 ) {
for (int k = 0; k < 4; k++) {
dbg_vf[k][nscan][t] = motion_scan[nscan][t][k];
}
double vx = motion_scan[nscan][t][INDX_VX];
double vy = motion_scan[nscan][t][INDX_VY];
dbg_vf[4][nscan][t] = Math.sqrt(vx*vx+vy*vy);
dbg_vf[5][nscan][t] = es;
}
}
}
}
String vf_title = imp_name+"-vector_field"+suffix_param; //
ShowDoubleFloatArrays.showArraysHyperstack(
dbg_vf, // double[][][] pixels,
cuasMotion.tilesX, // int width,
vf_title, // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
top_titles, // String [] frame_titles, // frame titles or null
true); // boolean show)
// filter
for (int nscan = 0; nscan < motion_scan.length; nscan++) {
for (int t=0; t<motion_scan[nscan].length; t++) {
if (motion_scan[nscan][t] != null) {
if (!filter5[nscan][t]) {
for (int k = 0; k < top_titles.length; k++) {
dbg_vf[k][nscan][t] = Double.NaN;
}
}
}
}
}
String vf_filtered_title = imp_name+"-vector_field_filtered"+suffix_param; //
ShowDoubleFloatArrays.showArraysHyperstack(
dbg_vf, // double[][][] pixels,
cuasMotion.tilesX, // int width,
vf_filtered_title, // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
top_titles, // String [] frame_titles, // frame titles or null
true); // boolean show)
double [][][] dbg_ve = new double [top_titles.length][num_corr_samples][cuasMotion.tilesX * cuasMotion.tilesY];
for (int nscan = 0; nscan < motion_scan.length; nscan++) {
for (int k = 0; k < top_titles.length; k++) {
Arrays.fill(dbg_ve[k][nscan], Double.NaN);
}
for (int t=0; t<extended_scan[nscan].length; t++) {
if (extended_scan[nscan][t] != null) {
double es = getEffectiveStrength(
extended_scan[nscan][t], // double [] mv_tile, // 4
speed_min, // double speed_min,
speed_pref, // double speed_pref,
speed_boost); //double speed_boost)
if (es > 0) {
for (int k = 0; k < 4; k++) {
dbg_ve[k][nscan][t] = extended_scan[nscan][t][k];
}
double vx = extended_scan[nscan][t][INDX_VX];
double vy = extended_scan[nscan][t][INDX_VY];
dbg_ve[4][nscan][t] = Math.sqrt(vx*vx+vy*vy);
dbg_ve[5][nscan][t] = es;
}
}
}
}
ShowDoubleFloatArrays.showArraysHyperstack(
dbg_ve, // double[][][] pixels,
cuasMotion.tilesX, // int width,
vf_extended, // String title, "time_derivs-rt"+diff_time_rt+"-rxy"+diff_time_rxy,
slice_titles, // String [] titles, // all slices*frames titles or just slice titles or null
top_titles, // String [] frame_titles, // frame titles or null
true); // boolean show)
//title_vf_all
showVectorFieldsSequence(
motion_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_vf_all, // String title,
false, // boolean nan_effective_strength,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
showVectorFieldsSequence(
motion_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_vf, // String title,
true, // boolean nan_effective_strength,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
showVectorFieldsSequence(
motion_scan_filtered, // 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_filtered, // 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_vf_extended, // String title,
false, // boolean nan_effective_strength,
true, // boolean show,
cuasMotion.tilesX); // int tilesX) {
}
if (debugLevel > -4) {
System.out.println("scan DONE");
......@@ -545,6 +575,20 @@ 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];
}
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];
......@@ -555,19 +599,345 @@ public class CuasMotion {
float [][][] fpixels_hyper = {fpixels,fpixels_rendered};
String [] hyper_titles_top = {"Source","Rendered"};
String hyper_title = imp_name+"-rendered"+suffix_param; //
ImagePlus imp_hyper = ShowDoubleFloatArrays.showArraysHyperstack(
fpixels_hyper, // float[][][] pixels,
fpixels_hyper, // float[][][] pixels,
cuasMotion.gpu_max_width, // int width,
hyper_title, // 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)
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
// 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) {
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,
targets_remain, // int [] targets_remain,
cuasMotion.tilesX); // int tilesX)
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("All DONE");
}
}
}
public static double[][][] filterAndShowTargets(
double [][][] coord_data,
double target_strength,
double [][] target_frac,
String [] slice_titles, //
String title_targets_filt,
int [] targets_remain,
int tilesX) {
// int [] targets_remain = new int [coord_data.length];
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)
///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 [][][] getAccumulatedCoordinates(
final double [][][] vector_fields, // centers
final double [][] 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 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;
// final int num_pix = accum_data[0].length;
// final int tilesY = num_tiles/tilesX;
final int width = GPUTileProcessor.DTT_SIZE * tilesX;
// final int height = num_pix/width;
final double [][][] acc_coord = new double[num_seq][num_tiles][];
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
double [] pix_tile = new double [tile2 * tile2];
// 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++) {
if (vector_fields[nSeq][ntile] != null) {
int tileX = ntile % tilesX;
int tileY = ntile / tilesX;
int px0 = tileX * GPUTileProcessor.DTT_SIZE + GPUTileProcessor.DTT_SIZE/2;
int py0 = tileY * GPUTileProcessor.DTT_SIZE + GPUTileProcessor.DTT_SIZE/2;
// copy 16x16 tile
for (int y = 0; y < tile2; y++) {
System.arraycopy(
accum_data[nSeq],
px0 + (py0 +y) * width,
pix_tile,
y * tile2,
tile2);
}
// find max
double [] mv = Correlation2d.getMaxXYCm( // last, average
pix_tile, // corrs.length-1], // double [] data,
tile2, // int data_width, // = 2 * transform_size - 1; // negative - will return center fraction
centroid_radius, // double radius, // 0 - all same weight, > 0 cosine(PI/2*sqrt(dx^2+dy^2)/rad)
n_recenter, // int refine, // re-center window around new maximum. 0 -no refines (single-pass)
null, // 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
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return acc_coord;
}
public static double [][][] getAccumulatedCoordinates(
final double [][][] vector_fields, // centers
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 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;
// final int num_pix = accum_data[0].length;
// final int tilesY = num_tiles/tilesX;
final int width = GPUTileProcessor.DTT_SIZE * tilesX;
// final int height = num_pix/width;
final double [][][] acc_coord = new double[num_seq][num_tiles][];
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
double [] pix_tile = new double [tile2 * tile2];
// 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++) {
if (vector_fields[nSeq][ntile] != null) {
int tileX = ntile % tilesX;
int tileY = ntile / tilesX;
int px0 = tileX * GPUTileProcessor.DTT_SIZE - GPUTileProcessor.DTT_SIZE/2; // top-left of 16x16 tile
int py0 = tileY * GPUTileProcessor.DTT_SIZE - GPUTileProcessor.DTT_SIZE/2; // top-left of 16x16 tile
// copy 16x16 tile
int indx_dst = 0;
for (int y = 0; y < tile2; y++) {
int indx_src = px0 + (py0 +y) * width;
for (int x = 0; x < tile2; x++) {
pix_tile[indx_dst++] = accum_data[nSeq][indx_src++]; // float-> double
}
}
// find max negative data_width to calculate fraction (mv[])
double [] mv = Correlation2d.getMaxXYCm( // last, average (Will be relative to the center of the tile)
pix_tile, // corrs.length-1], // double [] data,
-tile2, // int data_width, // = 2 * transform_size - 1; // negative - will return center fraction
centroid_radius, // double radius, // 0 - all same weight, > 0 cosine(PI/2*sqrt(dx^2+dy^2)/rad)
n_recenter, // int refine, // re-center window around new maximum. 0 -no refines (single-pass)
null, // 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
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return acc_coord;
}
public static float [][] getTargetImages(
final double [][][] vector_fields, // centers , just null/not null
final float [][] accum_data, // should be around 0, no low-freq
final int tilesX){
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;
final int num_pix = accum_data[0].length;
final int width = GPUTileProcessor.DTT_SIZE * tilesX;
float [][] taret_images = new float[num_seq][num_pix];
final Thread[] threads = ImageDtt.newThreadArray();
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
// 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()) {
Arrays.fill(taret_images[nSeq], Float.NaN);
for (int ntile = 0; ntile < num_tiles; ntile++) {
if (vector_fields[nSeq][ntile] != null) {
int tileX = ntile % tilesX;
int tileY = ntile / tilesX;
int px0 = tileX * GPUTileProcessor.DTT_SIZE - GPUTileProcessor.DTT_SIZE/2; // top-left of 16x16 tile
int py0 = tileY * GPUTileProcessor.DTT_SIZE - GPUTileProcessor.DTT_SIZE/2; // top-left of 16x16 tile
// copy 16x16 tile
for (int y = 0; y < tile2; y++) {
System.arraycopy(
accum_data[nSeq],
px0 + (py0 +y) * width,
taret_images[nSeq],
px0 + (py0 +y) * width,
tile2);
}
}
}
}
}
};
}
ImageDtt.startAndJoin(threads);
return taret_images;
}
public static double [][][] applyFilter(
double [][][] motion_scan,
boolean [][] filter5){
double [][][] filtered_scan = new double [motion_scan.length][motion_scan[0].length][];
for (int nscan = 0; nscan < motion_scan.length; nscan++) {
for (int t=0; t<motion_scan[nscan].length; t++) {
if ((motion_scan[nscan][t] != null) && filter5[nscan][t]) {
filtered_scan[nscan][t] = motion_scan[nscan][t].clone();
}
}
}
return filtered_scan;
}
public static ImagePlus showVectorFieldsSequence(
double [][][] vector_fields_sequence,
double speed_min,
double speed_pref,
double speed_boost,
String [] titles, // all slices*frames titles or just slice titles or null
String title,
boolean nan_effective_strength,
boolean show,
int tilesX) {
double [][][] img_data = new double [VF_TOP_TITLES.length][vector_fields_sequence.length][vector_fields_sequence[0].length];
for (int nscan = 0; nscan < vector_fields_sequence.length; nscan++) {
for (int k = 0; k < VF_TOP_TITLES.length; k++) {
Arrays.fill(img_data[k][nscan], Double.NaN);
}
for (int t=0; t<vector_fields_sequence[nscan].length; t++) {
if (vector_fields_sequence[nscan][t] != null) {
double es = getEffectiveStrength(
vector_fields_sequence[nscan][t], // double [] mv_tile, // 4
speed_min, // double speed_min,
speed_pref, // double speed_pref,
speed_boost); //double speed_boost)
if ((es > 0) || !nan_effective_strength) {
for (int k = 0; k < INDX_SPEED; k++) {
img_data[k][nscan][t] = vector_fields_sequence[nscan][t][k];
}
double vx = vector_fields_sequence[nscan][t][INDX_VX];
double vy = vector_fields_sequence[nscan][t][INDX_VY];
img_data[INDX_SPEED] [nscan][t] = Math.sqrt(vx*vx+vy*vy);
img_data[INDX_CONFIDENCE][nscan][t] = es;
}
}
}
}
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
VF_TOP_TITLES, // String [] frame_titles, // frame titles or null
show); // boolean show)
return imp;
}
public static double [][][] getVectorFieldHyper(String path){
int [] wh = new int [2];
......@@ -581,13 +951,13 @@ public class CuasMotion {
if (vf_file == null) {
return null;
}
int vect_len = vf_file.length;
int vect_len = INDX_SPEED; // vf_file.length;
int num_seq = vf_file[0].length;
int num_tiles = vf_file[0][0].length;
double [][][] vf = new double [num_seq][num_tiles][];
for (int nseq=0; nseq < num_seq; nseq++) {
for (int ntile = 0; ntile < num_tiles; ntile++) if (!Double.isNaN(vf_file[0][nseq][ntile])){
double [] v = new double[vect_len];
double [] v = new double[vect_len]; // cut to originally calculated fields
for (int i = 0; i < vect_len; i++) {
v[i] = vf_file[i][nseq][ntile];
}
......@@ -606,6 +976,56 @@ public class CuasMotion {
return name;
}
public static boolean [][] filterTargets(
final double [][][] target_coords,
final double target_strength,
final double [][] target_frac, // pairs - strength, minimal fraction for that strength
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 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 [] tc = target_coords[nSeq][ntile];
if (tc != null) {
double strength = target_coords[nSeq][ntile][INDX_STRENGTH];
if (strength > target_strength) {
check_target: {
double fraction = target_coords[nSeq][ntile][INDX_FRAC];
for (double [] frac_pair : target_frac) {
if ((strength > frac_pair[0]) && (fraction < frac_pair[1])) {
break check_target;
}
}
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,
final int tilesX,
......@@ -714,7 +1134,7 @@ public class CuasMotion {
public static double [][][] extendMotionScan(
final double [][][] motion_scan,
final boolean [][] filtered, // centers, should be non-overlapped
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){
......@@ -731,7 +1151,16 @@ public class CuasMotion {
for (int nSeq = ai.getAndIncrement(); nSeq < num_seq; nSeq = ai.getAndIncrement()) {
int num = 0;
double [][] ms = motion_scan[nSeq];
boolean [] centers = filtered[nSeq];
boolean has_filter = (filtered != null) && (filtered[nSeq] != null);
boolean [] centers = has_filter ? filtered[nSeq] : new boolean [ms.length];
if (!has_filter) {
for (int i = 0; i < centers.length; i++) {
centers[i] = ms[i] != null;
}
}
if ((filtered != null) && (filtered[nSeq] == null)) {
filtered[nSeq] = centers;
}
for (int tileY = 0; tileY < tilesY; tileY++) {
for (int tileX = 0; tileX < tilesX; tileX++) {
int ntile = tileX + tilesX * tileY;
......
......@@ -700,7 +700,7 @@ min_str_neib_fpn 0.35
public double cuas_reliable_str = 0.8; // use for relaible tiles if INTER-INTRA-LMA is available, not just DSI_MAIN
public double cuas_fat_zero = 1000.0; // phase correlation fat zero
public double cuas_cent_radius = 4.0; // centroids center radius
public double cuas_cent_radius = 3.0; // centroids center radius
public int cuas_n_recenter = 2; // when cosine window, re-center window these many times
public double cuas_rstr = 0.001; // minimal phase correlation maximums relative to max str
public boolean cuas_smooth = true; // used cosine window when averaging correlations
......@@ -712,7 +712,12 @@ min_str_neib_fpn 0.35
public double cuas_speed_min = 0.2; // minimal pixels per range (per cuas_corr_offset)
public double cuas_speed_pref = 0.5; // preferable speed (boost weights for faster targets)
public double cuas_speed_boost = 2.5; // speed boost limit
// target filtering after constant velocity accumulation
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_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)
......@@ -2139,12 +2144,19 @@ min_str_neib_fpn 0.35
gd.addNumericField("Local max range", this.cuas_max_range, 0,3,"",
"While filtering local correlation maximums: 1 - 3x3 neighbors, 2 - 5x5 ones.");
gd.addMessage("=== Moving target filtering ===");
gd.addNumericField("Minimal speed", this.cuas_speed_min, 5,8,"ppr",
"Minimal target speed in pixels per range (per cuas_corr_offset).");
gd.addNumericField("Preferable speed", this.cuas_speed_pref, 5,8,"ppr",
"Boost effective strength when speed is above this.");
gd.addNumericField("Maximal speed boost", this.cuas_speed_boost, 5,8,"",
"Maximal speed-caused effective strength boost.");
gd.addNumericField("Target radius", this.cuas_target_radius, 5,8,"pix",
"Target radius, also used to calculate fraction of totals inside (windowed) to all positive values.");
gd.addNumericField("Minimal target strength", this.cuas_target_strength, 5,8,"",
"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.addMessage("=== Debug ===");
gd.addCheckbox ("Save/show debug images", this.cuas_debug,
......@@ -3110,6 +3122,10 @@ min_str_neib_fpn 0.35
this.cuas_speed_pref = gd.getNextNumber();
this.cuas_speed_boost = gd.getNextNumber();
this.cuas_target_radius = gd.getNextNumber();
this.cuas_target_strength = gd.getNextNumber();
this.cuas_target_frac = stringToDouble2d(gd.getNextString());
this.cuas_debug = gd.getNextBoolean();
this.cuas_step_debug = gd.getNextBoolean();
......@@ -3999,6 +4015,10 @@ min_str_neib_fpn 0.35
properties.setProperty(prefix+"cuas_speed_pref", this.cuas_speed_pref+""); // double
properties.setProperty(prefix+"cuas_speed_boost", this.cuas_speed_boost+""); // double
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_debug", this.cuas_debug+""); // boolean
properties.setProperty(prefix+"cuas_step_debug", this.cuas_step_debug+""); // boolean
......@@ -4860,7 +4880,9 @@ min_str_neib_fpn 0.35
if (properties.getProperty(prefix+"cuas_speed_pref")!=null) this.cuas_speed_pref=Double.parseDouble(properties.getProperty(prefix+"cuas_speed_pref"));
if (properties.getProperty(prefix+"cuas_speed_boost")!=null) this.cuas_speed_boost=Double.parseDouble(properties.getProperty(prefix+"cuas_speed_boost"));
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_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"));
......@@ -5722,6 +5744,10 @@ min_str_neib_fpn 0.35
imp.cuas_speed_min = this.cuas_speed_min;
imp.cuas_speed_pref = this.cuas_speed_pref;
imp.cuas_speed_boost = this.cuas_speed_boost;
imp.cuas_target_frac = new double [this.cuas_target_frac.length][];
for (int i = 0; i < this.cuas_target_frac.length; i++) {
imp.cuas_target_frac[i] = this.cuas_target_frac[i].clone();
}
imp.cuas_debug = this.cuas_debug;
imp.cuas_step_debug = this.cuas_step_debug;
......@@ -6118,6 +6144,39 @@ min_str_neib_fpn 0.35
}
public static String double2dToString(double [][] d) {
String s = "";
for (int i = 0; i < d.length; i++) {
for (int j = 0; j < d[i].length; j++) {
Double D = d[i][j];
s+= D.toString();
if (j <(d[i].length - 1)) {
s +=",";
}
}
if (i < (d.length - 1)) {
s +=":";
}
}
return s;
}
public static double [][] stringToDouble2d(String s) {
String [] srows = s.split(":");
double [][] d = new double [srows.length][];
for (int i = 0; i < d.length; i++) {
String [] scols = srows[i].split(",");
d[i] = new double [scols.length];
for (int j = 0; j < d[i].length; j++) {
try {
d[i][j] = Double.valueOf(scols[j]);
} catch(NumberFormatException e){
d[i][j] = 0.0;
}
}
}
return d;
}
public static String rectangleToString(Rectangle r) {
return intsToString(new int []{r.x,r.y,r.width, r.height});
......
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