Commit 42058891 authored by Andrey Filippov's avatar Andrey Filippov

Improved reporting/logging results

parent b70fdc39
......@@ -183,9 +183,13 @@ public class CalibrationFileManagement {
}
public static void saveStringToFile (String path,String data){
saveStringToFile (path, data, false);
}
public static void saveStringToFile (String path,String data, boolean append){
BufferedWriter writer = null;
try {
writer = new BufferedWriter( new FileWriter( path));
writer = new BufferedWriter( new FileWriter( path, append));
writer.write( data);
} catch ( IOException e) {
......
......@@ -3711,7 +3711,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
final int blank_xy, //
final int [] wh, // result size
final int debugLevel){
final int dbg_x = 1144; // -2668;
final int dbg_x = -1144; // -2668;
final int dbg_y = 199; // 256;
final int height = data.length/width;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
package com.elphel.imagej.orthomosaic;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import com.elphel.imagej.calibration.CalibrationFileManagement;
import com.elphel.imagej.common.GenericJTabbedDialog;
import ij.Prefs;
import ij.text.TextWindow;
public class OrthoMapsParameters {
public static String RESULTS_SUFFIX = "-results.csv";
public static String LOG_SUFFIX = ".log";
// public boolean save;
// public boolean show;
public boolean table_datetime;
public boolean append_table;
public String save_dir;
public String object_type;
public double [] min_corrs; // one per
public double [] phaseCoeff; // one per
public double [] lpf_sigma; // one per; lpf_sigma
public double min_corr_full_rel;
public double min_corr_half_rel;
public double full_preference;
public double max_min_ratio;
public boolean[] combine_full;
public int corr_size;
public double adv_radius; //
public double search_radius; // look for other scene max within this distance from main
public double scale_warp;
public int extr_size;
public boolean remove_dc;
public double abs_edge_frac; // = 0.25;
public double abs_oversize; // = 1.8;
public boolean abs_force_round;
public int abs_mode; // = 1; // 0 - keep; 1 keep type and if half +/-1; 2 - keep type; 3 - any
public boolean abs_invert; // = true; // center has lower value than around
public double abs_outliers_frac;
public boolean abs_obscure_warm; // = true; // obscured can only be by warmer objects
public double abs_obscure_frac; // 0.25; // obscured threshold between center and outer
public boolean filt_keep;
public boolean filt_keep_pre;
public boolean filt_atonce;
public double filt_frac_max; // measure are at fraction of max
public double [][] filt_max_radius;
public double [][] filt_elongation;
public double filt_other_rad; // should be no disconnected high peaks in this radius (only for halves multiplied)
public double [] filt_other_frac; // no pixels around max at filt_other_rad should be higher than this fraction of max
public double [] filt_dist;
public double filt_height;
public double [] filt_full_half_frac;
public double [] filt_roundness;
public double [] filt_best;
public double filt_abs_contrast; // = 50.0;
public double filt_abs_easepart;
public boolean convolve_after; // true for old kernel tuning (kernel decimation before convolution)
public boolean corr_centered; // re-correlate first scene centered at candidates
public int debugLevel;
public String save_top_dir;
public String sub_dir;
public boolean show_images;
public boolean show_final_image;
public boolean save_images;
public boolean show_results;
public boolean append_log;
public String alt_mode;
public OrthoMapsParameters() {
setDefaults();
}
public void setDefaults() {
min_corrs = new double []{0.009, 0.0036}; // 0.0035}; // morning/evening
phaseCoeff = new double []{0.98,0.5};
lpf_sigma = new double []{0.0, 0.0};
min_corr_full_rel = 0.85; // try 0.85
min_corr_half_rel = 1.2; // increase correlation threshold for half-patterns relative to full patterns;
full_preference = 1.4;
max_min_ratio = 3.0;
combine_full = new boolean[] {true, true}; // try for other olso?
corr_size = 128; // pix
adv_radius = 30.0; // cm ?
search_radius = 15; // look for other scene max within this distance from main
object_type = "TM62";
scale_warp = 1.0; // use 4?
extr_size = 128;
remove_dc = true;
abs_edge_frac = 0.25;
abs_oversize = 1.8;
abs_force_round = false; // after selection best pattern, force full pattern
abs_mode = 1; // 0 - keep, 1 keep type and if half +/-1, 2 - keep type, 3 - any, force full pattern
abs_invert = true; // center has lower value than around
abs_outliers_frac = 0.3;
abs_obscure_warm = false; // true; // obscured can only be by warmer objects
abs_obscure_frac = 0.25; // obscured threshold between center and outer
filt_keep = false; // list filtered out, but actually keep them
filt_keep_pre = false; // Keep pre first filter
filt_atonce = false; // apply main/second together, false - first filter main only
filt_frac_max = 0.6; // 0.5; // measure are at fraction of max
filt_max_radius = new double[][] {{1.0,1.0},{1.2,1.2}}; // {1.0,1.0}}; // [second/main][full/half] - inactive now
filt_elongation = new double[][] {{1.7,1.7},{1.7,1.7}}; // [second/main][full/half] ellipse axis ratio
filt_other_rad = 25; // should be no disconnected high peaks in this radius (only for halves multiplied)
filt_other_frac = new double[] {0.8,0.68}; // -.8}; // no pixels around max at filt_other_rad should be higher than this fraction of max
filt_dist = new double[]{10.0,5.0}; // full offset and perpendicular to images offsets
filt_height = 0.2; // allow extra negative offset parallel to image offset, corresponding to object above ground
filt_full_half_frac = new double[]{0.675, 0.5}; // second probably not needed, it is for main
filt_roundness = new double[]{0.58, 0.0}; //{0.6, 0.0}; // second currently is not calculated/ used 215 mine1 0.059618
filt_best = new double[]{0.095, 0.0};// second currently is not calculated
filt_abs_contrast = 80.0; // 50.0;
filt_abs_easepart = 1.0; // 1.0-no ease for low AGL. Allow lower absolute contrast for partial patterns (high AGL)
convolve_after = false; // true for old kernel tuning (kernel decimation before convolution)
corr_centered = true; // re-correlate first scene centered at candidates
save_top_dir = "/media/elphel/NVME/lwir16-proc/ortho_videos/debug/sept12-13/pattern_match/";
sub_dir = "dbg_recenter_07";
show_images = false;
show_final_image = true;
save_images = true;
show_results = false;
table_datetime = true;
append_table = true;
append_log = true;
alt_mode= "??m";
debugLevel = 0;
}
public void setDefaults50() {
alt_mode="50m";
lpf_sigma = new double [] {0.25, 0.25};
phaseCoeff = new double [] {0.98, 0.5}; // {0.98, 0.5};{.995,.995}; //
full_preference = 1.2; // 1.4;
// min_corrs = new double[] {0.008, 0.0036};
min_corrs = new double[] {0.007,0.0036}; // {0.007, 0.0036};
min_corr_full_rel = 0.85; // try 0.85
min_corr_half_rel = 1.2; // increase correlation threshold for half-patterns relative to full patterns;
abs_edge_frac = 0.25;
abs_oversize = 1.8;
abs_force_round = false; // after selection best pattern, force full pattern
filt_abs_contrast = 85; // 70;
filt_roundness[0] = 0.36; //0.38; // 0.4; // 0.56;
filt_best[0] = 0.0085; // 0.01;
// mode == 1 seems slightly better for mine 5 (absolute contrast)
abs_mode = 1; // 0; // 1; // 0 - keep, 1 keep type and if half +/-1, 2 - keep type, 3 - any, force full pattern
abs_invert = true; // center has lower value than around
abs_outliers_frac = 0.3;
abs_obscure_warm = true; // false; // true; // obscured can only be by warmer objects
abs_obscure_frac = 0.25; // obscured threshold between center and outer
filt_max_radius = new double [][] {{0.47,0.29},{1.2,1.2}}; // {1.0,1.0}}; // [second/main][full/half] - inactive now
filt_elongation = new double [][] {{1.45,1.46},{1.7,1.7}}; // [second/main][full/half] ellipse axis ratio
filt_other_rad = 25; // should be no disconnected high peaks in this radius (only for halves multiplied)
filt_other_frac = new double []{0.65,0.68}; // -.8}; // no pixels around max at filt_other_rad should be higher than this fraction of max
}
public void setDefaults75() {
alt_mode="75m";
full_preference = 1.15; // 5 - 1.21
lpf_sigma = new double [] {0.25, 0.25};
phaseCoeff = new double [] {0.95, 0.95};
// min_corrs[0] = 0.0119;
min_corrs = new double[]{0.0090,0.008}; // A1: .0654
abs_edge_frac = 0.35;
abs_oversize = 2.2;
filt_abs_contrast = 75; // 70;
filt_abs_easepart = 0.85;
abs_obscure_warm = true;
// parameters for force round
abs_force_round = true;
filt_roundness[0] = 0.56; // 0.55;
filt_best[0] = 0.009; //****** tune, this one is inactive
filt_max_radius = new double [][] {{0.35,0.2},{0.35,0.2}}; // {1.0,1.0}}; // [second/main][full/half] - inactive now
filt_elongation = new double [][] {{1.45,1.55},{1.45,1.55}}; // [second/main][full/half] ellipse axis ratio
filt_other_rad = 25; // should be no disconnected high peaks in this radius (only for halves multiplied)
filt_other_frac = new double [] {0.6,0.6}; // -.8}; // no pixels around max at filt_other_rad should be higher than this fraction of max
}
public void setDefaults100() {
alt_mode="100m";
lpf_sigma = new double [] {0.25, 0.25};
// min_corrs = new double[]{0.0068,0.006};
min_corrs = new double[]{0.0064,0.006}; // A1: .0654
// min_corrs = new double[]{0.0066,0.0057};
abs_edge_frac = 0.35;
abs_oversize = 2.2;
filt_abs_contrast = 60;
filt_abs_easepart = 0.85;
phaseCoeff[0] = 0.95;
phaseCoeff[1] = 0.95;
abs_force_round = true;
filt_max_radius = new double [][] {{0.6,0.3}, {1.0,1.0}}; // {1.0,1.0}}; // [second/main][full/half] - inactive now
// filt_elongation = new double [][] {{1.4,1.5}, {1.7,1.7}};
filt_elongation = new double [][] {{1.4,1.55}, {1.7,1.7}};
filt_frac_max = 0.7;
filt_dist = new double[]{5.0,2.5}; // full offset and perpendicular to images offsets
filt_roundness[0] = 0.55; // 0.6;214-213_1694565491_890936-1694565488_589836 is 0.589
filt_best[0] = 0.0064; // tune
filt_other_frac = new double [] {0.75,0.68};// no pixels around max at filt_other_rad should be higher than this fraction of max
}
public boolean setupDialog(
int [] indices,
OrthoMap[] ortho_maps) {
GenericJTabbedDialog gd = new GenericJTabbedDialog("Correlate "+((indices.length==1)? "one image":"two images")+" with patterns, altitude "+alt_mode,1200,1100);
gd.addTab("General","General parameters");
gd.addStringField ("Object type", object_type, 20,"Object type/name.");
gd.addNumericField("Minimal correlation, first", min_corrs[0], 5,7,"","Minimal correlation value to keep, first scene.");
gd.addNumericField("Minimal correlation, second", min_corrs[1], 5,7,"","Minimal correlation value to keep, second scene.");
gd.addNumericField("Phase correlation main", phaseCoeff[0], 3,7,"","1.0 - pure phase correlation, 0.0 - regular correlation.");
gd.addNumericField("Phase correlation other", phaseCoeff[1], 3,7,"","1.0 - pure phase correlation, 0.0 - regular correlation.");
gd.addNumericField("Low-pass sigma main", lpf_sigma[0], 3,7,"","Low-pass sigma for phase correlation. 0 - no filtering, 0.25 - 4 pix.");
gd.addNumericField("Low-pass sigma other", lpf_sigma[1], 3,7,"","Low-pass sigma for phase correlation. 0 - no filtering, 0.25 - 4 pix.");
gd.addNumericField("Minimal relative full correlation", min_corr_full_rel, 5,7,"","Minimal relative correlation value with full circular pattern to keep.");
gd.addNumericField("Minimal relative half correlation", min_corr_half_rel, 5,7,"","Increase correlation threshold for partial patterns relative to min_corrs.");
gd.addNumericField("Prefer full pattern", full_preference, 3,7,"","Prefer full pattern to partial; scale by this value.");
gd.addNumericField("Max/min halves ratio", max_min_ratio, 3,7,"","Ratio of halves best/worst to use half-pattern.");
gd.addCheckbox ("Combine with full pattern, main", combine_full[0], "Multiply by normalized full pattern correlation maximum.");
gd.addCheckbox ("Combine with full pattern, other", combine_full[1], "Multiply by normalized full pattern correlation maximum.");
gd.addNumericField("Correlation size", corr_size, 0,4,"pix", "Should be power of 2.");
gd.addNumericField("Adversarial distance", adv_radius, 1,6,"pix", "Suppress weaker if they have closer strong ones.");
gd.addNumericField("Search other scene max", search_radius, 1,6,"pix", "Search for other scene max from the main one.");
gd.addNumericField("Scale warp", scale_warp, 1,6,"x", "Scale second image warping.");
gd.addNumericField("Extract object size", extr_size, 0,4,"", "Size of square object image to extract.");
gd.addCheckbox ("Remove DC", remove_dc, "Remove DC in extracted object images.");
gd.addMessage("Mitigating what seems to be a bug - kernels tuned to be convolved after decimation. Should be opposite?");
gd.addCheckbox ("Convolve after zoom out", convolve_after, "Zoom patterns before convolving with resolution-matching kernels.");
gd.addCheckbox ("Re-correlate centered", corr_centered, "Re-correlate main scene candidates cenetered.");
gd.addTab("Absolute Contrast","Preparing absolute contrast measurements for the main scene");
gd.addNumericField("Edge cutt-off fraction (<0.5)", abs_edge_frac, 5,7,"","Used for extracting inner and outer zones from tha existing patterns.");
gd.addNumericField("Radius of outer ring to pattern radius",abs_oversize, 5,7,"","Outer ring external radius as a mupltile of the pattern radius.");
gd.addCheckbox ("Force round", abs_force_round, "Force round pattern and recheck \"best\" correlation value.");
gd.addNumericField("Update subpattern mode", abs_mode, 0,4,"", "0 - keep, 1 keep type and if half, only change by +/-1, 2 - keep type, 3 - any.");
gd.addCheckbox ("Cold center", abs_invert, "Center pattern values are lower than around.");
gd.addNumericField("Outlier fraction when averaging", abs_outliers_frac, 5,7,"","Discard this fraction of pixels in inner and outer zones when averaging.");
gd.addCheckbox ("May be obscured only by warmer", abs_obscure_warm, "Half-pattern objects may be obscured by warmer (for cold objects).");
gd.addNumericField("\"warmer\" threshold", abs_obscure_frac, 5,7,"","Threshold fraction between average center and average around ring.");
gd.addTab("Filters","Filtering results to reduce false positives");
gd.addCheckbox ("Keep filtered out", filt_keep, "List filtered out, but actaually keep them.");
gd.addCheckbox ("Keep pre-filter", filt_keep_pre, "Keep even before the first scene filter.");
gd.addCheckbox ("Apply filters at once", filt_atonce, "If false, first filter by main scene only, do not process secondary scene if main failed.");
gd.addNumericField("Peak hight fraction", filt_frac_max, 5,7,"","Fraction of the peak hight for eigenvlues (radius and elongation).");
gd.addNumericField("Max radius, main, full", filt_max_radius[0][0], 5,7,"pix","Maximal peak cross-section average radius at certain height.");
gd.addNumericField("Max radius, main, halves", filt_max_radius[0][1], 5,7,"pix","Maximal peak cross-section average radius at certain height.");
gd.addNumericField("Max radius, other, full", filt_max_radius[1][0], 5,7,"pix","Maximal peak cross-section average radius at certain height.");
gd.addNumericField("Max radius, other, half", filt_max_radius[1][1], 5,7,"pix","Maximal peak cross-section average radius at certain height.");
gd.addNumericField("Max elongation, main, full", filt_elongation[0][0], 5,7,"","Maximal peak ellipse axis ratio at certain height.");
gd.addNumericField("Max elongation, main, halves", filt_elongation[0][1], 5,7,"","Maximal peak ellipse axis ratio at certain height.");
gd.addNumericField("Max elongation, other, full", filt_elongation[1][0], 5,7,"","Maximal peak ellipse axis ratio at certain height.");
gd.addNumericField("Max elongation, other, halves", filt_elongation[1][1], 5,7,"","Maximal peak ellipse axis ratio at certain height.");
gd.addNumericField("Other peak distance", filt_other_rad, 5,7,"pix","Should be no disconnected peaks within this radius from the used one. Set to 0 to disable.");
gd.addNumericField("Other peak fraction, main scene", filt_other_frac[0], 5,7,"","Maximal near peak fraction of the used maximum. Only for halves.");
gd.addNumericField("Other peak fraction, other scene", filt_other_frac[1], 5,7,"","Maximal near peak fraction of the used maximum. Only for halves.");
gd.addNumericField("Maximal offset", filt_dist[0], 5,7,"pix","Maximal other scene offset from the main.");
gd.addNumericField("Maximal offset perpendicular", filt_dist[1], 5,7,"pix","Maximal other scene offset perpendicular to offset between scenes.");
gd.addNumericField("Maximal object height", filt_height, 5,7,"m", "Maximal object height to allow extra offset.");
gd.addNumericField("Full/half corr minimal ratio, main",filt_full_half_frac[0], 5,7,"","Minimal correlation with full pattern strength ratio to correlation with a half-pattern.");
gd.addNumericField("Full/half corr minimal ratio, other",filt_full_half_frac[1], 5,7,"","Minimal correlation with full pattern strength ratio to correlation with a half-pattern.");
gd.addNumericField("Minimal roundness of round, main", filt_roundness[0], 5,7,"","Minimal ratio of worst half-pattern correlation to the full-pattern ones. Only for full patterns.");
gd.addNumericField("Minimal best corr , main", filt_best[0], 5,7,"","Minimal best correlation for all patterns, even if selected is a full one.");
gd.addNumericField("Minimal absolute contrast", filt_abs_contrast, 5,7,"","Minimal absolute difference between center and peripheral areas of the main scene objects.");
gd.addNumericField("Ease absolute contrast for halves", filt_abs_easepart, 5,7,"","Ease absolute contast requirements for high AGL (low resolution).");
gd.addTab("Save/show","Save/show generated images");
gd.addStringField ("Pattern match save directory", save_top_dir, 120, "Top directory to save pattern patch results");
gd.addStringField ("Save subdirectory", sub_dir, 80, "Subdirectory for versions of the same scene/pair of scenes");
gd.addCheckbox ("Show intermediate images", show_images, "Display all intermediate images.");
gd.addCheckbox ("Show final image", show_final_image, "Display final image with marked objects.");
gd.addCheckbox ("Save generated images", save_images, "Save generated image to the location defined by above.");
gd.addCheckbox ("Show result tables", show_results, "Display results tables.");
//
gd.addCheckbox ("Append results table", append_table,"Append results table.");
gd.addCheckbox ("Date/time when appending", table_datetime, "Include date/time when appending results.");
gd.addCheckbox ("Write to log", append_log, "Append log file.");
//
gd.addNumericField("Debug level", debugLevel, 0,4,"", "Debug level.");
gd.showDialog();
if (gd.wasCanceled()) return false;
object_type= gd.getNextString();
min_corrs[0]= gd.getNextNumber();
min_corrs[1]= gd.getNextNumber();
phaseCoeff[0]= gd.getNextNumber();
phaseCoeff[1]= gd.getNextNumber();
lpf_sigma[0]= gd.getNextNumber();
lpf_sigma[1]= gd.getNextNumber();
min_corr_full_rel= gd.getNextNumber();
min_corr_half_rel= gd.getNextNumber();
full_preference= gd.getNextNumber();
max_min_ratio= gd.getNextNumber();
combine_full[0] = gd.getNextBoolean();
combine_full[1] = gd.getNextBoolean();
corr_size= (int) gd.getNextNumber();
adv_radius= gd.getNextNumber();
search_radius= gd.getNextNumber();
scale_warp = gd.getNextNumber();
extr_size= (int) gd.getNextNumber();
remove_dc= gd.getNextBoolean();
convolve_after= gd.getNextBoolean();
corr_centered= gd.getNextBoolean();
abs_edge_frac = gd.getNextNumber();
abs_oversize = gd.getNextNumber();
abs_force_round= gd.getNextBoolean();
abs_mode = (int) gd.getNextNumber();
abs_invert = gd.getNextBoolean();
abs_outliers_frac = gd.getNextNumber();
abs_obscure_warm= gd.getNextBoolean();
abs_obscure_frac = gd.getNextNumber();
filt_keep= gd.getNextBoolean();
filt_keep_pre= gd.getNextBoolean();
filt_atonce= gd.getNextBoolean();
filt_frac_max= gd.getNextNumber();
filt_max_radius[0][0]= gd.getNextNumber();
filt_max_radius[0][1]= gd.getNextNumber();
filt_max_radius[1][0]= gd.getNextNumber();
filt_max_radius[1][1]= gd.getNextNumber();
filt_elongation[0][0]= gd.getNextNumber();
filt_elongation[0][1]= gd.getNextNumber();
filt_elongation[1][0]= gd.getNextNumber();
filt_elongation[1][1]= gd.getNextNumber();
filt_other_rad= gd.getNextNumber();
filt_other_frac[0]= gd.getNextNumber();
filt_other_frac[1]= gd.getNextNumber();
filt_dist[0] = gd.getNextNumber();
filt_dist[1] = gd.getNextNumber();
filt_height = gd.getNextNumber();
filt_full_half_frac[0]=gd.getNextNumber();
filt_full_half_frac[1]=gd.getNextNumber();
filt_roundness[0]= gd.getNextNumber();
filt_best[0]= gd.getNextNumber();
filt_abs_contrast= gd.getNextNumber();
filt_abs_easepart= gd.getNextNumber();
save_top_dir= gd.getNextString();
sub_dir= gd.getNextString();
show_images= gd.getNextBoolean();
show_final_image= gd.getNextBoolean();
save_images= gd.getNextBoolean();
show_results= gd.getNextBoolean();
append_table= gd.getNextBoolean();
table_datetime= gd.getNextBoolean();
append_log= gd.getNextBoolean();
debugLevel= (int) gd.getNextNumber();
setSaveDir(
indices, // int [] indices,
ortho_maps); // OrthoMap[] ortho_maps)
return true;
}
public void setSaveDir(
int [] indices,
OrthoMap[] ortho_maps) {
save_dir = null;
if (save_images) {
if (!save_top_dir.endsWith(Prefs.getFileSeparator())) {
save_top_dir+= Prefs.getFileSeparator();
}
if (indices.length == 1) {
save_dir=String.format("%s%03d-%s",
save_top_dir,indices[0],ortho_maps[indices[0]].getName());
} else if (indices.length == 2) {
save_dir=String.format("%s%03d-%03d_%s-%s",
save_top_dir,indices[0],indices[1],ortho_maps[indices[0]].getName(),ortho_maps[indices[1]].getName());
}
if (!sub_dir.equals("")) {
save_dir+= Prefs.getFileSeparator()+sub_dir;
}
// create if it does not exist
File fsave_dir = new File(save_dir);
fsave_dir.mkdirs();
save_dir += Prefs.getFileSeparator();
}
}
public void printReport(
boolean gen_results,
boolean gen_parameters,
OrthoMap [] ortho_maps,
int [] indices,
ArrayList<Integer> match_sort,
ArrayList <ItemMatch> matches_list,
int zoom_level,
double [] scene_xy_offset,
double scene_agl,
int num_patterns, // corrs_out[scene_num].length
int [] origin,
double [][] centers,
GroundObjectPattern gop,
double hi_lo_freq,
int [] hi_freq_wh,
double [][] hi_freq_arr) {
int sort_pattern_index = 0;
boolean [] has_filter_data0 = new boolean[2];
for (int i = 0; i < match_sort.size(); i++) {
int indx =match_sort.get(i);
ItemMatch match = matches_list.get(indx);
for (int j = 0; j < 2; j++) {
has_filter_data0[j] |= match.filter_data[0][j] != null;
}
}
if (gen_parameters) {
if (indices.length > 1) {
System.out.println(String.format("Main scene: (%03d) %17s",indices[0],ortho_maps[indices[0]].getName()));
System.out.println(String.format("Other scene: (%03d) %17s",indices[1],ortho_maps[indices[1]].getName()));
} else {
System.out.println(String.format("Scene: (%03d) %17s",indices[0],ortho_maps[indices[0]].getName()));
}
System.out.println("Searching for object type="+object_type+", found "+match_sort.size()+" of them."+
" PhaseCoeff=["+phaseCoeff[0]+","+phaseCoeff[1]+"], lpf = ["+lpf_sigma[0]+","+lpf_sigma[1]+"], min_corrs=["+min_corrs[0]+","+min_corrs[1]+
"], min_corr_full_rel="+min_corr_full_rel+", min_corr_half_rel="+min_corr_half_rel+", frac_max="+filt_frac_max);
System.out.println("filt_max_radius main =["+filt_max_radius[0][0]+","+filt_max_radius[0][1]+"], "+
"filt_max_radius other=["+filt_max_radius[1][0]+","+filt_max_radius[1][1]+"], "+
"filt_elongation main=["+filt_elongation[0][0]+","+filt_elongation[0][1]+"], "+
"filt_elongation other=["+filt_elongation[1][0]+","+filt_elongation[1][1]+"]");
System.out.println("filt_dist=["+filt_dist[0]+", "+filt_dist[1]+"] "+
"(First value is the total offset in pixels, second accounts for parallax.) "+
" filt_height="+filt_height+ " meters.");
System.out.println("filt_other_rad="+filt_other_rad+"pix, filt_other_frac=["+filt_other_frac[0]+", "+filt_other_frac[1]+"],"+
" filt_full_half_frac=["+filt_full_half_frac[0]+", "+filt_full_half_frac[1]+"], filt_roundness="+filt_roundness[0]+
", filt_best="+filt_best[0]+" .");
System.out.println("filt_abs_contrast="+filt_abs_contrast+", filt_abs_easepart="+filt_abs_easepart);
System.out.println("abs_edge_frac="+abs_edge_frac+", abs_oversize="+abs_oversize+
", abs_force_round="+abs_force_round+", abs_mode="+abs_mode+", abs_invert="+abs_invert);
System.out.println("abs_outliers_frac="+abs_outliers_frac+", abs_obscure_warm="+abs_obscure_warm+
", abs_obscure_frac="+abs_obscure_frac + ", Average hi_lo_freq="+hi_lo_freq);
if (indices.length > 1) {
System.out.println("Second image is offset by dx="+scene_xy_offset[0]+", dy="+scene_xy_offset[1]+", dist="+
Math.sqrt(scene_xy_offset[0]*scene_xy_offset[0]+scene_xy_offset[1]*scene_xy_offset[1])+" pix");
}
}
if (gen_results) {
// System.out.println("Updated object list with main scene peak areas and secondary scene maximums, areas and maximum distances from the main");
System.out.print(String.format("%4s: %9s %8s %8s %8s %8s %6s %3s %6s %6s",
" # ", " x/y ", " hfreq ","sel-corr", " best ","contrast","round","sub"," dist "," az "));
for (int j = 0; j < (num_patterns + 1); j++) if (j != sort_pattern_index) {
System.out.print(String.format(" %8s ","match_"+j));
}
if (has_filter_data0[0]) {
System.out.print(String.format("%6s %6s %6s %6s %6s %6s |",
"mf-rad", "mf-eln","mh-rad", "mh-eln", "mh-ofr", "m_fhr"));
} else {
System.out.print(" |");
}
if (indices.length > 1) {
System.out.print(String.format(" %8s %6s %6s %6s %7s %7s %7s %7s %7s | %8s %6s %6s %6s %6s %6s %7s %7s",
"of-corr","of-rad","of-eln", "of-dst", "of-dx", "of-dy","of-par","of-prp","elevat",
"oh-corr","oh-rad","oh-eln", "oh-ofr", "o_fhr", "oh-dst", "oh-dx","oh-dy"));
System.out.print(String.format("| %6s %6s"," dist2"," az2 "));
}
System.out.println(String.format(" %7s",
"removed"));
for (int i = 0; i < match_sort.size(); i++) {
int indx =match_sort.get(i);
ItemMatch match = matches_list.get(indx);
double [] match_values = match.getMatchValues(gop);
CorrelationPeakStats [][] filter_data = match.filter_data;
int [] icenter_xy = match.getIntXY();
double hfr = Double.NaN;
if (hi_freq_arr != null) {
int hfr_x = icenter_xy[0]/(corr_size/2);
int hfr_y = icenter_xy[1]/(corr_size/2);
hfr = hi_freq_arr[0][hfr_x + hfr_y * hi_freq_wh[0]];
}
double [] vert_offs = new double[2];
for (int j = 0; j < vert_offs.length; j++) {
vert_offs[j] = icenter_xy[j] - origin[j];
}
double vert_dist = Math.sqrt(vert_offs[0]*vert_offs[0]+vert_offs[1]*vert_offs[1]);
double vert_az= Math.atan2(vert_offs[1],vert_offs[0])*180.0/Math.PI;
System.out.print(String.format("%4d: %4d/%4d %8.5f %8.5f %8.5f %8.3f %6.3f %3d %6.1f %6.1f",
i,
icenter_xy[0],icenter_xy[1],
hfr,
match.getMatchValue(gop), // ,sort_pattern_index),
match.getMatchBestValue(gop),
match.getAbsoluteContrast(),
match.getRoundness(gop),
match.getPatternMatch(gop).getBestSub(), // 1-based
vert_dist, vert_az)); // horizontal distance and azimuth from the camera ground projection
for (int j = 0; j < match_values.length; j++) if (j != sort_pattern_index) {
System.out.print(String.format(" %8.5f",match_values[j]));
if (j != (match_values.length-1)) {
System.out.print(",");
} else {
System.out.print(" ");
}
}
boolean removed = match.isRemoved();
String sremoved = removed?" removed":"";
if (filter_data[0][0] != null) {
if (filter_data[0][1] == null) {
System.out.print(String.format(
"\t%6.3f\t%6.3f\t---\t---\t---\t---",
// main full and best half areas only, radius and elongation
filter_data[0][0].eff_rad, filter_data[0][0].elong)); // main full: radius and elongation
} else {
double m_fhr = filter_data[0][0].best_d/filter_data[0][1].best_d;
System.out.print(String.format(
"%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f |",
// main full and best half areas only, radius and elongation
filter_data[0][0].eff_rad, filter_data[0][0].elong, // main full: radius and elongation
filter_data[0][1].eff_rad, filter_data[0][1].elong, // main best half: radius and elongation
filter_data[0][1].max_other, // other max fraction of the main one
m_fhr));
}
} else {
System.out.print(" |");
}
if (indices.length > 1) {
double [] vert_offs2 = new double[2];
for (int j = 0; j < vert_offs.length; j++) {
vert_offs2[j] = icenter_xy[j] - centers[1][j];
}
double vert_dist2 = Math.sqrt(vert_offs2[0]*vert_offs2[0]+vert_offs2[1]*vert_offs2[1]);
double vert_az2= Math.atan2(vert_offs2[1],vert_offs2[0])*180.0/Math.PI;
double [] second_xy_offsets = filter_data[1][0].cent_offs;
// try elevation for second scene and full pattern only
double [] scnd_xy_proj = OrthoMapsCollection.projectOffsetOnVector(
second_xy_offsets, // double [] object_offset,
scene_xy_offset); // double [] scene_offset)
double obj_elev = OrthoMapsCollection.offsetToElevation(
second_xy_offsets, //double [] object_offset,
scene_xy_offset, // double [] scene_offset,
zoom_level, // int zoom_level,
scene_agl); // double agl)
// System.out.println(String.format("best_d=%7.5f, rad=%6.3f, elong=%6.3f, dist=%6.3f, dx=%6.3f, dy=%6.3f",
double o_fhr = filter_data[1][0].best_d/filter_data[1][1].best_d;
System.out.print(String.format(
" %8.5f %6.3f %6.3f %6.3f %7.3f %7.3f %7.3f %7.3f %7.3f | %8.5f %6.3f %6.3f %6.3f %6.3f %6.3f %7.3f %7.3f",
// for second full - everything and parallel/perpendicular+elevation
filter_data[1][0].best_d, filter_data[1][0].eff_rad, filter_data[1][0].elong, // full: corr, radius, elongation
filter_data[1][0].dist, filter_data[1][0].cent_offs[0], filter_data[1][0].cent_offs[1], // full: dist, dx, dy
scnd_xy_proj[0], scnd_xy_proj[1],obj_elev, // full: parallel, perpnd, elevation(m)
filter_data[1][1].best_d, filter_data[1][1].eff_rad, filter_data[1][1].elong, // half: corr, radius, elongation
filter_data[1][1].max_other, ///
o_fhr,
filter_data[1][1].dist, filter_data[1][1].cent_offs[0], filter_data[1][1].cent_offs[1])); // half: dist, dx, dy
System.out.print(String.format(
"| %6.1f %6.1f", vert_dist2, vert_az2));
}
System.out.println(String.format(" %7s",
sremoved));
}
}
}
public static String getBaseName(
OrthoMap [] ortho_maps,
int [] indices){
String basename = indices[0]+"-"+ortho_maps[indices[0]].getName();
if (indices.length > 1) {
basename = indices[0]+"-"+indices[1]+"_"+ortho_maps[indices[0]].getName()+"-"+ortho_maps[indices[1]].getName();
}
return basename;
}
public void generateReport(
String log_line, // should end with \n or be null
boolean show,
boolean save,
boolean gen_results,
boolean gen_parameters,
OrthoMap [] ortho_maps,
int [] indices,
ArrayList<Integer> match_sort,
ArrayList <ItemMatch> matches_list,
int zoom_level,
double [] scene_xy_offset,
double scene_agl,
int num_patterns, // corrs_out[scene_num].length
int [] origin,
double [][] centers,
GroundObjectPattern gop,
double hi_lo_freq,
int [] hi_freq_wh,
double [][] hi_freq_arr) {
StringBuffer sb_head_res = new StringBuffer();
StringBuffer sb_body_res = new StringBuffer();
StringBuffer sb_head_params = new StringBuffer();
StringBuffer sb_body_params = new StringBuffer();
int sort_pattern_index = 0;
// main table header
boolean [] has_filter_data0 = new boolean[2];
for (int i = 0; i < match_sort.size(); i++) {
int indx =match_sort.get(i);
ItemMatch match = matches_list.get(indx);
for (int j = 0; j < 2; j++) {
has_filter_data0[j] |= match.filter_data[0][j] != null;
}
}
if (gen_results) {
if (indices.length > 1) {
sb_head_res.append("scene\tother");
} else {
sb_head_res.append("scene");
}
sb_head_res.append("\tobj\tx\ty\thfreq\tsel-corr\tbest\tcontrast\tround\tsub\tdist\taz");
for (int j = 0; j < (num_patterns + 1); j++) if (j != sort_pattern_index) {
sb_head_res.append("\tmatch_"+j);
}
if (has_filter_data0[0]) {
sb_head_res.append("\tmf-rad\tmf-eln\tmh-rad\tmh-eln\tmh-ofr\tm_fhr");
}
if (indices.length > 1) {
sb_head_res.append("\tof-corr\tof-rad\tof-eln\tof-dst\tof-dx\tof-dy\tof-par\tof-prp\televat");
sb_head_res.append("\toh-corr\toh-rad\toh-eln\toh-ofr\to_fhr\toh-dst\toh-dx\toh-dy");
sb_head_res.append("\tdist2\taz2");
}
sb_head_res.append("\tremoved");
// main table lines
for (int i = 0; i < match_sort.size(); i++) {
int indx =match_sort.get(i);
ItemMatch match = matches_list.get(indx);
double [] match_values = match.getMatchValues(gop);
CorrelationPeakStats [][] filter_data = match.filter_data;
int [] icenter_xy = match.getIntXY();
double hfr = Double.NaN;
if (hi_freq_arr != null) {
int hfr_x = icenter_xy[0]/(corr_size/2);
int hfr_y = icenter_xy[1]/(corr_size/2);
hfr = hi_freq_arr[0][hfr_x + hfr_y * hi_freq_wh[0]];
}
double [] vert_offs = new double[2];
for (int j = 0; j < vert_offs.length; j++) {
vert_offs[j] = icenter_xy[j] - origin[j];
}
double vert_dist = Math.sqrt(vert_offs[0]*vert_offs[0]+vert_offs[1]*vert_offs[1]);
double vert_az= Math.atan2(vert_offs[1],vert_offs[0])*180.0/Math.PI;
if (indices.length > 1) {
sb_body_res.append(String.format("%4d\t%4d",indices[0],indices[1]));
} else {
sb_body_res.append(String.format("%4d",indices[0]));
}
sb_body_res.append(String.format("\t%4d\t%4d\t%4d\t%8.5f\t%8.5f\t%8.5f\t%8.3f\t%6.3f\t%3d\t%6.1f\t%6.1f",
i,
icenter_xy[0],icenter_xy[1],
hfr,
match.getMatchValue(gop), // ,sort_pattern_index),
match.getMatchBestValue(gop),
match.getAbsoluteContrast(),
match.getRoundness(gop),
match.getPatternMatch(gop).getBestSub(), // 1-based
vert_dist, vert_az)); // horizontal distance and azimuth from the camera ground projection
for (int j = 0; j < match_values.length; j++) if (j != sort_pattern_index) {
sb_body_res.append(String.format("\t%8.5f",match_values[j]));
}
boolean removed = match.isRemoved();
String sremoved = removed?" removed":"";
// (filter_data == null) ||(filter_data[0] == null) || - always != null
if (filter_data[0][0] != null) {
if (filter_data[0][1] == null) {
sb_body_res.append(String.format(
"\t%6.3f\t%6.3f\t---\t---\t---\t---",
// main full and best half areas only, radius and elongation
filter_data[0][0].eff_rad, filter_data[0][0].elong)); // main full: radius and elongation
} else {
double m_fhr = filter_data[0][0].best_d/filter_data[0][1].best_d;
sb_body_res.append(String.format(
"\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%6.3f",
// main full and best half areas only, radius and elongation
filter_data[0][0].eff_rad, filter_data[0][0].elong, // main full: radius and elongation
filter_data[0][1].eff_rad, filter_data[0][1].elong, // main best half: radius and elongation
filter_data[0][1].max_other, // other max fraction of the main one
m_fhr));
}
}
if (indices.length > 1) {
double [] vert_offs2 = new double[2];
for (int j = 0; j < vert_offs.length; j++) {
vert_offs2[j] = icenter_xy[j] - centers[1][j];
}
double vert_dist2 = Math.sqrt(vert_offs2[0]*vert_offs2[0]+vert_offs2[1]*vert_offs2[1]);
double vert_az2= Math.atan2(vert_offs2[1],vert_offs2[0])*180.0/Math.PI;
double [] second_xy_offsets = filter_data[1][0].cent_offs;
// try elevation for second scene and full pattern only
double [] scnd_xy_proj = OrthoMapsCollection.projectOffsetOnVector(
second_xy_offsets, // double [] object_offset,
scene_xy_offset); // double [] scene_offset)
double obj_elev = OrthoMapsCollection.offsetToElevation(
second_xy_offsets, //double [] object_offset,
scene_xy_offset, // double [] scene_offset,
zoom_level, // int zoom_level,
scene_agl); // double agl)
// System.out.println(String.format("best_d=%7.5f, rad=%6.3f, elong=%6.3f, dist=%6.3f, dx=%6.3f, dy=%6.3f",
double o_fhr = filter_data[1][0].best_d/filter_data[1][1].best_d;
sb_body_res.append(String.format(
"\t%8.5f\t%6.3f\t%6.3f\t%6.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%8.5f\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%6.3f\t%7.3f\t%7.3f",
// for second full - everything and parallel/perpendicular+elevation
filter_data[1][0].best_d, filter_data[1][0].eff_rad, filter_data[1][0].elong, // full: corr, radius, elongation
filter_data[1][0].dist, filter_data[1][0].cent_offs[0], filter_data[1][0].cent_offs[1], // full: dist, dx, dy
scnd_xy_proj[0], scnd_xy_proj[1],obj_elev, // full: parallel, perpnd, elevation(m)
filter_data[1][1].best_d, filter_data[1][1].eff_rad, filter_data[1][1].elong, // half: corr, radius, elongation
filter_data[1][1].max_other, ///
o_fhr,
filter_data[1][1].dist, filter_data[1][1].cent_offs[0], filter_data[1][1].cent_offs[1])); // half: dist, dx, dy
sb_body_res.append(String.format(
"\t%6.1f\t%6.1f", vert_dist2, vert_az2));
}
sb_body_res.append(String.format("\t%7s\n",sremoved));
}
}
if (gen_parameters) {
// parameters header
sb_head_params.append("\ntype\tscene\tname");
if (indices.length > 1) {
sb_head_params.append("\tother\tother_name");
}
sb_head_params.append("\tph_corr\tlpf\tcorr\tbest\tcntrst\tround\trelfull\trelhalf\tfracmx");
sb_head_params.append("\trad_mf\trad_mh\teln_mf\teln_mh");
sb_head_params.append("\tdist\tprlx\theight");
sb_head_params.append("\toth_rad\toth_frac\tfh_frac");
sb_head_params.append("\teasepart\tedge\tovrsize\tf-rnd\tamode\tinvert\toutlier\twarm_obs\tfrac_obs");
sb_head_params.append("\tavg_hifr");
// parameters for the second scene
if (indices.length > 1) {
if (indices.length > 1) sb_head_params.append("\tph.c_1\tlpf_1\tcorr_1\tbest_1");
sb_head_params.append("\trad_of\trad_oh\teln_of\teln_oh");
sb_head_params.append("\toffs\toffs_x\toffs_y");
}
// data row
sb_body_params.append(String.format("%s\t%d\t%s", object_type,indices[0], ortho_maps[indices[0]].getName()));
if (indices.length > 1) {
sb_body_params.append(String.format("\t%d\t%s", indices[1], ortho_maps[indices[1]].getName()));
}
sb_body_params.append(String.format("\t%6.2f\t%6.2f\t%8.6f\t%8.6f\t%6.2f\t%5.3f\t%7.5f\t%7.5f\t%7.5f",
phaseCoeff[0],lpf_sigma[0],min_corrs[0],filt_best[0],filt_abs_contrast,filt_roundness[0], min_corr_full_rel,min_corr_half_rel,filt_frac_max));
sb_body_params.append(String.format("\t%6.4f\t%6.4f\t%6.4f\t%6.4f",
filt_max_radius[0][0],filt_max_radius[0][1],filt_elongation[0][0],filt_elongation[0][1]));
sb_body_params.append(String.format("\t%6.3f\t%6.3f\t%6.3f", filt_dist[0],filt_dist[1],filt_height));
sb_body_params.append(String.format("\t%5.1f\t%6.4f\t%6.4f", filt_other_rad,filt_other_frac[0],filt_full_half_frac[0]));
sb_body_params.append(String.format("\t%5.3f\t%5.2f\t%5.2f\t%b\t%d\t%b\t%5.3f\t%b\t%5.3f",
filt_abs_easepart,abs_edge_frac,abs_oversize,abs_force_round,
abs_mode,abs_invert,abs_outliers_frac,abs_obscure_warm,abs_obscure_frac));
sb_body_params.append(String.format("\t%8.6f", hi_lo_freq));
// parameters for the second scene
if (indices.length > 1) {
sb_body_params.append(String.format("\t%6.2f\t%6.2f\t%8.6f\t8.6f",
phaseCoeff[1],lpf_sigma[1],min_corrs[1],filt_best[1]));
sb_body_params.append(String.format("\t%6.4f\t%6.4f\t%6.4f\t%6.4f",
filt_max_radius[1][0],filt_max_radius[1][1],filt_elongation[1][0],filt_elongation[1][1]));
sb_body_params.append(String.format("\t%6.1f\t%6.1f\t%6.1f",
Math.sqrt(scene_xy_offset[0]*scene_xy_offset[0]+scene_xy_offset[1]*scene_xy_offset[1]),
scene_xy_offset[0],scene_xy_offset[1]));
}
sb_body_params.append("\n");
}
String basename = getBaseName(
ortho_maps, // OrthoMap [] ortho_maps,
indices); // int [] indices)
if (show_results && show) {
if (gen_results) {
new TextWindow(basename+"-results", sb_head_res.toString(), sb_body_res.toString(), 1500,400);
}
if (gen_parameters) {
new TextWindow(basename+"-parameters", sb_head_params.toString(), sb_body_params.toString(), 1200,400);
}
}
StringBuffer sb = new StringBuffer();
if (gen_results) {
sb.append(sb_head_res);
sb.append("\n");
sb.append(sb_body_res);
if (gen_parameters) sb.append("\n"); // extra line
}
if (gen_parameters) {
sb.append(sb_head_params);
sb.append("\n");
sb.append(sb_body_params);
}
if (save_images && save && (gen_results || gen_parameters)) {
StringBuffer sb1 = new StringBuffer();
if (table_datetime && append_table) {
sb1.append(new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime())+"\n");
}
sb1.append(sb);
String path = save_dir+basename+RESULTS_SUFFIX;
CalibrationFileManagement.saveStringToFile (
path, //String path,
sb1.toString(), // data,
append_table); // boolean append)
if (debugLevel > -4) {
System.out.println ("Results "+(append_table? "appended":"saved")+" to "+path);
}
}
if (append_log) {
StringBuffer sb1 = new StringBuffer();
if (log_line != null) {
sb1.append(log_line);
}
sb1.append (sb);
String log_path = save_dir+basename+LOG_SUFFIX;
CalibrationFileManagement.saveStringToFile (
log_path, //String path,
sb1.toString(), // data,
true); // boolean append)
}
System.out.println("generateReport() DONE");
}
}
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