Commit 86efce83 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Extracting radial pattern

parent 8667ae4b
Loading
Loading
Loading
Loading
+301 −25
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ public class ComboMatch {
	public static boolean openTestPairGps(
			 CLTParameters    clt_parameters,
			 GPUTileProcessor gpu_tile_processor, // initialized by the caller
			 boolean    extract_mines,
			 boolean          extract_objects,
			 int              debugLevel) {
		GPU_TILE_PROCESSOR = gpu_tile_processor;
		PairwiseOrthoMatch pairwiseOrthoMatch = null;
@@ -55,6 +55,19 @@ public class ComboMatch {
		String [] gpu_spair = null;
		boolean use_marked_image =    false; // will be set if found
		String [] all_scenes = null;
		ArrayList<ObjectLocation> object_list = null;
		int zool_lev_objects = 0;
		if (extract_objects) {
			if (imp_sel == null) {
				System.out.println("Need multi-sliced image with marked objects as points");
				return false;
			} 
			int [] zoom_lev_objectsp = new int [1];
			object_list = getObjectsFromSelectedImage(
					imp_sel,
					zoom_lev_objectsp); // ImagePlus imp)
			zool_lev_objects = zoom_lev_objectsp[0];
		} else {
			if (imp_sel != null) {
				pair_names = new String[2];
				String [][] all_scenes1=new String[1][];
@@ -68,6 +81,7 @@ public class ComboMatch {
					all_scenes = all_scenes1[0];
				}
			}
		}
		// find -L /media/elphel/SSD3-4GB/lwir16-proc/berdich3/linked/linked_1697875868-1697879449-b/ -type f -name "*-GCORR-GEO.tiff" | sort  > GCORR-GEO.list

//		String files_list_path =          "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/maps_03_short.list";
@@ -254,6 +268,236 @@ public class ComboMatch {
			maps_collection = new OrthoMapsCollection(files_list_path); // should have ".list" extension
		}
		String [] names = maps_collection.getNames();
		if (object_list != null) {
			int       corr_size =                128;
			int       extr_size =     200; // 256;
			int       zoomout =        2; //  1; //2; // 1; 2 for simulated,1 - for extracted 
			int       patt_choice =     3;
			double    phaseCoeff =      0.98;
			double    min_corr  =       0.01; // 0.0025; // real max >0.005 with scale -500000;
			int       radius_search =  32;
			int       radius_centroid = 4;
			double    lim_rad =        80; // 60; // 40; // 50.0;
			double    trans_width =    60; // 40; // 20.0;
			double    reversal_rad =   0; // 26;// 22; // cut at first direction reversal after
			double    frac_outliers =   0.4;
			int default_kernel =        1; // 0; // 1; // default kernel choice 25-> 50// 1 for simulated, 0 - for extracted 
			boolean   only_correlate =  true;
			int       sub_pattern_index = 0;
			
//			String pattern_dir= "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/debug/mines/pattern_25m_zoom1/synthetic/";
			String pattern_dir= "/media/elphel/NVME/lwir16-proc/ortho_videos/mines_extract/evening_50m_sept12/debug_cross/new_synth/";
			String [] pattern_files={
					"patterns_r30.0_e8.0_ir10.0_ie8.0_is-0.1_or45.0_oe30.0_os-1.5_h8_w0.6_s-40.0_200x200.tif",
					"old_02.tiff",
					"patterns_r30.0_e24.0_ir10.0_ie8.0_is-0.1_or62.0_oe40.0_os-1.0_h8_w0.6_s-60.0_200x200.tif",
					"patterns_r30.0_e8.0_ir10.0_ie8.0_is-0.1_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif",
					"patterns_r30.0_e8.0_ir10.0_ie8.0_is0.0_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif",
					"patterns_r30.0_e6.0_ir10.0_ie8.0_is0.0_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif",
					"patterns_r30.0_e6.0_ir10.0_ie6.0_is-1.0_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif",
					"patterns_r30.0_e6.0_ir10.0_ie6.0_is-0.8_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif",
					"patterns_r30.0_e4.0_ir10.0_ie4.0_is-1.0_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif",
					"patterns_r30.0_e5.0_ir12.0_ie5.0_is-1.0_or45.0_oe30.0_os-1.0_h8_w0.6_s-60.0_200x200.tif",
					"patterns_r30.0_e5.0_ir12.0_ie5.0_is-1.0_or45.0_oe20.0_os-1.0_h8_w0.6_s-60.0_200x200.tif",
					"patterns_r30.0_e5.0_ir12.0_ie5.0_is-1.0_or50.0_oe40.0_os-1.0_h8_w0.6_s-60.0_200x200.tif", // best
					"patterns_r30.0_e5.0_ir12.0_ie5.0_is-1.0_or55.0_oe50.0_os-1.0_h8_w0.6_s-60.0_200x200.tif",
					"patterns_r30.0_e5.0_ir12.0_ie5.0_is0.0_or50.0_oe40.0_os-1.0_h8_w0.6_s-60.0_200x200.tif"
					};
			
			
			GenericJTabbedDialog gdo = new GenericJTabbedDialog("Set image pair",1200,900);
			gdo.addNumericField("Correlation size",          corr_size,       0,4,"",
					"Correlation size, power of 2");
			gdo.addNumericField("Extracted size",            extr_size,  0,4,"",
					"size of a square output size");
//			gdo.addStringField ("Pattern directory",          OrthoMap.pattern_dir, 180, 	"Absolute path including trailing \"/\".");
//			gdo.addChoice      ("Pattern filename:",          OrthoMap.pattern_files, OrthoMap.pattern_files[patt_choice]);
			gdo.addStringField ("Pattern directory",          pattern_dir, 180, 	"Absolute path including trailing \"/\".");
			gdo.addChoice      ("Pattern filename:",          pattern_files, OrthoMap.pattern_files[patt_choice]);
			gdo.addNumericField("Zoom-out factor",            zoomout,  0,4,"x", "Reduce pattern resolution to match image.");
			gdo.addNumericField("Phase correlation coefficient",  phaseCoeff,  3,7,"","1.0 - pure phase correlation, 0.0 - regular correlation.");
			gdo.addNumericField("Minimal correlation",        min_corr,  5,7,"","Minimal correlation value to keep.");
			gdo.addNumericField("Search radius",              radius_search,    0,4,"pix", "Radius to search for the object center.");
			gdo.addNumericField("Centroid radius",            radius_centroid,  0,4,"pix", "Limit centroid radius.");
			gdo.addMessage("Clean-up circular pattern:");
		
			gdo.addNumericField("Limit output patter radius", lim_rad,        0,4,"pix", "All zero outside this radius.");
			gdo.addNumericField("Transition width",           trans_width,    0,4,"pix", "cosine transition width.");
			gdo.addNumericField("Last reversal radius",       reversal_rad,   0,4,"pix", "Cut at first derivative reversal after this.");
			gdo.addNumericField("Outlier fraction",           frac_outliers,  3,7,"", "Remove outliers when averaging different directions.");
			gdo.addCheckbox     ("Only correlate",            only_correlate, "do not generate circular kernel.");
			gdo.addNumericField("subpattern index",           sub_pattern_index,0,4,"", "0 - full pattern, 1-8 - half-pattern.");

			//only_correlate
			gdo.showDialog();
			if (gdo.wasCanceled()) return false;
			corr_size =                (int) gdo.getNextNumber();
			extr_size =           (int) gdo.getNextNumber();
//			OrthoMap.pattern_dir=       gdo.getNextString();		
//			String pattern_file = OrthoMap.pattern_files[gdo.getNextChoiceIndex()];
			pattern_dir=                gdo.getNextString();		
			String pattern_file =       pattern_files[gdo.getNextChoiceIndex()];
			zoomout=              (int) gdo.getNextNumber();
			phaseCoeff=                 gdo.getNextNumber();
			min_corr=                   gdo.getNextNumber();
			radius_search=        (int) gdo.getNextNumber();
			radius_centroid=      (int) gdo.getNextNumber();
			lim_rad=                    gdo.getNextNumber();      
			trans_width=                gdo.getNextNumber();
			reversal_rad=               gdo.getNextNumber();
			frac_outliers=              gdo.getNextNumber();
			only_correlate =            gdo.getNextBoolean();
			sub_pattern_index=    (int) gdo.getNextNumber();
			
			System.out.println("Will extract objects here, image zoom_level="+zool_lev_objects);
			for (ObjectLocation ol: object_list) {
				System.out.println(ol.name+": "+ol.xy_meters[0]+"/"+ol.xy_meters[1]);
			}
			maps_collection.reverseRender(
					object_list, // ArrayList<ObjectLocation> objects,
					zool_lev_objects);   // int         zoom_level){
			System.out.println("Object coordinates in source images: ");
			for (ObjectLocation ol: object_list) {
				System.out.println(ol.name+": "+ol.getPixels()[0]+"/"+ol.getPixels()[1]);
			}
			double [][] object_stack = new double [object_list.size()][];
			String [] object_titles = new String [object_stack.length];
			for (int i = 0; i < object_stack.length; i++) {
				ObjectLocation ol = object_list.get(i);
				object_titles[i] = ol.getName();
				object_stack[i] = ol.extractObjectImage(
						maps_collection,
						extr_size);

			}
			ImagePlus imp_obj = ShowDoubleFloatArrays.makeArrays(
					object_stack,
					extr_size,
					extr_size,
					OrthoMap.removeKnownExtension(imp_sel.getTitle())+"-OBJECT_"+extr_size+"x"+extr_size+".tiff",				
					object_titles); // test_titles,
			imp_obj.show();
			
			// get pattern(s)
//			String pattern_path=OrthoMap.pattern_dir+pattern_file;
			String pattern_path=pattern_dir+pattern_file;
			ImagePlus imp_pattern = new ImagePlus(pattern_path);
			int pattern_size =  imp_pattern.getWidth();
			if (pattern_size == 0) {
				System.out.println("testPatternCorrelate(): pattern \""+pattern_path+"\" is not found.");
				return false;
			}
			System.out.println("Using pattern file: "+pattern_path+", subpattern="+sub_pattern_index);
			ImageStack stack_pattern = imp_pattern.getStack();
			int nSlices = stack_pattern.getSize();
			double [][] patterns = new double[nSlices][];
			String [] pattern_labels = new String[nSlices];
			for (int n = 0; n < patterns.length; n++) {
				pattern_labels[n]=stack_pattern.getShortSliceLabel(n+1);
				float [] fpixels_pattern = (float[]) stack_pattern.getPixels(n+1);
				patterns[n]=new double[fpixels_pattern.length];
				for (int i = 0; i < fpixels_pattern.length; i++) {
					patterns[n][i] = fpixels_pattern[i];
				}
			}
			double [] kernel =  OrthoMap.getConvolutionKernel(default_kernel);
			double [][] centers = new double [object_stack.length][];
			for (int i = 0; i < object_stack.length; i++) {
				String    dbg_prefix = "corr_patt_"+i;
				ObjectLocation ol = object_list.get(i);
				centers[i] = ObjectLocation.getPatternCenter(
						object_stack[i], // double [] data,
						patterns[sub_pattern_index],     // double [] pattern,
						kernel,          // double [] kernel,
						zoomout,         // int       zoomout,
						phaseCoeff,      // double    phaseCoeff,
						min_corr,        // double    min_corr,
						radius_search,   // int       radius_search,
						radius_centroid, // int       radius_centroid,
						dbg_prefix,      // String    dbg_prefix,
						debugLevel);     // int       debugLevel)
				System.out.println(i+": center at "+centers[i][0]+"/"+centers[i][1]+", strength="+centers[i][2]);
			}
			PointRoi roi = new PointRoi();
			roi.setOptions("label");
			for (int i = 0; i < centers.length; i++) {
				roi.addPoint(centers[i][0]+extr_size/2, centers[i][1]+extr_size/2, i+1); // ,1);
			}
			imp_obj.setRoi(roi);
			if (only_correlate) {
				System.out.println("testPatternCorrelate(): correlation DONE, only_correlate is set to true, exiting");
				return true;
			}
			
//			imp_obj.show();
			// First process each captured object separately, then compare and average?
			// TODO: use finer grid, deconvolve with altitude kernel, calculate effective width of the pattern
			double [][] output_patterns = new double [object_stack.length+1][];
			String [] output_patt_titles = new String[output_patterns.length];
			output_patt_titles[output_patt_titles.length-1]= "average";
			output_patterns[object_stack.length] = new double [corr_size*corr_size];
//object_titles
			boolean debug_good = debugLevel > -4;
			boolean [][] good_pix = debug_good ? (new boolean[object_stack.length][extr_size*extr_size]) : null; // debugging
			String settings_str = "_fo"+frac_outliers+"_lr"+lim_rad+"_tw"+trans_width+"_rr"+reversal_rad;
			for (int i = 0; i < object_stack.length; i++) {
				output_patterns[i] = ObjectLocation.getRadialPattern(
						object_stack[i], // double [] data,
						centers[i],      // double [] xy_offs,
						corr_size,       // int       corr_size, 
						lim_rad,         // double    lim_rad,     // outside all 0
						trans_width,     //double    trans_width, // lim_rad-trans_width - start reducing
						frac_outliers,   // double    frac_outliers,
						reversal_rad,   // double     reversal_rad,
						((good_pix != null)? good_pix[i] : null), // boolean [] good,       // null or same size as data
						debugLevel);     // int       debugLevel)
				output_patt_titles[i] = object_titles[i];
				for (int j = 0; j < output_patterns[i].length; j++) {
					output_patterns[object_stack.length][j] += output_patterns[i][j];
				}
			}
			for (int j = 0; j < output_patterns[0].length; j++) {
				output_patterns[object_stack.length][j] /= object_stack.length;
			}
			ImagePlus imp_out_patt = ShowDoubleFloatArrays.makeArrays(
					output_patterns,
					corr_size,
					corr_size,
					OrthoMap.removeKnownExtension(imp_sel.getTitle())+"-PATTERN"+settings_str+"_"+corr_size+"x"+corr_size+".tiff",				
					output_patt_titles); // test_titles,
			imp_out_patt.show();
			if (good_pix != null) {
				double [][] object_stack_masked = new double [2 * object_stack.length][]; 
				String [] object_titles_masked = new String [2 * object_stack.length];
				PointRoi roi_masked = new PointRoi();
				roi_masked.setOptions("label");
				for (int i = 0; i < centers.length; i++) {
					roi_masked.addPoint(centers[i][0]+extr_size/2, centers[i][1]+extr_size/2, 2*i+1); // ,1);
					roi_masked.addPoint(centers[i][0]+extr_size/2, centers[i][1]+extr_size/2, 2*i+2); // ,1);
				}

				for (int i = 0; i < object_stack.length; i++) {
					object_stack_masked[2*i + 0] = object_stack[i];
					object_stack_masked[2*i + 1] = object_stack[i].clone();
					for (int j = 0; j < object_stack[i].length; j++) {
						if (!good_pix[i][j]) {
							object_stack_masked[2*i + 1][j] = Double.NaN;
						}
					}
				}
				ImagePlus imp_obj_masked = ShowDoubleFloatArrays.makeArrays(
						object_stack_masked,
						extr_size,
						extr_size,
						OrthoMap.removeKnownExtension(imp_sel.getTitle())+"-OBJECT_MASKED"+settings_str+"_"+extr_size+"x"+extr_size+".tiff",				
						object_titles_masked); // test_titles,
				imp_obj_masked.setRoi(roi_masked);
				imp_obj_masked.show();
			}
			return true;
		}
		
		
		if (use_marked_image) {
			// verify matching names
			//all_scenes
@@ -691,6 +935,50 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341
		return null;
	}

	public static ArrayList<ObjectLocation> getObjectsFromSelectedImage(
			ImagePlus imp,
			int [] zoom_levp) {
		// get zoom from the name and list of the slice names prefixes (before second "_"
		String title = imp.getTitle();
		String[] tokens = title.replace(".","_").split("_");
		for (int i = 0; i < tokens.length; i++) {
			if (tokens[i].startsWith("zoom")) {
				int zoom_level = Integer.parseInt(tokens[i].substring(4));
				System.out.println("zoom level = "+zoom_level);
				double pix_size = OrthoMap.getPixelSizeMeters (zoom_level); // meters
				ImageStack stack_scenes = imp.getStack();
				int nSlices = stack_scenes.getSize();
				String [] scene_names = new String [nSlices];
				for (int n = 0; n < scene_names.length; n++) {
					scene_names[n] = stack_scenes.getSliceLabel(n+1).substring(0,17);
				}
				PointRoi pRoi = (PointRoi) imp.getRoi();
				FloatPolygon fp = pRoi.getContainedFloatPoints();
				// Use only 2 last markers
				if (fp == null) {
					System.out.println("getPairFromSelectedImage(): no markers found");
					return null;
				}
				ArrayList<ObjectLocation> list = new ArrayList<ObjectLocation>();
				for (int np = 0; np < fp.npoints; np++) {
					String name = scene_names[pRoi.getPointPosition(np) -1];
					double [] xy_meters = {
							fp.xpoints[np] * pix_size, 
							fp.ypoints[np] * pix_size};
					list.add(new ObjectLocation (
							name,        // String name,
							xy_meters)); // double [] xy_meters)
				}
				if (zoom_levp != null) {
					zoom_levp[0] = zoom_level;
				}
				return list;
			}
		}
		return null;
	}
	
	
	public static String [] getPairChoices(
			int [][] pairs,
			String [] names) {
@@ -703,18 +991,6 @@ adjusted affines[1] for a pair: 1694564291_293695/1694564778_589341
	
	
	
	/*
	public static TDCorrTile [] rectilinearCorrelate_TD( // scene0/scene1
			final CLTParameters          clt_parameters,
			final float  [][]            fpixels, // to check for empty
			final int                    img_width,
			Rectangle                    woi, // if null, use full GPU window
			final double [][][]          affine,  // [2][2][3] affine coefficients to translate common to 2 images
			final boolean                batch_mode,
			final int                    debugLevel) {
	 */
	
	
	public static double [][][] rectilinearVectorField( // scene0/scene1
			final CLTParameters          clt_parameters,
			final float  [][]            fpixels, // to check for empty
+388 −0

File changed.

Preview size limit exceeded, changes collapsed.

+39 −40
Original line number Diff line number Diff line
@@ -67,6 +67,20 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
			"/media/elphel/NVME/lwir16-proc/ortho_videos/kernel_50_100.tiff"
	};

	public static String pattern_dir= "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/debug/mines/pattern_25m_zoom1/synthetic/";
	public static String [] pattern_files=
		{"patterns_50m_zoom1_200x200.tiff",
		"patterns_50m_evening_zoom1_200x200.tiff",
		"patterns_50m_evening_01_zoom1_200x200_00.tiff",
		"patterns_50m_evening_02_zoom1_200x200_00.tiff",
		"patterns_50m_evening_03_zoom1_200x200_00.tiff",
		"patterns_50m_evening_04_zoom1_200x200_00.tiff",
		"patterns_50m_evening_05_zoom1_200x200_00.tiff",
		"mine1_zoom0.tiff",
		"mine2_zoom0.tiff",
		"mine3_zoom0.tiff",
		"mine4_zoom0.tiff",
		"mine6_zoom0.tiff"};
	
	
	public static final String ALT_SUFFIX = "-ALT";
@@ -1095,9 +1109,12 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
	 * @return square kernel as a 1-d double array or null
	 */
	public static double [] getConvolutionKernel() {
		return getConvolutionKernel(kernel_paths.length-1);
	}
	public static double [] getConvolutionKernel(int choice) {
		String kernel_path = null;
		GenericJTabbedDialog gds = new GenericJTabbedDialog("Select kernel path",1200,400);
		gds.addChoice("Kernel path:", kernel_paths, kernel_paths[kernel_paths.length-1]);
		gds.addChoice("Kernel path:", kernel_paths, kernel_paths[choice]);
		gds.showDialog();
		if (gds.wasCanceled()) return null;
		int kernel_index = gds.getNextChoiceIndex();
@@ -3038,6 +3055,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
			double [] wnd_in,
			double    phaseCoeff) {
//		phaseCoeff = 0.5;
		boolean dbg=false;
		double [] data = data_in.clone();
		double [] pattern = pattern_in.clone();
		double [] wnd = wnd_in.clone();
@@ -3047,7 +3065,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
		for (int i = 0; i < data.length; i++) {
			data[i] *= wnd[i];
		}
		{
		if (dbg) {
			String [] rslt_titles= {"original","window","windowed","pattern"};
			ShowDoubleFloatArrays.showArrays(
					new double[][] {data_orig, wnd, data, pattern},
@@ -3096,7 +3114,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
			}
		}
		
		{
		if (dbg) {
			String [] rslt_titles= {"corr", "original","window","windowed","pattern"};
			ShowDoubleFloatArrays.showArrays(
					new double[][] {corr_out, data_orig, wnd, data_orig2, pattern_orig},
@@ -3106,7 +3124,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
					convolve?"output_conv":("output_corr"+phaseCoeff),
					rslt_titles);
		}
		System.out.println("testPhaseCorr() done");
		if (dbg) System.out.println("testPhaseCorr() done");
		return corr_out;
	}
	
@@ -3192,8 +3210,8 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
	
	public static void testPatternCorrelate(
			ImagePlus imp_src) {
		/*
		String pattern_dir= "/media/elphel/SSD3-4GB/lwir16-proc/ortho_videos/debug/mines/pattern_25m_zoom1/synthetic/";
//		String pattern_file= "patterns_50m_zoom1_200x200.tiff";
		String [] pattern_files=
			{"patterns_50m_zoom1_200x200.tiff",
			"patterns_50m_evening_zoom1_200x200.tiff",
@@ -3202,6 +3220,7 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
			"patterns_50m_evening_03_zoom1_200x200_00.tiff",
			"patterns_50m_evening_04_zoom1_200x200_00.tiff",
			"patterns_50m_evening_05_zoom1_200x200_00.tiff"};
      */			
		int       zoomout =     2; // 1;
		int       corr_size = 128; // 256;
		double    phaseCoeff = 0.5;
@@ -3297,7 +3316,6 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{

		double [][] corrs_out =     new double[patterns.length][]; 
		double [][] convolve_out =  new double[patterns.length][]; 
//		double [][] lim_corr =      new double[patterns.length][];
		double [][] corr_patterns = new double[patterns.length][];
		for (int n = 0; n < patterns.length; n++) {
			corr_patterns[n] = patternZoomCropPad(
@@ -3331,6 +3349,11 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
				height,
				removeKnownExtension(imp_src.getTitle())+"-PATTERN_CORRS",				
				patt_titles); // test_titles,
		
		
		
		
		
		if (src_marks != null) {
			PointRoi roi = new PointRoi();
			roi.setOptions("label");
@@ -3881,40 +3904,16 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
	public static void testPatternGenerate() {
		int       half_size = 100;
		boolean   half_pix = false; // center between pixels
		boolean   evening_mode = false; // glare around object, use radius 
		double    radius_out= 42;
		double    edge_out =  6;
		double    scale_out = 1.5;
		boolean   evening_mode = true; // false; // glare around object, use radius 
		double    radius =   30; // 32; // 32;
		double    edge=      15; //  4;
		double    radius_in= 15; // if 0 - skip
		double    edge_in =   8;
		double    scale_in = -0.05;
		double    radius_out= 42;
		double    edge_out =  6;
		double    scale_out = 1.5;
		double    scale =  -200; // black 200
		if (evening_mode) {
			radius_out= 42;
			edge_out =  8;
			scale_out =-1.5; // relative to scale
			radius =   30; // 32; // 32;
			edge=      15; //  4;
			radius_in= 10; // if 0 - skip
			edge_in =   8;
			scale_in = -0.7;
			scale =   -40; // black 200
			
		} else {
			radius_out= 42;
			edge_out =  6;
			scale_out =.08;
			radius =   30; // 32; // 32;
			edge=      15; //  4;
			radius_in= 15; // if 0 - skip
			edge_in =   8;
			scale_in = -0.05;
			scale =  -170; // black 200
		}
		
		
		
		boolean   normalize = false;
		int       halves_number = 8; // hidden mines - number of diameter cuts
@@ -3930,15 +3929,15 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
		if (gd0.wasCanceled()) return;
		evening_mode=        gd0.getNextBoolean();
		if (evening_mode) {
			radius_out= 62; // 42;
			edge_out =  40; // 8;
			scale_out =-1.5; // relative to scale
			radius =   30; // 32; // 32;
			edge=       24; // 8; //  4;
			edge=       8; // 8; //  4;
			radius_in= 10; // if 0 - skip
			edge_in =   8;
			scale_in = -0.1; // 7;
			scale =   -40; // black 200
			scale_in = 0; // -0.1; // 7;
			radius_out= 45; // 42;
			edge_out =  30; // 8;
			scale_out =-1.0; // relative to scale
			scale =   -60; // black 200
		} else {
			radius_out= 42;
			edge_out =  6;
+58 −0
Original line number Diff line number Diff line
@@ -396,6 +396,64 @@ public class OrthoMapsCollection implements Serializable{
		return bounds;
	}
	
	/**
	 * Use object coordinates (now metric) on the composite image to
	 * determine corresponding pixel coordinates of the source images
	 * @param objects ArrayList of objects with the scene name and xy coordinates
	 *                in the composite image. Will fill in pixel coordinates of the objects 
	 * @param zoom_level zoom level of the composite image
	 */
	public void reverseRender(
			ArrayList<ObjectLocation> objects,
			int         zoom_level){
		int [][] bounds = getBoundsPixels( // should be for rectified, {-bounds[0][0], -bounds[0][1]} - exact center
				zoom_level,
				null); 
		int width =  bounds[0][1] - bounds[0][0]; // bounds[x][0] - negative 
		int height = bounds[1][1] - bounds[1][0];
		/*
		int [] indices = new int [ortho_maps.length]; //maybe will get rid of
		for (int i = 0; i < indices.length; i++) {
			indices[i] = i;
		}
		*/
		final int reference_index = 0; 
		for (ObjectLocation ol: objects) {
			int nmap =getIndex(ol.getName());
			final double scale = 1.0/OrthoMap.getPixelSizeMeters(zoom_level);
			final double src_scale = 1.0/OrthoMap.getPixelSizeMeters(ortho_maps[nmap].orig_zoom_level); // pix per meter
			double [][] mbounds = ortho_maps[nmap].getBoundsMeters(true); // keep original bounds
			double [] enu_offset = ortho_maps[reference_index].enuOffsetTo(ortho_maps[nmap]);
			double [] scaled_out_center = { // xy center to apply affine to
					-bounds[0][0] + scale * enu_offset[0],
					-bounds[1][0] - scale * enu_offset[1]};
			double [] metric_center = { // back to meters to match objects
					scaled_out_center[0]/scale,
					scaled_out_center[1]/scale};
			double dX = ol.getMetric()[0]-metric_center[0]; // matching dX, dY in renderMulti()
			double dY = ol.getMetric()[1]-metric_center[1];
			
//			final int [][] obounds = new int [2][2]; // output (rectified, combined) image bounds, relative to thje top-left
//			for (int n = 0; n< 2; n++) {
//				obounds[n][0] = (int) Math.floor(scaled_out_center[n] + scale*mbounds[n][0]);
//				obounds[n][1] = (int) Math.ceil (scaled_out_center[n] + scale*mbounds[n][1]);
//			}
			// Output window size (keep original affine - OK if will not exactly fit)
//			final int ownd_width =  obounds[0][1] - obounds[0][0];
//			final int ownd_height = obounds[1][1] - obounds[1][0];
//			final int ownd_len = ownd_width * ownd_height;
			double [][] src_bounds=ortho_maps[nmap].getBoundsMeters (true); // using original affines
			final double [] src_center = {-src_bounds[0][0],-src_bounds[1][0]}; // x,y center offset in the source image
			final double [][] affine = ortho_maps[nmap].affine; // only here use provided
//			final int src_width =      ortho_maps[nmap].getImageData().width;
//			final int src_height =     ortho_maps[nmap].getImageData().height;
//			final float [] src_img =   ortho_maps[nmap].getImageData().data; // FIXME: will not use
			double [] xy_src = { // pixels of the source image
					src_scale * (affine[0][0]*dX + affine[0][1]*dY + affine[0][2] + src_center[0]),
					src_scale * (affine[1][0]*dX + affine[1][1]*dY + affine[1][2] + src_center[1])};
			ol.setPixels(xy_src);
		}
	}
	
	
	public ImagePlus renderMulti (