Commit 6f3b31c5 authored by Andrey Filippov's avatar Andrey Filippov

matching tilts with affines

parent 83ce74fe
......@@ -54,10 +54,13 @@ public class ERSTiltLMA {
private double [] last_ymfx = null;
private double [][] last_jt = null;
public double [][][] aff_pairs_nosr = null;
public double [][][] aff_pairs_inosr = null; // inverted pairs affines w/o scale and rotation
public double [][][][] aff_tilts = null;
public boolean invert_q2a = false;
// debug
public double [][][] aff_pairs = null; // pairwise image-based affines
public double [][] diff_tilts = null; // pairwise differential tilts
public boolean last3only = false; // true; // debug feature
public double scale_pairs = 1e3; // 1e4; // increase fX and derivatives for pairs
public double delta= 1e-7;
......@@ -99,7 +102,16 @@ public class ERSTiltLMA {
return svd;
}
public void printResults(boolean degrees) {
/**
* Get differential tilts between the second and the first scenes in each pair
* @return [pair]{tiltX,tiltY}
*/
public double [][] getDiffTilts(){
return diff_tilts;
}
public void printSceneResults(boolean degrees, boolean percents) {
double [][] pseudo_xy = getPseudoXY();
double [][][] ers_affines = getERSAffines();
SingularValueDecomposition [] svd = getSVD();
......@@ -116,8 +128,59 @@ public class ERSTiltLMA {
}
return;
}
public void printPairsResults(boolean degrees, boolean percents) {
double sd = degrees? 180/Math.PI : 1.0;
double sp = percents? 100 : 1;
String svd_title = SingularValueDecomposition.titleString(degrees);
double [] fx = getFxDerivs(
parameters_vector, // double [] vector,
null, // final double [][] jt, // should be null or initialized with [vector.length][]
0); // final int debug_level)
String tab_title_rad = String.format(
"%4s\t%4s\t%4s\t%11s\t%11s\t%11s\t%11s\t%11s\t%11s\t%11s\t%s",
"#","scn0","scn1","tiltX","tiltY","tilt","tilt-dir","elevation","pair_\u0394w","residual",svd_title);
String tab_title_deg = String.format(
"%4s\t%4s\t%4s\t%11s\t%11s\t%11s\t%11s\t%11s\t%11s\t%11s\t%s",
"#","scn0","scn1","tiltX","tiltY","tilt","tilt-dir\u00B0","elevation\u00B0","pair_\u0394w","residual",svd_title);
String tab_title_rad_perc = String.format(
"%4s\t%4s\t%4s\t%11s\t%11s\t%11s\t%11s\t%11s\t%11s\t%11s\t%s",
"#","scn0","scn1","tiltX%","tiltY%","tilt%","tilt-dir","elevation","pair_\u0394w%","residual%",svd_title);
String tab_title_deg_perc = String.format(
"%4s\t%4s\t%4s\t%11s\t%11s\t%11s\t%11s\t%11s\t%11s\t%11s\t%s",
"#","scn0","scn1","tiltX%","tiltY%","tilt%","tilt-dir\u00B0","elevation\u00B0","pair_\u0394w%","residual%",svd_title);
String title =degrees ? (percents?tab_title_deg_perc:tab_title_deg) : (percents?tab_title_rad_perc:tab_title_rad);
String fmt_rad= "%4d\t%4d\t%4d\t%11.8f\t%11.8f\t%11.8f\t%11.8f\t%11.8f\t%11.8f\t%11.8f\t%s";
String fmt_deg= "%4d\t%4d\t%4d\t%11.8f\t%11.8f\t%11.8f\t%11.6f\t%11.6f\t%11.8f\t%11.8f\t%s";
String fmt_rad_perc="%4d\t%4d\t%4d\t%11.6f%%\t%11.6f%%\t%11.6f%%\t%11.8f\t%11.8f\t%11.6f%%\t%11.6f%%\t%s";
String fmt_deg_perc="%4d\t%4d\t%4d\t%11.6f%%\t%11.6f%%\t%11.6f%%\t%11.6f\t%11.6f\t%11.6f%%\t%11.6f%%\t%s";
String fmt =degrees ? (percents?fmt_deg_perc:fmt_deg) : (percents?fmt_rad_perc:fmt_rad);
System.out.println(title);
double [] fit_err = new double [num_pairs];
for (int npair=0; npair < num_pairs; npair++) {
int [] pscenes = {indices[cpairs[npair][0]], indices[cpairs[npair][1]]};
double [] dtilt_xy = diff_tilts[npair];
double dtilt = Math.sqrt(dtilt_xy[0]*dtilt_xy[0]+dtilt_xy[1]*dtilt_xy[1]);
double tilt_dir = Math.atan2(dtilt_xy[1],dtilt_xy[0]);
double tilt_ang = Math.atan(dtilt);
double [][] aff_pair = aff_pairs[npair]; // image-based affine for a pair
SingularValueDecomposition svd_aff_pair = SingularValueDecomposition.singularValueDecompose(aff_pair);
// just to see - which is zeroed - beta or gamma? gamma changes, beta stays
String ssvd = svd_aff_pair.toString(degrees, 1);
double pair_dw = svd_aff_pair.getDW();
fit_err[npair] = fx[npair] / scale_pairs; // dW -> %
System.out.println(String.format(fmt,
npair, pscenes[0], pscenes[1], sp*dtilt_xy[0], sp*dtilt_xy[1], sp*dtilt, sd*tilt_dir, sd*tilt_ang,
sp*pair_dw, sp*fit_err[npair], ssvd));
}
return;
}
/*
* Starting with tilts0 and tilt1 = tilt0+tilt_diff (differential
......@@ -155,9 +218,13 @@ public class ERSTiltLMA {
this.cpairs = cpairs;
num_scenes = indices.length;
num_pairs = cpairs.length;
aff_pairs_nosr = new double [num_pairs][][];
aff_pairs = new double [num_pairs][][]; // preserving for stats, not used in processing
diff_tilts= new double [num_pairs][];
aff_pairs_inosr = new double [num_pairs][][];
aff_tilts = new double [num_pairs][2][][];
for (int npair = 0; npair < num_pairs; npair++) {
aff_pairs[npair] = affine_pairs[npair]; // preserving for stats
diff_tilts[npair] = new double [] {tilts[npair][1][0]-tilts[npair][0][0],tilts[npair][1][1]-tilts[npair][0][1]};
double [][] affine_pair_nors = SingularValueDecomposition.removeTiltRotScale(
affine_pairs[npair], // double [][] A,
false, // boolean removeTilt,
......@@ -165,7 +232,7 @@ public class ERSTiltLMA {
true, // boolean removeScale,
false, // boolean removeOffset,
false); // boolean max_is_scale);
aff_pairs_nosr[npair] = QuatUtils.matInverse2x2(affine_pair_nors); // maybe reverse order and do not use inversion?
aff_pairs_inosr[npair] = QuatUtils.matInverse2x2(affine_pair_nors); // maybe reverse order and do not use inversion?
for (int i = 0; i < 2; i++) {
aff_tilts[npair][i] = QuatUtils.tiltToAffine( // convert tilts to affines as they will not be modified later
tilts[npair][i]); // double [] tilt,
......@@ -223,7 +290,7 @@ public class ERSTiltLMA {
double [][][] aff_err = QuatUtils.pseudoAffineDiffAndDerivatives( //affineDiffAndDerivatives(
pseudo_xy, // double [][] txy, // [scene][direction]
aff_tilts[npair], // double [][][] a_tilts,
aff_pairs_nosr[npair], // double [][] iaff_pair, // affine pair inversed
aff_pairs_inosr[npair], // double [][] iaff_pair, // affine pair inversed
invert_q2a); // boolean invert_q2a) // invert result affines (to match "usual")
if (jt == null) {
aff_err = new double [][][] {aff_err[0]}; //
......@@ -248,7 +315,7 @@ public class ERSTiltLMA {
for (int ithread = 0; ithread < threads.length; ithread++) {
threads[ithread] = new Thread() {
public void run() {
for (int nscene = ai.getAndIncrement(); nscene < num_pairs; nscene = ai.getAndIncrement()) {
for (int nscene = ai.getAndIncrement(); nscene < num_scenes; nscene = ai.getAndIncrement()) {
int pindx = num_pairs + 2*nscene;
for (int j = 0; j < 2; j++) {
fX[pindx+j] = vector[2*nscene + j];
......
......@@ -61,6 +61,8 @@ public class OrthoAltitudeMatch {
boolean test_quat0 = false;
boolean test_quat2= false; // true;
boolean use_degrees = true;
boolean use_percents = true;
boolean debug_tilts = true;
boolean invert_order= false; // print them
......@@ -160,6 +162,7 @@ public class OrthoAltitudeMatch {
int [] ipair = {indices[cpair[0]], indices[cpair[1]]};
if (updateStatus) {
IJ.showStatus("Processing pair "+npair+" of "+condensed_pairs.length+" "+ipair[0]+"->"+ipair[1]);
IJ.showProgress(1.0*npair/condensed_pairs.length-1);
}
PairwiseOrthoMatch pairwiseOrthoMatch = ortho_maps[ipair[0]].getMatch(ortho_maps[ipair[1]].getName(), true); // ?
if (pairwiseOrthoMatch == null) {
......@@ -914,7 +917,9 @@ public class OrthoAltitudeMatch {
System.out.println("LMA -> "+lma_rslt);
if (lma_rslt >= 0) {
if (debugLevel > -3) {
ersTiltLMA.printResults(use_degrees);
ersTiltLMA.printSceneResults(use_degrees, use_percents);
ersTiltLMA.printPairsResults(use_degrees, use_percents);
}
}
System.out.println();
......@@ -924,7 +929,7 @@ public class OrthoAltitudeMatch {
QuatUtils.testPseudoAffineDiffAndDerivatives(
pseudo_xy, // double [][] xy, // [scene][direction]
ersTiltLMA.aff_tilts[npair], // double [][][] a_tilts,
ersTiltLMA.aff_pairs_nosr[npair], // double [][] iaff_pair, // affine pair inversed
ersTiltLMA.aff_pairs_inosr[npair], // double [][] iaff_pair, // affine pair inversed
invert_q2a); // boolean invert_q2a){ // invert result affines (to match "usual")
System.out.println();
}
......
......@@ -6567,6 +6567,9 @@ public class OrthoMapsCollection implements Serializable{
boolean flt_show_rms = true; // clt_parameters.imp.flt_show_rms; // true;
boolean flt_show_zoom = true; // clt_parameters.imp.flt_show_zoom; // true;
boolean flt_show_alt = true; // clt_parameters.imp.flt_show_alt; // true;
boolean flt_show_svd = true;
boolean flt_show_degrees = true;
boolean alt_overwrite = clt_parameters.imp.alt_overwrite; // false; // overwrite existing altitude match pairs
boolean alt_pairwise = clt_parameters.imp.alt_pairwise; // false; // overwrite existing altitude match pairs
......@@ -6619,7 +6622,7 @@ public class OrthoMapsCollection implements Serializable{
flt_nan_rms = gdf.getNextBoolean();
flt_alt = gdf.getNextChoiceIndex();
alt_overwrite = gdf.getNextBoolean();
alt_pairwise = gdf.getNextBoolean();
alt_pairwise = gdf.getNextBoolean();
save_each = gdf.getNextBoolean();
log_append = gdf.getNextBoolean();
log_path = gdf.getNextString();
......@@ -6670,8 +6673,11 @@ public class OrthoMapsCollection implements Serializable{
flt_show_rms, // boolean show_rms,
flt_show_zoom, // boolean show_zoom,
flt_show_alt, // boolean show_alt,
use_tab, // boolean use_tab,
null); // String extra_line)
use_tab, // boolean use_tab,
null, // String extra_line)
flt_show_svd, // boolean show_svd,
flt_show_degrees); // boolean use_degrees);
{
System.out.println("Selected\t"+available_pairs.length+"\tscene pairs for matching");
if (use_tab) {
......@@ -6682,6 +6688,10 @@ public class OrthoMapsCollection implements Serializable{
if (flt_show_zoom) System.out.print(String.format("\t%4s", "Zoom"));
if (flt_show_alt) System.out.print(String.format("\t%7s\t%7s\t%7s", "tiltX","tiltY","offs"));
if (flt_show_sfm) System.out.print(String.format("\t%5s\t%5s", "SfM0","SfM1"));
if (flt_show_svd) {
String svd_title=SingularValueDecomposition.titleString(flt_show_degrees);
System.out.print("\t"+ svd_title);
}
System.out.println();
}
for (int i = 0; i < available_pairs.length; i++) {
......@@ -7535,6 +7545,30 @@ public class OrthoMapsCollection implements Serializable{
boolean show_alt,
boolean use_tab,
String extra_line) {
return textPairs (
plist, // int [][] plist,
show_names, // boolean show_names,
show_overlap, // boolean show_overlap,
show_rms, // boolean show_rms,
show_zoom, // boolean show_zoom,
show_alt, // boolean show_alt,
use_tab, // boolean use_tab,
extra_line, // String extra_line,
false, // boolean show_svd,
false); // boolean use_degrees);
}
public String [] textPairs (
int [][] plist,
boolean show_names,
boolean show_overlap,
boolean show_rms,
boolean show_zoom,
boolean show_alt,
boolean use_tab,
String extra_line,
boolean show_svd,
boolean use_degrees) {
boolean show_sfm = show_alt;
// TODO: show SfM of each scene
......@@ -7563,6 +7597,11 @@ public class OrthoMapsCollection implements Serializable{
}
}
if (show_sfm) text_pairs[i] += String.format(use_tab?"\t%5.1f\t%5.1f":" S %5.1f %5.1f", sfm_gain[0],sfm_gain[1]);
if (show_svd && use_tab && (pairwiseOrthoMatch.getAffine()!=null)) { // now only for tab
SingularValueDecomposition svd = SingularValueDecomposition.singularValueDecompose(pairwiseOrthoMatch.getAffine());
String ssvd = svd.toString(use_degrees, 1);
text_pairs[i] += "\t"+ssvd;
}
}
}
if (extra_line !=null) {
......
......@@ -1466,33 +1466,56 @@ q11 - q22 = c3
double [][][] a_tilts,
double [][] iaff_pair, // affine pair inversed
boolean invert_q2a){ // invert result affines (to match "usual")
double delta= 1e-6;
double delta= 1e-8;
/*
xy = new double [][] {
{xy[0][0]-0.1,xy[0][1]+0.1},
{xy[1][0]+0.1,xy[1][1]+0.1}
};
a_tilts = new double[][][] {
{
{a_tilts[0][0][0], a_tilts[0][0][1]-0.01},
{a_tilts[0][1][0]-0.01,a_tilts[0][1][1]}
},
{
{a_tilts[1][0][0], a_tilts[1][0][1]-0.1},
{a_tilts[1][1][0]-0.1, a_tilts[1][1][1]}
}
};
iaff_pair = new double [][] {
{iaff_pair[0][0], iaff_pair[0][1]+0.1},
{iaff_pair[1][0]+0.1,iaff_pair[1][1]}
};
*/
double [][] xy_m = new double [][] {
{xy[0][0],xy[0][1]},
{xy[1][0],xy[1][1]}
};
a_tilts = new double[][][] {
double [][][] a_tilts_m= new double[][][] {
{
{a_tilts[0][0][0],a_tilts[0][0][1]},
{a_tilts[0][1][0],a_tilts[0][1][1]}
},
{
{a_tilts[1][0][0],a_tilts[1][0][1]},
{a_tilts[1][1][0],a_tilts[1][1][1]}
{a_tilts[1][0][0], a_tilts[1][0][1]},
{a_tilts[1][1][0], a_tilts[1][1][1]}
}
};
iaff_pair = new double [][] {
double [][] iaff_pair_m = new double [][] {
{iaff_pair[0][0],iaff_pair[0][1]},
{iaff_pair[1][0],iaff_pair[1][1]}
};
testPseudoAffineDiffAndDerivatives(
xy, // double [][] xy, // [scene][direction]
a_tilts, // double [][][] a_tilts,
iaff_pair, // double [][] iaff_pair, // affine pair inversed
invert_q2a, //boolean invert_q2a, // invert result affines (to match "usual")
delta); // double delta);
xy_m, // double [][] xy, // [scene][direction]
a_tilts_m, // double [][][] a_tilts,
iaff_pair_m, // double [][] iaff_pair, // affine pair inversed
invert_q2a, // boolean invert_q2a, // invert result affines (to match "usual")
delta); // double delta);
}
public static void testPseudoAffineDiffAndDerivatives(
......@@ -1544,11 +1567,11 @@ q11 - q22 = c3
System.out.println(String.format("%5s\t%20s\t%20s\t%20s\t%20s",
"mode#", "dx0", "dy0", "dx1", "dy1"));
System.out.println(String.format("%5s\t%20.12f\t%20.12f\t%20.12f\t%20.12f",
"deriv", s*dWdW[0], s*dWdW[1], s*dWdW[2], s*dWdW[3]));
"deriv", s*dWdW[1], s*dWdW[2], s*dWdW[3], s*dWdW[4]));
System.out.println(String.format("%5s\t%20.12f\t%20.12f\t%20.12f\t%20.12f",
"delta", s*dWdW_delta[0], s*dWdW_delta[1],s*dWdW_delta[2],s*dWdW_delta[3]));
"delta", s*dWdW_delta[1], s*dWdW_delta[2],s*dWdW_delta[3],s*dWdW_delta[4]));
System.out.println(String.format("%5s\t%20.12f\t%20.12f\t%20.12f\t%20.12f",
"diff", s*(dWdW_delta[0]-dWdW[0]), s*(dWdW_delta[1]-dWdW[1]), s*(dWdW_delta[2]-dWdW[2]), s*(dWdW_delta[3]-dWdW[3])));
"diff", s*(dWdW_delta[1]-dWdW[1]), s*(dWdW_delta[2]-dWdW[2]), s*(dWdW_delta[3]-dWdW[3]), s*(dWdW_delta[4]-dWdW[4])));
System.out.println ("Change xy[0][0] >= 1.0 to exit");
System.out.println ();
}
......
......@@ -49,6 +49,11 @@ public class SingularValueDecomposition {
public double getMinScale() {return Math.min(w1,w2);}
public double getMaxScale() {return Math.max(w1,w2);}
// Measure of tilt - difference between singular values (they both are assumed to be ~= 1.0)
public double getDW() {
return Math.abs(w1-w2);
}
public static String titleString(boolean degrees) {
SingularValueDecomposition svd= new SingularValueDecomposition(0,0,0,0,0);
return svd.toString(degrees, 2);
......@@ -67,20 +72,21 @@ public class SingularValueDecomposition {
//System.out.println("svd_affine_pair= ["+svd_affine_pair.scale+ ","+svd_affine_pair.getTiltAngle()+ ","+svd_affine_pair.gamma+ ","+svd_affine_pair.rot+
// "] tilt="+(svd_affine_pair.getTiltAngle()*180/Math.PI)+ "\u00B0, dir="+(svd_affine_pair.gamma*180/Math.PI)+"\u00B0");
String tab_title_rad = String.format("%10s\t%10s\t%10s\t%10s\t%10s\t%10s\t%10s\t%10s",
"scale","tilt","gamma","beta","rot", "w1", "w2", "ratio");
"scale","tilt","gamma","beta","rot", "w1", "w2", "\u0394w"); // ratio");
String tab_title_deg = String.format("%10s\t%10s\t%10s\t%10s\t%10s\t%10s\t%10s\t%10s",
"scale","tilt\u00B0","gamma\u00B0","beta\u00B0","rot\u00B0", "w1", "w2", "ratio");
"scale","tilt\u00B0","gamma\u00B0","beta\u00B0","rot\u00B0", "w1", "w2", "\u0394w"); // ratio");
String tab_fmt_rad = "%10.8f\t%10.7f\t%10.7f\t%10.7f\t%10.7f\t%10.8f\t%10.8f\t%10.8f";
String tab_fmt_deg = "%10.8f\t%10.5f\t%10.5f\t%10.5f\t%10.5f\t%10.8f\t%10.8f\t%10.8f";
String fmt_rad = " scale=%10.8f,tilt= %10.7f, gamma=%10.7f, beta=%10.7f, rot=%10.7f, w1=%10.8f, w2=%10.8f, ratio=%10.8f";
String fmt_deg = " scale=%10.8f,tilt= %10.5f\u00B0, gamma=%10.5f\u00B0, beta=%10.5f\u00B0, rot=%10.5f\u00B0, w1=%10.8f, w2=%10.8f, ratio=%10.8f";
String fmt_rad = " scale=%10.8f,tilt= %10.7f, gamma=%10.7f, beta=%10.7f, rot=%10.7f, w1=%10.8f, w2=%10.8f, \u0394w=%10.8f"; // ratio=%10.8f";
String fmt_deg = " scale=%10.8f,tilt= %10.5f\u00B0, gamma=%10.5f\u00B0, beta=%10.5f\u00B0, rot=%10.5f\u00B0, w1=%10.8f, w2=%10.8f, \u0394w=%10.8f"; // ratio=%10.8f\";
if (tab_mode==2) {
return degrees?tab_title_deg:tab_title_rad;
}
String fmt = (tab_mode==1)?(degrees ? tab_fmt_deg : tab_fmt_rad):(degrees ? fmt_deg : fmt_rad);
double s = degrees ? (180/Math.PI):1;
// String fmt=degrees ? fmt_deg : fmt_rad;
return String.format(fmt, scale, s*getTiltAngle(), s*gamma, s*beta, s*rot, w1, w2, ratio);
// return String.format(fmt, scale, s*getTiltAngle(), s*gamma, s*beta, s*rot, w1, w2, ratio);
return String.format(fmt, scale, s*getTiltAngle(), s*gamma, s*beta, s*rot, w1, w2, Math.abs(w1-w2));
}
......
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