Commit c3505d27 authored by Andrey Filippov's avatar Andrey Filippov

Working snapshot,single-connected pairs

parent d8f3ec21
......@@ -1303,6 +1303,8 @@ public class ComboMatch {
System.out.println("This can happen if files have different resolution for new run.");
System.out.println("Verify path, then modify filenames[i], break at line above: 'maps_collection.ortho_maps[i].setFileName(filenames[i])'.");
System.out.println("Reduce i by 1 and continue");
} else {
maps_collection.ortho_maps[i] = new OrthoMap(path);
}
}
return true;
......
......@@ -913,6 +913,10 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
int swidth = getWidth();
int sheight = getHeight();
final float [] spix = orig_image.data;
if (swidth*sheight != spix.length) {
System.out.println ("downScaleForGPU(): swidth="+ swidth+", sheight="+sheight+", swidth*sheight="+(swidth*sheight)+", spix.length="+spix.length);
System.out.println ();
}
final int width = (swidth+frscale-1)/frscale;
final int height = (sheight+frscale-1)/frscale;
final int tiles = width * height;
......@@ -939,17 +943,28 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
for (int py = 0; py < tileH; py++) {
int ls = (tileY*frscale + py)*swidth;
for (int px = 0; px < tileW; px++) {
double d = spix[ls + tileX*frscale+px];
int indx = ls + tileX*frscale+px;
if ((indx >=0) && (indx < spix.length)) {
double d = spix[ls + tileX*frscale+px]; //java.lang.ArrayIndexOutOfBoundsException: Index 3892800 out of bounds for length 3892680
if (!Double.isNaN(d)) {
double w = wnd[py][px];
sw += w;
swd += w*d;
}
if (sw > 0) {
opix[tileY * width + tileX] = (float) (swd/sw);
} else {
System.out.println("downScaleForGPU(): indx = "+indx+" ("+spix.length+"), tileX= "+
tileX+", tileY="+tileY+", px="+px+", py="+py+", ls="+ls);
}
// if (sw > 0) {
// opix[tileY * width + tileX] = (float) (swd/sw);
// }
}
}
if (sw > 0) {
opix[tileY * width + tileX] = (float) (swd/sw);
}
}
}
};
......
......@@ -29,6 +29,8 @@ import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import com.elphel.imagej.cameras.CLTParameters;
......@@ -218,6 +220,7 @@ public class OrthoMultiLMA {
OrthoMapsCollection maps_collection,
String orthoMapsCollection_path
) {
boolean all_pairs = true;
boolean move_only = clt_parameters.imp.pmap_move_only; // false;
boolean ignore_affines = clt_parameters.imp.pmap_ignore_affines; // false;
boolean use_inv = clt_parameters.imp.pmap_use_inv; // false;
......@@ -232,22 +235,23 @@ public class OrthoMultiLMA {
int debugLevel = clt_parameters.imp.pmap_debugLevel; // 2;
GenericJTabbedDialog gd = new GenericJTabbedDialog("Pairwise Match Parameters",1200,400);
gd.addCheckbox ("Use all available pairs", all_pairs, "Use all available pairs.");
gd.addCheckbox ("Moves only", move_only, "Moves only, no affine transform.");
gd.addCheckbox ("Ignore existing affines", ignore_affines, "Start from unity matrices, ignore saved affines.");
gd.addCheckbox ("Use reversed pairs", use_inv, "Use reversed (late-early timestamps) pairs.");
gd.addNumericField("Skew pull", skew_pull, 7,10,"", "Intention to have axes perpendicular.");
gd.addNumericField("Tilt pull", tilt_pull, 7,10,"", "Intention to have axes same length.");
gd.addNumericField("Scale pull", scale_pull, 7,10,"", "Intention to have average scale of images = 1.0.");
gd.addNumericField("Position pull", position_pull,7,10,"", "Intension to match IMS (GNSS) coordinates.");
gd.addNumericField("Skew pull", skew_pull, 7,11,"", "Intention to have axes perpendicular.");
gd.addNumericField("Tilt pull", tilt_pull, 7,11,"", "Intention to have axes same length.");
gd.addNumericField("Scale pull", scale_pull, 7,11,"", "Intention to have average scale of images = 1.0.");
gd.addNumericField("Position pull", position_pull,7,11,"", "Intension to match IMS (GNSS) coordinates.");
gd.addNumericField("Overlap inportance", overlap_pow, 3,7,"", "Raise overlap fraction (of the smaller image) to this power before using as weight.");
gd.addNumericField("RMSE relative improvement",rms_diff, 8,10,"", "Relative RMSE improvement to exit LMA.");
gd.addNumericField("RMSE relative improvement",rms_diff, 8,11,"", "Relative RMSE improvement to exit LMA.");
gd.addNumericField("LMA iterations", num_iter, 0,3,"",".Maximal number of the LMA iterations.");
gd.addCheckbox ("Show result image", show_result, ".");
gd.addNumericField("Debug level for maps", debugLevel, 0,3,"","Debug building for LMA building maps.");
gd.showDialog();
if (gd.wasCanceled()) return -1;
all_pairs = gd.getNextBoolean();
move_only = gd.getNextBoolean();
ignore_affines = gd.getNextBoolean();
use_inv = gd.getNextBoolean();
......@@ -265,6 +269,7 @@ public class OrthoMultiLMA {
clt_parameters, // CLTParameters clt_parameters,
maps_collection, // OrthoMapsCollection maps_collection,
orthoMapsCollection_path, // String orthoMapsCollection_path,
all_pairs, // boolean all_pairs,
move_only, // boolean move_only,
ignore_affines, // boolean ignore_affines,
use_inv, // boolean use_inv,
......@@ -282,6 +287,7 @@ public class OrthoMultiLMA {
CLTParameters clt_parameters,
OrthoMapsCollection maps_collection,
String orthoMapsCollection_path,
boolean all_pairs,
boolean move_only,
boolean ignore_affines,
boolean use_inv,
......@@ -296,9 +302,37 @@ public class OrthoMultiLMA {
int debugLevel) {
double [] val_coord = null; // 1 - valid, 0 - invalid, minimize coordinates errors
boolean corr_avg= (skew_pull > 0) || (tilt_pull > 0) || (scale_pull > 0);
int [] indices = maps_collection.getScenesSelection(
int [] indices = null;
if (all_pairs) {
boolean [] used_scenes = new boolean [maps_collection.ortho_maps.length];
for (int scene0 = 0; scene0 < (used_scenes.length-1); scene0++) {
Set<String> match_names = maps_collection.ortho_maps[scene0].pairwise_matches.keySet();
for (String scene1_name:match_names) {
PairwiseOrthoMatch match = maps_collection.ortho_maps[scene0].getMatch(scene1_name); // defined only
if (match != null) {
int scene1 = maps_collection.getIndex(scene1_name);
used_scenes[scene0] = true;
used_scenes[scene1] = true;
}
}
}
int num_scenes = 0;
for (int i = 0; i < used_scenes.length; i++) if (used_scenes[i]){
num_scenes++;
}
indices = new int [num_scenes];
int indx = 0;
for (int i = 0; i < used_scenes.length; i++) if (used_scenes[i]){
indices[indx++] = i;
}
if (debugLevel > -1) {
System.out.println("buildOrthoMap(): got "+indices.length+" scenes with pairs");
}
} else {
indices = maps_collection.getScenesSelection(
null, // boolean select_all,
" to build a map"); // String purpose)
" to build a map with LMA from pair-wise matches"); // String purpose)
}
OrthoMultiLMA oml = new OrthoMultiLMA(
corr_avg,
move_only);
......
......@@ -57,6 +57,8 @@ public class PairsGraph {
public PairsGraph (
OrthoMapsCollection orthoMapsCollection,
int [] indices,
double min_overlap_frac,
double max_rmse_reuse,
boolean multi,
int debugLevel) {
this.orthoMapsCollection = orthoMapsCollection;
......@@ -75,19 +77,30 @@ public class PairsGraph {
}
int num_defined = 0;
int num_undefined = 0;
int num_bad = 0;
int num_low_overlap = 0;
for (int i = 0; i < indices.length-1; i++) {
for (int j = i+1; j < indices.length; j++){
String name2 = ortho_maps[indices[j]].getName();
PairwiseOrthoMatch match = ortho_maps[indices[i]].getMatch(name2,true);
if (match != null) {
if (match.getOverlap() < min_overlap_frac){
num_low_overlap++;
} else {
if (match.isDefined()) {
if ((match.getOverlap() < min_overlap_frac) || ((max_rmse_reuse > 0) && !(match.getRMS() <= max_rmse_reuse))) {
pair_state[i][j] = PAIR_UNDEFINED;
num_undefined++;
num_bad++;
} else {
pair_state[i][j] = PAIR_DEFINED;
num_defined++;
recordPair(
new int [] {i,j}, // int [] pair,
true, // boolean success,
multi);
}
} else {
pair_state[i][j] = PAIR_UNDEFINED;
num_undefined++;
......@@ -96,19 +109,38 @@ public class PairsGraph {
}
}
}
HashSet<Integer> hs = new HashSet<Integer>();
for (int i:groups) {
hs.add(i);
}
pairs = multi? getPairsIndicesMulti():getPairsIndicesSingle();
if (debugLevel > 0) {
if (debugLevel > -1) {
System.out.println("Number of scenes - "+indices.length);
System.out.println("Number of defined pairs - "+num_defined);
System.out.println("Number of undefined pairs - "+num_undefined);
System.out.println("Number of disconnected groups - "+hs.size());
System.out.println("Number of low overlap pairs ("+min_overlap_frac+") - "+num_low_overlap);
System.out.println("Number of bad rms pairs ("+max_rmse_reuse+") - "+num_bad);
System.out.println("Number of disconnected groups - "+getNumberOfGroups());
}
}
public int getNumberOfGroups() {
HashSet<Integer> hs = new HashSet<Integer>();
for (int i:groups) {
hs.add(i);
}
return hs.size();
}
public int [] getIndices() {
return indices;
}
public boolean useMultiThreaded() {
return multi;
}
public double getOverlap(
int [] pair) {
return overlaps[Math.min(pair[0],pair[1])][Math.max(pair[0],pair[1])];
}
public boolean dryRun(
int heur,
int debugLevel) {
......
......@@ -37,6 +37,9 @@ public class PairwiseOrthoMatch implements Serializable {
this.rms = rms;
this.overlap = overlap;
}
public double getRMS() {
return this.rms;
}
public boolean isDefined() {
return affine != null;
......
......@@ -143,6 +143,7 @@ public class IntersceneMatchParameters {
// pairwise match parameters
public int pwise_zoom = -5;
public double pwise_overlap = 0.25;
public double pwise_max_rms = 0.6; // maximal acceptable LMA RMS - best during refine
public boolean pwise_skip_exist = true;
public boolean pwise_refine_exist = true; // if false, start from scratch, true - start from previous
public boolean pwise_delete_fail = true; // delete existing match if now failed
......@@ -795,7 +796,7 @@ public class IntersceneMatchParameters {
gd.addNumericField("Spiral search radius", this.ospir_range, 3,7,"scaled pix", "Maximal radius of the spiral search, in scaled pixels.");
gd.addNumericField("Mitigate small overlap", this.ospir_double, 3,7,"","For small overlaps increase zoom by 1 and range - twice.");
gd.addNumericField("RMSE to end search", this.ospir_good_rms, 3,7,"scaled pix", "Maximal RMSE to consider match, in scaled pixels.");
gd.addNumericField("Satisfactory RMSE", this.ospir_max_rms, 3,7,"scaled pix", "Maximal RMSE to consider match, in scaled pixels.");
gd.addNumericField("Satisfactory RMSE, spiral", this.ospir_max_rms, 3,7,"scaled pix", "Maximal RMSE to consider match, in scaled pixels, during spiral.");
gd.addNumericField("Minimal overlap", this.ospir_overlap, 0,4,"scaled pix ^ 2","Minimal overlap area in square scaled pixels.");
gd.addNumericField("LMA iterations", this.ospir_num_iter, 0,2,"", "Number of LMA iterations during spiral search.");
gd.addNumericField("RMSE at first iteration", this.ospir_rms_iter[0], 3,7,"scaled pix","Maximal RMSE at first iteration.");
......@@ -806,6 +807,7 @@ public class IntersceneMatchParameters {
gd.addMessage ("Pairwise image matching");
gd.addNumericField("Zoom level", this.pwise_zoom, 0,3,"","Low-res images to determine overlaps.");
gd.addNumericField("Minimal overlap fraction", this.pwise_overlap, 3,7,"", "Minimal overlap area as a fraction of the smaller of the two images.");
gd.addNumericField("Satisfactory RMSE, refine", this.pwise_max_rms, 3,7,"scaled pix", "Maximal RMSE to consider match, in scaled pixels, during refine (high res).");
gd.addCheckbox ("Skip existing", this.pwise_skip_exist, "Do not regenerate if match with same or higher resolution exists.");
gd.addCheckbox ("Refine existing", this.pwise_refine_exist, "Refine existing matches (false - start from scratch with spiral search).");
gd.addCheckbox ("Delete failed", this.pwise_delete_fail, "Delete previous matches if it failed now.");
......@@ -819,12 +821,12 @@ public class IntersceneMatchParameters {
gd.addCheckbox ("Moves only", this.pmap_move_only, "Moves only, no affine transform.");
gd.addCheckbox ("Ignore existing affines", this.pmap_ignore_affines, "Start from unity matrices, ignore saved affines.");
gd.addCheckbox ("Use reversed pairs", this.pmap_use_inv, "Use reversed (late-early timestamps) pairs.");
gd.addNumericField("Skew pull", this.pmap_skew_pull, 3,7,"", "Intention to have axes perpendicular.");
gd.addNumericField("Tilt pull", this.pmap_tilt_pull, 3,7,"", "Intention to have axes same length.");
gd.addNumericField("Scale pull", this.pmap_scale_pull, 3,7,"", "Intention to have average scale of images = 1.0.");
gd.addNumericField("Position pull", this.pmap_position_pull, 3,7,"", "Intension to match IMS (GNSS) coordinates.");
gd.addNumericField("Skew pull", this.pmap_skew_pull, 7,11,"", "Intention to have axes perpendicular.");
gd.addNumericField("Tilt pull", this.pmap_tilt_pull, 7,11,"", "Intention to have axes same length.");
gd.addNumericField("Scale pull", this.pmap_scale_pull, 7,11,"", "Intention to have average scale of images = 1.0.");
gd.addNumericField("Position pull", this.pmap_position_pull,7,11,"", "Intension to match IMS (GNSS) coordinates.");
gd.addNumericField("Overlap inportance", this.pmap_overlap_pow, 3,7,"", "Raise overlap fraction (of the smaller image) to this power before using as weight.");
gd.addNumericField("RMSE relative improvement", this.pmap_rms_diff, 3,7,"", "Relative RMSE improvement to exit LMA.");
gd.addNumericField("RMSE relative improvement", this.pmap_rms_diff, 8,11,"", "Relative RMSE improvement to exit LMA.");
gd.addNumericField("LMA iterations", this.pmap_num_iter, 0,3,"",".Maximal number of the LMA iterations.");
gd.addCheckbox ("Show result image", this.pmap_show_result, ".");
gd.addNumericField("Debug level for maps", this.pmap_debugLevel, 0,3,"","Debug building for LMA building maps.");
......@@ -1721,6 +1723,7 @@ public class IntersceneMatchParameters {
this.pwise_zoom = (int) gd.getNextNumber();
this.pwise_overlap = gd.getNextNumber();
this.pwise_max_rms = gd.getNextNumber();
this.pwise_skip_exist = gd.getNextBoolean();
this.pwise_refine_exist = gd.getNextBoolean();
this.pwise_delete_fail = gd.getNextBoolean();
......@@ -2249,6 +2252,8 @@ public class IntersceneMatchParameters {
properties.setProperty(prefix+"pwise_zoom", this.pwise_zoom + ""); // int
properties.setProperty(prefix+"pwise_overlap", this.pwise_overlap + ""); // double
properties.setProperty(prefix+"pwise_max_rms", this.pwise_max_rms + ""); // double
properties.setProperty(prefix+"pwise_skip_exist", this.pwise_skip_exist + ""); // boolean
properties.setProperty(prefix+"pwise_refine_exist", this.pwise_refine_exist + ""); // boolean
properties.setProperty(prefix+"pwise_delete_fail", this.pwise_delete_fail + ""); // boolean
......@@ -2740,6 +2745,8 @@ public class IntersceneMatchParameters {
if (properties.getProperty(prefix+"pwise_zoom")!=null) this.pwise_zoom=Integer.parseInt(properties.getProperty(prefix+ "pwise_zoom"));
if (properties.getProperty(prefix+"pwise_overlap")!=null) this.pwise_overlap=Double.parseDouble(properties.getProperty(prefix+ "pwise_overlap"));
if (properties.getProperty(prefix+"pwise_max_rms")!=null) this.pwise_max_rms=Double.parseDouble(properties.getProperty(prefix+ "pwise_max_rms"));
if (properties.getProperty(prefix+"pwise_skip_exist")!=null) this.pwise_skip_exist=Boolean.parseBoolean(properties.getProperty(prefix+ "pwise_skip_exist"));
if (properties.getProperty(prefix+"pwise_refine_exist")!=null) this.pwise_refine_exist=Boolean.parseBoolean(properties.getProperty(prefix+"pwise_refine_exist"));
if (properties.getProperty(prefix+"pwise_delete_fail")!=null) this.pwise_delete_fail=Boolean.parseBoolean(properties.getProperty(prefix+ "pwise_delete_fail"));
......@@ -3257,6 +3264,7 @@ public class IntersceneMatchParameters {
imp.pwise_zoom = this.pwise_zoom;
imp.pwise_overlap = this.pwise_overlap;
imp.pwise_max_rms = this.pwise_max_rms;
imp.pwise_skip_exist = this.pwise_skip_exist;
imp.pwise_refine_exist = this.pwise_refine_exist;
imp.pwise_delete_fail = this.pwise_delete_fail;
......
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