Commit ef8c6ac2 authored by Andrey Filippov's avatar Andrey Filippov

preparing for adding pairwise matching after single-connected are

subject to LMA
parent 099bf912
......@@ -850,6 +850,7 @@ public class Eyesis_Correction implements PlugIn, ActionListener {
addButton("Warp pair", panelLWIRWorld, color_process);
addButton("Read Tiff", panelLWIRWorld, color_process);
addButton("Test video", panelLWIRWorld, color_process);
addButton("Ortho", panelLWIRWorld, color_process);
addButton("Ortho Pairs", panelLWIRWorld, color_process);
addButton("Manual pair", panelLWIRWorld, color_process);
addButton("Extract Objects", panelLWIRWorld, color_process);
......@@ -5718,7 +5719,7 @@ public class Eyesis_Correction implements PlugIn, ActionListener {
e.printStackTrace();
}
// ComboMatch.testReadTiff();
} else if (label.equals("Ortho Pairs") || label.equals("Extract Objects") || label.equals("Manual pair")) {
} else if (label.equals("Ortho") || label.equals("Ortho Pairs") || label.equals("Extract Objects") || label.equals("Manual pair")) {
DEBUG_LEVEL = MASTER_DEBUG_LEVEL;
EYESIS_CORRECTIONS.setDebug(DEBUG_LEVEL);
if (GPU_TILE_PROCESSOR == null) {
......@@ -5739,6 +5740,7 @@ public class Eyesis_Correction implements PlugIn, ActionListener {
ComboMatch.openTestPairGps(
CLT_PARAMETERS, // CLTParameters clt_parameters,
GPU_TILE_PROCESSOR,
label.equals("Ortho"),// boolean dflt_options,
label.equals("Extract Objects"), // boolean extract_mines,
label.equals("Manual pair"), // boolean manual_pair,
DEBUG_LEVEL);
......
......@@ -50,6 +50,7 @@ public class ComboMatch {
public static int gpu_max_width= 4096;
public static int gpu_max_height= 4096;
public static String [] FILES_LISTS_PATHS = {
"/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/nov3_50-75",
"/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_sep12-13_50-25-50-75-100m",
"/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_19_sep13_25-50-75-100m",
"/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_nov3_50-75",
......@@ -60,6 +61,7 @@ public class ComboMatch {
public static boolean openTestPairGps(
CLTParameters clt_parameters,
GPUTileProcessor gpu_tile_processor, // initialized by the caller
boolean dflt_options,
boolean extract_objects,
boolean manual_pair,
int debugLevel) {
......@@ -102,8 +104,8 @@ public class ComboMatch {
}
}
}
// find -L /media/elphel/SSD3-4GB/lwir16-proc/berdich3/linked/linked_1697875868-1697879449-b/ -type f -name "*-GCORR-GEO.tiff" | sort > GCORR-GEO.list
// find -L /media/elphel/SSD3-4GB/lwir16-proc/berdich3/linked/linked_1697875868-1697879449-b/ -type f -name "*-GCORR-GEO.tiff" | sort > GCORR-GEO.list
// find -L . -path "*-BC-FLAT_CLN-VERT-GCORR-GEO.tiff" -newermt "2024-06-01" -print > GCORR-GEO.list
// String files_list_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_03_short.list";
// String orthoMapsCollection_path = "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/ortho_maps_collection.data";
......@@ -155,7 +157,7 @@ public class ComboMatch {
gpu_spair = new String[]{"1694564291_293695","1694564778_589341"}; // Morning Sep, 13 50m, 75m #97, #139
}
*/
double [][][] image_enuatr = {{{0,0,0},{0,0,0}},{{0,0,0},{0,0,0}}};
// double [][][] image_enuatr = {{{0,0,0},{0,0,0}},{{0,0,0},{0,0,0}}};
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
......@@ -173,7 +175,7 @@ public class ComboMatch {
boolean update_match = true; // use false to save new version of data
boolean render_match = false; // true;
boolean test_multi_lma = false;
boolean pattern_match = true; // false;
boolean pattern_match = !dflt_options; //true; // false;
boolean bounds_to_indices = true;
int temp_mode = 0;
......@@ -200,7 +202,7 @@ public class ComboMatch {
GenericJTabbedDialog gd = new GenericJTabbedDialog("Set image pair",1200,800);
// gd.addChoice ("Files list/data path (w/o extension):", FILES_LISTS_PATHS, FILES_LISTS_PATHS[default_list_choice]);
gd.addChoice ("Files list/data path (w/o extension):", FILES_LISTS_PATHS, omtch_img_set);
gd.addCheckbox ("Use saved maps collection", use_saved_collection, "If false - use files list.");
gd.addCheckbox ("Use saved maps collection ", use_saved_collection, " (if available). If false - use files list.");
gd.addCheckbox ("Save maps collection", save_collection, "Save maps collection to be able to restore.");
gd.addCheckbox ("Process correlations", process_correlation, "false to skip to just regenerate new save file.");
// int num_tries_fit = 10;
......@@ -318,23 +320,32 @@ public class ComboMatch {
log_append = gd.getNextBoolean();
log_path = gd.getNextString();
OrthoMapsCollection maps_collection=null;
boolean use_files_list = false;
if (use_saved_collection) {
try {
maps_collection = OrthoMapsCollection.readOrthoMapsCollection (orthoMapsCollection_path);
} catch (ClassNotFoundException | IOException e) {
use_files_list = true;
System.out.println("Saved data not found: "+orthoMapsCollection_path+", building from a list "+files_list_path);
// TODO Auto-generated catch block
e.printStackTrace();
// e.printStackTrace();
}
//files_list_path
if (update_kernel_patterns) {
maps_collection.updateKernels(files_list_path);
maps_collection.updatePatterns(files_list_path);
if (!use_files_list) {
if (update_kernel_patterns) {
maps_collection.updateKernels(files_list_path);
maps_collection.updatePatterns(files_list_path);
}
}
} else {
use_files_list = true;
}
if (use_files_list) { // using files list
maps_collection = new OrthoMapsCollection(files_list_path); // should have ".list" extension
maps_collection.updateNumberScenes();
maps_collection.updateSfmGain();
}
if (update_bl_bc) {
boolean OK = updateBlBcFileNames(
suffixes_bl_bc[suffix_bc_bl_indx], // String suffix,
......@@ -857,22 +868,96 @@ public class ComboMatch {
available_pairs[i][0] = pairs_list.get(i).x;
available_pairs[i][1] = pairs_list.get(i).y;
}
boolean flt_list = clt_parameters.imp.flt_list; // true;
boolean flt_undef_only = clt_parameters.imp.flt_undef_only; // false;
double flt_min_overlap = clt_parameters.imp.flt_min_overlap; // 0.0;
double flt_max_overlap = clt_parameters.imp.flt_max_overlap; // 1.0;
double flt_min_rms = clt_parameters.imp.flt_min_rms; // 0.0;
double flt_max_rms = clt_parameters.imp.flt_max_rms; // 2.0;
boolean flt_nan_rms = clt_parameters.imp.flt_nan_rms; // false;
boolean flt_show_names = clt_parameters.imp.flt_show_names; // true;
boolean flt_show_overlaps = clt_parameters.imp.flt_show_overlaps; // true;
boolean flt_show_rms = clt_parameters.imp.flt_show_rms; // true;
boolean flt_update_config = false;
String flt_extra_line = "--- select a single image ---";
GenericJTabbedDialog gdf = new GenericJTabbedDialog("Select pairs filter/display",800,500);
gdf.addCheckbox ("Filter pairs", flt_list, "Filter available pairs.");
gdf.addCheckbox ("Keep undefined pairs only", flt_undef_only, "Keep only undefined pairs (affines== null).");
gdf.addNumericField("Minimal scene overlap (0..1)",flt_min_overlap, 3,7,"", "Minimal overlap of the scenes to keep (0-no overlap, 1.0 - smaller scene is inside the parger one.");
gdf.addNumericField("Maximal scene overlap (0..1)",flt_max_overlap, 3,7,"", "Maximal overlap of the scenes to keep (0-no overlap, 1.0 - smaller scene is inside the parger one.");
gdf.addNumericField("Minimal RMSE", flt_min_rms, 3,7,"", "Minimal LMA RMSE of the scene pair.");
gdf.addNumericField("Maximal RMSE", flt_max_rms, 3,7,"", "Maximal LMA RMSE of the scene pair.");
gdf.addCheckbox ("NaN RMS (failed match)", flt_nan_rms, "Keep only failed matches with RMSE=NaN.");
gdf.addCheckbox ("Show scene names", flt_show_names, "Show scene full names (timestamps) in selection drop-down list.");
gdf.addCheckbox ("Show scene overlaps", flt_show_overlaps, "Show scene overlaps (in percents) in selection drop-down list.");
gdf.addCheckbox ("Show pairs RMSE", flt_show_rms, "Show scene match RMSE in selection drop-down list.");
gdf.addCheckbox ("Update configuration", flt_update_config, "Update matching configuration parameters to be saved as defaults.");
gdf.showDialog();
if (gdf.wasCanceled()) return false;
flt_list = gdf.getNextBoolean();
flt_undef_only = gdf.getNextBoolean();
flt_min_overlap = gdf.getNextNumber();
flt_max_overlap = gdf.getNextNumber();
flt_min_rms = gdf.getNextNumber();
flt_max_rms = gdf.getNextNumber();
flt_nan_rms = gdf.getNextBoolean();
flt_show_names = gdf.getNextBoolean();
flt_show_overlaps = gdf.getNextBoolean();
flt_show_rms = gdf.getNextBoolean();
flt_update_config = gdf.getNextBoolean();
if (flt_update_config) {
clt_parameters.imp.flt_list = flt_list;
clt_parameters.imp.flt_undef_only = flt_undef_only;
clt_parameters.imp.flt_min_overlap = flt_min_overlap;
clt_parameters.imp.flt_max_overlap = flt_max_overlap;
clt_parameters.imp.flt_min_rms = flt_min_rms;
clt_parameters.imp.flt_max_rms = flt_max_rms;
clt_parameters.imp.flt_nan_rms = flt_nan_rms;
clt_parameters.imp.flt_show_names = flt_show_names;
clt_parameters.imp.flt_show_overlaps = flt_show_overlaps;
clt_parameters.imp.flt_show_rms = flt_show_rms;
}
if (flt_list) {
available_pairs = maps_collection.filterPairs(
available_pairs, // int [][] plist_in,
flt_undef_only, // boolean undef_only,
flt_min_overlap, // double min_overlap,
flt_max_overlap, // double max_overlap,
flt_min_rms, // double min_rms,
flt_max_rms, // double max_rms,
flt_nan_rms); // boolean nan_rms)
}
String [] choices_all = maps_collection.textPairs (
available_pairs, // int [][] plist,
flt_show_names, // boolean show_names,
flt_show_overlaps, // boolean show_overlap,
flt_show_rms, // boolean show_rms,
flt_extra_line); // String extra_line)
/*
String [] choices = getPairChoices(
available_pairs, // int [][] pairs,
names); // String [] names)
String [] choices_all = new String[choices.length+1];
System.arraycopy(choices, 0, choices_all, 0, choices.length);
choices_all[choices_all.length-1] = "--- select a single image ---";
*/
GenericJTabbedDialog gdc = new GenericJTabbedDialog("Select image pair",1200,100);
int num_choice_lines = 50;
gdc.addChoice("Image pair:",
choices_all,
choices_all[choices.length], // -1],
choices_all[choices_all.length - 1], // -1],
"Select processed image pair or request a single image selection", num_choice_lines);
gdc.showDialog();
if (gdc.wasCanceled()) return false;
int pair= gdc.getNextChoiceIndex();
if (pair >= choices.length) {
if (pair >= (choices_all.length -1)) {
int default_choice = 0;
int num_scene_lines = 50;
if (process_correlation || render_match) { // select a second image to match
......@@ -932,7 +1017,7 @@ public class ComboMatch {
// imp_pat_match.show();
}
} else {
} else { // gpu_spair.length >= 2
if (test_multi_lma) {
OrthoMultiLMA.testMultiLMA(
clt_parameters, // CLTParameters clt_parameters,
......@@ -956,11 +1041,31 @@ public class ComboMatch {
pairwiseOrthoMatch = maps_collection.ortho_maps[gpu_pair[0]].getMatch(
maps_collection.ortho_maps[gpu_pair[1]].getName());
}
if (pairwiseOrthoMatch == null) { // try undefined
pairwiseOrthoMatch = maps_collection.ortho_maps[gpu_pair[0]].getMatch(
maps_collection.ortho_maps[gpu_pair[1]].getName(), true);
if (pairwiseOrthoMatch != null) {
double [][] aff0 = maps_collection.ortho_maps[gpu_pair[0]].getAffine();
double [][] aff1 = maps_collection.ortho_maps[gpu_pair[1]].getAffine();
double [] enuOffset = maps_collection.ortho_maps[gpu_pair[1]].enuOffsetTo(maps_collection.ortho_maps[gpu_pair[0]]);
double [] rd = {enuOffset[0], -enuOffset[1]}; // {right,down} of the image
PairwiseOrthoMatch aff_match = new PairwiseOrthoMatch (
aff0, // double [][] affine0,
aff1, // double [][] affine1,
rd); // double [] rd);
double [][] daffine = aff_match.getAffine();
pairwiseOrthoMatch.setAffine(daffine);
}
}
if (pairwiseOrthoMatch == null) {
System.out.println("No correlation data is available for pairs "+gpu_spair[0]+
" - "+gpu_spair[1]+" need to implement/search reverse, a spiral search or restart command");
System.out.println("after loading a corresponding full map image and marking same feature on");
System.out.print("after loading a corresponding full map image and marking same feature on ");
System.out.println("each of the two selected slices, reference one first");
} else {
affine1 = pairwiseOrthoMatch.getAffine();
double [][][] affines = {affine0,affine1};
......
......@@ -236,7 +236,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
if (undefined_only) {
String [] matches = pairwise_matches.keySet().toArray(new String[0]);
for (String match:matches) {
if (!getMatch(match).isDefined()) {
PairwiseOrthoMatch pm = getMatch(match);
if ((pm == null) || !pm.isDefined()) {
unsetMatch(match);
}
}
......@@ -483,7 +484,14 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
// TODO Auto-generated catch block
e.printStackTrace();
}
lla = ElphelTiffReader.getLLA(imp_prop);
try {
lla = ElphelTiffReader.getLLA(imp_prop);
} catch (NullPointerException e) {
System.out.println("No GPS data in "+path);
// TODO Auto-generated catch block
e.printStackTrace();
}
dt = ElphelTiffReader.getLocalDateTime(imp_prop);
vert_meters = ElphelTiffReader.getXYOffsetMeters(imp_prop);
orig_pix_meters = ElphelTiffReader.getPixelSize(imp_prop)[0];
......
......@@ -42,6 +42,7 @@ import com.elphel.imagej.tileprocessor.OpticalFlow;
import com.elphel.imagej.tileprocessor.TDCorrTile;
import com.elphel.imagej.tileprocessor.TileNeibs;
import ij.IJ;
import ij.ImagePlus;
import ij.ImageStack;
import ij.Prefs;
......@@ -926,6 +927,7 @@ public class OrthoMapsCollection implements Serializable{
int [] wh,
int [] origin, // maps[0] as a reference
double [][] centers){
boolean updateStatus = true;
boolean use_alt = ground_planes != null;
final int dbg_x=707, dbg_y=-615;
int [][] bounds;
......@@ -958,6 +960,7 @@ public class OrthoMapsCollection implements Serializable{
final double [][] dpixels = new double [indices.length][width * height];
for (int indx = 0; indx < indices.length; indx++) { //:indices) { // = 0; nmap< ortho_maps.length; nmap++) {
if (updateStatus) IJ.showStatus("Preparing slice "+indx+" of "+indices.length);
final int findx= indx;
final int nmap = indices[indx]; // nmap;
final double [][] affine = (affines !=null) ? affines[indx]: ortho_maps[nmap].affine; // only here use provided
......@@ -1215,20 +1218,27 @@ public class OrthoMapsCollection implements Serializable{
}
if (pairwiseOrthoMatch.rms < good_rms) { // immediately OK
return pairwiseOrthoMatch; // pairwiseOrthoMatch.affine will have adjusted affine[1]
best_pom.ok = true;
if (debugLevel > -4) {
System.out.println("SpiralMatch(): best RMSE="+best_pom.rms+" < "+good_rms+
" for nx = "+best_nx+", ny="+best_ny+", using it.");
}
return best_pom; // pairwiseOrthoMatch; // pairwiseOrthoMatch.affine will have adjusted affine[1]
}
if ((best_pom != null) && (best_pom.rms <= max_rms)) {
if (debugLevel > -4) {
System.out.println("SpiralMatch(): best RMSE="+best_pom.rms+" < "+max_rms+
" for nx = "+best_nx+", ny="+best_ny+", using it.");
}
best_pom.ok = true;
return best_pom;
}
if (debugLevel > -4) {
// delegating too large rms to the caller (it will have best_pom.ok==false
if ((debugLevel > -4) && ((best_pom == null) || Double.isNaN(best_pom.rms))){
System.out.println("SpiralMatch(): Failed to find a good match candidate. Best RMSE="+
((best_pom != null)? best_pom.rms:"N/A")+", max_rms= "+max_rms+"");
}
return null; // pairwiseOrthoMatch.affine will have adjusted affine[1]
return best_pom; // null; // pairwiseOrthoMatch.affine will have adjusted affine[1]
}
......@@ -4959,22 +4969,45 @@ public class OrthoMapsCollection implements Serializable{
pull_tilt, // double pull_tilt, // > 0
pull_scale, // double pull_scale, // = 0
spiral_debug); // int debugLevel)
if ((pairwiseOrthoMatch == null) || Double.isNaN(pairwiseOrthoMatch.rms)) {
if (delete_failed) {
ortho_maps[ipair[0]].unsetMatch(ortho_maps[ipair[1]].getName());
}
String str_failed = delete_failed?"%4d\t%4d\t%s\t%s\t%6.4f\t%3d\tFAILED\tREMOVED\n":"%4d\t%4d\t%s\t%s\t%6.4f\t%3d\tFAILED\n";
// late failure
if ((pairwiseOrthoMatch != null) && !Double.isNaN(pairwiseOrthoMatch.rms) && !pairwiseOrthoMatch.ok) {
// String str_failed = delete_failed?
// "%4d\t%4d\t%s\t%s\t%6.4f\t%3d\tFAILED\tREMOVED\n":
// "%4d\t%4d\t%s\t%s\t%6.4f\t%3d\tFAILED\n";
String str_failed = delete_failed?
"%4d\t%4d\t%s\t%s\t%6.4f\t%3d\t%3d\t%3d\t%6.4f\tREMOVED\n":
"%4d\t%4d\t%s\t%s\t%6.4f\t%3d\t%3d\t%3d\t%6.4f\n";
if (log_append && (log_path != null)) { // assuming directory exists
StringBuffer sb = new StringBuffer();
sb.append(String.format(str_failed,
ipair[0], ipair[1], ortho_maps[ipair[0]].getName(), ortho_maps[ipair[1]].getName(),
overlaps[overlap_indx], initial_zoom));
overlaps[overlap_indx], initial_zoom,
pairwiseOrthoMatch.nxy[0],pairwiseOrthoMatch.nxy[1],pairwiseOrthoMatch.rms));
CalibrationFileManagement.saveStringToFile (
log_path, //String path,
sb.toString(), // data,
true); // boolean append)
}
}
if ((pairwiseOrthoMatch == null) || !pairwiseOrthoMatch.ok) {
if (delete_failed) {
ortho_maps[ipair[0]].unsetMatch(ortho_maps[ipair[1]].getName());
}
if ((pairwiseOrthoMatch != null) && Double.isNaN(pairwiseOrthoMatch.rms)) {
String str_failed = delete_failed?"%4d\t%4d\t%s\t%s\t%6.4f\t%3d\tFAILED\tREMOVED\n":"%4d\t%4d\t%s\t%s\t%6.4f\t%3d\tFAILED\n";
if (log_append && (log_path != null)) { // assuming directory exists
StringBuffer sb = new StringBuffer();
sb.append(String.format(str_failed,
ipair[0], ipair[1], ortho_maps[ipair[0]].getName(), ortho_maps[ipair[1]].getName(),
overlaps[overlap_indx], initial_zoom));
CalibrationFileManagement.saveStringToFile (
log_path, //String path,
sb.toString(), // data,
true); // boolean append)
}
}
failed_pairs.add(pair);
pairwiseOrthoMatch = null;
continue;
} else {
spiral_rms = pairwiseOrthoMatch.rms;
......@@ -5035,11 +5068,11 @@ public class OrthoMapsCollection implements Serializable{
failed_pairs.add(pair);
sb.append(String.format(str_failed));
if (debugLevel > -4) System.out.print("Final adjustment"+str_failed);
if (debugLevel > -4) System.out.print("Final adjustment (1)"+str_failed);
} else {
pairwiseOrthoMatch.overlap = overlaps[overlap_indx]; // needed here if refining old/manual w/o overlap
sb.append(String.format("\t%6.4f\t%3d\n",pairwiseOrthoMatch.rms,pairwiseOrthoMatch.zoom_lev));
if (debugLevel > -4) System.out.println("Final adjustment RMSE="+pairwiseOrthoMatch.rms+
if (debugLevel > -4) System.out.println("Final adjustment (2) RMSE="+pairwiseOrthoMatch.rms+
", overlap = "+pairwiseOrthoMatch.overlap);
ortho_maps[ipair[0]].setMatch(ortho_maps[ipair[1]].getName(),pairwiseOrthoMatch);
if (save_each && (orthoMapsCollection_path != null)) {
......@@ -5531,24 +5564,40 @@ public class OrthoMapsCollection implements Serializable{
pull_tilt, // double pull_tilt, // > 0
pull_scale, // double pull_scale, // = 0
spiral_debug); // int debugLevel)
Point pair = new Point(next_pair[0],next_pair[1]);
boolean success = (pairwiseOrthoMatch != null) && !Double.isNaN(pairwiseOrthoMatch.rms);
if (!success) { // not yet add to pairsGraph until verified with high-res
String str_failed = "%4d\t%4d\t%s\t%s\t%6.4f\t%3d\tFAILED\n";
// late failure
if ((pairwiseOrthoMatch != null) && !Double.isNaN(pairwiseOrthoMatch.rms) && !pairwiseOrthoMatch.ok) {
String str_failed = "%4d\t%4d\t%s\t%s\t%6.4f\t%3d\t%3d\t%3d\t%6.4f\tFAILED\n";
if (log_append && (log_path != null)) { // assuming directory exists
StringBuffer sb = new StringBuffer();
sb.append(String.format(str_failed,
ipair[0], ipair[1], ortho_maps[ipair[0]].getName(), ortho_maps[ipair[1]].getName(),
overlap_frac,
initial_zoom));
overlap_frac, initial_zoom,
pairwiseOrthoMatch.nxy[0],pairwiseOrthoMatch.nxy[1],pairwiseOrthoMatch.rms));
CalibrationFileManagement.saveStringToFile (
log_path, //String path,
sb.toString(), // data,
true); // boolean append)
}
}
Point pair = new Point(next_pair[0],next_pair[1]);
boolean success = (pairwiseOrthoMatch != null) && pairwiseOrthoMatch.ok; // && !Double.isNaN(pairwiseOrthoMatch.rms)
if (!success) { // not yet add to pairsGraph until verified with high-res
if ((pairwiseOrthoMatch == null) || Double.isNaN(pairwiseOrthoMatch.rms)) { // too high RMS already reported
String str_failed = "%4d\t%4d\t%s\t%s\t%6.4f\t%3d\tFAILED\n";
if (log_append && (log_path != null)) { // assuming directory exists
StringBuffer sb = new StringBuffer();
sb.append(String.format(str_failed,
ipair[0], ipair[1], ortho_maps[ipair[0]].getName(), ortho_maps[ipair[1]].getName(),
overlap_frac,
initial_zoom));
CalibrationFileManagement.saveStringToFile (
log_path, //String path,
sb.toString(), // data,
true); // boolean append)
}
}
failed_pairs.add(pair);
// continue;
} else { // success!
spiral_rms = pairwiseOrthoMatch.rms;
// new_pairs.add(pair); // adjusted with spiral
......@@ -5598,11 +5647,11 @@ public class OrthoMapsCollection implements Serializable{
String str_failed = String.format("\t%6.4f\tFAILED\n",pairwiseOrthoMatch.rms);
failed_pairs.add(pair);
sb.append(String.format(str_failed));
if (debugLevel > -4) System.out.print("Final adjustment"+str_failed);
if (debugLevel > -4) System.out.print("Final adjustment (3)"+str_failed);
} else {
pairwiseOrthoMatch.overlap = overlap_frac; // needed here if refining old/manual w/o overlap
sb.append(String.format("\t%6.4f\t%3d\n",pairwiseOrthoMatch.rms,pairwiseOrthoMatch.zoom_lev));
if (debugLevel > -4) System.out.println("Final adjustment RMSE="+pairwiseOrthoMatch.rms+
if (debugLevel > -4) System.out.println("Final adjustment (4) RMSE="+pairwiseOrthoMatch.rms+
", overlap = "+pairwiseOrthoMatch.overlap);
ortho_maps[ipair[0]].setMatch(ortho_maps[ipair[1]].getName(),pairwiseOrthoMatch);
if (save_each && (orthoMapsCollection_path != null)) {
......@@ -6384,5 +6433,112 @@ public class OrthoMapsCollection implements Serializable{
}
return pairs;
}
/**
* Filter list of image pairs by overlap and RMSE
* @param list_in array of image pairs indices
* @param undef_only only keep undefined pairs (no affine transform), ignore RMSE parameters
* @param min_overlap minimal pair overlap
* @param max_overlap maximal pair overlap
* @param min_rms minimal RMSE
* @param max_rms maximal RMSE
* @param nan_rms use only NaN RMSE pairs
* @return filtered array of pair indices
*/
public int [][] filterPairs(
int [][] list_in,
boolean undef_only,
double min_overlap,
double max_overlap,
double min_rms,
double max_rms,
boolean nan_rms){
ArrayList<Point> plist = new ArrayList<Point>();
int num_all = 0;
int num_def = 0;
for (int [] ipair: list_in) {
Point pair = new Point(ipair[0],ipair[1]);
PairwiseOrthoMatch pairwiseOrthoMatch = ortho_maps[pair.x].getMatch(
ortho_maps[pair.y].getName(), undef_only || nan_rms);
if (pairwiseOrthoMatch != null) {
num_all++;
boolean defined = pairwiseOrthoMatch.isDefined();
if (defined) {
num_def++;
}
if (undef_only) {
if (!defined) {
plist.add(pair);
}
} else {
if ((pairwiseOrthoMatch.overlap >= min_overlap) && (pairwiseOrthoMatch.overlap <= max_overlap)) {
if (nan_rms) {
if (Double.isNaN(pairwiseOrthoMatch.rms)) {
plist.add(pair);
}
} else if ((pairwiseOrthoMatch.rms >= min_rms) && (pairwiseOrthoMatch.rms <= max_rms)) {
plist.add(pair);
}
}
}
} else {
// System.out.println("pair=["+pair.x+","+pair.y+"] "+
// ortho_maps[pair.x].getName()+"->"+ortho_maps[pair.y].getName());
}
}
System.out.println("num_all = "+num_all+", num_def="+num_def+", remained="+plist.size());
int [][] pairs = new int [plist.size()][2];
for (int i = 0; i < pairs.length; i++) {
pairs[i][0] = plist.get(i).x;
pairs[i][1] = plist.get(i).y;
}
return pairs;
}
/**
* Create text representation of the image pairs for drop-down selection lists
* @param plist ArrayList<Point> as pairs of scenes indices
* @param show_names show full scene names (timestamps)
* @param show_overlap show scene overlap in percents
* @param show_rms show pairs RMSE
* @param extra_line null or an extra string to be added as a last element
* @return Array of strings to be shown in a drop-down list
*/
public String [] textPairs (
int [][] plist,
boolean show_names,
boolean show_overlap,
boolean show_rms,
String extra_line) {
String [] text_pairs = new String [plist.length+((extra_line !=null)? 1 : 0)];
for (int i = 0; i < plist.length; i++) {
int [] pair = plist[i];
PairwiseOrthoMatch pairwiseOrthoMatch = ortho_maps[pair[0]].getMatch(
ortho_maps[pair[1]].getName(), true); // include undefined
if (pairwiseOrthoMatch== null) {
System.out.println("pair=["+pair[0]+","+pair[1]+"] "+
ortho_maps[pair[0]].getName()+"->"+ortho_maps[pair[1]].getName());
}
text_pairs[i] = String.format("%3d -> %3d", pair[0], pair[1]);
if (show_names) {
text_pairs[i] += String.format(" (%s -> %s)", ortho_maps[pair[0]].getName(),ortho_maps[pair[1]].getName());
}
if (pairwiseOrthoMatch != null) {
if (show_overlap) {
text_pairs[i] += String.format(" %5.1f%%", 100*pairwiseOrthoMatch.overlap);
}
if (show_rms) {
text_pairs[i] += String.format(" %5.3f", pairwiseOrthoMatch.rms);
}
}
}
if (extra_line !=null) {
text_pairs[plist.length] = extra_line;
}
return text_pairs;
}
}
......@@ -16,6 +16,7 @@ public class PairwiseOrthoMatch implements Serializable {
public transient int [] nxy = null; // not saved, just to communicate for logging
public transient double overlap = 0.0;
public transient double [] equalize1to0 = {1,0}; // value1 = equalize2to1[0]*value2+equalize2to1[1]
public transient boolean ok = false;
// public PairwiseOrthoMatch() {}
public double getOverlap() {
......@@ -75,6 +76,7 @@ public class PairwiseOrthoMatch implements Serializable {
pom.nxy = nxy.clone();
}
pom.equalize1to0 = this.equalize1to0.clone();
pom.ok = this.ok;
return pom;
}
/**
......
......@@ -88,6 +88,13 @@ public class IntersceneMatchParameters {
public boolean sfm_average_neibs = false; // Average neighbors disparity among them
public boolean sfm_fill_weak = false; // Fill too weak tiles from nearest neighbors
public boolean sfm_extrapolate = false; // Extrapolate tiles with no SfM data (near edges)
// Filter SfM reference disparity
public double sfm_max_dip = 0.1; // maximal dip relative to lowest neighbor (0 - any)
public double sfm_max_bump = 0.5; // maximal bump relative to highest neighbor (0 - any)
public boolean sfm_filter_nan = true; // replace NaN by defined neighbors average
public boolean sfm_only = false; // process only series with SfM (temporary feature)
// debug
public boolean sfm_save_seq = true; // Save SfM sequence image in model directory
public boolean sfm_show_seq = true; // Show SfM sequence
......@@ -181,10 +188,24 @@ public class IntersceneMatchParameters {
public int pequ_num_iter = 100; // 50;
public int pequ_debugLevel = 2;
// pairs selection/display parameters
public boolean flt_list = true;
public boolean flt_undef_only = false;
public double flt_min_overlap = 0.0;
public double flt_max_overlap = 1.0;
public double flt_min_rms = 0.0;
public double flt_max_rms = 2.0;
public boolean flt_nan_rms = false;
public boolean flt_show_names = true;
public boolean flt_show_overlaps = true;
public boolean flt_show_rms = true;
public String patt_save_top = "/media/elphel/NVME/lwir16-proc/ortho_videos/debug/sept12-13/pattern_match/";
public String patt_save_subdir = "combo_maps";
public double [] getImsMountATR() {
return new double [] {
ims_mount_atr[0] * Math.PI/180,
......@@ -778,6 +799,17 @@ min_str_neib_fpn 0.35
"Fill too weak tiles from nearest neighbors.");
gd.addCheckbox ("Extrapolate no SfM data", this.sfm_extrapolate,
"Extrapolate tiles with no SfM data (near edges).");
gd.addMessage ("SfM filter reference disparity");
gd.addNumericField("Maximal dip", this.sfm_max_dip, 5,8,"pix",
"Maximal dip relative to lowest neighbor (0 - any).");
gd.addNumericField("Maximal bump", this.sfm_max_bump, 5,8,"pix",
"Maximal bump relative to highest neighbor (0 - any).");
gd.addCheckbox ("Replace NaNds", this.sfm_filter_nan,
"Replace NaNs by defined neighbors average.");
gd.addCheckbox ("Process SfM only", this.sfm_only,
"Process only series with SfM (temporary feature to fix previously wrong SfM).");
gd.addMessage ("SfM debug images");
gd.addCheckbox ("Save SfM sequence image", this.sfm_save_seq,
"Save SfM sequence image in model directory.");
......@@ -893,7 +925,19 @@ min_str_neib_fpn 0.35
gd.addNumericField("LMA iterations", this.pequ_num_iter, 0,3,"",".Maximal number of the LMA iterations.");
gd.addNumericField("Debug level for equalization",this.pequ_debugLevel, 0,3,"","Debug level for global (LMA-based) intensity equalization.");
gd.addMessage ("Pattern match parameters");
gd.addMessage ("Pairs selection/display parameters");
gd.addCheckbox ("Filter pairs", this.flt_list, "Filter available pairs.");
gd.addCheckbox ("Keep undefined pairs only", this.flt_undef_only, "Keep only undefined pairs (affines== null).");
gd.addNumericField("Minimal scene overlap (0..1)",this.flt_min_overlap, 3,7,"", "Minimal overlap of the scenes to keep (0-no overlap, 1.0 - smaller scene is inside the parger one.");
gd.addNumericField("Minimal scene overlap (0..1)",this.flt_max_overlap, 3,7,"", "Maximal overlap of the scenes to keep (0-no overlap, 1.0 - smaller scene is inside the parger one.");
gd.addNumericField("Minimal RMSE", this.flt_min_rms, 3,7,"", "Minimal LMA RMSE of the scene pair.");
gd.addNumericField("Maximal RMSE", this.flt_max_rms, 3,7,"", "Maximal LMA RMSE of the scene pair.");
gd.addCheckbox ("NaN RMS (failed match)", this.flt_nan_rms, "Keep only failed matches with RMSE=NaN.");
gd.addCheckbox ("Show scene names", this.flt_show_names, "Show scene full names (timestamps) in selection drop-down list.");
gd.addCheckbox ("Show scene overlaps", this.flt_show_overlaps, "Show scene overlaps (in percents) in selection drop-down list.");
gd.addCheckbox ("Show pairs RMSE", this.flt_show_rms, "Show scene match RMSE in selection drop-down list.");
gd.addMessage ("Pattern match directories");
gd.addStringField ("Pattern match save directory",this.patt_save_top, 120, "Top directory to save combo maps");
gd.addStringField ("Save subdirectory", this.patt_save_subdir, 80, "Subdirectory for versions of the same scene/pair of scenes");