Commit 29e261ef authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Adding filtering by absolute contrast

parent 6cbc4b32
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -777,7 +777,7 @@ public class ObjectLocation {
		}
		}
		
		
		// min_weight = 10.0
		// min_weight = 10.0
		// Starting from very center remove fartherst (first or last) pixel,
		// Starting from very center remove farthest (first or last) pixel,
		// until remaining weight drops below min_weight or sw0[]*(1-frac_outliers).
		// until remaining weight drops below min_weight or sw0[]*(1-frac_outliers).
		// weight of the previous radius may fall also, but likely not too much
		// weight of the previous radius may fall also, but likely not too much
		for (int nr = 1; nr < sw.length; nr++) {
		for (int nr = 1; nr < sw.length; nr++) {
+244 −0
Original line number Original line Diff line number Diff line
@@ -18,6 +18,8 @@ import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashMap;
import java.util.List;
import java.util.List;
import java.util.Properties;
import java.util.Properties;
@@ -1855,6 +1857,248 @@ public class OrthoMap implements Comparable <OrthoMap>, Serializable{
		return convolved;
		return convolved;
	}
	}
	
	
	/**
	 * Calculate absolute contrast of the pattern
	 * @param data extracted square image with the object exactly
	 *             in the center
	 * @param ipattern square pattern array corresponding to data. 1 means 
	 *                 average (w/o outliers) and add, 2 - average and subtract
	 * @param outliers_frac - fraction of outliers to remove while averaging
	 * @param debug show debug images
	 * @return difference between average in-pattern (1) and outside (2) average
	 *         values  
	 */
	public static double getAbsoluteContrast(
			double [] data,
			int    [] ipattern,
			double    outliers_frac,
			boolean   debug) {
		if (debug) {
			int size = (int) Math.sqrt(data.length);
			ShowDoubleFloatArrays.showArrays(
					data,
					size,
					size,
					"extracted_data");
			
		}
		ArrayList<ArrayList<Integer>> lists = new ArrayList<ArrayList<Integer>>();
		for (int i = 0; i < 2; i++) {
			lists.add(new ArrayList<Integer>());
		}
		double [] swd = new double [2],sw = new double [2], avg= new double[2], fracw=new double[2];
		for (int n = 0; n < swd.length; n++) {
			ArrayList<Integer> list = lists.get(n);
			int n1 = n+1;
			for (int i = 0; i < ipattern.length; i++) if (ipattern[i] == n1){
				sw[n] += 1;
				swd[n]+= data[i];
				list.add(i);
			}
			avg[n] = swd[n]/sw[n];
			fracw[n] = (1.0-outliers_frac) * sw[n];
		}
		if (debug) {
			System.out.println("getAbsoluteContrast() before outliers: avg[0] ="+avg[0]+", avg[1]="+avg[1]+", avg[0]-avg[1]="+(avg[0]-avg[1]));
		}
		if (outliers_frac > 0) {
			for (int n = 0; n < swd.length; n++) {
				ArrayList<Integer> list = lists.get(n);
				Collections.sort(list, new Comparator<Integer>() {
					@Override
					public int compare(Integer lhs, Integer rhs) {
						double rhsd = data[rhs];
						double lhsd = data[lhs];
						return (rhsd > lhsd) ? -1 : (rhsd < lhsd) ? 1 : 0;
					}
				});
				while (sw[n] >= fracw[n]) {
					int indx_first = list.get(0);
					int indx_last = list.get(list.size()-1);
					boolean remove_first = Math.abs(data[indx_first] - avg[n]) > Math.abs(data[indx_last] - avg[n]);
					int indx_worst = remove_first? indx_first : indx_last;
					double d = data[indx_worst];
					double sw_new = sw[n] - 1.0;
					avg[n] = (avg[n] * sw[n] - d)/sw_new;
					sw[n] = sw_new;
					list.remove(remove_first ? 0 : list.size()-1);
				}
			}
		}
		if (debug) {
			int    [] ipattern1 = new int [ipattern.length];
			for (int n = 0; n < lists.size(); n++) {
				ArrayList<Integer> list = lists.get(n);
				for (Integer i: list) {
					ipattern1[i] = n+1;
				}
			}
			int [][] ipatterns = {ipattern, ipattern1};
			double [][] dbg_img = new double [2][ipattern.length];
			for (int n = 0; n < ipatterns.length; n++) {
				for (int i= 0; i < ipatterns[n].length; i++) if (ipatterns[n][i] != 0){
					switch (ipatterns[n][i]) {
					case 1: dbg_img[n][i] = 1.0; break;
					case 2: dbg_img[n][i] = -1.0; break;
					}
				}
			}
			int size = (int) Math.sqrt(ipattern.length);
			ShowDoubleFloatArrays.showArrays(
					dbg_img,
					size,
					size,
					true,
					"integer_patterns_before_after");
		}
		if (debug) {
			System.out.println("getAbsoluteContrast() after outliers: avg[0] ="+avg[0]+", avg[1]="+avg[1]+", avg[0]-avg[1]="+(avg[0]-avg[1]));
		}
		return avg[0]-avg[1];
	}
	
	/**
	 * From existing pattern (only for simple dark main scene)
	 * create two zones to calculate average (w/o outliers) inside
	 * the pattern and around it. Mark inner with 1, outer - 2, keep
	 * other 0. Then later find 2 averages (removing outliers) and their
	 * difference - absolute contrast.
	 * @param patterns set of square patterns, first [0] for full pattern,
	 *                 others - for half-patterns cut in different directions. 
	 * @param edge_frac consider in-pattern if normalized value (normalized by
	 *                  the value with maximal absolute value) is above
	 *                  1-edge_frac, completely out if it is below edge_frac.
	 * @param oversize scale patterns by this value to create outer area (marked 2)
	 * @param debug  show debug images
	 * @return integer array corresponding to the original patterns. 1 means
	 *         "in-patter" (average w/o outliers and add), 2 means "around pattern"-
	 *         average w/o outliers and subtract.
	 */
	public static int[][] getIntPatterns(
			double [][] patterns,
			double edge_frac, // 0.15
			double oversize,
			boolean debug) {
		double low_thresh = edge_frac;
		double high_thresh = 1.0 - edge_frac;
		int size = (int) Math.sqrt(patterns[0].length);
		double xc = size/2;
		double yc = size/2;
		int [][] ipatterns = new int [patterns.length][patterns[0].length];
		double amax = 0;
		double absmax = 0;
		for (int i = 0; i < patterns[0].length; i++) {
			double d = patterns[0][i];
			double ad = Math.abs(d);
			if (ad > absmax) {
				absmax = ad;
				amax = d;
			}
		}
		double scale = 1.0/amax;
		double [][] npatterns = new double [patterns.length][patterns[0].length];
		for (int n = 0; n < patterns.length; n++) {
			for (int i = 0; i < patterns[n].length; i++) {
				npatterns[n][i] = patterns[n][i] * scale;
			}
		}
		// create full pattern first
		int num_1 = 0, num_2=0;
		for (int y=0; y < size; y++) {
			double ys= yc+ (y-yc)/oversize;
			for (int x=0; x < size; x++) {
				int indx = y*size+x;
				if (npatterns[0][indx] > high_thresh) {
					ipatterns[0][indx] = 1;
					num_1++;
				} else if (npatterns[0][indx] <= low_thresh) {// interpolate scaled version, between - keep zero
					double xs = xc+ (x-xc)/oversize;
					// interpolate
					int iys = (int) Math.floor(ys);
					double fys = ys-iys;
					int ixs = (int) Math.floor(xs);
					double fxs = xs-ixs;
					int sindx = iys*size+ixs;
					double sd0 = 
							(1-fys)*(1-fxs)*npatterns[0][sindx] + 
							(1-fys)*(  fxs)*npatterns[0][sindx+1] + 
							(  fys)*(1-fxs)*npatterns[0][sindx+size] + 
							(  fys)*(  fxs)*npatterns[0][sindx+size+1]; 
					if (sd0 > high_thresh) {
						ipatterns[0][indx] = 2;
						num_2++;
					}
				}
			}
		}
		if ((num_1 == 0) || (num_2==0)) {
			System.out.println("getIntPatterns(): wrong pattern or parameters: num_1="+num_1+", num2="+num_2);
			return null;
		}
		// Other patterns
		for (int n = 1; n < npatterns.length; n++) {
			for (int y=0; y < size; y++) {
				double ys= yc+ (y-yc)/oversize;
				for (int x=0; x < size; x++) {
					int indx = y*size+x;
					if (ipatterns[0][indx] == 1) {
						if (npatterns[n][indx]/npatterns[0][indx] > 0.5) {
							ipatterns[n][indx] = ipatterns[0][indx]; //= 1
						}
					} else if (ipatterns[0][indx] == 2) {
						double xs = xc+ (x-xc)/oversize;
						// interpolate
						int iys = (int) Math.floor(ys);
						double fys = ys-iys;
						int ixs = (int) Math.floor(xs);
						double fxs = xs-ixs;
						int sindx = iys*size+ixs;
						double sd0 = 
								(1-fys)*(1-fxs)*npatterns[0][sindx] + 
								(1-fys)*(  fxs)*npatterns[0][sindx+1] + 
								(  fys)*(1-fxs)*npatterns[0][sindx+size] + 
								(  fys)*(  fxs)*npatterns[0][sindx+size+1]; 
						
						double sdn = 
								(1-fys)*(1-fxs)*npatterns[n][sindx] + 
								(1-fys)*(  fxs)*npatterns[n][sindx+1] + 
								(  fys)*(1-fxs)*npatterns[n][sindx+size] + 
								(  fys)*(  fxs)*npatterns[n][sindx+size+1]; 
						if (sdn/sd0 > 0.5) {
							ipatterns[n][indx] = ipatterns[0][indx]; // =2
						}
					}
				}
			}
		}
		if (debug) {
			ShowDoubleFloatArrays.showArrays(
					npatterns,
					size,
					size,
					true,
					"normalized_patterns");
			double [][] dbg_img = new double [ipatterns.length][ipatterns[0].length];
			for (int n = 0; n < ipatterns.length; n++) {
				for (int i= 0; i < ipatterns[n].length; i++) if (ipatterns[n][i] != 0){
					switch (ipatterns[n][i]) {
					case 1: dbg_img[n][i] = 1.0; break;
					case 2: dbg_img[n][i] = -1.0; break;
					}
				}
			}
			ShowDoubleFloatArrays.showArrays(
					dbg_img,
					size,
					size,
					true,
					"integer_patterns");
		}
		return ipatterns;
	}
	
	
	
	public static double [] extractKernel(
	public static double [] extractKernel(
			double [] data,
			double [] data,
			int       kernel_radius,
			int       kernel_radius,
+28 −3
Original line number Original line Diff line number Diff line
@@ -1976,6 +1976,8 @@ public class OrthoMapsCollection implements Serializable{
		double [][][] corrs_out =     new double[indices.length][][]; 
		double [][][] corrs_out =     new double[indices.length][][]; 
		double [][][] convolve_out =  new double[indices.length][][]; 
		double [][][] convolve_out =  new double[indices.length][][]; 
		double [][][] corr_patterns = new double[indices.length][][];
		double [][][] corr_patterns = new double[indices.length][][];
		int    [][][] icorr_patterns= new int[indices.length][][]; // will only be used for main !
		
		double [][][] filtered_corrs = new double[indices.length][][];		
		double [][][] filtered_corrs = new double[indices.length][][];		
		int [] zoomout = new int[indices.length];
		int [] zoomout = new int[indices.length];
		ImagePlus [] imp_corrs = new ImagePlus[indices.length];
		ImagePlus [] imp_corrs = new ImagePlus[indices.length];
@@ -2066,8 +2068,17 @@ public class OrthoMapsCollection implements Serializable{
							kernels_all[scene_num],      // final double [] kernel,
							kernels_all[scene_num],      // final double [] kernel,
							corr_size);                  // final int width)
							corr_size);                  // final int width)
				}
				}
				
			}
			}
			if (scene_num == 0) {
				double oversize = 1.8;
				double edge_frac = 0.25;
				icorr_patterns[scene_num] =  OrthoMap.getIntPatterns(
						corr_patterns[scene_num], // double [][] patterns,
						edge_frac,                // double edge_frac, // 0.15
						oversize,                 // double oversize,
						true);                    // boolean debug);
			}

		}
		}
		// Splitting - above done for both scenes, below - just for the main one
		// Splitting - above done for both scenes, below - just for the main one
		for (int scene_num = 0; scene_num < indices.length; scene_num++) { // will probably just use first one, second - derivative
		for (int scene_num = 0; scene_num < indices.length; scene_num++) { // will probably just use first one, second - derivative
@@ -2200,6 +2211,7 @@ public class OrthoMapsCollection implements Serializable{
					num_non_overlap++;
					num_non_overlap++;
				}
				}
			}
			}
			
			if (num_non_overlap > 0) {
			if (num_non_overlap > 0) {
				System.out.println("Removed "+num_non_overlap+" objects outside of the scenes overlap, "+match_sort.size()+" remain");
				System.out.println("Removed "+num_non_overlap+" objects outside of the scenes overlap, "+match_sort.size()+" remain");
			}
			}
