Loading src/main/java/com/elphel/imagej/common/PolynomialApproximation.java +513 −353 Original line number Diff line number Diff line package com.elphel.imagej.common; import java.util.concurrent.atomic.AtomicInteger; import com.elphel.imagej.tileprocessor.ImageDtt; import com.elphel.imagej.tileprocessor.QuadCLT; import Jama.LUDecomposition; import Jama.Matrix; Loading Loading @@ -601,6 +606,161 @@ public class PolynomialApproximation { return norm; } public static double [] getYXRegression( final double [] data_x, final double [] data_y, final boolean [] mask) { final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX); final AtomicInteger ai = new AtomicInteger(0); final double [] as0 = new double[threads.length]; final double [] asx = new double[threads.length]; final double [] asx2 = new double[threads.length]; final double [] asy = new double[threads.length]; final double [] asxy= new double[threads.length]; final AtomicInteger ati = new AtomicInteger(0); ai.set(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int thread_num = ati.getAndIncrement(); for (int ipix = ai.getAndIncrement(); ipix < data_x.length; ipix = ai.getAndIncrement()) if ((mask == null) || mask[ipix]){ double x = data_x[ipix]; double y = data_y[ipix]; if (!Double.isNaN(x) && !Double.isNaN(y)) { as0 [thread_num] += 1; asx [thread_num] += x; asx2[thread_num] += x * x; asy [thread_num] += y; asxy[thread_num] += x * y; } } // for (int ipix } }; } ImageDtt.startAndJoin(threads); double s0 = 0.0; double sx = 0.0; double sx2 = 0.0; double sy = 0.0; double sxy= 0.0; for (int i = 0; i < threads.length; i++) { s0+= as0[i]; sx+= asx[i]; sx2+= asx2[i]; sy+= asy[i]; sxy+= asxy[i]; } double dnm = s0 * sx2 - sx*sx; double a = (sxy * s0 - sy * sx) / dnm; double b = (sy * sx2 - sxy * sx) / dnm; return new double[] {a,b}; } /** * Get best fit ax+b symmetrical for X and Y, same weights * https://en.wikipedia.org/wiki/Deming_regression#Orthogonal_regression * @param data_x * @param data_y * @param mask * @return */ //RuntimeException public static double [] getOrthoRegression( // symmetrical for X and Y, same eror weights final double [] data_x, final double [] data_y, final boolean [] mask_in) { final boolean [] mask = new boolean [data_x.length]; final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX); final AtomicInteger ai = new AtomicInteger(0); final double [] as0 = new double[threads.length]; final double [] asx = new double[threads.length]; final double [] asy = new double[threads.length]; final AtomicInteger ati = new AtomicInteger(0); ai.set(0); // Find centroid first for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int thread_num = ati.getAndIncrement(); for (int ipix = ai.getAndIncrement(); ipix < data_x.length; ipix = ai.getAndIncrement()) if ((mask_in == null) || mask_in[ipix]){ double x = data_x[ipix]; double y = data_y[ipix]; if (!Double.isNaN(x) && !Double.isNaN(y)) { as0 [thread_num] += 1; asx [thread_num] += x; asy [thread_num] += y; mask[ipix] = true; } } // for (int ipix } }; } ImageDtt.startAndJoin(threads); double s0 = 0.0; double sx = 0.0; double sy = 0.0; for (int i = 0; i < threads.length; i++) { s0+= as0[i]; sx+= asx[i]; sy+= asy[i]; } double [] z_mean = {sx/s0, sy/s0}; // complex final double [] as_re = new double[threads.length]; final double [] as_im = new double[threads.length]; ai.set(0); ati.set(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int thread_num = ati.getAndIncrement(); for (int ipix = ai.getAndIncrement(); ipix < data_x.length; ipix = ai.getAndIncrement()) if ((mask == null) || mask[ipix]){ double x = data_x[ipix]-z_mean[0]; double y = data_y[ipix]-z_mean[1]; as_re[thread_num] += x*x - y*y; as_im[thread_num] += 2*x*y; } // for (int ipix } }; } ImageDtt.startAndJoin(threads); double s_re = 0.0; double s_im = 0.0; for (int i = 0; i < threads.length; i++) { s_re+= as_re[i]; s_im+= as_im[i]; } // https://en.wikipedia.org/wiki/Square_root#Algebraic_formula // sqrt (s_re+i*s_im) double sqrt_re = Math.sqrt(0.5 * (Math.sqrt(s_re*s_re + s_im*s_im) +s_re)); double sqrt_im = ((s_im > 0)? 1 : -1) * Math.sqrt(0.5 * (Math.sqrt(s_re*s_re + s_im*s_im) - s_re)); double a = sqrt_im/sqrt_re; double b = z_mean[1]- a * z_mean[0]; return new double[] {a,b}; } public static void applyRegression( final double [] data, // clone by caller final double [] regression) { final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX); final AtomicInteger ai = new AtomicInteger(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { for (int ipix = ai.getAndIncrement(); ipix < data.length; ipix = ai.getAndIncrement()){ data[ipix] = regression[0] * data[ipix] + regression[1]; } } }; } ImageDtt.startAndJoin(threads); } public static double [] invertRegression(double [] regression) { return new double [] {1.0/regression[0], -regression[1]/regression[0]}; } } src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java +6 −3 Original line number Diff line number Diff line Loading @@ -171,7 +171,7 @@ public class ComboMatch { boolean pattern_match = true; // false; boolean bounds_to_indices = true; int temp_mode = 1; int temp_mode = 0; boolean restore_temp = true; double frac_remove = clt_parameters.imp.pmtch_frac_remove; // 0.15; double metric_error = clt_parameters.imp.pmtch_metric_err; // 0.05; // 0.02;// 2 cm Loading Loading @@ -1030,10 +1030,13 @@ 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); // Avoid renderMulti() - it duplicates code renderMultiDouble() int eq_mode = 2; // calculate ImagePlus imp_img_pair = maps_collection.renderMulti ( //_zoom<integer> is needed for opening with "Extract Objects" command title, // String title, OrthoMapsCollection.MODE_IMAGE, // int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask // boolean use_alt, // OrthoMapsCollection.MODE_IMAGE, // int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask // boolean use_alt, eq_mode, //int eq_mode, // 0 - ignore equalization, 1 - use stored equalization, 2 - calculate equalization gpu_pair, // int [] indices, // null or which indices to use (normally just 2 for pairwise comparison) bounds_to_indices, // boolean bounds_to_indices, temp_mode, // int temp_mode, // 0 - do nothing, 1 - equalize average,2 - try to correct Loading src/main/java/com/elphel/imagej/orthomosaic/OrthoMap.java +20 −54 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ public transient double agl = Double.NaN; public transient int num_scenes = -1;; // number of scenes that made up this image public transient double sfm_gain = Double.NaN; // maximal SfM gain of this map public transient double [] equalize = {1,0}; // rectified value = equalize[0]*source_value+equalize[1] private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); oos.writeObject(path); Loading @@ -137,6 +138,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ oos.writeObject(agl); oos.writeObject(num_scenes); oos.writeObject(sfm_gain); oos.writeObject(equalize); } private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { Loading @@ -160,6 +162,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ agl = (double) ois.readObject(); num_scenes = (int) ois.readObject(); sfm_gain = (double) ois.readObject(); // equalize = new double[] {1,0}; equalize = (double []) ois.readObject(); images = new HashMap <Integer, FloatImageData>(); // field images was not saved averageImagePixel = Double.NaN; // average image pixel value (to combine with raw) Loading @@ -167,6 +171,18 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ // pairwise_matches = new HashMap<Double, PairwiseOrthoMatch>(); } double getEqualized(double d) { return d * equalize[0] + equalize[1]; } double [] getEqualize() { return equalize; } void setEqualize(double [] equalize) { this.equalize = equalize; } @Override public int compareTo(OrthoMap otherPlayer) { return Double.compare(ts, otherPlayer.ts); Loading Loading @@ -1717,9 +1733,9 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ }; } ImageDtt.startAndJoin(threads); double [] ab = getDatiRegression( temp, // final double [] temp, dati, // final double [] dati, double [] ab = PolynomialApproximation.getYXRegression( temp, // final double [] data_x, dati, // final double [] data_y, flat); // final boolean [] mask); double a = ab[0]; double b = ab[1]; Loading Loading @@ -1774,56 +1790,6 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ return flat; } private static double [] getDatiRegression( final double [] temp, final double [] dati, final boolean [] mask) { final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX); final AtomicInteger ai = new AtomicInteger(0); final double [] as0 = new double[threads.length]; final double [] asx = new double[threads.length]; final double [] asx2 = new double[threads.length]; final double [] asy = new double[threads.length]; final double [] asxy= new double[threads.length]; final AtomicInteger ati = new AtomicInteger(0); ai.set(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int thread_num = ati.getAndIncrement(); for (int ipix = ai.getAndIncrement(); ipix < temp.length; ipix = ai.getAndIncrement()) if (mask[ipix]){ double x = temp[ipix]; double y = dati[ipix]; if (!Double.isNaN(x+y)) { as0 [thread_num] += 1; asx [thread_num] += x; asx2[thread_num] += x * x; asy [thread_num] += y; asxy[thread_num] += x * y; } } // for (int ipix } }; } ImageDtt.startAndJoin(threads); double s0 = 0.0; double sx = 0.0; double sx2 = 0.0; double sy = 0.0; double sxy= 0.0; for (int i = 0; i < threads.length; i++) { s0+= as0[i]; sx+= asx[i]; sx2+= asx2[i]; sy+= asy[i]; sxy+= asxy[i]; } double dnm = s0 * sx2 - sx*sx; double a = (sxy * s0 - sy * sx) / dnm; double b = (sy * sx2 - sxy * sx) / dnm; return new double[] {a,b}; } private static int [][] getCirclePoints( double radius) { Loading Loading
src/main/java/com/elphel/imagej/common/PolynomialApproximation.java +513 −353 Original line number Diff line number Diff line package com.elphel.imagej.common; import java.util.concurrent.atomic.AtomicInteger; import com.elphel.imagej.tileprocessor.ImageDtt; import com.elphel.imagej.tileprocessor.QuadCLT; import Jama.LUDecomposition; import Jama.Matrix; Loading Loading @@ -601,6 +606,161 @@ public class PolynomialApproximation { return norm; } public static double [] getYXRegression( final double [] data_x, final double [] data_y, final boolean [] mask) { final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX); final AtomicInteger ai = new AtomicInteger(0); final double [] as0 = new double[threads.length]; final double [] asx = new double[threads.length]; final double [] asx2 = new double[threads.length]; final double [] asy = new double[threads.length]; final double [] asxy= new double[threads.length]; final AtomicInteger ati = new AtomicInteger(0); ai.set(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int thread_num = ati.getAndIncrement(); for (int ipix = ai.getAndIncrement(); ipix < data_x.length; ipix = ai.getAndIncrement()) if ((mask == null) || mask[ipix]){ double x = data_x[ipix]; double y = data_y[ipix]; if (!Double.isNaN(x) && !Double.isNaN(y)) { as0 [thread_num] += 1; asx [thread_num] += x; asx2[thread_num] += x * x; asy [thread_num] += y; asxy[thread_num] += x * y; } } // for (int ipix } }; } ImageDtt.startAndJoin(threads); double s0 = 0.0; double sx = 0.0; double sx2 = 0.0; double sy = 0.0; double sxy= 0.0; for (int i = 0; i < threads.length; i++) { s0+= as0[i]; sx+= asx[i]; sx2+= asx2[i]; sy+= asy[i]; sxy+= asxy[i]; } double dnm = s0 * sx2 - sx*sx; double a = (sxy * s0 - sy * sx) / dnm; double b = (sy * sx2 - sxy * sx) / dnm; return new double[] {a,b}; } /** * Get best fit ax+b symmetrical for X and Y, same weights * https://en.wikipedia.org/wiki/Deming_regression#Orthogonal_regression * @param data_x * @param data_y * @param mask * @return */ //RuntimeException public static double [] getOrthoRegression( // symmetrical for X and Y, same eror weights final double [] data_x, final double [] data_y, final boolean [] mask_in) { final boolean [] mask = new boolean [data_x.length]; final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX); final AtomicInteger ai = new AtomicInteger(0); final double [] as0 = new double[threads.length]; final double [] asx = new double[threads.length]; final double [] asy = new double[threads.length]; final AtomicInteger ati = new AtomicInteger(0); ai.set(0); // Find centroid first for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int thread_num = ati.getAndIncrement(); for (int ipix = ai.getAndIncrement(); ipix < data_x.length; ipix = ai.getAndIncrement()) if ((mask_in == null) || mask_in[ipix]){ double x = data_x[ipix]; double y = data_y[ipix]; if (!Double.isNaN(x) && !Double.isNaN(y)) { as0 [thread_num] += 1; asx [thread_num] += x; asy [thread_num] += y; mask[ipix] = true; } } // for (int ipix } }; } ImageDtt.startAndJoin(threads); double s0 = 0.0; double sx = 0.0; double sy = 0.0; for (int i = 0; i < threads.length; i++) { s0+= as0[i]; sx+= asx[i]; sy+= asy[i]; } double [] z_mean = {sx/s0, sy/s0}; // complex final double [] as_re = new double[threads.length]; final double [] as_im = new double[threads.length]; ai.set(0); ati.set(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int thread_num = ati.getAndIncrement(); for (int ipix = ai.getAndIncrement(); ipix < data_x.length; ipix = ai.getAndIncrement()) if ((mask == null) || mask[ipix]){ double x = data_x[ipix]-z_mean[0]; double y = data_y[ipix]-z_mean[1]; as_re[thread_num] += x*x - y*y; as_im[thread_num] += 2*x*y; } // for (int ipix } }; } ImageDtt.startAndJoin(threads); double s_re = 0.0; double s_im = 0.0; for (int i = 0; i < threads.length; i++) { s_re+= as_re[i]; s_im+= as_im[i]; } // https://en.wikipedia.org/wiki/Square_root#Algebraic_formula // sqrt (s_re+i*s_im) double sqrt_re = Math.sqrt(0.5 * (Math.sqrt(s_re*s_re + s_im*s_im) +s_re)); double sqrt_im = ((s_im > 0)? 1 : -1) * Math.sqrt(0.5 * (Math.sqrt(s_re*s_re + s_im*s_im) - s_re)); double a = sqrt_im/sqrt_re; double b = z_mean[1]- a * z_mean[0]; return new double[] {a,b}; } public static void applyRegression( final double [] data, // clone by caller final double [] regression) { final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX); final AtomicInteger ai = new AtomicInteger(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { for (int ipix = ai.getAndIncrement(); ipix < data.length; ipix = ai.getAndIncrement()){ data[ipix] = regression[0] * data[ipix] + regression[1]; } } }; } ImageDtt.startAndJoin(threads); } public static double [] invertRegression(double [] regression) { return new double [] {1.0/regression[0], -regression[1]/regression[0]}; } }
src/main/java/com/elphel/imagej/orthomosaic/ComboMatch.java +6 −3 Original line number Diff line number Diff line Loading @@ -171,7 +171,7 @@ public class ComboMatch { boolean pattern_match = true; // false; boolean bounds_to_indices = true; int temp_mode = 1; int temp_mode = 0; boolean restore_temp = true; double frac_remove = clt_parameters.imp.pmtch_frac_remove; // 0.15; double metric_error = clt_parameters.imp.pmtch_metric_err; // 0.05; // 0.02;// 2 cm Loading Loading @@ -1030,10 +1030,13 @@ 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); // Avoid renderMulti() - it duplicates code renderMultiDouble() int eq_mode = 2; // calculate ImagePlus imp_img_pair = maps_collection.renderMulti ( //_zoom<integer> is needed for opening with "Extract Objects" command title, // String title, OrthoMapsCollection.MODE_IMAGE, // int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask // boolean use_alt, // OrthoMapsCollection.MODE_IMAGE, // int mode, // 0 - regular image, 1 - altitudes, 2 - black/white mask // boolean use_alt, eq_mode, //int eq_mode, // 0 - ignore equalization, 1 - use stored equalization, 2 - calculate equalization gpu_pair, // int [] indices, // null or which indices to use (normally just 2 for pairwise comparison) bounds_to_indices, // boolean bounds_to_indices, temp_mode, // int temp_mode, // 0 - do nothing, 1 - equalize average,2 - try to correct Loading
src/main/java/com/elphel/imagej/orthomosaic/OrthoMap.java +20 −54 Original line number Diff line number Diff line Loading @@ -115,6 +115,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ public transient double agl = Double.NaN; public transient int num_scenes = -1;; // number of scenes that made up this image public transient double sfm_gain = Double.NaN; // maximal SfM gain of this map public transient double [] equalize = {1,0}; // rectified value = equalize[0]*source_value+equalize[1] private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); oos.writeObject(path); Loading @@ -137,6 +138,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ oos.writeObject(agl); oos.writeObject(num_scenes); oos.writeObject(sfm_gain); oos.writeObject(equalize); } private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { Loading @@ -160,6 +162,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ agl = (double) ois.readObject(); num_scenes = (int) ois.readObject(); sfm_gain = (double) ois.readObject(); // equalize = new double[] {1,0}; equalize = (double []) ois.readObject(); images = new HashMap <Integer, FloatImageData>(); // field images was not saved averageImagePixel = Double.NaN; // average image pixel value (to combine with raw) Loading @@ -167,6 +171,18 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ // pairwise_matches = new HashMap<Double, PairwiseOrthoMatch>(); } double getEqualized(double d) { return d * equalize[0] + equalize[1]; } double [] getEqualize() { return equalize; } void setEqualize(double [] equalize) { this.equalize = equalize; } @Override public int compareTo(OrthoMap otherPlayer) { return Double.compare(ts, otherPlayer.ts); Loading Loading @@ -1717,9 +1733,9 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ }; } ImageDtt.startAndJoin(threads); double [] ab = getDatiRegression( temp, // final double [] temp, dati, // final double [] dati, double [] ab = PolynomialApproximation.getYXRegression( temp, // final double [] data_x, dati, // final double [] data_y, flat); // final boolean [] mask); double a = ab[0]; double b = ab[1]; Loading Loading @@ -1774,56 +1790,6 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{ return flat; } private static double [] getDatiRegression( final double [] temp, final double [] dati, final boolean [] mask) { final Thread[] threads = ImageDtt.newThreadArray(QuadCLT.THREADS_MAX); final AtomicInteger ai = new AtomicInteger(0); final double [] as0 = new double[threads.length]; final double [] asx = new double[threads.length]; final double [] asx2 = new double[threads.length]; final double [] asy = new double[threads.length]; final double [] asxy= new double[threads.length]; final AtomicInteger ati = new AtomicInteger(0); ai.set(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { int thread_num = ati.getAndIncrement(); for (int ipix = ai.getAndIncrement(); ipix < temp.length; ipix = ai.getAndIncrement()) if (mask[ipix]){ double x = temp[ipix]; double y = dati[ipix]; if (!Double.isNaN(x+y)) { as0 [thread_num] += 1; asx [thread_num] += x; asx2[thread_num] += x * x; asy [thread_num] += y; asxy[thread_num] += x * y; } } // for (int ipix } }; } ImageDtt.startAndJoin(threads); double s0 = 0.0; double sx = 0.0; double sx2 = 0.0; double sy = 0.0; double sxy= 0.0; for (int i = 0; i < threads.length; i++) { s0+= as0[i]; sx+= asx[i]; sx2+= asx2[i]; sy+= asy[i]; sxy+= asxy[i]; } double dnm = s0 * sx2 - sx*sx; double a = (sxy * s0 - sy * sx) / dnm; double b = (sy * sx2 - sxy * sx) / dnm; return new double[] {a,b}; } private static int [][] getCirclePoints( double radius) { Loading