Commit 7ad0875e authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Matching altitudes

parent 1cc6d251
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ public class DoubleGaussianBlur {
	 * @param extraLines Number of lines (parallel to the blurring direction)
	 *                  below and above the roi bounds that should be processed.
	 */
	// TODO: Make threaded!
	public void blur1Direction(double [] pixels,
			int        width,
			int       height,
+127 −3
Original line number Diff line number Diff line
@@ -11,6 +11,8 @@ import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Properties;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
@@ -27,6 +29,7 @@ import com.elphel.imagej.gpu.TpTask;
import com.elphel.imagej.ims.Imx5;
import com.elphel.imagej.readers.ElphelTiffReader;
import com.elphel.imagej.tileprocessor.ImageDtt;
import com.elphel.imagej.tileprocessor.IntersceneMatchParameters;
import com.elphel.imagej.tileprocessor.OpticalFlow;
import com.elphel.imagej.tileprocessor.QuadCLT;
import com.elphel.imagej.tileprocessor.TDCorrTile;
@@ -166,10 +169,13 @@ public class ComboMatch {
		boolean create_pairwise_affines =  false;
		boolean augment_pairwise_affines = false; // needs to repeat create_pairwise_matches to update overlaps
		boolean equalize_overlaps =        false;
		boolean altitude_match_pairs =     false;
		boolean display_pairs =            false;
		boolean create_map =               false;
		boolean create_equalize =          false;
		
		
		
		boolean use_saved_collection = true; // false;
		boolean save_collection =     true;
		boolean process_correlation = true; // use false to save new version of data
@@ -187,6 +193,7 @@ public class ComboMatch {
		boolean update_lla =          false; // re-read file metadata
		boolean update_kernel_patterns = false;
		boolean update_bl_bc =        false;
		boolean fix_duplicates =      false;
		String [] suffixes_bl_bc=     {"","-BL","-BC"};
		boolean log_append =           clt_parameters.imp.pwise_log_append;
		String log_path =              clt_parameters.imp.pwise_log_path;
@@ -232,6 +239,8 @@ public class ComboMatch {
		gd.addCheckbox    ("Create pairwise affines",          create_pairwise_affines, "Create affines for scene pairs.");
		gd.addCheckbox    ("Augment pairwise affines",         augment_pairwise_affines, "Augment pairwise affines after building initial map and re-running create_pairwise_matches.");
		gd.addCheckbox    ("Equalize overlap pairs",           equalize_overlaps, "Equalize intensities in overlaps.");
		gd.addCheckbox    ("Altitude match pairs",             altitude_match_pairs, "Pairwise match scenes altitude.");
		gd.addCheckbox    ("Display pairs",                    display_pairs, "Display pairwise match data.");
		gd.addCheckbox    ("Create map",                       create_map, "Create combined map from pairwise matches.");
		gd.addCheckbox    ("Equalize intensities",             create_equalize, "Create map intensities equalization from pairwise matches.");
		gd.addNumericField("Remove fraction of worst matches",   frac_remove,  3,7,"",	"When fitting scenes remove this fraction of worst match.");
@@ -241,6 +250,8 @@ public class ComboMatch {
		}
		gd.addCheckbox    ("Update files metadata",     update_lla, "Re-read files metadata (if it was modified)");
		gd.addCheckbox    ("Update kernels/patterns",   update_kernel_patterns, "Re-read kernels and patterns from *.list file");
		gd.addCheckbox    ("Remove duplicate scenes",   fix_duplicates, "Remove scenes with the same timestamp");
		
		gd.addCheckbox    ("Update BC/BL suffix",       update_bl_bc,
				"Change source filenames to use -BC for bicubic, -BL - for bilinear, or empty - for old bilinear files");
		gd.addChoice("BL/BC suffix:",        
@@ -284,6 +295,8 @@ public class ComboMatch {
		create_pairwise_affines =   gd.getNextBoolean();
		augment_pairwise_affines =  gd.getNextBoolean();
		equalize_overlaps =         gd.getNextBoolean();
		altitude_match_pairs =      gd.getNextBoolean();
		display_pairs =             gd.getNextBoolean();
		create_map =                gd.getNextBoolean();
		create_equalize =           gd.getNextBoolean();
		frac_remove =               gd.getNextNumber();
@@ -293,6 +306,7 @@ public class ComboMatch {
		}
		update_lla=                 gd.getNextBoolean();
		update_kernel_patterns=     gd.getNextBoolean();
		fix_duplicates=             gd.getNextBoolean();
		update_bl_bc=               gd.getNextBoolean();
		suffix_bc_bl_indx =         gd.getNextChoiceIndex();
		log_append =                gd.getNextBoolean();
@@ -325,6 +339,9 @@ public class ComboMatch {
			maps_collection.updateNumberScenes();
			maps_collection.updateSfmGain();
		}
		if (fix_duplicates) {
			removeDuplicateScenes (maps_collection);
		}
		
		if (update_bl_bc) {
			boolean OK = updateBlBcFileNames(
@@ -826,6 +843,19 @@ public class ComboMatch {
			return ok; // Just exit, do not try other commands.  if (!ok) return false;
		}
		
		if (altitude_match_pairs) {
			boolean ok =maps_collection.altutudeMatchPairs(
					clt_parameters, // CLTParameters    clt_parameters,
					orthoMapsCollection_savepath); // String orthoMapsCollection_path);
			return ok; // Just exit, do not try other commands.  if (!ok) return false;
		}
		
		if (display_pairs) {
			boolean ok =maps_collection.displayScenePairs(
					clt_parameters, // CLTParameters    clt_parameters,
					orthoMapsCollection_savepath); // String orthoMapsCollection_path);
			return ok; // Just exit, do not try other commands.  if (!ok) return false;
		}
        if (process_correlation || render_match || pattern_match || test_multi_lma) {
//        	int [] gpu_pair;
        	if (gpu_spair == null) {
@@ -864,11 +894,15 @@ public class ComboMatch {
				boolean flt_filt_zoom =      clt_parameters.imp.flt_filt_zoom;     //  true;
				int     flt_min_zoom =       clt_parameters.imp.flt_min_zoom;      // -2;
				int     flt_max_zoom =       clt_parameters.imp.flt_max_zoom;      // 10;
        		double  flt_min_sfm =        clt_parameters.imp.flt_min_sfm;       //  0.0;
        		double  flt_max_sfm =        clt_parameters.imp.flt_max_sfm;       //1000.0;
				int     flt_alt =            clt_parameters.imp.flt_alt;           // 0;
        		
        		boolean flt_show_names =     clt_parameters.imp.flt_show_names;    //  true;
        		boolean flt_show_overlaps =  clt_parameters.imp.flt_show_overlaps; //  true;
        		boolean flt_show_rms =       clt_parameters.imp.flt_show_rms;      //  true;
        		boolean flt_show_zoom =      clt_parameters.imp.flt_show_zoom;     //  true;
        		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);
@@ -882,11 +916,16 @@ public class ComboMatch {
				gdf.addCheckbox    ("Filter by zoom level"  ,      flt_filt_zoom, "Filter by the zoom level used for matching.");
				gdf.addNumericField("Minimal zoom",                flt_min_zoom, 0,3,"","Minimal zoom level used for matching.");
				gdf.addNumericField("Maximal zoom",                flt_max_zoom, 0,3,"","Maximal zoom level used for matching.");
				gdf.addNumericField("Minimal SfM gain",            flt_min_sfm,  3,7,"","Minimal SfM gain of the minimum in the scene pair.");
				gdf.addNumericField("Maximal SfM gain",            flt_max_sfm,  3,7,"","Maximal SfM gain of the minimum in the scene pair.");
				gdf. addChoice("Filter by pairwise ALT availability",IntersceneMatchParameters.FLT_ALT_MODES, IntersceneMatchParameters.FLT_ALT_MODES[flt_alt],
						"Filter by pairwise ALT availability.");
				
				gdf.addCheckbox    ("Show scene names",            flt_show_names, "Show scene full names (timestamps) in selection drop-down list.");
				gdf.addCheckbox    ("Show scene overlaps",         flt_show_overlaps, "Show scene overlaps (in percents) in selection drop-down list.");
				gdf.addCheckbox    ("Show pairs RMSE",             flt_show_rms, "Show scene match RMSE in selection drop-down list.");
				gdf.addCheckbox    ("Show zoom level",             flt_show_zoom, "Show zoom level.");
				gdf.addCheckbox    ("Show ALT",                    flt_show_alt,  "Show altitude data availability.");
				
				gdf.addCheckbox    ("Update configuration",        flt_update_config, "Update matching configuration parameters to be saved as defaults.");
				gdf.showDialog();
@@ -901,11 +940,15 @@ public class ComboMatch {
		        flt_filt_zoom     = gdf.getNextBoolean();
		        flt_min_zoom =(int) gdf.getNextNumber(); 
		        flt_max_zoom =(int) gdf.getNextNumber(); 
		        flt_min_sfm       = gdf.getNextNumber();
		        flt_max_sfm       = gdf.getNextNumber();
		        flt_alt           = gdf.getNextChoiceIndex();

				flt_show_names    = gdf.getNextBoolean();
				flt_show_overlaps = gdf.getNextBoolean();
				flt_show_rms      = gdf.getNextBoolean();
				flt_show_zoom  =    gdf.getNextBoolean();				
				flt_show_alt  =     gdf.getNextBoolean();				
				flt_update_config = gdf.getNextBoolean();
				if (flt_update_config) {
					clt_parameters.imp.flt_list =          flt_list;
@@ -918,10 +961,14 @@ public class ComboMatch {
					clt_parameters.imp.flt_filt_zoom =     flt_filt_zoom;
					clt_parameters.imp.flt_min_zoom =      flt_min_zoom;
					clt_parameters.imp.flt_max_zoom =      flt_max_zoom;
	        		clt_parameters.imp.flt_min_sfm =       flt_min_sfm;
	        		clt_parameters.imp.flt_max_sfm =       flt_max_sfm;
					clt_parameters.imp.flt_alt =           flt_alt;					
					clt_parameters.imp.flt_show_names =    flt_show_names;
					clt_parameters.imp.flt_show_overlaps = flt_show_overlaps;
					clt_parameters.imp.flt_show_rms =      flt_show_rms;
					clt_parameters.imp.flt_show_zoom =     flt_show_zoom;
					clt_parameters.imp.flt_show_alt =      flt_show_alt;
				}

				if (flt_list) {
@@ -935,7 +982,11 @@ public class ComboMatch {
							flt_nan_rms,     // boolean  nan_rms)
							flt_filt_zoom,   // boolean          filt_zoom,
							flt_min_zoom,    // int              min_zoom,
							flt_max_zoom);   // int              max_zoom)
							flt_max_zoom,    // int              max_zoom)
							flt_min_sfm,     // double           min_sfm,
							flt_max_sfm,     // double           max_sfm,
							flt_alt);        // int               flt_alt)

				}
				
				String [] choices_all = maps_collection.textPairs (
@@ -944,6 +995,8 @@ public class ComboMatch {
						flt_show_overlaps, // boolean          show_overlap,
						flt_show_rms,      // boolean          show_rms,
						flt_show_zoom,     // boolean          show_zoom,
						flt_show_alt,      // boolean          show_alt,
						false,             // boolean          use_tab,
						flt_extra_line);   // String           extra_line)
				
				GenericJTabbedDialog gdc = new GenericJTabbedDialog("Select image pair",1200,100);
@@ -1399,6 +1452,77 @@ public class ComboMatch {
		return pairwiseOrthoMatch;
	}
	
	public static boolean removeDuplicateScenes(
			OrthoMapsCollection maps_collection) {
		String duplicate_name=null;
		do {
			HashSet<String> scene_names = new HashSet<String>();
			duplicate_name=null;
			for (int i = 0; i < maps_collection.ortho_maps.length; i++) {
				String name = maps_collection.ortho_maps[i].getName();
				if (scene_names.contains(name)) {
					duplicate_name=name;
					break;
				}
				scene_names.add(name);
			}
			if (duplicate_name != null) {
				long latest_modified = -1;
				int latest_index = -1;
				ArrayList<Integer> duplicates = new ArrayList<Integer>();
				for (int i = 0; i < maps_collection.ortho_maps.length; i++) {
					if (maps_collection.ortho_maps[i].getName().equals(duplicate_name)) {
						duplicates.add(i);
						long mod_ts = (new File(maps_collection.ortho_maps[i].getPath())).lastModified();
						if (mod_ts > latest_modified) {
							latest_index = i;
						}
					}
				}
				if (duplicates.size()> 1) {
					System.out.println("removeDuplicateScenes(): found " +duplicates.size()+ " duplicates for scene "+duplicate_name+":");
					for (int i :duplicates) {
						System.out.println(((i==latest_index)?"  KEEP ":"REMOVE ")+maps_collection.ortho_maps[i].getPath());
					}
					
					// combine pairwise matches, remove self-paired
					HashMap <String, PairwiseOrthoMatch>        combo_pairwise_matches = new HashMap <String, PairwiseOrthoMatch>();
					OrthoMap [] new_maps = new OrthoMap[maps_collection.ortho_maps.length-duplicates.size()+1];
					int indx = 0;
					int new_indx = -1;
					for (int i = 0; i < maps_collection.ortho_maps.length; i++) {
						if (duplicates.contains(i)) {
							for (String key:maps_collection.ortho_maps[i].pairwise_matches.keySet()) {
								if (!key.equals(duplicate_name) && !combo_pairwise_matches.containsKey(key)) {
									combo_pairwise_matches.put(key, maps_collection.ortho_maps[i].pairwise_matches.get(key));
								}
							}
						}
						if (!duplicates.contains(i) || (i == latest_index)) {
							
							if (i == latest_index) {
								new_indx = indx;
							}
							new_maps[indx++] = maps_collection.ortho_maps[i];
						}
					}
					maps_collection.ortho_maps = new_maps;
					maps_collection.ortho_maps[new_indx].pairwise_matches = combo_pairwise_matches;
					// remove pairs with (now) itself 
				} else {
					System.out.println("removeDuplicateScenes(): BUG - number of duplicates = "+duplicates.size()+", aborting.");
					return false;
				}
				// find latest file
			}
			
		} while (duplicate_name != null);
		maps_collection.reindex();
		return true;
	}
	

	
	public static boolean updateBlBcFileNames(
			String suffix,
			String before,
+308 −0

File added.

Preview size limit exceeded, changes collapsed.

+292 −2
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import java.util.concurrent.atomic.AtomicInteger;

import com.elphel.imagej.cameras.CLTParameters;
import com.elphel.imagej.common.DoubleFHT;
import com.elphel.imagej.common.DoubleGaussianBlur;
import com.elphel.imagej.common.GenericJTabbedDialog;
import com.elphel.imagej.common.PolynomialApproximation;
import com.elphel.imagej.common.ShowDoubleFloatArrays;
@@ -3468,6 +3469,141 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
		return mask;
	}

	/**
	 * Remove specified fractions (0 <= (rlow+rhigh) <= 1.0) of too low  and too high values 
	 * @param data double [] input data
	 * @param mask_in optional (may be null) mask for the data array. Will be modified if provided.
	 * @param abs_dif high limit of the histogram (reasonably higher than useful range of the data[])
	 * @param rel_frac fraction of the highest data[] elements to remove
	 * @param ground_plane null or {tilt_x, tilt_y, offs, x0,y0}, where tilt_x and tilt_y are per pixel.
	 *                     x0, y0 are also in pixels (not meters)
	 * @param width - width of the data[] array. Only used if ground_plane != null                     
	 * @param num_bins number of the histogram bins
	 * @return boolean array of the remaining data elements. Input mask_in array (if not null) is modified too.
	 */
	public static boolean [] removeRelativeLowHigh (
			final double [] data,
			final boolean [] mask_in,
			final double abs_diff,
			final double rel_frac,
			final double []  ground_plane, // tiltx,tilty, offs, x0(pix), y0(pix) or null
			final int     width, // only used with ground_plane != null;
			final int    num_bins) {
		final boolean [] mask = (mask_in == null) ? new boolean [data.length] : mask_in;
		if (mask_in == null) {
			Arrays.fill(mask, true);
		}
		final Thread[] threads = ImageDtt.newThreadArray();
		final AtomicInteger ai = new AtomicInteger(0);
		final AtomicInteger ati = new AtomicInteger(0);
		final double [][] hist2 = new double [threads.length][num_bins];
		final double scale = num_bins/abs_diff;
		for (int ithread = 0; ithread < threads.length; ithread++) {
			threads[ithread] = new Thread() {
				public void run() {
					int thread_num = ati.getAndIncrement();
					for (int nPix = ai.getAndIncrement(); nPix < data.length; nPix = ai.getAndIncrement()) if (mask[nPix]){
						double d = data[nPix];
						if (!Double.isNaN(d)) {
							if (ground_plane != null) {
								double x = nPix % width - ground_plane[3];
								double y = nPix/width - ground_plane[4];
								double tilt_x = ground_plane[0];
								double tilt_y = ground_plane[1];
								double offs = ground_plane[2];
								d -= x * tilt_x + y * tilt_y + offs;
							}
							int bin = Math.min(Math.max(((int) Math.round(Math.abs(d)*scale)), 0), num_bins-1);
							hist2[thread_num][bin] += 1.0; 
						}
					}
				}
			};
		}		      
		ImageDtt.startAndJoin(threads);
		ai.set(0);
		final double [] hist =    new double [num_bins];
		for (int ithread = 0; ithread < threads.length; ithread++) {
			threads[ithread] = new Thread() {
				public void run() {
					for (int bin = ai.getAndIncrement(); bin < num_bins; bin = ai.getAndIncrement()) {
						for (int i = 0; i < hist2.length; i++) {
							hist[bin]+= hist2[i][bin];
						}
					}
				}
			};
		}		      
		ImageDtt.startAndJoin(threads);
		double sw = 0;
		for (int bin = 0; bin < num_bins; bin++) {
			sw += hist[bin];
		}
//		double trlow = sw * rlow;
		double trhigh = sw * rel_frac; // rhigh;
		double sh = 0, shp = 0;
		double threshold_high = abs_diff; // abs_high;
		for (int bin = num_bins-1; bin>=0; bin--) {
			shp = sh;
			sh += hist[bin];
			if (sh > trhigh) {
				double r = (sh-trhigh)/(sh-shp);
				threshold_high = (bin + r)/scale; // abs_low + (bin + r)/scale;
				break;
			}
		}
		sh = 0; 
		shp = 0;
		/*
		double threshold_low = abs_low;
		for (int bin = 0; bin < num_bins; bin++) {
			shp = sh;
			sh += hist[bin];
			if (sh > trlow) {
				double r = (trlow-shp)/(sh-shp);
				threshold_low = abs_low + (bin + r)/scale;
				break;
			}
		}
		final double fthreshold_low = threshold_low;
		*/
		final double fthreshold_high = threshold_high;
		if (ground_plane == null) {
			return removeAbsoluteLowHigh (
					data,           // final double [] data,
					mask,           // final boolean [] mask,
					fthreshold_high,  // final double threshold_high,
					-fthreshold_high); // fthreshold_low); // final double threshold_low)
		}
		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 nPix = ai.getAndIncrement(); nPix < data.length; nPix = ai.getAndIncrement()) if (mask[nPix]){
						double d = data[nPix];
						if (!Double.isNaN(d)) {
							double x = nPix % width - ground_plane[3];
							double y = nPix/width - ground_plane[4];
							double tilt_x = ground_plane[0];
							double tilt_y = ground_plane[1];
							double offs = ground_plane[2];
							d -= x * tilt_x + y * tilt_y + offs;
//							if (!((d >= fthreshold_low) && (d <= fthreshold_high))) {
							if (!((d >= -fthreshold_high) && (d <= fthreshold_high))) {
								mask[nPix] = false;
							}
						}
					}
				}
			};
		}		      
		ImageDtt.startAndJoin(threads);
		return mask;
	}
	
	
	
	/**
	 * Remove (mask out) tiles that have high product of distance (in pixels) from the vertical point
	 * by the metric difference between the elevation and an approximation plane 
@@ -3523,6 +3659,50 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
		return mask;
	}
	
	public static double [] getBorderWeights(
			final double []  data,
			final double     sigma,
			int              width) {
		double [] weights = new double [data.length];
		final Thread[] threads = ImageDtt.newThreadArray();
		final AtomicInteger ai = new AtomicInteger(0);
		for (int ithread = 0; ithread < threads.length; ithread++) {
			threads[ithread] = new Thread() {
				public void run() {
					for (int nPix = ai.getAndIncrement(); nPix < data.length; nPix = ai.getAndIncrement()){
						weights[nPix] = Double.isNaN(data[nPix])? -1:1;
					}
				}
			};
		}		      
		ImageDtt.startAndJoin(threads);
		
		// TODO: Make threaded !
		(new DoubleGaussianBlur()).blurDouble(
				weights,              // double[] pixels,
				width,                // int width,
				weights.length/width, // int height,
				sigma,                // double sigmaX,
				sigma,                // double sigmaY,
				0.01);                // double accuracy);
		ai.set(0);
		for (int ithread = 0; ithread < threads.length; ithread++) {
			threads[ithread] = new Thread() {
				public void run() {
					for (int nPix = ai.getAndIncrement(); nPix < data.length; nPix = ai.getAndIncrement()){
						if (weights[nPix] < 0) {
							weights[nPix] = 0;
						}
					}
				}
			};
		}		      
		ImageDtt.startAndJoin(threads);
		return weights;
	}
	
	
	
	
	
	/**
@@ -3534,12 +3714,13 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
	 * @param xy0    a pair of x0, y0 - origin where the plane is referenced too
	 * @return double array of {tiltx, tilty, offset, xy0[0] and xy0[1]).
	 */
	private static double [] getPlane(
	public static double [] getPlane(
			final double []   data,
			final boolean [] mask,
			final double []  weight,
			final int        width,
			final double []  xy0) {
		int debug = -1;
		final double [][][] mdatai = new double [data.length][][];
		AtomicInteger anum_good = new AtomicInteger(0);
		final Thread[] threads = ImageDtt.newThreadArray();
@@ -3547,7 +3728,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
		for (int ithread = 0; ithread < threads.length; ithread++) {
			threads[ithread] = new Thread() {
				public void run() {
					for (int nPix = ai.getAndIncrement(); nPix < data.length; nPix = ai.getAndIncrement()) if (mask[nPix]){
					for (int nPix = ai.getAndIncrement(); nPix < data.length; nPix = ai.getAndIncrement()) if ((mask == null) || mask[nPix]){
						double d = data[nPix];
						if (!Double.isNaN(d)) {
							int x = nPix % width;  
@@ -3577,11 +3758,40 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
				null,       // damping,    // double [] damping, null OK
				-1);        // debug level
		if (approx2d != null) {
			if (debug > 0) {
				double [] plane=new double[data.length];
				double [] diff=new double[data.length];
				double [] dweight = (weight != null) ? weight: new double[data.length];
				double [] dmask =   new double[data.length];
				double [] masked = new double[data.length];
				Arrays.fill(masked, Double.NaN);
				for (int nPix = 0; nPix < plane.length; nPix++) {
					int x = nPix % width;  
					int y = nPix / width;
					double dx = x-xy0[0];
					double dy = y-xy0[1];
					plane[nPix] = approx2d[0][2]+approx2d[0][0]*dx+approx2d[0][1]*dy;
					diff[nPix] = data[nPix]-plane[nPix];
					dmask[nPix] = ((mask == null) || Double.isNaN(data[nPix]))? Double.NaN : (mask[nPix]?2:1);
					if ((mask == null) || mask[nPix]) {
						masked[nPix] = diff[nPix];
					}
				}
				ShowDoubleFloatArrays.showArrays(
						new double[][] {data,plane,diff,masked,dweight,dmask},
						width,
						data.length/width,
						true,
						"plane_approximation",
						new String[] {"data","approx","diff","masked","weight","mask"});
			}
			
			return new double[] {approx2d[0][0], approx2d[0][1], approx2d[0][2], xy0[0], xy0[1]}; // tiltX, tiltY, offset
		}
		return null;
	}
	
	
	/**
	 * Trying to estimate image OTF to modify correlation results. Some images are better, some - worse
	 * (blurred because of elevation errors)? For all image or parts of it? So on some images all
@@ -5359,6 +5569,86 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
		return new double [] {beta, s,t, g_p_b};
	}
	
	public static Rectangle getDefinedBounds(
			final double [][] data_slices,
			final int width) { // null or same length as data_slices[i]
		final int height = data_slices[0].length/width;
		final Thread[] threads = ImageDtt.newThreadArray();
		final AtomicInteger ai = new AtomicInteger(0);
		final AtomicInteger ati = new AtomicInteger(0);
		final int [][][] bounds =  new int [threads.length][2][2]; // [thread][x/y][min/max]
		for (int i = 0; i < bounds.length; i++) {
			bounds[i][0][0] = width; // min x
			bounds[i][1][0] = height;// min y
			bounds[i][0][1] = -1;    // max x
			bounds[i][1][1] = -1;    // max y
		}
		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_slices[0].length; ipix = ai.getAndIncrement()) {
						pix_loop: {
							for (int i = 0; i < data_slices.length; i++) {
								if (Double.isNaN(data_slices[i][ipix])) {
									break pix_loop;
								}
							}
							int px = ipix % width;
							int py = ipix / width;
							if (px < bounds[thread_num][0][0]) bounds[thread_num][0][0] = px; 
							if (px > bounds[thread_num][0][1]) bounds[thread_num][0][1] = px; 
							if (py < bounds[thread_num][1][0]) bounds[thread_num][1][0] = py; 
							if (py > bounds[thread_num][1][1]) bounds[thread_num][1][1] = py; 
						}
					}
				}
			};
		}		      
		ImageDtt.startAndJoin(threads);
		for (int i = 1; i < bounds.length; i++) {
			for (int j = 0; j < 2; j++) {
				bounds [0][j][0] = Math.min(bounds [0][j][0], bounds [i][j][0]);
				bounds [0][j][1] = Math.max(bounds [0][j][1], bounds [i][j][1]);
			}
		}
		Rectangle rbounds = new Rectangle(
				bounds[0][0][0],
				bounds [0][1][0],
				bounds[0][0][1]-bounds[0][0][0]+1,
				bounds[0][1][1]-bounds[0][1][0]+1);
		return rbounds;
	}
	
 	public static double [] subtractWoi(
			final double [] data0,
			final double [] data1,
			final int       width,
			Rectangle woi_in) {
		final int height = data0.length/width;
		if (woi_in == null) {
			woi_in =new Rectangle(0,0,width,height);
		}
		final Rectangle woi = new Rectangle(woi_in);
		final int woi_len = woi.width*woi.height;
		final double [] data_out =new double [woi_len];
		final Thread[] threads = ImageDtt.newThreadArray();
		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 < woi_len; iPix = ai.getAndIncrement()) {
						int x = woi.x + (iPix % woi.width);
						int y = woi.y + (iPix / woi.width);
						int nPix = y * width + x;
						data_out[iPix] = data1[nPix] - data0[nPix];
					}
				}
			};
		}		      
		ImageDtt.startAndJoin(threads);
		return data_out;

	}
	
}
+505 −80

File changed.

Preview size limit exceeded, changes collapsed.

Loading