Commit d3389b58 authored by Andrey Filippov's avatar Andrey Filippov

More on quaternions - affines

parent 0abd52b8
......@@ -177,7 +177,7 @@ public class ComboMatch {
boolean use_saved_collection = true; // false;
boolean save_collection = true;
boolean save_collection = false; // true;
boolean process_correlation = true; // use false to save new version of data
int num_tries_fit = 10;
boolean update_match = true; // use false to save new version of data
......@@ -210,7 +210,7 @@ public class ComboMatch {
pattern_match = false;
}
GenericJTabbedDialog gd = new GenericJTabbedDialog("Set image pair",1200,800);
GenericJTabbedDialog gd = new GenericJTabbedDialog("Set image pair",1200,900);
// 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 available). If false - use files list.");
......@@ -433,7 +433,7 @@ public class ComboMatch {
};
GenericJTabbedDialog gdo = new GenericJTabbedDialog("Set image pair",1200,900);
GenericJTabbedDialog gdo = new GenericJTabbedDialog("Set image pair",1200,1000);
gdo.addNumericField("Correlation size", corr_size, 0,4,"",
"Correlation size, power of 2");
gdo.addNumericField("Extracted size", extr_size, 0,4,"",
......@@ -858,6 +858,12 @@ public class ComboMatch {
}
if (process_correlation || render_match || pattern_match || test_multi_lma) {
// int [] gpu_pair;
boolean removeTilt = false;
boolean removeRot = false;
boolean removeScale = false;
boolean removeOffset = false;
boolean max_is_scale = false;
if (gpu_spair == null) {
ArrayList<Point> pairs_list = new ArrayList<Point>();
for (OrthoMap map : maps_collection.ortho_maps) {
......@@ -905,7 +911,7 @@ public class ComboMatch {
boolean flt_show_alt = clt_parameters.imp.flt_show_alt; // true;
boolean flt_update_config = false;
String flt_extra_line = "--- select a single image ---";
GenericJTabbedDialog gdf = new GenericJTabbedDialog("Select pairs filter/display",800,500);
GenericJTabbedDialog gdf = new GenericJTabbedDialog("Select pairs filter/display",800,600);
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.");
......@@ -999,15 +1005,27 @@ public class ComboMatch {
false, // boolean use_tab,
flt_extra_line); // String extra_line)
GenericJTabbedDialog gdc = new GenericJTabbedDialog("Select image pair",1200,100);
GenericJTabbedDialog gdc = new GenericJTabbedDialog("Select image pair",1200,300);
int num_choice_lines = 50;
gdc.addChoice("Image pair:",
choices_all,
choices_all[choices_all.length - 1], // -1],
"Select processed image pair or request a single image selection", num_choice_lines);
gdc.addCheckbox ("Remove tilt", removeTilt, "Remove tilts from the pairwise affine transform.");
gdc.addCheckbox ("Remove Rotation", removeRot, "Remove rotation from the pairwise affine transform.");
gdc.addCheckbox ("Remove Scale", removeScale, "Remove scale from the pairwise affine transform.");
gdc.addCheckbox ("Remove Translation", removeOffset, "Remove translation from the pairwise affine transform.");
gdc.addCheckbox ("Max eigenvalue is scale", max_is_scale, "Maximal eigenvalue is scale (false - minimal is).");
// boolean max_is_scale = false;
gdc.showDialog();
if (gdc.wasCanceled()) return false;
int pair= gdc.getNextChoiceIndex();
int pair= gdc.getNextChoiceIndex();
removeTilt = gdc.getNextBoolean();
removeRot = gdc.getNextBoolean();
removeScale = gdc.getNextBoolean();
removeOffset = gdc.getNextBoolean();
max_is_scale = gdc.getNextBoolean();
if (pair >= (choices_all.length -1)) {
int default_choice = 0;
int num_scene_lines = 50;
......@@ -1118,7 +1136,36 @@ public class ComboMatch {
} else {
affine1 = pairwiseOrthoMatch.getAffine();
affine1 = pairwiseOrthoMatch.getAffine().clone();
if (debugLevel > -4) {
System.out.println("removeTilt="+ removeTilt);
System.out.println("removeRot="+ removeRot);
System.out.println("removeScale="+ removeScale);
System.out.println("removeOffset="+removeOffset);
System.out.println("max_is_scale="+max_is_scale);
if (removeTilt || removeRot || removeScale || removeOffset) {
SingularValueDecomposition svd_affine_pair = SingularValueDecomposition.singularValueDecomposeScaleTiltGamma(affine1, true); // y_down_ccw); // boolean y_down_ccw)
System.out.println("Full (original) affine transform:");
System.out.println(QuatUtils.affinesToString(affine1, "full_affine"));
System.out.println("full_affine_svd" + svd_affine_pair.toString(true)); // use_degrees));
}
}
affine1 = SingularValueDecomposition.removeTiltRotScale(
affine1, // double [][] A,
removeTilt, // boolean removeTilt,
removeRot, // boolean removeRot,
removeScale, // boolean removeScale,
removeOffset, // boolean removeOffset)
max_is_scale); //boolean max_is_scale)
if (debugLevel > -4) {
if (removeTilt || removeRot || removeScale || removeOffset) {
SingularValueDecomposition svd_affine_pair = SingularValueDecomposition.singularValueDecomposeScaleTiltGamma(affine1, true); // y_down_ccw); // boolean y_down_ccw)
System.out.println("Final differential affine transform:");
System.out.println(QuatUtils.affinesToString(affine1, "affine1 "));
System.out.println("affine1_svd " + svd_affine_pair.toString(true)); // use_degrees));
}
}
double [][][] affines = {affine0,affine1};
int [] zooms = {initial_zoom, min_zoom_lev, 1000,1000}; // make automatic
// double scale = 2.0; // scale vectors when warping;
......@@ -1239,6 +1286,14 @@ public class ComboMatch {
}
if (render_match) {
String title=String.format("multi_%03d-%03d_%s-%s_zoom%d_%d",gpu_pair[0],gpu_pair[1],gpu_spair[0],gpu_spair[1],min_zoom_lev,zoom_lev);
if (removeTilt || removeRot || removeScale || removeOffset) {
title += "_no-";
if (removeTilt) title += "T";
if (removeRot) title += "R";
if (removeScale) title += "S";
if (removeOffset) title += "O";
if (max_is_scale) title += "X";
}
// Avoid renderMulti() - it duplicates code renderMultiDouble()
int eq_mode = 2; // calculate
ImagePlus imp_img_pair = maps_collection.renderMulti (
......@@ -2077,7 +2132,7 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341
{2139.833, 1474.5},
{ 461.5, 1493.5}}};
boolean set_coords = true; // false;
GenericJTabbedDialog gd = new GenericJTabbedDialog("Set image pair",1090,900);
GenericJTabbedDialog gd = new GenericJTabbedDialog("Select processing moder",1090,900);
gd.addStringField ("First image path", image_paths[0], 120, "First image full path");
gd.addStringField ("Second image path", image_paths[1], 120, "Second image full path");
gd.addCheckbox ("Set image markers to following coordinates", set_coords, "Delete markers and set them according to data.");
......
......@@ -55,10 +55,15 @@ public class OrthoAltitudeMatch {
String log_path,
String orthoMapsCollection_path,
int debugLevel) {
boolean dbg_planes = false;
boolean y_down_ccw = true;
boolean invert_q2a = true;
boolean test_quat = true;
if (test_quat) {
boolean test_quat = false;
boolean test_quat0 = false;
boolean test_quat2= true;
boolean use_degrees = true;
if (test_quat0) {
QuatUtils.testQuatAff();
}
......@@ -183,12 +188,15 @@ public class OrthoAltitudeMatch {
double [] alt_data5 = null;
int num_bins = 1000;
for (int ntry = 0; ntry <= alt_refine; ntry++) {
String dbg_name = (dbg_planes && (ntry == alt_refine)) ? ("plane_approximation_"+ipair[1]+"-"+ipair[0]+"_"+ntry) :null;
// String dbg_name = (dbg_planes ) ? ("plane_approximation_"+ipair[1]+"-"+ipair[0]+"_"+ntry) :null;
alt_data5 = OrthoMap.getPlane(
diff_data, // final double [] data,
mask, // final boolean [] mask,
weight, // final double [] weight,
woi_overlap.width, // final int width,
xy0); // final double [] xy0) {
xy0, // final double [] xy0) {
dbg_name);
if ((alt_outliers > 0) && (ntry < alt_refine)){ // not the last pass
mask = OrthoMap.removeRelativeLowHigh (
diff_data, // final double [] data,
......@@ -203,11 +211,216 @@ public class OrthoAltitudeMatch {
}
}
double [] alt_data = {alt_data5[0]/pix_size_meters, alt_data5[1]/pix_size_meters,alt_data5[2]};
if (test_quat2) {
System.out.println("***************** npair="+npair+": "+ipair[0]+" -> "+ipair[1]);
boolean [][] masks = new boolean[2][];
double [][] alt_data5s = new double[2][];
double [][] data_overlap = new double[2][];
double [][] alt_datas = new double[3][];
double [][] affine_pair = pairwiseOrthoMatch.getAffine();
// calculate second from first and pair
double [][] affine0 = ortho_maps[ipair[0]].getAffine();
Matrix A0 = new Matrix (
new double [][] {{affine0[0][0],affine0[0][1]},{affine0[1][0],affine0[1][1]}});
Matrix A10 = new Matrix (
new double [][] {{affine_pair[0][0],affine_pair[0][1]},{affine_pair[1][0],affine_pair[1][1]}});
Matrix A1a = A10.times(A0);
double [][] affine1a = new double[][] {
{A1a.get(0,0),A1a.get(0,1)},
{A1a.get(1,0),A1a.get(1,1)}};
double [][][] affines = new double [][][] {ortho_maps[ipair[0]].getAffine(),ortho_maps[ipair[1]].getAffine(), affine1a};
SingularValueDecomposition svd_affine_pair = SingularValueDecomposition.singularValueDecomposeScaleTiltGamma(affine_pair, y_down_ccw); // boolean y_down_ccw)
SingularValueDecomposition[] svd_affines = {
SingularValueDecomposition.singularValueDecomposeScaleTiltGamma(affines[0], y_down_ccw),
SingularValueDecomposition.singularValueDecomposeScaleTiltGamma(affines[1], y_down_ccw),
SingularValueDecomposition.singularValueDecomposeScaleTiltGamma(affines[2], y_down_ccw)};
// calculate individual tilts
for (int ns = 0; ns < cpair.length; ns++) {
data_overlap[ns] = OrthoMap.extractWoi(
alt_multi[cpair[ns]], // final double [] data0,
width, // final int width,
woi_overlap); // Rectangle woi_in);
for (int ntry = 0; ntry <= alt_refine; ntry++) {
String dbg_name = (dbg_planes && (ntry == alt_refine)) ? ("plane_approximation_"+ipair[ns]+"_"+npair) :null;
alt_data5s[ns] = OrthoMap.getPlane(
data_overlap[ns], // final double [] data,
masks[ns], // final boolean [] mask,
weight, // final double [] weight,
woi_overlap.width, // final int width,
xy0, // final double [] xy0) {
dbg_name);
if ((alt_outliers > 0) && (ntry < alt_refine)){ // not the last pass
masks[ns] = OrthoMap.removeRelativeLowHigh (
data_overlap[ns], // final double [] data,
null, // mask, // final boolean [] mask_in, // new mask for all data and latest plane
alt_abs_outliers, // final double abs_diff,
alt_outliers, // final double rel_frac,
alt_data5s[ns], // final double [] ground_plane, // tiltx,tilty, offs, x0(pix), y0(pix) or null
woi_overlap.width,// final int width, // only used with ground_plane != null;
num_bins); // final int num_bins)
} else {
break;
}
}
alt_datas[ns] = new double [] {alt_data5s[ns][0]/pix_size_meters, alt_data5s[ns][1]/pix_size_meters,alt_data5s[ns][2]};
}
alt_datas[2] = new double [3];
for (int i = 0; i < alt_datas[2].length; i++) {
alt_datas[2][i] = alt_datas[0][i]+alt_data[i]; // simulated alt_datas[1]
}
System.out.println(QuatUtils.affinesToString(affine_pair, "affine_pair "));
System.out.println("svd_affine_pair= " + svd_affine_pair.toString(use_degrees));
System.out.println();
System.out.println(QuatUtils.affinesToString(affines[0] , "affines[0]= "));
System.out.println("svd_affines[0]= " + svd_affines[0].toString(use_degrees));
System.out.println();
System.out.println(QuatUtils.affinesToString(affines[1] , "affines[1]= "));
System.out.println("svd_affines[1]= " + svd_affines[1].toString(use_degrees));
System.out.println();
System.out.println(QuatUtils.affinesToString(affines[2] , "affines[2]= "));
System.out.println("svd_affines[2]= " + svd_affines[2].toString(use_degrees));
System.out.println();
System.out.println("tilt_diff"+ QuatUtils.tiltToString (alt_data, y_down_ccw, use_degrees));
System.out.println("tilt[0] "+ QuatUtils.tiltToString (alt_datas[0], y_down_ccw, use_degrees));
System.out.println("tilt[1] "+ QuatUtils.tiltToString (alt_datas[1], y_down_ccw, use_degrees));
System.out.println("tilt[2] "+ QuatUtils.tiltToString (alt_datas[2], y_down_ccw, use_degrees));
System.out.println();
double [][] quat_scenes = new double [alt_datas.length][];
double [] quat_diff_scenes = QuatUtils.sceneRelLocalGround(
alt_data, // double [] txy,
affine_pair, // double [][] affine,
y_down_ccw); // boolean y_down_ccw)
System.out.println("quat_diff_scenes= "+QuatUtils.toString(quat_diff_scenes,use_degrees));
for (int ns = 0; ns < quat_scenes.length; ns++) {
quat_scenes[ns] = QuatUtils.sceneRelLocalGround(
alt_datas[ns], // double [] txy,
affines[ns], // double [][] affine,
y_down_ccw); // boolean y_down_ccw)
System.out.println("quat_scenes["+ns+"]="+QuatUtils.toString(quat_scenes[ns],use_degrees));
// 0, 1 and simulated 2?
}
double [] quat1a = QuatUtils.multiplyScaled(quat_scenes[0], quat_diff_scenes);
double [] quat1b = QuatUtils.multiplyScaled(quat_diff_scenes, quat_scenes[0]);
System.out.println("quat1a = "+QuatUtils.toString(quat1a,use_degrees));
System.out.println("quat1b = "+QuatUtils.toString(quat1b,use_degrees)); // reversed order
double aff_qscenes [][][] = new double [quat_scenes.length][][];
SingularValueDecomposition[] svd_acenes = new SingularValueDecomposition[ aff_qscenes.length];
for (int ns = 0; ns < aff_qscenes.length; ns++) {
aff_qscenes[ns] = QuatUtils.quatToAffine(quat_scenes[ns] ,invert_q2a,true);
svd_acenes[ns]=SingularValueDecomposition.singularValueDecomposeScaleTiltGamma(aff_qscenes[ns], y_down_ccw);
System.out.println(QuatUtils.affinesToString(aff_qscenes[ns], "aff_qscenes["+ns+"]"));
System.out.println("svd_acenes["+ns+"]=" + svd_acenes[ns].toString(use_degrees));
System.out.println();
}
System.out.println(QuatUtils.affinesToString(affine_pair, "affine_pair "));
System.out.println("svd_affine_pair= " + svd_affine_pair.toString(use_degrees));
System.out.println("+++++++++++++ Relative affine from quat2 to quat0 (from tilts, should match affine_pair)");
double [][] adq20 = QuatUtils.matMult2x2(aff_qscenes[2], QuatUtils.matInverse2x2(aff_qscenes[0]));
SingularValueDecomposition svd_adq20=SingularValueDecomposition.singularValueDecomposeScaleTiltGamma(adq20, y_down_ccw);
System.out.println(QuatUtils.affinesToString(adq20, "adq20 "));
System.out.println("svd_adq20= " + svd_adq20.toString(use_degrees));
System.out.println();
// double [][] adq20i = QuatUtils.matMult2x2(QuatUtils.matInverse2x2(aff_qscenes[0]),aff_qscenes[2]);
double [][] adq20i = QuatUtils.matInverse2x2(adq20);
SingularValueDecomposition svd_adq20i=SingularValueDecomposition.singularValueDecomposeScaleTiltGamma(adq20i, y_down_ccw);
System.out.println(QuatUtils.affinesToString(adq20i, "adq20i "));
System.out.println("svd_adq20i= " + svd_adq20i.toString(use_degrees));
System.out.println();
double [][] adq20_diff = QuatUtils.matMult2x2(adq20, QuatUtils.matInverse2x2(affine_pair));
SingularValueDecomposition svd_adq20_diff=SingularValueDecomposition.singularValueDecomposeScaleTiltGamma(adq20_diff, y_down_ccw);
System.out.println(QuatUtils.affinesToString(adq20_diff, "adq20_diff"));
System.out.println("svd_adq20_diff= " + svd_adq20_diff.toString(use_degrees));
System.out.println();
/*
double [][] iadq20 = QuatUtils.matInverse2x2(adq20);
SingularValueDecomposition svd_iadq20=SingularValueDecomposition.singularValueDecomposeScaleTiltGamma(iadq20, y_down_ccw);
System.out.println(QuatUtils.affinesToString(iadq20, "iadq20 "));
System.out.println("svd_iadq20= " + svd_iadq20.toString(use_degrees));
System.out.println();
*/
double [][] affq1a =QuatUtils.quatToAffine(quat1a ,invert_q2a,true);
SingularValueDecomposition svd_affq1a=SingularValueDecomposition.singularValueDecomposeScaleTiltGamma(affq1a, y_down_ccw);
System.out.println(QuatUtils.affinesToString(affq1a, "affq1a "));
System.out.println("svd_affq1a= " + svd_affq1a.toString(use_degrees));
System.out.println();
double [][] affq1b =QuatUtils.quatToAffine(quat1b ,invert_q2a,true);
SingularValueDecomposition svd_affq1b=SingularValueDecomposition.singularValueDecomposeScaleTiltGamma(affq1b, y_down_ccw);
System.out.println(QuatUtils.affinesToString(affq1b, "affq1b "));
System.out.println("svd_affq1b= " + svd_affq1b.toString(use_degrees));
System.out.println();
// combine aff_qscenes[0] and affine_pair
double [][] aff_gnd2 = QuatUtils.matMult2x2(affine_pair, aff_qscenes[0]);
SingularValueDecomposition saff_gnd2=SingularValueDecomposition.singularValueDecomposeScaleTiltGamma(aff_gnd2, y_down_ccw);
System.out.println(QuatUtils.affinesToString(aff_gnd2, "aff_gnd2 "));
System.out.println("saff_gnd2= " + saff_gnd2.toString(use_degrees));
System.out.println();
// convert aff_gnd2 to a pair of quaternions
double[][] qaff2_gnd_pm = QuatUtils.affineToQuatScaled(aff_gnd2, false, y_down_ccw);
double [][] qaff2_gnd_diff = {
QuatUtils.divideScaled(qaff2_gnd_pm[0], quat_scenes[2]),
QuatUtils.divideScaled(qaff2_gnd_pm[1], quat_scenes[2])
};
System.out.println("Should match:");
System.out.println("quat_scenes[2] = "+QuatUtils.toString(quat_scenes[2],use_degrees)); // reversed order
System.out.println("qaff2_gnd_pm[0] = "+QuatUtils.toString(qaff2_gnd_pm[0],use_degrees)); // reversed order
System.out.println("qaff2_gnd_diff[0] = "+QuatUtils.toString(qaff2_gnd_diff[0],use_degrees)); // reversed order
System.out.println("qaff2_gnd_pm[1] = "+QuatUtils.toString(qaff2_gnd_pm[1],use_degrees)); // reversed order
System.out.println("qaff2_gnd_diff[1] = "+QuatUtils.toString(qaff2_gnd_diff[1],use_degrees)); // reversed order
System.out.println();
double [][] qvariants = {
QuatUtils.divideScaled(qaff2_gnd_pm[0], quat_scenes[0]),
QuatUtils.divideScaled(qaff2_gnd_pm[1], quat_scenes[0])};
double [][] qvariants_diff = {
QuatUtils.divideScaled(qvariants[0], quat_diff_scenes),
QuatUtils.divideScaled(qvariants[1], quat_diff_scenes)
};
System.out.println("qvariants[0] = "+QuatUtils.toString(qvariants[0],use_degrees)); // reversed order
System.out.println("qvar_diff[0] = "+QuatUtils.toString(qvariants_diff[0],use_degrees)); // reversed order
System.out.println("qvariants[1] = "+QuatUtils.toString(qvariants[1],use_degrees)); // reversed order
System.out.println("qvar_diff[1] = "+QuatUtils.toString(qvariants_diff[1],use_degrees)); // reversed order
System.out.println();
// test
double[][] qaff1_gnd_pm = QuatUtils.affineToQuatScaled(aff_qscenes[0], false, y_down_ccw);
double [][] qvariants_test = {
QuatUtils.divideScaled(qaff1_gnd_pm[0], quat_scenes[0]),
QuatUtils.divideScaled(qaff1_gnd_pm[1], quat_scenes[0])};
// double [][] qvariants_test_diff = {
// QuatUtils.divideScaled(qvariants_test[0], quat_diff_scenes),
// QuatUtils.divideScaled(qvariants_test[0], quat_diff_scenes)
// };
System.out.println("tvariants[0] = "+QuatUtils.toString(qvariants_test[0],use_degrees)); // reversed order
// System.out.println("tvar_diff[0] = "+QuatUtils.toString(qvariants_test_diff[0],use_degrees)); // reversed order
System.out.println("tvariants[1] = "+QuatUtils.toString(qvariants_test[1],use_degrees)); // reversed order
// System.out.println("tvar_diff[1] = "+QuatUtils.toString(qvariants_test_diff[1],use_degrees)); // reversed order
System.out.println();
}
if (test_quat) {
System.out.println(">>>>>>>>>>>>>>>>> npair="+npair+": "+ipair[0]+" -> "+ipair[1]);
boolean use_degrees = true;
boolean [][] masks = new boolean[2][];
double [][] alt_data5s = new double[2][];
......@@ -224,12 +437,14 @@ public class OrthoAltitudeMatch {
woi_overlap); // Rectangle woi_in);
for (int ntry = 0; ntry <= alt_refine; ntry++) {
String dbg_name = (dbg_planes && (ntry == alt_refine)) ? ("plane_approximation_"+ipair[ns]+"_"+npair) :null;
alt_data5s[ns] = OrthoMap.getPlane(
data_overlap[ns], // final double [] data,
masks[ns], // final boolean [] mask,
weight, // final double [] weight,
woi_overlap.width, // final int width,
xy0); // final double [] xy0) {
xy0, // final double [] xy0) {
dbg_name);
if ((alt_outliers > 0) && (ntry < alt_refine)){ // not the last pass
masks[ns] = OrthoMap.removeRelativeLowHigh (
data_overlap[ns], // final double [] data,
......@@ -256,74 +471,20 @@ public class OrthoAltitudeMatch {
}
double [] quat_rdiff = QuatUtils.invert(quat_diff);
/// double [] quat2a = QuatUtils.multiply(quats01[0], quat_diff);
/// double [] quat2b = QuatUtils.multiply(quat_diff, quats01[0]);
double [] quat2a = QuatUtils.multiply(quats01[0], quat_diff);
double [] quat2b = QuatUtils.multiply(quat_diff, quats01[0]);
double [] quat2ap = QuatUtils.pureTilt(quat2a);
double [] quat2bp = QuatUtils.pureTilt(quat2b);
/*
double [] quat2an = QuatUtils.normalize(quat2a);
double [] quat2bn = QuatUtils.normalize(quat2b);
double [] quat2apn = QuatUtils.normalize(quat2ap);
double [] quat2bpn = QuatUtils.normalize(quat2bp);
*/
/*
double [] quat1ar = QuatUtils.multiply(quats01[1], quat_rdiff);
double [] quat1br = QuatUtils.multiply(quat_rdiff, quats01[1]);
double [] quat1cr = QuatUtils.multiply(quats01[2], quat_rdiff);
double [] quat1dr = QuatUtils.multiply(quat_rdiff, quats01[2]);
*/
/*
double [] quat1apr = QuatUtils.pureTilt(quat1ar);
double [] quat1bpr = QuatUtils.pureTilt(quat1br);
double [] quat1cpr = QuatUtils.pureTilt(quat1cr);
double [] quat1dpr = QuatUtils.pureTilt(quat1dr);
*/
/*
double [] quat1aprn = QuatUtils.normalize(quat1apr);
double [] quat1bprn = QuatUtils.normalize(quat1bpr);
double [] quat1cprn = QuatUtils.normalize(quat1cpr);
double [] quat1dprn = QuatUtils.normalize(quat1dpr);
double [] quat1arn = QuatUtils.normalize(quat1ar);
double [] quat1brn = QuatUtils.normalize(quat1br);
double [] quat1crn = QuatUtils.normalize(quat1cr);
double [] quat1drn = QuatUtils.normalize(quat1dr);
*/
//pureTilt
System.out.println("alt_data= ["+alt_data[0]+","+alt_data[1]+","+alt_data[2]+"]");
System.out.println("alt_datas[0]=["+alt_datas[0][0]+","+alt_datas[0][1]+","+alt_datas[0][2]+"]");
System.out.println("alt_datas[1]=["+alt_datas[1][0]+","+alt_datas[1][1]+","+alt_datas[1][2]+"]");
System.out.println("alt_datas[2]=["+alt_datas[2][0]+","+alt_datas[2][1]+","+alt_datas[2][2]+"]");
/*
System.out.println("quat_diff= ["+quat_diff[0]+","+quat_diff[1]+","+quat_diff[2]+","+quat_diff[3]+"] "+QuatUtils.norm(quat_diff));
System.out.println("quats01[0]= ["+quats01[0][0]+","+quats01[0][1]+","+quats01[0][2]+","+quats01[0][3]+"] "+QuatUtils.norm(quats01[0]));
System.out.println("quats01[1]= ["+quats01[1][0]+","+quats01[1][1]+","+quats01[1][2]+","+quats01[1][3]+"] "+QuatUtils.norm(quats01[1]));
System.out.println("quats01[2]= ["+quats01[2][0]+","+quats01[2][1]+","+quats01[2][2]+","+quats01[2][3]+"] "+QuatUtils.norm(quats01[2]));
*/
System.out.println("quat2a= ["+quat2a[0]+","+quat2a[1]+","+quat2a[2]+","+quat2a[3]+"] "+QuatUtils.norm(quat2a));
System.out.println("quat2b= ["+quat2b[0]+","+quat2b[1]+","+quat2b[2]+","+quat2b[3]+"] "+QuatUtils.norm(quat2b));
System.out.println("quat2ap= ["+quat2ap[0]+","+quat2ap[1]+","+quat2ap[2]+","+quat2ap[3]+"] "+QuatUtils.norm(quat2ap));
System.out.println("quat2bp= ["+quat2bp[0]+","+quat2bp[1]+","+quat2bp[2]+","+quat2bp[3]+"] "+QuatUtils.norm(quat2bp));
/*
System.out.println("quat2an= ["+quat2an[0]+","+quat2an[1]+","+quat2an[2]+","+quat2an[3]+"] "+QuatUtils.norm(quat2an));
System.out.println("quat2bn= ["+quat2bn[0]+","+quat2bn[1]+","+quat2bn[2]+","+quat2bn[3]+"] "+QuatUtils.norm(quat2bn));
System.out.println("quat2apn= ["+quat2apn[0]+","+quat2apn[1]+","+quat2apn[2]+","+quat2apn[3]+"] "+QuatUtils.norm(quat2apn));
System.out.println("quat2bpn= ["+quat2bpn[0]+","+quat2bpn[1]+","+quat2bpn[2]+","+quat2bpn[3]+"] "+QuatUtils.norm(quat2bpn));
System.out.println("quat1apr= ["+quat1apr[0]+","+quat1apr[1]+","+quat1apr[2]+","+quat1apr[3]+"] "+QuatUtils.norm(quat1apr)); // +
System.out.println("quat1bpr= ["+quat1bpr[0]+","+quat1bpr[1]+","+quat1bpr[2]+","+quat1bpr[3]+"] "+QuatUtils.norm(quat1bpr)); // ++
System.out.println("quat1cpr= ["+quat1cpr[0]+","+quat1cpr[1]+","+quat1cpr[2]+","+quat1cpr[3]+"] "+QuatUtils.norm(quat1cpr)); // +++
System.out.println("quat1dpr= ["+quat1dpr[0]+","+quat1dpr[1]+","+quat1dpr[2]+","+quat1dpr[3]+"] "+QuatUtils.norm(quat1dpr)); // +++
System.out.println("quat1aprn= ["+quat1aprn[0]+","+quat1aprn[1]+","+quat1aprn[2]+","+quat1aprn[3]+"] "+QuatUtils.norm(quat1aprn)); // +
System.out.println("quat1bprn= ["+quat1bprn[0]+","+quat1bprn[1]+","+quat1bprn[2]+","+quat1bprn[3]+"] "+QuatUtils.norm(quat1bprn)); // ++
System.out.println("quat1cprn= ["+quat1cprn[0]+","+quat1cprn[1]+","+quat1cprn[2]+","+quat1cprn[3]+"] "+QuatUtils.norm(quat1cprn)); // +++
System.out.println("quat1dprn= ["+quat1dprn[0]+","+quat1dprn[1]+","+quat1dprn[2]+","+quat1dprn[3]+"] "+QuatUtils.norm(quat1dprn)); // +++
System.out.println("quat1arn= ["+quat1arn[0]+","+quat1arn[1]+","+quat1arn[2]+","+quat1arn[3]+"] "+QuatUtils.norm(quat1arn)); // +
System.out.println("quat1brn= ["+quat1brn[0]+","+quat1brn[1]+","+quat1brn[2]+","+quat1brn[3]+"] "+QuatUtils.norm(quat1brn)); // ++
System.out.println("quat1crn= ["+quat1crn[0]+","+quat1crn[1]+","+quat1crn[2]+","+quat1crn[3]+"] "+QuatUtils.norm(quat1crn)); // +++
System.out.println("quat1drn= ["+quat1drn[0]+","+quat1drn[1]+","+quat1drn[2]+","+quat1drn[3]+"] "+QuatUtils.norm(quat1drn)); // +++
*/
double [][] affine_pair = pairwiseOrthoMatch.getAffine();
// calculate second from first and pair
......@@ -338,28 +499,7 @@ public class OrthoAltitudeMatch {
{A1a.get(1,0),A1a.get(1,1)}};
double [][][] affines = new double [][][] {ortho_maps[ipair[0]].getAffine(),ortho_maps[ipair[1]].getAffine(), affine1a};
boolean make__pure_tilt = false;
/*
double [][] aff1_stretch = QuatUtils.quatToAffine(
quats01[0], // double [] quat,
true, // boolean stretch,
make__pure_tilt, // boolean make__pure_tilt)
y_down_ccw); // boolean y_down_ccw);
double [][] aff1_shrink = QuatUtils.quatToAffine(
quats01[0], // double [] quat,
false, // boolean stretch,
make__pure_tilt, // boolean make__pure_tilt)
y_down_ccw); // boolean y_down_ccw);
double [][] aff2_shrink = QuatUtils.quatToAffine(
quats01[2], // double [] quat,
false, // boolean stretch,
make__pure_tilt, // boolean make__pure_tilt)
y_down_ccw); // boolean y_down_ccw);
double [][] aff2_stretch = QuatUtils.quatToAffine(
quats01[2], // double [] quat,
true, // boolean stretch,
make__pure_tilt, // boolean make__pure_tilt)
y_down_ccw); // boolean y_down_ccw);
*/
double [][] aff1_stretch = QuatUtils.quatToAffine( // use old for stretch
quats01[0], // double [] quat,
true, // boolean stretch,
......@@ -477,11 +617,6 @@ public class OrthoAltitudeMatch {
for (int i = 0; i < svariants.length; i++) {
System.out.println(" qvariant["+i+"] = ["+qvariants[i][0]+ ","+qvariants[i][1]+ ","+qvariants[i][2]+ ","+qvariants[i][3]+ "] scale="+svariants[i]);
/// taffines[i] = QuatUtils.quatToAffine(
/// qvariants[i], // double [] quat,
/// false, // boolean stretch,
/// false, // make__pure_tilt, // boolean make__pure_tilt)
/// y_down_ccw); // boolean y_down_ccw);
taffines[i] = QuatUtils.quatToAffine(
qvariants[i], // double [] quat,
invert_q2a, // boolean invert,
......@@ -494,6 +629,24 @@ public class OrthoAltitudeMatch {
QuatUtils.divideScaled(qa1a_pm[1], qa0_pm[0]),
QuatUtils.divideScaled(qa1a_pm[0], qa0_pm[1]),
QuatUtils.divideScaled(qa1a_pm[1], qa0_pm[1])};
double [][] qvariantsa_diff = new double [qvariantsa.length][2];
for (int i = 0; i < qvariantsa_diff.length; i++) {
qvariantsa_diff[i] = QuatUtils.divideScaled(qvariantsa[i], quat_diff);
}
System.out.println("\n--------------------------------");
System.out.println("quat_diff= "+QuatUtils.toString(quat_diff,use_degrees));
System.out.println();
for (int i = 0; i < qvariantsa.length; i++) {
System.out.println("qvarianta["+i+"] = "+QuatUtils.toString(qvariantsa[i],use_degrees));
}
System.out.println();
for (int i = 0; i < qvariantsa_diff.length; i++) {
System.out.println("qvar_diff["+i+"] = "+QuatUtils.toString(qvariantsa_diff[i],use_degrees));
}
System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
for (int i = 0; i < qvariantsa.length; i++) {
System.out.println("qvarianta["+i+"] = "+QuatUtils.toString(qvariantsa[i],use_degrees));
System.out.println("taffines["+i+"]= [["+taffines[i][0][0]+ ","+taffines[i][0][1]+"]");
......
......@@ -3732,7 +3732,21 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
final double [] weight,
final int width,
final double [] xy0) {
int debug = -1;
return getPlane(
data, // final double [] data,
mask, // final boolean [] mask,
weight, //final double [] weight,
width, // final int width,
xy0, // final double [] xy0,
null); // String dbg_title)
}
public static double [] getPlane(
final double [] data,
final boolean [] mask,
final double [] weight,
final int width,
final double [] xy0,
String dbg_title) {
final double [][][] mdatai = new double [data.length][][];
AtomicInteger anum_good = new AtomicInteger(0);
final Thread[] threads = ImageDtt.newThreadArray();
......@@ -3770,7 +3784,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
null, // damping, // double [] damping, null OK
-1); // debug level
if (approx2d != null) {
if (debug > 0) {
if (dbg_title != null) {
double [] plane=new double[data.length];
double [] diff=new double[data.length];
double [] dweight = (weight != null) ? weight: new double[data.length];
......@@ -3794,7 +3808,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
width,
data.length/width,
true,
"plane_approximation",
dbg_title,
new String[] {"data","approx","diff","masked","weight","mask"});
}
......
......@@ -5204,7 +5204,7 @@ public class OrthoMapsCollection implements Serializable{
boolean flt_update_config = false;
GenericJTabbedDialog gdf = new GenericJTabbedDialog("Select pairs filter/display",800,1100);
GenericJTabbedDialog gdf = new GenericJTabbedDialog("Select pairs filter/display",800,1200);
gdf.addMessage("Filter pairs parameters");
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.");
......@@ -6342,7 +6342,7 @@ public class OrthoMapsCollection implements Serializable{
boolean flt_update_config = false;
boolean select_pairs = false;
GenericJTabbedDialog gdf = new GenericJTabbedDialog("Select pairs filter/display",800,1100);
GenericJTabbedDialog gdf = new GenericJTabbedDialog("Select pairs filter/display",800,1200);
gdf.addMessage("Filter pairs parameters");
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.");
......@@ -6581,7 +6581,7 @@ public class OrthoMapsCollection implements Serializable{
boolean flt_update_config = false;
GenericJTabbedDialog gdf = new GenericJTabbedDialog("Select pairs filter/display",800,1100);
GenericJTabbedDialog gdf = new GenericJTabbedDialog("Select pairs filter/display",800,1200);
gdf.addMessage("Filter pairs parameters");
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.");
......
......@@ -45,7 +45,8 @@ public final class QuatUtils { // static class
String fmt_deg = "[%12.9f, %12.9f,%12.9f, %12.9f], tilt=%12.7f\u00B0, dir=%12.7f\u00B0, scale=%12.10f";
double s = degrees ? (180/Math.PI):1;
String fmt=degrees ? fmt_deg : fmt_rad;
return String.format(fmt, quat[0], quat[1],quat[2],quat[3], s*2*Math.acos(quat[0]), s*Math.atan2(quat[2],quat[1]), scale);
String rslt=String.format(fmt, quat[0], quat[1],quat[2],quat[3], s*2*Math.acos(quat[0]), s*Math.atan2(quat[2],quat[1]), scale);
return rslt;
}
/**
......@@ -300,7 +301,10 @@ public final class QuatUtils { // static class
if (t == 0) {
return UNIT_QUAT;
}
double [] axis = {ty/t,-tx/t,0}; // pi/2 CW
tx/=t;
ty/=t;
double [] axis = {ty,-tx,0}; // pi/2 CW
/* sin (A/2) = +-sqrt((1 - cos(A))/2)
* cos (A/2) = +-sqrt((1 + cos(A))/2)
......@@ -313,6 +317,64 @@ public final class QuatUtils { // static class
return quat;
}
public static String tiltToString (
double [] txy,
boolean y_down_ccw,
boolean degrees) {
String fmt_rad = " tilt= %10.7f, dir=%10.7f";
String fmt_deg = " tilt= %10.5f\u00B0, dir=%10.5f\u00B0";
double k = degrees ? (180/Math.PI):1;
String fmt=degrees ? fmt_deg : fmt_rad;
String s = String.format(" = [%12.9f, %12.9f, %15.9f]", txy[0], txy[1], txy[2]);
double tx = txy[0], ty = y_down_ccw?-txy[1]:txy[1]; // invert y
double t2 = tx*tx + ty*ty;
double t = Math.sqrt(t2);
if (t == 0) {
return s;
}
tx/=t;
ty/=t;
double [] axis = {ty,-tx,0}; // pi/2 CW
double dir = Math.atan2(axis[1],axis[0]);
double tilt = Math.atan(t);
s+= String.format(fmt, k*tilt, k*dir);
return s;
}
public static double [] sceneRelLocalGround(
double [] txy,
double [][] affine, // used for rot and scale Now can be null
boolean y_down_ccw) { // boolean y_down_ccw) for tilts and affine
double [] qtilts = tiltToQuaternion(txy,y_down_ccw);
boolean inv_aff = true; // invert affine
double scale = 1.0;
double rot = 0;
if (affine != null) {
if (inv_aff) {
affine = matInverse2x2(affine);
}
SingularValueDecomposition svd= SingularValueDecomposition.singularValueDecomposeScaleTiltBeta(
affine,
y_down_ccw);
scale = svd.getMaxScale();
rot = svd.getRotAngle(); // TODO: check sign !
}
// Now beta,rot correspond to Y - up
double chalfrot = Math.cos(rot/2);
double shalfrot = Math.sin(rot/2);
double [] qrot = {chalfrot,0,0,shalfrot}; // rotation around vertical axis
double [] qinv_tilts = invert(qtilts); //scene to ground
double [] qrt= multiply(qrot,qinv_tilts);
// double [] quat= scale(multiply(qrot,qinv_tilts),scale);
double [] quat= scale(multiply(qinv_tilts,qrot),scale);
return quat;
}
/**
* Remove rotation around Z-axis, keep only tilt around axis in XY plane
* @param quat_in input rotation that may include rotation around Z (vertical) axis
......@@ -563,7 +625,7 @@ q11 - q22 = c3
*/
public static double [][] affineToQuatScaled (
double [][] affine,
boolean stretch,
boolean stretch,// false
boolean y_down_ccw) {
affine = matInverse2x2(affine);
......
......@@ -29,10 +29,16 @@ public class SingularValueDecomposition {
}
// A = getR1() * getW() getR2() = getR1() * getW() * getIR1() * getRot()
public static double [][] getUnity(){
return new double [][] {{1,0},{0,1}};
}
public double [][] getR1(){ return rotMatrix(beta);}
public double [][] getR2(){ return rotMatrix(gamma);}
public double [][] getIR1(){return rotMatrix(-beta);}
public double [][] getIR1(){return rotMatrix(-beta);} // never used
public double [][] getRot(){return rotMatrix(rot);}
public double [][] getW(){
return new double [][] {{w1,0},{0,w1}};
}
public double getTiltAngle() {
if (ratio <= 1.0) return Math.acos(ratio);
else return Math.acos(1/ratio);
......@@ -46,19 +52,16 @@ public class SingularValueDecomposition {
public String toString(boolean degrees) {
//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 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, 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";
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);
}
public double [][] getW(){
return new double [][] {{w1,0},{0,w1}};
}
/**
* Decomposing linear transform into rotation
* Decomposing linear transform into rotations and scales. OK to use full 2x3 affine
* R1={{cos(beta),sin(beta)},{-sin(beta), cos(beta)}} ,
* non-uniform scale transform W={{w1,0}{0,w2}}, and rotation
* R2={{cos(gamma),sin(gamma)},{-sin(gamma), cos(gamma)}}
......@@ -90,6 +93,64 @@ public class SingularValueDecomposition {
svd.ratio = svd.w2/svd.w1;
return svd;
}
public static double [][] removeTiltRotScale(
double [][] A,
boolean removeTilt,
boolean removeRot,
boolean removeScale,
boolean removeOffset,
boolean max_is_scale) {
SingularValueDecomposition svd = singularValueDecompose(A);
double [][] AR = removeTiltRotScale(
svd, // SingularValueDecomposition svd,
removeTilt, // boolean removeTilt,
removeRot, // boolean removeRot,
removeScale, // boolean removeScale)
max_is_scale); // boolean max_is_scale)
if (A[0].length < 3) {
return AR;
}
A=A.clone();
if (removeOffset) {
for (int i = 0; i < 2; i++) {
A[i][2] = 0;
}
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
A[i][j] = AR[i][j];
}
}
return A;
}
public static double [][] removeTiltRotScale(
SingularValueDecomposition svd,
boolean removeTilt,
boolean removeRot,
boolean removeScale,
boolean max_is_scale) {
double [][] R1 = svd.getR1();
double [][] IR1 = svd.getIR1();
// double [][] W = svd.getW();
double scale = max_is_scale?Math.max(svd.w1,svd.w2):Math.min(svd.w1,svd.w2);
double w1 =svd.w1, w2 = svd.w2;
if (removeScale) {
w1 /= scale;
w2 /= scale;
scale = 1.0;
}
if (removeTilt) {
w1 = scale;
w2 = scale;
}
double [][]W = {{w1,0},{0, w2}};
double [][] R = removeRot? getUnity() : svd.getRot();
double [][] A = QuatUtils.matMult2x2(QuatUtils.matMult2x2(QuatUtils.matMult2x2(R1, W), IR1), R);
return A;
}
public static double [] getMinMaxEigenValues(double [][] A) {
double a00=A[0][0],a01=A[0][1],a10=A[1][0],a11=A[1][1];
......
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