Commit 3abbfc39 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

quadratic photometric equalization

parent f0866aad
Loading
Loading
Loading
Loading
+2 −3
Original line number Original line Diff line number Diff line
@@ -3218,9 +3218,9 @@ public class CLTParameters {
 		gd.addMessage  ("It is applied when the source files are read.");
 		gd.addMessage  ("It is applied when the source files are read.");
		gd.addCheckbox ("Enable photometric calibration",            this.photo_en,
		gd.addCheckbox ("Enable photometric calibration",            this.photo_en,
				"Equalize per- sensor gains and offsets. Requires disparity map. Save to reference scene and with current scene (to .corr-zml).");
				"Equalize per- sensor gains and offsets. Requires disparity map. Save to reference scene and with current scene (to .corr-zml).");
		gd.addNumericField("Full photometric (re)calibrations",      this.photo_num_full, 0,3,"pix",
		gd.addNumericField("Full photometric (re)calibrations",      this.photo_num_full, 0,3,"",
				"Full recalibratrions include re-importing raw images with updated offsets/gains");
				"Full recalibratrions include re-importing raw images with updated offsets/gains");
		gd.addNumericField("Refines",                                this.photo_num_refines, 0,3,"pix",
		gd.addNumericField("Refines",                                this.photo_num_refines, 0,3,"",
				"Calculate calibration, remove outliers (e.g. FG/BG) and repeat");
				"Calculate calibration, remove outliers (e.g. FG/BG) and repeat");
		gd.addNumericField("Minimal DSI strength",                   this.photo_min_strength, 5,7,"",
		gd.addNumericField("Minimal DSI strength",                   this.photo_min_strength, 5,7,"",
				"Do not use weak tiles.");
				"Do not use weak tiles.");
@@ -3895,7 +3895,6 @@ public class CLTParameters {
		gd.addTab         ("O-Flow", "parameters for the interscene Optical FLow calculations");
		gd.addTab         ("O-Flow", "parameters for the interscene Optical FLow calculations");
		this.ofp.dialogQuestions(gd);
		this.ofp.dialogQuestions(gd);


		gd.addTab         ("Inter-Match", "Parameters for full-resolution (no decimation/macrotiles) scene matching");
		this.imp.dialogQuestions(gd);
		this.imp.dialogQuestions(gd);
		
		
		gd.addTab         ("Inter-LMA", "parameters for the interscene LMA fitting");
		gd.addTab         ("Inter-LMA", "parameters for the interscene LMA fitting");
+428 −455

File changed.

Preview size limit exceeded, changes collapsed.

+2 −0
Original line number Original line Diff line number Diff line
@@ -4666,6 +4666,8 @@ public class OpticalFlow {
						threadsMax,
						threadsMax,
						debugLevel-2);
						debugLevel-2);
			}
			}
		} else {
			System.out.println("Using photometric calibration from scene "+quadCLTs[ref_index].getPhotometricScene());
		}
		}
		
		
		if (test_ers) { // only debug feature
		if (test_ers) { // only debug feature
+69 −71
Original line number Original line Diff line number Diff line
@@ -2276,8 +2276,8 @@ public class QuadCLT extends QuadCLTCPU {
		System.out.println("processCLTQuadCorrs(): processing "+getTotalFiles(set_channels)+" files ("+set_channels.length+" file sets) finished at "+
		System.out.println("processCLTQuadCorrs(): processing "+getTotalFiles(set_channels)+" files ("+set_channels.length+" file sets) finished at "+
				IJ.d2s(0.000000001*(System.nanoTime()-this.startTime),3)+" sec, --- Free memory3="+Runtime.getRuntime().freeMemory()+" (of "+Runtime.getRuntime().totalMemory()+")");
				IJ.d2s(0.000000001*(System.nanoTime()-this.startTime),3)+" sec, --- Free memory3="+Runtime.getRuntime().freeMemory()+" (of "+Runtime.getRuntime().totalMemory()+")");
	}
	}
	
	@Deprecated 
	public static boolean calibratePhotometric(
	public static boolean calibratePhotometric( // not used
			CLTParameters     clt_parameters,
			CLTParameters     clt_parameters,
			final QuadCLT     ref_scene, // now - may be null - for testing if scene is rotated ref
			final QuadCLT     ref_scene, // now - may be null - for testing if scene is rotated ref
			final double      min_strength,
			final double      min_strength,
@@ -2505,6 +2505,7 @@ public class QuadCLT extends QuadCLTCPU {
			double [] avg_pix = new double [len];
			double [] avg_pix = new double [len];
			double [] offsets = new double[dpixels.length];
			double [] offsets = new double[dpixels.length];
			double [] scales =  new double[dpixels.length];
			double [] scales =  new double[dpixels.length];
			double [] scales2 = new double[dpixels.length];
			double    s0 =  0.0;
			double    s0 =  0.0;
			double    sx=   0.0;
			double    sx=   0.0;
			double    sx2 = 0.0;
			double    sx2 = 0.0;
@@ -2512,7 +2513,17 @@ public class QuadCLT extends QuadCLTCPU {
			double [] sxy = new double[num_sens];
			double [] sxy = new double[num_sens];
			boolean [] good_pix = new boolean[len];
			boolean [] good_pix = new boolean[len];
			double [][] pa_coeff = new double[num_sens][];
			double [][] pa_coeff = new double[num_sens][];
			double min_abs_a = 1E-9;
			Arrays.fill(good_pix, true);
			Arrays.fill(good_pix, true);
			
			double [] offs_old =    ref_scene.getLwirOffsets();
			double [] scales_old =  ref_scene.getLwirScales();
			double [] scales2_old = ref_scene.getLwirScales2();
			
			double [] offs_new =    new double [num_sens];
			double [] scales_new =  new double [num_sens];
			double [] scales2_new = new double [num_sens];
			
			for (int nref = 0; nref < num_refines; nref++) {
			for (int nref = 0; nref < num_refines; nref++) {
				Arrays.fill(avg_pix, 0.0);
				Arrays.fill(avg_pix, 0.0);
				int num_good = 0;
				int num_good = 0;
@@ -2527,77 +2538,74 @@ public class QuadCLT extends QuadCLTCPU {
					}
					}
				}
				}
				double [][] pa_data = new double [num_good][2];
				double [][] pa_data = new double [num_good][2];
				double [][] raw = new double [num_sens][len];
				for (int nsens = 0; nsens < num_sens; nsens++) {
				for (int nsens = 0; nsens < num_sens; nsens++) {
					Arrays.fill(raw[nsens],Double.NaN); // debug only
					
					int indx = 0;
					int indx = 0;
					for (int i = 0; i < len; i++) if (good_pix[i]){
					for (int i = 0; i < len; i++) if (good_pix[i]){
						pa_data[indx][0] = dpixels[nsens][i]; 
						double A0 = scales2_old[nsens];
						double B0 = scales_old[nsens];
						double C0 = offs_old[nsens];
						double a = A0;
						double b = (B0 - 2 * C0 * A0);
						double c = (C0*C0*A0 -C0 * B0 - dpixels[nsens][i]);
						double p = -c/b;
						if (Math.abs(a) >= min_abs_a) {
							p= (-b + Math.sqrt(b*b - 4 * a * c))/(2 * a);
						}
						raw[nsens][i] = p;
						pa_data[indx][0] = p; // dpixels[nsens][i]; 
						pa_data[indx][1] = avg_pix[i];
						pa_data[indx][1] = avg_pix[i];
						indx++;
						indx++;
					}
					}
					// quadratic
					// quadratic
					pa_coeff[nsens] =(new PolynomialApproximation(0)).polynomialApproximation1d(pa_data, quadratic ? 2 : 1);
					pa_coeff[nsens] =(new PolynomialApproximation(0)).polynomialApproximation1d(pa_data, quadratic ? 2 : 1);
					double a = pa_coeff[nsens][2];
					double b = pa_coeff[nsens][1];
					double c = pa_coeff[nsens][0];
					double A = a;
					double C = -c/b;
					if (Math.abs(a) >= min_abs_a) {
						C = (-b + Math.sqrt(b*b - 4*a*c))/(2 * a);
					}
					}
					double B = 2 * C * a + b;
					scales2_new[nsens] = A;
					scales_new [nsens] = B;
					offs_new[nsens] =    C;
				}
				
				if (debug) {
				if (debug) {
					System.out.println("calibratePhotometric() nref="+nref);
					System.out.println("calibratePhotometric() nref="+nref);
					/*
					System.out.println(String.format("%3s %8s %8s %8s",
							"chn","   c   ","   b   ", " 1e6*a "));
					for (int n = 0; n < num_sens; n++) {
					for (int n = 0; n < num_sens; n++) {
						System.out.println(String.format("%2d: %8.4f %8.6f %8.6f", n,pa_coeff[n][0],pa_coeff[n][1], 1e6*pa_coeff[n][2]));
						System.out.println(String.format("%2d: %8.4f %8.6f %8.6f", n,pa_coeff[n][0],pa_coeff[n][1], 1e6*pa_coeff[n][2]));
					}
					}
					System.out.println();
					System.out.println();
					double [][] diffs = new double [num_sens][len];
					*/
					for (int n = 0; n < num_sens; n++) {
					System.out.println(String.format("%3s %10s %8s %8s %10s %8s %8s",
						Arrays.fill(diffs[n], Double.NaN);
						//  "chn","   c   ","   b   ", " 1e6*a "));          
					}
							"chn","  offs0  ","scale0 ", "scale20","  offs "," scale ", " scale2"));
					for (int i = 0; i < len; i++)  if (good_pix[i]) { // if (!Double.isNaN(avg_pix[i])){
					for (int n = 0; n < num_sens; n++) {
					for (int n = 0; n < num_sens; n++) {
//							diffs[n][i] = dpixels[n][i] - (scales[n] * avg_pix[i] + offsets[n]);
						System.out.println(String.format("%2d: %10.4f %8.5f %8.5f %10.4f %8.5f %8.5f",
							diffs[n][i] = -(avg_pix[i] - pa_coeff[n][2] * dpixels[n][i] * dpixels[n][i] - pa_coeff[n][1] * dpixels[n][i] - pa_coeff[n][0]); 
								n,offs_old[n],scales_old[n], 1e6*scales2_old[n],
						}
								offs_new[n],scales_new[n], 1e6*scales2_new[n]));
					}
					(new ShowDoubleFloatArrays()).showArrays( // out of boundary 15
							diffs,
							width,
							height,
							true,
							"photometric-quad-err"+nref);
					}
					}
					System.out.println();
					
					
					
					
				Arrays.fill(offsets,0.0);
				Arrays.fill(scales,0.0);
				s0 =  0.0;
				sx=   0.0;
				sx2 = 0.0;
				Arrays.fill(sy,0.0);
				Arrays.fill(sxy,0.0);
				for (int i = 0; i < len; i++)  if (good_pix[i]) { // !Double.isNaN(avg_pix[i])){
					s0 +=  1.0;
					sx +=  avg_pix[i];
					sx2 += avg_pix[i] * avg_pix[i];
					for (int n = 0; n < num_sens; n++) {
						sy[n] +=  dpixels[n][i];
						sxy[n] += dpixels[n][i] * avg_pix[i];
					}
				}
				for (int n = 0; n < num_sens; n++) {
					double d = s0 * sx2 + sx * sy[n];
					scales[n] =  (sxy[n] * s0 + sy[n] * sy[n]) / d;
					offsets[n] = (sy[n] * sx2 -sxy[n]*sx) / d;
				}
					
					
				
				if (debug) {
					System.out.println("calibratePhotometric() nref="+nref);
					for (int n = 0; n < num_sens; n++) {
						System.out.println(String.format("%2d: %8.4f %8.6f", n,offsets[n],scales[n]));
					}
					System.out.println();
					double [][] diffs = new double [num_sens][len];
					double [][] diffs = new double [num_sens][len];
					for (int n = 0; n < num_sens; n++) {
					for (int n = 0; n < num_sens; n++) {
						Arrays.fill(diffs[n], Double.NaN);
						Arrays.fill(diffs[n], Double.NaN);
					}
					}
					for (int i = 0; i < len; i++)  if (good_pix[i]) { // if (!Double.isNaN(avg_pix[i])){
					for (int i = 0; i < len; i++)  if (good_pix[i]) { // if (!Double.isNaN(avg_pix[i])){
						for (int n = 0; n < num_sens; n++) {
						for (int n = 0; n < num_sens; n++) {
							diffs[n][i] = dpixels[n][i] - (scales[n] * avg_pix[i] + offsets[n]);
							double poffs = raw[n][i] - offs_new[n];
							diffs[n][i] = -(avg_pix[i] -
									(poffs * scales_new[n] + poffs*poffs*scales2_new[n]));  
						}
						}
					}
					}
					(new ShowDoubleFloatArrays()).showArrays( // out of boundary 15
					(new ShowDoubleFloatArrays()).showArrays( // out of boundary 15
@@ -2605,14 +2613,13 @@ public class QuadCLT extends QuadCLTCPU {
							width,
							width,
							height,
							height,
							true,
							true,
							"photometric-err"+nref);
							"photometric-quad-err"+nref);

					// dpix_orig[n] =  dpixels[n].clone();
					double [][] corrected = new double [num_sens][len];
					double [][] corrected = new double [num_sens][len];
					for (int n = 0; n < num_sens; n++) {
					for (int n = 0; n < num_sens; n++) {
						Arrays.fill(corrected[n], Double.NaN);
						Arrays.fill(corrected[n], Double.NaN);
						for (int i = 0; i < len; i++)  if (!Double.isNaN(dpixels[n][i])){
						for (int i = 0; i < len; i++)  if (!Double.isNaN(dpixels[n][i])){
							corrected[n][i] = (dpixels[n][i] - offsets[n])/scales[n];
							double poffs = raw[n][i] - offs_new[n];
							corrected[n][i] =	(poffs * scales_new[n] + poffs*poffs*scales2_new[n]);  
						}
						}
					}
					}


@@ -2621,15 +2628,16 @@ public class QuadCLT extends QuadCLTCPU {
							width,
							width,
							height,
							height,
							true,
							true,
							"photometric-corr"+nref);
							"photometric-quad-corr"+nref);
				}				
				}				
				//max_diff
				//max_diff
				if (nref < (num_refines-1)) {
				if (nref < (num_refines-1)) {
					for (int i = 0; i < len; i++)  if (good_pix[i]) { // !Double.isNaN(avg_pix[i])){
					for (int i = 0; i < len; i++)  if (good_pix[i]) { // !Double.isNaN(avg_pix[i])){
						for (int n = 0; n < num_sens; n++) {
						for (int n = 0; n < num_sens; n++) {
							double diff = Math.abs(dpixels[n][i] - (scales[n] * avg_pix[i] + offsets[n]));
							double poffs = raw[n][i] - offs_new[n];
							double diff = Math.abs(avg_pix[i] -
									(poffs * scales_new[n] + poffs*poffs*scales2_new[n]));
							if (diff > max_diff) {
							if (diff > max_diff) {
//								dpixels[n][i] = Double.NaN;
								good_pix[i] = false;
								good_pix[i] = false;
								break;
								break;
							}
							}
@@ -2637,22 +2645,12 @@ public class QuadCLT extends QuadCLTCPU {
					}
					}
				}
				}
			}
			}
			double [] offsets_old = ref_scene.getLwirOffsets();
			double [] scales_old =  ref_scene.getLwirScales();
			double [] scales2_old = ref_scene.getLwirScales2();
			double [] offsets_new = new double[num_sens];
			double [] scales_new =  new double[num_sens];
			double [] scales2_new = new double[num_sens];
			for (int n = 0; n < num_sens; n++) {
				scales_new[n] = scales_old[n]/scales[n];
				offsets_new[n] = offsets_old[n]  + offsets[n] / scales_old[n];
			}
			System.out.println("calibratePhotometric() Updated calibration:");
			System.out.println("calibratePhotometric() Updated calibration:");
			for (int n = 0; n < num_sens; n++) {
			for (int n = 0; n < num_sens; n++) {
				System.out.println(String.format("%2d: %8.4f %8.6f %8.6f", n,offsets_new[n],scales_new[n], scales2_new[n]));
				System.out.println(String.format("%2d: %10.4f %8.6f %8.6f", n,offs_new[n],scales_new[n], 1E6*scales2_new[n]));
			}
			}
			System.out.println();
			System.out.println();
			ref_scene.setLwirOffsets (offsets_new);
			ref_scene.setLwirOffsets (offs_new);
			ref_scene.setLwirScales  (scales_new);
			ref_scene.setLwirScales  (scales_new);
			ref_scene.setLwirScales2 (scales2_new);
			ref_scene.setLwirScales2 (scales2_new);
			return true;
			return true;
+20 −4
Original line number Original line Diff line number Diff line
@@ -151,6 +151,7 @@ public class QuadCLTCPU {
	boolean new_image_data =                               false;
	boolean new_image_data =                               false;
    boolean [][]                                           saturation_imp = null; // (near) saturated pixels or null
    boolean [][]                                           saturation_imp = null; // (near) saturated pixels or null
    boolean                                                is_aux = false;
    boolean                                                is_aux = false;
    String                                                 photometric_scene = null;
    double  []                                             lwir_offsets = null; // per image subtracted values
    double  []                                             lwir_offsets = null; // per image subtracted values
    double []                                              lwir_scales =  null;  // per image scales
    double []                                              lwir_scales =  null;  // per image scales
    double []                                              lwir_scales2 = null;  // per image quadratic scales
    double []                                              lwir_scales2 = null;  // per image quadratic scales
@@ -264,6 +265,8 @@ public class QuadCLTCPU {
		if (qParent.saturation_imp != null) this.saturation_imp = qParent.saturation_imp.clone(); // each camera will be re-written, not just modified, so shallow copy 
		if (qParent.saturation_imp != null) this.saturation_imp = qParent.saturation_imp.clone(); // each camera will be re-written, not just modified, so shallow copy 
		this.is_aux =                 qParent.is_aux;
		this.is_aux =                 qParent.is_aux;
//		this.is_mono =                 qParent.is_mono;
//		this.is_mono =                 qParent.is_mono;
		
		this.photometric_scene =      qParent.photometric_scene; 
		this.lwir_offsets =           ErsCorrection.clone1d(qParent.lwir_offsets);
		this.lwir_offsets =           ErsCorrection.clone1d(qParent.lwir_offsets);
		this.lwir_scales =            ErsCorrection.clone1d(qParent.lwir_scales);
		this.lwir_scales =            ErsCorrection.clone1d(qParent.lwir_scales);
		this.lwir_scales2 =           ErsCorrection.clone1d(qParent.lwir_scales2);
		this.lwir_scales2 =           ErsCorrection.clone1d(qParent.lwir_scales2);
@@ -1807,13 +1810,20 @@ public class QuadCLTCPU {
    	} else {
    	} else {
    		lwir_offset = Double.NaN;
    		lwir_offset = Double.NaN;
    	}
    	}
    	this.photometric_scene = getImageName();
    }
    public String getPhotometricScene() {
    	return this.photometric_scene;
    }
    }
    
    
    public void setLwirScales(double [] scales) {
    public void setLwirScales(double [] scales) {
    	lwir_scales = scales; // will need to update properties!
    	lwir_scales = scales; // will need to update properties!
    	this.photometric_scene = getImageName();
    }
    }
    public void setLwirScales2(double [] scales2) {
    public void setLwirScales2(double [] scales2) {
    	lwir_scales2 = scales2; // will need to update properties!
    	lwir_scales2 = scales2; // will need to update properties!
    	this.photometric_scene = getImageName();
    }
    }
    public double [] getColdHot() { // USED in lwir
    public double [] getColdHot() { // USED in lwir
@@ -2018,7 +2028,9 @@ public class QuadCLTCPU {
			properties.setProperty(prefix+"lwir_scales2",
			properties.setProperty(prefix+"lwir_scales2",
					IntersceneMatchParameters.doublesToString(this.lwir_scales2));
					IntersceneMatchParameters.doublesToString(this.lwir_scales2));
		}
		}
		if (this.photometric_scene != null) {
			properties.setProperty(prefix+"photometric_scene", this.photometric_scene);
		}
	}
	}
@@ -2066,6 +2078,10 @@ public class QuadCLTCPU {
			properties.setProperty(this_prefix+"lwir_scales2",
			properties.setProperty(this_prefix+"lwir_scales2",
					IntersceneMatchParameters.doublesToString(this.lwir_scales2));
					IntersceneMatchParameters.doublesToString(this.lwir_scales2));
		}
		}
		if (other_properties.getProperty(other_prefix+"photometric_scene")!=null) {
			this.photometric_scene= (String) other_properties.getProperty(other_prefix+"photometric_scene");
			properties.setProperty(this_prefix+"photometric_scene", this.photometric_scene);
		}
		
		
		
		
		/*
		/*
@@ -2190,9 +2206,9 @@ public class QuadCLTCPU {
			this.lwir_scales2= IntersceneMatchParameters.StringToDoubles(
			this.lwir_scales2= IntersceneMatchParameters.StringToDoubles(
					properties.getProperty(prefix+"lwir_scales2"),0);
					properties.getProperty(prefix+"lwir_scales2"),0);
		}
		}
			
		if (properties.getProperty(prefix+"photometric_scene")!=null) {
		
			this.photometric_scene= (String) properties.getProperty(prefix+"photometric_scene");
		
		}
	}
	}
	public void setKernelImageFile(ImagePlus img_kernels){ // not used in lwir
	public void setKernelImageFile(ImagePlus img_kernels){ // not used in lwir