@@ -2226,6 +2238,7 @@ public class OrthoMapsCollection implements Serializable{
						System.out.print(",");
						System.out.print(",");
					}
					}
				}
				}
				
			}
			}
//			boolean remove_dc = true;
//			boolean remove_dc = true;
			if (scene_num == 0) {
			if (scene_num == 0) {
@@ -2353,6 +2366,18 @@ public class OrthoMapsCollection implements Serializable{
							imps_extracted_corr, // ImagePlus[]           imps_extracted_corr, // may be null - will not be displayed
							imps_extracted_corr, // ImagePlus[]           imps_extracted_corr, // may be null - will not be displayed
							imps_extracted_corr_half); // ImagePlus[]           imps_extracted_corr_half
							imps_extracted_corr_half); // ImagePlus[]           imps_extracted_corr_half
				}
				}
				double [] abs_contrast = new double [match_sort.size()];
				double    outliers_frac = 0.3;
				for (int i = 0; i < match_sort.size(); i++) {
					int indx =match_sort.get(i);
					ItemMatch match = matches_list.get(indx);
					int best_patt= match.getPatternMatch(gops[scene_num]).getBestSub();
					abs_contrast[i] = OrthoMap.getAbsoluteContrast(
							extracted_objects[scene_num][i],         // double [] data,
							icorr_patterns[scene_num][best_patt-1], //int    [] ipattern,
							outliers_frac,                        // double    outliers_frac,
							true);                                // boolean   debug);
				}	
				// Correlate second scene only for selected fragments
				// Correlate second scene only for selected fragments
				for (int scene_other = 1; scene_other < indices.length; scene_other++) { // normally just 1
				for (int scene_other = 1; scene_other < indices.length; scene_other++) { // normally just 1
					filter_data[scene_other] = new double[match_sort.size()][2][]; // [scene][max][0-full, 1 - half][0- max, 1 - area, 2 - distance]
					filter_data[scene_other] = new double[match_sort.size()][2][]; // [scene][max][0-full, 1 - half][0- max, 1 - area, 2 - distance]