Commit 12d3c947 authored by Andrey Filippov's avatar Andrey Filippov

Cleaned up/implemented generation of the scene stats and combo images

parent 640b8df3
......@@ -148,11 +148,12 @@ public class ComboMatch {
int gpu_width= clt_parameters.imp.rln_gpu_width; // 3008;
int gpu_height= clt_parameters.imp.rln_gpu_height; // 3008;
int zoom_lev = -3; // 0; // +1 - zoom in twice, -1 - zoom out twice
boolean show_map_stats = false;
boolean show_combo_map = false; // true;
boolean show_combo_mask = false; // generate image mas (where it is defined)_
boolean use_alt = false;
boolean show_centers = true;
// boolean show_map_stats = false;
boolean show_combo = false; // true;
// boolean show_combo_mask = false; // generate image mas (where it is defined)_
// boolean use_alt = false;
// boolean show_centers = true;
boolean use_saved_collection = true; // false;
boolean save_collection = true;
boolean process_correlation = true; // use false to save new version of data
......@@ -212,11 +213,11 @@ public class ComboMatch {
"GPU image width");
gd.addNumericField("GPU image height", gpu_height, 0,4,"",
"GPU image height");
gd.addCheckbox ("Show transformation centers", show_centers, "Mark verticals from the UAS on the ground.");
gd.addCheckbox ("Show statistics for ortho images", show_map_stats, "Generate and show statistics for ortho maps.");
gd.addCheckbox ("Show combo image map", show_combo_map, "Load and process altitude maps.");
gd.addCheckbox ("Show combo image mask", show_combo_mask, "Display combo binary image.");
gd.addCheckbox ("Show altitude combo image", use_alt, "Load and process altitude maps.");
// gd.addCheckbox ("Show transformation centers", show_centers, "Mark verticals from the UAS on the ground.");
// gd.addCheckbox ("Show statistics for ortho images", show_map_stats, "Generate and show statistics for ortho maps.");
gd.addCheckbox ("Show combo maps/stats", show_combo, "Generate/save combo maps and stats.");
// gd.addCheckbox ("Show combo image mask", show_combo_mask, "Display combo binary image.");
// gd.addCheckbox ("Show altitude combo image", use_alt, "Load and process altitude maps.");
gd.addNumericField("Remove fraction of worst matches", frac_remove, 3,7,"", "When fitting scenes remove this fraction of worst match.");
gd.addNumericField("Maximal metric error", metric_error, 3,7,"m", "Maximal tolerable fitting error caused by elevation variations.");
if (use_marked_image ) {
......@@ -257,11 +258,11 @@ public class ComboMatch {
OrthoMap.setGPUWidthHeight(gpu_width,gpu_height);
show_centers = gd.getNextBoolean();
show_map_stats = gd.getNextBoolean();
show_combo_map = gd.getNextBoolean();
show_combo_mask = gd.getNextBoolean();
use_alt = gd.getNextBoolean();
// show_centers = gd.getNextBoolean();
// show_map_stats = gd.getNextBoolean();
show_combo = gd.getNextBoolean();
// show_combo_mask = gd.getNextBoolean();
// use_alt = gd.getNextBoolean();
// gpu_spair[0] = gd.getNextString();
// gpu_spair[1] = gd.getNextString();
......@@ -741,48 +742,9 @@ public class ComboMatch {
// which pair to compare
// String [] gpu_spair = {names[gpu_ipair[0]],names[gpu_ipair[1]]};
int [] origin = new int[2];
ImagePlus imp_img = null;
if (show_map_stats) {
boolean ok = maps_collection.showScenesStats(false); // boolean select_all)
if (!ok) {
return false;
}
// System.out.println("Exiting after generating stats");
// return true; // do not process anything else
}
if (show_combo_map) {
imp_img = maps_collection.renderMulti (
"multi_zoom"+zoom_lev, // String title,
OrthoMapsCollection.MODE_IMAGE, // int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask // boolean use_alt,
show_centers, // boolean show_centers,
zoom_lev, // int zoom_level,
temp_mode, // int temp_mode, // 0 - do nothing, 1 - equalize average,2 - try to correct
origin); // int [] origin){
imp_img.show();
}
ImagePlus imp_alt = null;
if (use_alt) {
imp_alt =maps_collection.renderMulti (
"multi_alt_zoom"+zoom_lev, // String title,
// true, // boolean use_alt,
OrthoMapsCollection.MODE_ALT, // int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask // boolean use_alt,
show_centers, // boolean show_centers,
zoom_lev, // int zoom_level,
0, // int temp_mode, // 0 - do nothing, 1 - equalize average,2 - try to correct
origin); // int [] origin){
imp_alt.show();
}
if (show_combo_mask) {
imp_alt =maps_collection.renderMulti (
"multi_alt_zoom"+zoom_lev, // String title,
// true, // boolean use_alt,
OrthoMapsCollection.MODE_MASK, // int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask // boolean use_alt,
show_centers, // boolean show_centers,
zoom_lev, // int zoom_level,
0, // int temp_mode, // 0 - do nothing, 1 - equalize average,2 - try to correct
origin); // int [] origin){
imp_alt.show();
if (show_combo) { // now all modes, and stats?
maps_collection.processComboMap(debugLevel);
return true;
}
if (process_correlation || render_match || pattern_match) {
// int [] gpu_pair;
......@@ -953,8 +915,6 @@ public class ComboMatch {
}
}
if (pattern_match) {
ImagePlus imp_pat_match = maps_collection.patternMatchDualWrap (
gpu_pair, // int [] indices, // null or which indices to use (normally just 2 for pairwise comparison)
......@@ -974,7 +934,7 @@ public class ComboMatch {
temp_mode, // int temp_mode, // 0 - do nothing, 1 - equalize average,2 - try to correct
affines, // double [][][] affines, // null or [indices.length][2][3]
warp, // FineXYCorr warp,
show_centers, // boolean show_centers,
true, // show_centers, // boolean show_centers,
min_zoom_lev, // int zoom_level,
origin); // int [] origin){
imp_img_pair.show();
......
......@@ -200,6 +200,16 @@ public class ItemMatch {
return match.getMatch(indx);
}
public double getMatchBestValue(String pattern_path) {
ItemPatternMatch match = pattern_matches.get(pattern_path);
if (match == null) {
System.out.println("No matches found for pattern "+pattern_path);
return Double.NaN;
}
return match.getBestMatchValue();
}
/**
......@@ -212,6 +222,17 @@ public class ItemMatch {
return getMatchValue(groundObjectPattern.getPatternPath());
}
/**
* Return actual best correlation value regardless of where best subpattern index
* points to - it may be forced to point to the full pattern by absolute contrast
* @param groundObjectPattern
* @return maximal correlation value amoong the full pattern and all half-patterns.
*/
public double getMatchBestValue(GroundObjectPattern groundObjectPattern) {
return getMatchBestValue(groundObjectPattern.getPatternPath());
}
public double getMatchValue(String pattern_path) {
int indx = getPatternMatch(pattern_path).getBestSub(); // -1;
......@@ -231,6 +252,7 @@ public class ItemMatch {
int indx){
String pattern_path = groundObjectPattern.getPatternPath();
return sortByMatch(match_list, pattern_path, keep_removed, indx);
}
public static ArrayList<Integer> sortByMatch(
......@@ -238,6 +260,9 @@ public class ItemMatch {
String pattern_path,
boolean keep_removed,
int indx){
if (indx < 0) {
return sortByBestMatch (match_list, pattern_path, keep_removed);
}
double large_enough = 1.0;
ArrayList<Integer> result_list= new ArrayList<Integer>(match_list.size());
for (int i = 0; i < match_list.size(); i++) {
......@@ -258,6 +283,32 @@ public class ItemMatch {
return result_list;
}
public static ArrayList<Integer> sortByBestMatch(
ArrayList<ItemMatch> match_list,
String pattern_path,
boolean keep_removed){
double large_enough = 1.0;
ArrayList<Integer> result_list= new ArrayList<Integer>(match_list.size());
for (int i = 0; i < match_list.size(); i++) {
if (keep_removed || !match_list.get(i).isRemoved()) {
result_list.add(i);
}
}
Collections.sort(result_list, new Comparator<Integer>() {
@Override
public int compare(Integer lhs, Integer rhs) {
ItemMatch rhsm = match_list.get(rhs);
ItemMatch lhsm = match_list.get(lhs);
double rhsd = rhsm.getMatchBestValue(pattern_path) - (rhsm.isRemoved() ? large_enough:0 );
double lhsd = lhsm.getMatchBestValue(pattern_path) - (lhsm.isRemoved() ? large_enough:0 );
return (rhsd > lhsd) ? 1 : (rhsd < lhsd) ? -1 : 0; // decreasing
}
});
return result_list;
}
public static void setExtractedObjects(
int scene_num,
int extr_size,
......
......@@ -41,6 +41,25 @@ public class ItemPatternMatch {
}
return sub_matches[indx];
}
/**
* Return actual largest value of full and all half patterns, regardless of best_sub which can point
* to full pattern even if the correlation value is larger for partial
* @return
*/
public double getBestMatchValue() { //
if (sub_matches == null) {
return Double.NaN;
}
double best = 0;
for (int i = 1; i < sub_matches.length; i++) {
if (sub_matches[i] > best) {
best = sub_matches[i];
}
}
return best;
}
public double [] getMatches() {
return sub_matches;
......
......@@ -2165,7 +2165,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
}
}
double threshold = obscure_frac * avg[0] + (1.0 - obscure_frac) * avg[1];
double threshold = (1.0 - obscure_frac) * avg[0] + obscure_frac * avg[1];
double over_thresh = (avg[0] < avg[1]) ? (zone3_min_max[0] - threshold) : (threshold - zone3_min_max[1]);
......
......@@ -24,6 +24,7 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import com.elphel.imagej.cameras.CLTParameters;
import com.elphel.imagej.common.DoubleGaussianBlur;
import com.elphel.imagej.common.GenericJTabbedDialog;
import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.gpu.GPUTileProcessor;
......@@ -31,6 +32,7 @@ import com.elphel.imagej.gpu.TpTask;
import com.elphel.imagej.tileprocessor.ImageDtt;
import com.elphel.imagej.tileprocessor.OpticalFlow;
import com.elphel.imagej.tileprocessor.TDCorrTile;
import com.elphel.imagej.tileprocessor.TileNeibs;
import ij.ImagePlus;
import ij.ImageStack;
......@@ -485,7 +487,6 @@ public class OrthoMapsCollection implements Serializable{
public ImagePlus renderMulti (
String title,
// boolean use_alt,
int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask
boolean show_centers,
int zoom_level,
......@@ -493,7 +494,6 @@ public class OrthoMapsCollection implements Serializable{
int [] origin){
return renderMulti (
title, // String title,
// use_alt, // boolean use_alt,'
mode, // int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask
null, // int [] indices, // null or which indices to use (normally just 2 for pairwise comparison)
false, // bounds_to_indices, // boolean bounds_to_indices,
......@@ -1950,6 +1950,7 @@ public class OrthoMapsCollection implements Serializable{
double [] phaseCoeff = {0.98,0.5};
double [] lpf_sigma = {0.0, 0.0};
double min_corr_full_rel = 0.85; // try 0.85
double min_corr_half_rel = 1.2; // increase correlation threshold for half-patterns relative to full patterns;
double full_preference = 1.4;
double max_min_ratio = 3.0;
boolean[] combine_full = {true, true}; // try for other olso?
......@@ -1976,18 +1977,16 @@ public class OrthoMapsCollection implements Serializable{
boolean filt_atonce = false; // apply main/second together, false - first filter main only
double filt_frac_max = 0.6; // 0.5; // measure are at fraction of max
double [][] filt_max_radius = {{1.0,1.0},{1.2,1.2}}; // {1.0,1.0}}; // [second/main][full/half] - inactive now
// double [][] filt_elongation = {{1.5,1.5},{1.7,1.7}}; // [second/main][full/half] ellipse axis ratio
double [][] filt_elongation = {{1.7,1.7},{1.7,1.7}}; // [second/main][full/half] ellipse axis ratio
double filt_other_rad = 25; // should be no disconnected high peaks in this radius (only for halves multiplied)
double [] filt_other_frac = {0.8,0.68}; // -.8}; // no pixels around max at filt_other_rad should be higher than this fraction of max
// double [] filt_dist = {8.0,5.0}; // full offset and perpendicular to images offsets
// make conditional distance - decrease if small offset (increase for large to accommodate +30/-10cm
double [] filt_dist = {10.0,5.0}; // full offset and perpendicular to images offsets
double filt_height = 0.2; // allow extra negative offset parallel to image offset, corresponding to object above ground
// double [] filt_full_half_frac = {0.7, 0.5}; // second probably not needed, it is for main
double [] filt_full_half_frac = {0.675, 0.5}; // second probably not needed, it is for main
double [] filt_roundness = {0.58, 0.0}; //{0.6, 0.0}; // second currently is not calculated/ used 215 mine1 0.059618
double [] filt_best = {0.095, 0.0};// second currently is not calculated
double filt_abs_contrast = 80.0; // 50.0;
double filt_abs_easepart = 1.0; // 1.0-no ease for low AGL. Allow lower absolute contrast for partial patterns (high AGL)
boolean convolve_after = false; // true for old kernel tuning (kernel decimation before convolution)
......@@ -1995,29 +1994,53 @@ public class OrthoMapsCollection implements Serializable{
int debugLevel = 1;
String save_top_dir = "/media/elphel/NVME/lwir16-proc/ortho_videos/debug/sept12-13/pattern_match/";
String sub_dir = "dbg_recenter_02";
String sub_dir = "dbg_recenter_06";
boolean show_images = true;
boolean save_images = true;
String alt_mode="50m";
String alt_mode="??m";
// Overwrite some defaults based on AGL
if (scene0_agl > ((50+75)/2)) {
if (scene0_agl < ((75+100)/2)) { // 75m defaults
if (scene0_agl <= ((50+75)/2)) { // add versions for morning/morning or morning/evening
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
} else if (scene0_agl < ((75+100)/2)) { // 75m defaults
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[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;
filt_roundness[0] = 0.53;
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)
......@@ -2026,9 +2049,9 @@ public class OrthoMapsCollection implements Serializable{
} else { // 100m defaults
alt_mode="100m";
lpf_sigma = new double [] {0.25, 0.25};
// min_corrs = new double[]{0.0068,0.006};
// 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};
// min_corrs = new double[]{0.0066,0.0057};
abs_edge_frac = 0.35;
abs_oversize = 2.2;
filt_abs_contrast = 60;
......@@ -2037,17 +2060,18 @@ public class OrthoMapsCollection implements Serializable{
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.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
// adv_radius = 20; // pix?
}
// adv_radius = 20; // pix?
}
//++++++++++++++++++++++++++++ show altitude mode +++++++++++++++++++++++
GenericJTabbedDialog gd = new GenericJTabbedDialog("Correlate "+((indices.length==1)? "one image":"two images")+" with patterns, altitude "+alt_mode,1200,1100);
gd.addTab("General","General parameters");
......@@ -2059,6 +2083,7 @@ public class OrthoMapsCollection implements Serializable{
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.");
......@@ -2107,6 +2132,7 @@ public class OrthoMapsCollection implements Serializable{
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).");
......@@ -2131,6 +2157,7 @@ public class OrthoMapsCollection implements Serializable{
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();
......@@ -2175,7 +2202,8 @@ public class OrthoMapsCollection implements Serializable{
filt_height = gd.getNextNumber();
filt_full_half_frac[0]=gd.getNextNumber();
filt_full_half_frac[1]=gd.getNextNumber();
filt_roundness[0]=gd.getNextNumber();
filt_roundness[0]= gd.getNextNumber();
filt_best[0]= gd.getNextNumber();
filt_abs_contrast= gd.getNextNumber();
filt_abs_easepart= gd.getNextNumber();
......@@ -2196,6 +2224,7 @@ public class OrthoMapsCollection implements Serializable{
phaseCoeff, // double [] phaseCoeff
lpf_sigma, //double [] lpf_sigma, // one per, lpf_sigma
min_corr_full_rel, // double min_corr_full_rel,
min_corr_half_rel, // double min_corr_half_rel,
full_preference, // double full_preference,
max_min_ratio, // double max_min_ratio,
combine_full, // boolean[] combine_full,
......@@ -2225,6 +2254,7 @@ public class OrthoMapsCollection implements Serializable{
filt_height, // double filt_height,
filt_full_half_frac, // double [] filt_full_half_frac,
filt_roundness, // double [] filt_half_full_frac,
filt_best, // double [] filt_best,
filt_abs_contrast, // double filt_abs_contrast, // = 50.0;
filt_abs_easepart, // double filt_abs_easepart,
convolve_after, // boolean convolve_after,
......@@ -2246,6 +2276,7 @@ public class OrthoMapsCollection implements Serializable{
double [] phaseCoeff, // one per
double [] lpf_sigma, // one per, lpf_sigma
double min_corr_full_rel,
double min_corr_half_rel,
double full_preference,
double max_min_ratio,
boolean[] combine_full,
......@@ -2275,6 +2306,7 @@ public class OrthoMapsCollection implements Serializable{
double filt_height,
double [] filt_full_half_frac,
double [] filt_roundness,
double [] filt_best,
double filt_abs_contrast, // = 50.0;
double filt_abs_easepart,
boolean convolve_after, // mitigating kernels tuned for decimate before convolve
......@@ -2284,7 +2316,15 @@ public class OrthoMapsCollection implements Serializable{
boolean show_images, // = true;
boolean save_images, // = true;
int debugLevel) {
boolean sort_by_best = true; // false - as was, by selected pattern
double ease_first_best = 0.9; // before recenter
// sample around + and - 128/spectrum_sample[0]
// from (128/spectrum_sample[0])/spectrum_sample[1]
// to (128/spectrum_sample[0])*spectrum_sample[1].
// Calculate average of FFT power spectrum on both sides, in both directions and get ratio
double [] spectrum_sample = {14, 1.5};
double search_radius_recenter = 3; // how far to look for updated correlation peak after recenter
if (warp != null) {
warp.scale_warp = scale_warp;
......@@ -2591,12 +2631,13 @@ public class OrthoMapsCollection implements Serializable{
best_patt); // int best_sub);
matches_list.add(item_match);
}
int sort_pattern_index = 0; //combo. 1 - full pattern
int sort_pattern_index = 0; // used in other places, not just for sorting
int sort_pattern_mode = sort_by_best? -1 : 0; // -1 - best match, regardles off best pointer 0; //combo. 1 - full pattern
ArrayList<Integer> match_sort = ItemMatch.sortByMatch(
matches_list, // ArrayList<ItemMatch> match_list,
gops[scene_num],
false, // boolean keep_removed,// GroundObjectPattern groundObjectPattern,
sort_pattern_index); // int indx)
sort_pattern_mode); // int indx)
// Print all results
System.out.println("Match candidates ("+match_sort.size()+
") that exceed minimal correlation strength of "+min_corrs[scene_num]);
......@@ -2662,7 +2703,7 @@ public class OrthoMapsCollection implements Serializable{
if (num_non_overlap > 0) {
System.out.println("Removed "+num_non_overlap+" objects outside of the scenes overlap, "+match_sort.size()+" remain");
}
System.out.print(String.format("%4s: %9s %8s %6s %3s"," # ", " x/y ", " best ","round", "sub"));
System.out.print(String.format("%4s: %9s %8s %8s %6s %3s"," # ", " x/y ", "sel-corr"," best ","round", "sub"));
for (int j = 0; j < (corrs_out[scene_num].length + 1); j++) if (j != sort_pattern_index) {
System.out.print(String.format(" %8s ","match_"+j));
}
......@@ -2672,10 +2713,11 @@ public class OrthoMapsCollection implements Serializable{
ItemMatch match = matches_list.get(indx);
double [] match_values = match.getMatchValues(gops[scene_num]);
int [] icenter_xy = match.getIntXY();
System.out.print(String.format("%4d: %4d/%4d %8.5f %6.3f %3d",
System.out.print(String.format("%4d: %4d/%4d %8.5f %8.5f %6.3f %3d",
i,
icenter_xy[0],icenter_xy[1],
match.getMatchValue(gops[scene_num]),
match.getMatchBestValue(gops[scene_num]),
match.getRoundness (gops[scene_num]),
match.getPatternMatch(gops[scene_num]).getBestSub())); // 1-based
for (int j = 0; j < match_values.length; j++) if (j != sort_pattern_index) {
......@@ -2836,12 +2878,12 @@ public class OrthoMapsCollection implements Serializable{
matches_list, // ArrayList<ItemMatch> match_list,
gops[scene_num], // GroundObjectPattern groundObjectPattern,
false, // boolean keep_removed,// GroundObjectPattern groundObjectPattern,
sort_pattern_index); // int indx)
sort_pattern_mode); // int indx)
// Print all results
System.out.println("Centered match candidates ("+match_sort.size()+
")"); // +min_corrs[scene_num]);
// print updated list
System.out.print(String.format("%4s: %9s %8s %6s %3s"," # ", " x/y ", " best ","round", "sub"));
System.out.print(String.format("%4s: %9s %8s %8s %6s %3s"," # ", " x/y ", "sel-corr"," best ","round", "sub"));
for (int j = 0; j < (corrs_out[scene_num].length + 1); j++) if (j != sort_pattern_index) {
System.out.print(String.format(" %8s ","match_"+j));
}
......@@ -2851,10 +2893,11 @@ public class OrthoMapsCollection implements Serializable{
ItemMatch match = matches_list.get(indx);
double [] match_values = match.getMatchValues(gops[scene_num]);
int [] icenter_xy = match.getIntXY();
System.out.print(String.format("%4d: %4d/%4d %8.5f %6.3f %3d",
System.out.print(String.format("%4d: %4d/%4d %8.5f %8.5f %6.3f %3d",
i,
icenter_xy[0],icenter_xy[1],
match.getMatchValue(gops[scene_num]),
match.getMatchBestValue(gops[scene_num]),
match.getRoundness (gops[scene_num]),
match.getPatternMatch(gops[scene_num]).getBestSub())); // 1-based
for (int j = 0; j < match_values.length; j++) if (j != sort_pattern_index) {
......@@ -2959,12 +3002,14 @@ public class OrthoMapsCollection implements Serializable{
filt_main_other, // new boolean [] filt_main_other,
min_corrs, // double [] min_corrs, // one per
min_corr_full_rel, // double min_corr_full_rel,
min_corr_half_rel, // double min_corr_half_rel,
filt_max_radius, // double [][] filt_max_radius,
filt_elongation, // double [][] filt_elongation,
filt_dist, // double [] filt_dist,
filt_height, // double filt_height,
filt_full_half_frac,// double [] filt_full_half_frac,
filt_roundness, // double [] filt_roundness,
filt_best, // double [] filt_best,
filt_abs_contrast, // double filt_abs_contrast,
filt_abs_easepart, // double filt_abs_easepart,
gops[scene_num], // GroundObjectPattern gop,
......@@ -3023,7 +3068,7 @@ public class OrthoMapsCollection implements Serializable{
if (indices.length > 1) {
// print updated table after some scenes may be removed by the filter
System.out.println("\nAfter first scene filtering:");
System.out.print(String.format("%4s: %9s %8s %8s %6s %3s"," # ", " x/y ", " best ","contrast","round", "sub"));
System.out.print(String.format("%4s: %9s %8s %8s %8s %6s %3s"," # ", " x/y ", "sel-corr"," best ","contrast","round", "sub"));
for (int j = 0; j < (corrs_out[scene_num].length + 1); j++) if (j != sort_pattern_index) {
System.out.print(String.format(" %8s ","match_"+j));
}
......@@ -3040,10 +3085,11 @@ public class OrthoMapsCollection implements Serializable{
// double best_val = match.getMatchValue(gops[scene_num],sort_pattern_index);
// so it is updated after best subpattern could be changed in setAbsoluteContrasts()
//match_values[match.getPatternMatch(gops[scene_num]).getBestSub() -1];
System.out.print(String.format("%4d: %4d/%4d %8.5f %8.3f %6.3f %3d",
System.out.print(String.format("%4d: %4d/%4d %8.5f %8.5f %8.3f %6.3f %3d",
i,
icenter_xy[0],icenter_xy[1],
match.getMatchValue(gops[scene_num]),
match.getMatchBestValue(gops[scene_num]),
match.getAbsoluteContrast(),
match.getRoundness(gops[scene_num]),
match.getPatternMatch(gops[scene_num]).getBestSub())); // 1-based
......@@ -3151,12 +3197,14 @@ public class OrthoMapsCollection implements Serializable{
filt_main_other, // new boolean [] filt_main_other,
min_corrs, //double [] min_corrs, // one per
min_corr_full_rel, // double min_corr_full_rel,
min_corr_half_rel, // double min_corr_half_rel,
filt_max_radius, // double [][] filt_max_radius,
filt_elongation, // double [][] filt_elongation,
filt_dist, // double [] filt_dist,
filt_height, // double filt_height,
filt_full_half_frac,// double [] filt_other_frac, // null - disable, for all full (round) patterns.
filt_roundness, // double [] filt_roundness,
filt_best, // double [] filt_best,
filt_abs_contrast, // double filt_abs_contrast,
filt_abs_easepart, // double filt_abs_easepart,
gops[scene_num], // GroundObjectPattern gop,
......@@ -3208,7 +3256,7 @@ public class OrthoMapsCollection implements Serializable{
}
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+", frac_max="+frac_max);
"], min_corr_full_rel="+min_corr_full_rel+", min_corr_half_rel="+min_corr_half_rel+", frac_max="+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]+"], "+
......@@ -3217,7 +3265,8 @@ public class OrthoMapsCollection implements Serializable{
"(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_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);
......@@ -3229,7 +3278,7 @@ public class OrthoMapsCollection implements Serializable{
Math.sqrt(scene_xy_offset[0]*scene_xy_offset[0]+scene_xy_offset[1]*scene_xy_offset[1])+" pix");
}
// 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 %6s %3s"," # ", " x/y ", " best ","contrast","round","sub"));
System.out.print(String.format("%4s: %9s %8s %8s %8s %6s %3s"," # ", " x/y ", "sel-corr", " best ","contrast","round","sub"));
for (int j = 0; j < (corrs_out[scene_num].length + 1); j++) if (j != sort_pattern_index) {
System.out.print(String.format(" %8s ","match_"+j));
}
......@@ -3249,10 +3298,11 @@ public class OrthoMapsCollection implements Serializable{
double [] match_values = match.getMatchValues(gops[scene_num]);
CorrelationPeakStats [][] filter_data = match.filter_data;
int [] icenter_xy = match.getIntXY();
System.out.print(String.format("%4d: %4d/%4d %8.5f %8.3f %6.3f %3d",
System.out.print(String.format("%4d: %4d/%4d %8.5f %8.5f %8.3f %6.3f %3d",
i,
icenter_xy[0],icenter_xy[1],
match.getMatchValue(gops[scene_num]), // ,sort_pattern_index),
match.getMatchBestValue(gops[scene_num]),
match.getAbsoluteContrast(),
match.getRoundness(gops[scene_num]),
match.getPatternMatch(gops[scene_num]).getBestSub())); // 1-based
......@@ -3430,12 +3480,14 @@ public class OrthoMapsCollection implements Serializable{
boolean [] filt_main_other, // length== number of scenes
double [] min_corrs, // one per
double min_corr_full_rel,
double min_corr_half_rel,
double [][] filt_max_radius,
double [][] filt_elongation,
double [] filt_dist,
double filt_height,
double [] filt_full_half_frac,
double [] filt_roundness,
double [] filt_best,
double filt_abs_contrast,
double filt_abs_easepart,
GroundObjectPattern gop,
......@@ -3471,6 +3523,7 @@ public class OrthoMapsCollection implements Serializable{
double abs_contrast = match.getAbsoluteContrast();
double roundness = match.getRoundness(gop);
int best_patt= match.getPatternMatch(gop).getBestSub(); // 1-based
double best_value = match.getMatchBestValue(gop);
boolean is_partial = best_patt != 1; // only apply to combined full/half correlations, just full may have nearby maximums near the same size
double [] strength_full_half_ratio = new double[num_scenes];
for (int scene_num = 0; scene_num < num_scenes; scene_num++) if (filt_main_other[scene_num] && (filter_data[scene_num] != null)){
......@@ -3497,6 +3550,15 @@ public class OrthoMapsCollection implements Serializable{
if (!match.isRemoved()) num_removed++;
match.remove();
}
// only apply to full patterns, because partial can be filtered without it
if (!is_partial && !(best_value >= filt_best[0])) { // NaN - also bad
System.out.println(name+": filtered out by "+NAME_MO[0]+
" scene because it is full-pattern and its best correlation value = "+
best_value+ " < "+filt_best[0]);
if (!match.isRemoved()) num_removed++;
match.remove();
}
for (int hf = 0; hf < 2; hf++) {
for (int scene_num = 0; scene_num < num_scenes; scene_num++) if (filt_main_other[scene_num]){
if (Double.isNaN(filter_data[scene_num][hf].best_d)) {
......@@ -3527,6 +3589,15 @@ public class OrthoMapsCollection implements Serializable{
if (!match.isRemoved()) num_removed++;
match.remove();
}
if (is_partial && (hf > 0) && (corr_val < min_corr_half_rel * min_corrs[scene_num])) {
System.out.println(name+": filtered out by "+NAME_MO[scene_num]+
" because it is partial and correlation maximum value for "+
NAME_FH[hf]+ " = "+corr_val+" < "+ min_corr_half_rel*min_corrs_other[scene_num][hf]+
" (increased by "+min_corr_half_rel+" from base "+min_corrs[scene_num]+").");
if (!match.isRemoved()) num_removed++;
match.remove();
}
if (scene_num > 0) { // other scene
// {best_d, eff_rad, elong, dist, cent_offs[0], cent_offs[1]} ;
if (dist > filt_dist[0]) {
......@@ -3717,11 +3788,17 @@ public class OrthoMapsCollection implements Serializable{
dir_contrasts[i][0] *= -1;
}
boolean bad_obscurant = obscure_warm && (dir_contrasts[i][1] < 0);
if (try_sub[i] && !bad_obscurant && (dir_contrasts[i][0] > 0)) {
if ((best_index < 0) || (dir_contrasts[i][0] > dir_contrasts[best_index][0])) {
if (try_sub[i] && (dir_contrasts[i][0] > 0)) {
if (bad_obscurant) {
if (debugLevel > -4) {
System.out.println("setAbsoluteContrasts(): removing pattern_sub="+i
+", match object="+mn+" because of the bad obscurant (cold for cold object)");
}
} else {
best_index = i;
}
}
}
if (best_index < 0) {
best_index = 0;
......@@ -3783,11 +3860,9 @@ public class OrthoMapsCollection implements Serializable{
return ortho_maps[scene_number].getName();
}
public boolean showScenesStats(boolean select_all) {
public String [] getScenesList() {
String [] lines = new String [ortho_maps.length];
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss.SS zzz");// may be VV instead of zzz
String time_zone_name = "Europe/Kyiv";
for (int indx = 0; indx < ortho_maps.length; indx++) {
OrthoMap map = ortho_maps[indx];
LocalDateTime ldt = map.getLocalDateTime();
......@@ -3799,21 +3874,54 @@ public class OrthoMapsCollection implements Serializable{
lines[indx]=String.format(
"%3d %17s %26s %6.2f",indx, name, sdt, agl);
}
return lines;
}
public int [] getScenesSelection(
boolean [] pre_selects,
String purpose) { // " to generate stats", " to generate images"
String [] lines = getScenesList();
int [] sel_50 = {125,126,127,129,135,136,137,138,139,140,141,144,145,146,147,148,155,156,157,158};
int [] sel_75 = {170,177,178,183,187,188,189,192,193,199,200,204};
int [] sel_100 = {207,208,212,213,214,215,218,220};
boolean [] selection = new boolean [lines.length];
if (select_all) {
if (pre_selects != null) {
if (pre_selects[0]) {
Arrays.fill(selection, true);
}
select_all = false;
GenericJTabbedDialog gd = new GenericJTabbedDialog("Select scenes to generate stats ",1200,1000);
gd.addCheckbox ("Select all maps", select_all, "Select all scenes, reopen this dialog.");
if (pre_selects[1]) {
for (int i:sel_50) {
selection[i] = true;
}
}
if (pre_selects[2]) {
for (int i:sel_75) {
selection[i] = true;
}
}
if (pre_selects[3]) {
for (int i:sel_100) {
selection[i] = true;
}
}
}
pre_selects = new boolean[4];
GenericJTabbedDialog gd = new GenericJTabbedDialog("Select scenes",1200,1000);
gd.addCheckbox ("Select all maps", pre_selects[0], "Select all scenes, reopen this dialog.");
gd.addCheckbox ("Select 50m used maps", pre_selects[1], "Select 50m scenes, reopen this dialog.");
gd.addCheckbox ("Select 75m used maps", pre_selects[2], "Select 50m scenes, reopen this dialog.");
gd.addCheckbox ("Select 100m used maps", pre_selects[3], "Select 50m scenes, reopen this dialog.");
for (int i = 0; i < lines.length; i++) {
gd.addCheckbox (lines[i], selection[i], "Select scene number "+i);
}
gd.showDialog();
if (gd.wasCanceled()) return false;
select_all= gd.getNextBoolean();
if (select_all) {
return showScenesStats(select_all);
if (gd.wasCanceled()) return null;
pre_selects[0]= gd.getNextBoolean();
pre_selects[1]= gd.getNextBoolean();
pre_selects[2]= gd.getNextBoolean();
pre_selects[3]= gd.getNextBoolean();
if (pre_selects[0] ||pre_selects[1] || pre_selects[2] || pre_selects[3]) {
return getScenesSelection(pre_selects, purpose);
}
int num_sel = 0;
for (int i = 0; i < selection.length; i++) {
......@@ -3827,6 +3935,459 @@ public class OrthoMapsCollection implements Serializable{
for (int i = 0; i < selection.length; i++) if (selection[i]) {
indices[indx++] = i;
}
return indices;
}
public boolean processComboMap(
int debugLevel) {
int [] indices = getScenesSelection(
null, // boolean select_all,
" to process"); // String purpose)
if (indices == null) {
return false;
}
boolean more = true;
while (more) { // generate multiple images/stats for the same selection
more = processComboSelection(indices, debugLevel);
}
return true;
}
public boolean processComboSelection(
int [] indices,
int debugLevel) {
boolean show_map_stats = false;
boolean show_combo_map = false; // true;
boolean show_alt_map = false;
boolean show_combo_mask = false; // generate image mas (where it is defined)
boolean show_frames = false;
int frame_shrink = 4;
int frame_grow = 4;
double frame_blur = 1.0;
double frame_cut_frac = 0.01;
int zoom_lev = -2; // 0; // +1 - zoom in twice, -1 - zoom out twice
int margins = 10;
boolean show_centers = true;
boolean bounds_to_indices = true;
boolean merge_layers = false; // instead of individuals
String save_top_dir = "/media/elphel/NVME/lwir16-proc/ortho_videos/debug/sept12-13/pattern_match/";
String sub_dir = "combo_maps";
boolean show_images = true;
boolean save_images = true;
GenericJTabbedDialog gd = new GenericJTabbedDialog("Combo map/stats generation",1200,1000);
gd.addCheckbox ("Show statistics for ortho images", show_map_stats, "Generate and show statistics for ortho maps.");
gd.addCheckbox ("Show image map", show_combo_map, "Generate composite map of images.");
gd.addCheckbox ("Show altitudes", show_alt_map, "Generate composite process altitude maps.");
gd.addCheckbox ("Show image masks", show_combo_mask, "Generate composite binary image.");
gd.addCheckbox ("Show image frames", show_frames, "Generate image borders.");
gd.addNumericField("Shrink inner frames", frame_shrink, 0,4,"pix","Shrink inner of the frames from the actual image borders.");
gd.addNumericField("Grow outer frames", frame_grow, 0,4,"pix","Grow outer of the frames from the actual image borders.");
gd.addNumericField("Blur frames", frame_blur, 3,7,"pix","Blur frames for anti-aliasing.");
gd.addNumericField("Cut threshold", frame_cut_frac, 3,7,"","After blurring, replace lower values by NaN.");
gd.addNumericField("Zoom level", zoom_lev, 0,4,"",
"Zoom level: +1 - zoom in twice, -1 - zoom out twice");
gd.addNumericField("Margins", margins, 0,4,"",
"Add margins around images");
gd.addCheckbox ("Show transformation centers", show_centers, "Mark verticals from the UAS on the ground.");
gd.addCheckbox ("Bounds to selected images", bounds_to_indices, "Set combo image bounds to selected images only. False - all images.");
gd.addCheckbox ("Merge layers", merge_layers, "Generate composite binary image.");
gd.addStringField ("Pattern match save directory", save_top_dir, 120, "Top directory to save combo maps");
gd.addStringField ("Save subdirectory", sub_dir, 80, "Subdirectory for versions of the same scene/pair of scenes");
gd.addCheckbox ("Show generated images", show_images, "Display generated images.");
gd.addCheckbox ("Save generated images", save_images, "Save generated image to the location defined by above..");
gd.showDialog();
if (gd.wasCanceled()) return false;
show_map_stats = gd.getNextBoolean();
show_combo_map = gd.getNextBoolean();
show_alt_map = gd.getNextBoolean();
show_combo_mask = gd.getNextBoolean();
show_frames = gd.getNextBoolean();
frame_shrink = (int) gd.getNextNumber();
frame_grow = (int) gd.getNextNumber();
frame_blur = gd.getNextNumber();
frame_cut_frac = gd.getNextNumber();
zoom_lev = (int) gd.getNextNumber();
margins = (int) gd.getNextNumber();
show_centers = gd.getNextBoolean();
bounds_to_indices = gd.getNextBoolean();
merge_layers = gd.getNextBoolean();
save_top_dir= gd.getNextString();
sub_dir= gd.getNextString();
show_images= gd.getNextBoolean();
save_images= gd.getNextBoolean();
String 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());
}
save_dir=save_top_dir;
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();
}
if (show_map_stats) {
String time_zone_name = "Europe/Kyiv";
String [] stats = getScenesStats(indices, time_zone_name); // int [] indices)
TextWindow tw = new TextWindow("Ortho_images_stats", stats[0], stats[1], 1250,1000);
if (save_images && (save_dir != null)) {
String path = save_dir+"ortho_images_stats.csv";
tw.getTextPanel().saveAs(path);
if (debugLevel > -4) {
System.out.println("Saved stats to "+path);
}
}
}
double pix_m = OrthoMap.getPixelSizeMeters (zoom_lev);
if (show_combo_map) {
int [] wh = new int[2];
int [] origin = new int[2];
double [][] centers = show_centers? (new double [indices.length][]): null;
double [][] dmulti = renderMultiDouble (
null, // double [][] ground_planes, // null - images, non-null altitudes. use new double[2][3] for old way alt
indices, // int [] indices, // null or which indices to use (normally just 2 for pairwise comparison)
bounds_to_indices, // boolean bounds_to_indices,
null, // affines, // double [][][] affines, // null or [indices.length][2][3]
null, // warp, // FineXYCorr warp,,
zoom_lev, // int zoom_level,
wh, // int [] wh,
origin, // int [] origin){ // maps[0] as a reference
centers); // double [][] centers)
if (margins > 0) {
addMargins(
dmulti, // double [][] dmulti,
wh, // int width,
margins); // int margins)
}
showSaveMap(
indices, // int [] indices,
dmulti, // double [][] dmulti,
wh[0], // int width,
centers, // int [][] centers,
merge_layers, // boolean merge_layers,
false, // boolean use_max,
show_images, // boolean show,
save_images, // boolean save,
save_dir, // String save_dir,
"_"+indices.length+"_MAP-"+pix_m, // String suffix
debugLevel); // int debugLevel)
}
if (show_alt_map) {
int [] wh = new int[2];
int [] origin = new int[2];
double [][] centers = show_centers? (new double [indices.length][]): null;
double [][] dmulti = renderMultiDouble (
new double [indices.length][] , // double [][] ground_planes, // null - images, non-null altitudes. use new double[2][3] for old way alt
indices, // int [] indices, // null or which indices to use (normally just 2 for pairwise comparison)
bounds_to_indices, // boolean bounds_to_indices,
null, // affines, // double [][][] affines, // null or [indices.length][2][3]
null, // warp, // FineXYCorr warp,,
zoom_lev, // int zoom_level,
wh, // int [] wh,
origin, // int [] origin){ // maps[0] as a reference
centers); // double [][] centers)
if (margins > 0) {
addMargins(
dmulti, // double [][] dmulti,
wh, // int width,
margins); // int margins)
}
showSaveMap(
indices, // int [] indices,
dmulti, // double [][] dmulti,
wh[0], // int width,
centers, // int [][] centers,
merge_layers, // boolean merge_layers,
false, // boolean use_max,
show_images, // boolean show,
save_images, // boolean save,
save_dir, // String save_dir,
"_"+indices.length+"_ALT-"+pix_m, // String suffix
debugLevel); // int debugLevel)
}
if (show_combo_mask) {
int [] wh = new int[2];
int [] origin = new int[2];
double [][] centers = show_centers? (new double [indices.length][]): null;
double [][] dmulti = renderMultiDouble (
null, // double [][] ground_planes, // null - images, non-null altitudes. use new double[2][3] for old way alt
indices, // int [] indices, // null or which indices to use (normally just 2 for pairwise comparison)
bounds_to_indices, // boolean bounds_to_indices,
null, // affines, // double [][][] affines, // null or [indices.length][2][3]
null, // warp, // FineXYCorr warp,,
zoom_lev, // int zoom_level,
wh, // int [] wh,
origin, // int [] origin){ // maps[0] as a reference
centers); // double [][] centers)
if (margins > 0) {
addMargins(
dmulti, // double [][] dmulti,
wh, // int width,
margins); // int margins)
}
for (int n = 0; n < dmulti.length; n++) {
for (int i = 0; i < dmulti[n].length; i++) {
dmulti[n][i] = Double.isNaN(dmulti[n][i])? 0:1;
}
}
showSaveMap(
indices, // int [] indices,
dmulti, // double [][] dmulti,
wh[0], // int width,
centers, // int [][] centers,
merge_layers, // boolean merge_layers,
true, // boolean use_max,
show_images, // boolean show,
save_images, // boolean save,
save_dir, // String save_dir,
"_"+indices.length+"_MASK-"+pix_m, // String suffix
debugLevel); // int debugLevel)
}
if (show_frames) {
int [] wh = new int[2];
int [] origin = new int[2];
double [][] centers = show_centers? (new double [indices.length][]): null;
double [][] dmulti = renderMultiDouble (
null, // double [][] ground_planes, // null - images, non-null altitudes. use new double[2][3] for old way alt
indices, // int [] indices, // null or which indices to use (normally just 2 for pairwise comparison)
bounds_to_indices, // boolean bounds_to_indices,
null, // affines, // double [][][] affines, // null or [indices.length][2][3]
null, // warp, // FineXYCorr warp,,
zoom_lev, // int zoom_level,
wh, // int [] wh,
origin, // int [] origin){ // maps[0] as a reference
centers); // double [][] centers)
if (margins > 0) {
addMargins(
dmulti, // double [][] dmulti,
wh, // int width,
margins); // int margins)
}
double [][] dframes = new double [dmulti.length][];
for (int n = 0; n < dmulti.length; n++) {
dframes[n] = createBorderByNaN(
dmulti[n], // double [] data,
wh[0], // int width,
frame_shrink, // int frame_shrink,
frame_grow, // int frame_grow,
frame_blur, // double frame_blur,
frame_cut_frac); // double cut_frac)
// for (int i = 0; i < dmulti[n].length; i++) {
// dmulti[n][i] = Double.isNaN(dmulti[n][i])? 0:1;
// }
}
showSaveMap(
indices, // int [] indices,
dframes, // double [][] dmulti,
wh[0], // int width,
centers, // int [][] centers,
merge_layers, // boolean merge_layers,
true, // boolean use_max,
show_images, // boolean show,
save_images, // boolean save,
save_dir, // String save_dir,
"_"+indices.length+"_FRAME-"+pix_m, // String suffix
debugLevel); // int debugLevel)
}
/*
show_frames = gd.getNextBoolean();
frame_shrink = (int) gd.getNextNumber();
frame_grow = (int) gd.getNextNumber();
frame_blur = gd.getNextNumber();
*/
//showScenesStats
//show_combo_mask
return true;
}
public static void addMargins(
double [][] dmulti,
int [] wh,
int margins){
int width = wh[0];
int height = dmulti[0].length/width;
int widthm = width+2*margins;
int heightm = height + 2* margins;
int indx0m = (widthm + 1) * margins;
for (int n = 0; n < dmulti.length; n++) {
double [] d = new double[widthm*heightm];
Arrays.fill(d, Double.NaN);
for (int row = 0; row < height; row++) {
System.arraycopy(
dmulti[n],
row*width,
d,
indx0m + widthm * row,
width);
}
dmulti[n] = d;
}
wh[0] = widthm;
wh[1] = heightm;
}
public static double [] createBorderByNaN(
double [] data,
int width,
int frame_shrink,
int frame_grow,
double frame_blur,
double cut_frac) {
double [] dframe =new double [data.length];
int height = data.length/width;
final TileNeibs tnSurface = new TileNeibs(width, height);
boolean [] mask_in = new boolean[data.length];
for (int i = 0; i < data.length; i++) {
mask_in[i] = !Double.isNaN(data[i]);
}
boolean [] mask_out = mask_in.clone();
tnSurface.shrinkSelection(
frame_shrink, // shrink,
mask_in, // tiles,
null); // prohibit);
tnSurface.growSelection(
frame_grow, // grow,
mask_out, // tiles,
null); // prohibit);
if (frame_blur > 0) {
for (int i = 0; i < dframe.length; i++) {
dframe[i] = (mask_out[i] && !mask_in[i]) ? 1.0 : 0.0;
}
// DoubleGaussianBlur gb = new DoubleGaussianBlur();
(new DoubleGaussianBlur()).blurDouble(
dframe,
width,
height,
frame_blur,
frame_blur,
0.01);
double max = 0.0;
for (int i = 0; i < dframe.length; i++) {
max = Math.max(max, dframe[i]);
}
double threshold = max*cut_frac;
for (int i = 0; i < dframe.length; i++) {
if (dframe[i] < threshold) {
dframe[i] = Double.NaN;
}
}
} else {
for (int i = 0; i < dframe.length; i++) {
dframe[i] = (mask_out[i] && !mask_in[i]) ? 1.0 : Double.NaN;
}
}
return dframe;
}
public void showSaveMap(
int [] indices,
double [][] dmulti,
int width,
double [][] centers,
boolean merge_layers,
boolean use_max,
boolean show,
boolean save,
String save_dir,
String suffix, // "_"+indices.length+"_MAP"
int debugLevel) {
boolean show_centers = centers != null;
if (merge_layers) {
dmulti = new double [][] {mergeLayers(dmulti,use_max)};
}
String [] titles = new String[dmulti.length];
for (int i = 0; i < titles.length; i++) {
titles[i] = String.format("%03d-%s", indices[i], ortho_maps[indices[i]].getName());
}
ImagePlus imp = ShowDoubleFloatArrays.makeArrays(
dmulti,
width,
dmulti[0].length/width,
ortho_maps[indices[0]].getName()+(merge_layers? "_MERGED":"")+suffix+".tiff",
titles);
if (show_centers) {
PointRoi roi = new PointRoi();
for (int i = 0; i < centers.length; i++) {
roi.addPoint(centers[i][0],centers[i][1], 1+(merge_layers?0:i));
}
roi.setOptions("label");
imp.setRoi(roi);
}
showSaveImagePlus(
imp, // ImagePlus imp,
show, // boolean show,
save, // boolean save,
save_dir, // String save_dir,
debugLevel); // int debugLevel)
}
public static double [] mergeLayers(
double [][] layers,
boolean use_max) { // false - use last
if ((layers == null) || (layers.length == 0)){
return null;
}
double [] merged = layers[0].clone();
for (int n = 1; n < layers.length; n++) {
if (use_max) {
for (int i = 0; i < merged.length; i++) if (!Double.isNaN(layers[n][i])) {
if (Double.isNaN(merged[i])) {
merged[i] = layers[n][i];
} else {
merged[i] = Math.max(layers[n][i],merged[i]);
}
}
} else {
for (int i = 0; i < merged.length; i++) if (!Double.isNaN(layers[n][i])) {
merged[i] = layers[n][i];
}
}
}
return merged;
}
public boolean showScenesStats() {
String time_zone_name = "Europe/Kyiv";
int [] indices = getScenesSelection(
null, // boolean select_all,
" to generate stats"); // String purpose)
if (indices == null) {
return false;
}
String [] stats = getScenesStats(indices, time_zone_name); // int [] indices)
new TextWindow("Ortho_images_stats", stats[0], stats[1], 1250,1000);
return true;
......
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