Commit 001d0838 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Created partial kernel with monochrome (LWIR) sensors

parent 0d69b27b
Loading
Loading
Loading
Loading
+45 −7
Original line number Diff line number Diff line
@@ -208,13 +208,22 @@ public class Aberration_Calibration extends PlugInFrame implements ActionListene
	public static EyesisAberrations.OTFFilterParameters OTF_FILTER = new  EyesisAberrations.OTFFilterParameters(
			0.008, // deconvInvert - when FFT component is less than this fraction of the maximal value, replace 1/z with Z
			2.0,   // zerofreqSize - used for filtering oversampling artifacts - size of zero freq maximum (if absent on simulated model PS)
			2.5,   // smoothPS - smooth model PS for rejecting aliases (0 - no smooth, >0 additional Gauss before FFT smaller than normal by this ratio)
			0.002, // deconvInvert - when FFT component is less than this fraction of the maximal value, replace 1/z with Z
			1.0,   // zerofreqSize - used for filtering oversampling artifacts - size of zero freq maximum (if absent on simulated model PS)
			1.25,   // smoothPS - smooth model PS for rejecting aliases (0 - no smooth, >0 additional Gauss before FFT smaller than normal by this ratio)
			0.02,  // thresholdHigh -used for filtering oversampling artifacts - relative to max PS value to make filter completely rejecting
			0.002  // thresholdLow - used for filtering oversampling artifacts - relative to max PS to make filter completely transmissive
	);
	public static EyesisAberrations.OTFFilterParameters OTF_FILTER_LWIR = new  EyesisAberrations.OTFFilterParameters(
			0.01,  // deconvInvert - when FFT component is less than this fraction of the maximal value, replace 1/z with Z
			1.0,   // zerofreqSize - used for filtering oversampling artifacts - size of zero freq maximum (if absent on simulated model PS)
			1.25,  // smoothPS - smooth model PS for rejecting aliases (0 - no smooth, >0 additional Gauss before FFT smaller than normal by this ratio)
			0.2,   // thresholdHigh -used for filtering oversampling artifacts - relative to max PS value to make filter completely rejecting
			0.05   // thresholdLow - used for filtering oversampling artifacts - relative to max PS to make filter completely transmissive
	);
	public static MatchSimulatedPattern.PatternDetectParameters PATTERN_DETECT = new MatchSimulatedPattern.PatternDetectParameters (
			0.4, // GAUSS_WIDTH=    0.4; //0 - use Hamming window - initWindowFunction()
			0.2, // corrGamma - pattern detection: gamma applied to PS
@@ -1185,7 +1194,7 @@ if (MORE_BUTTONS) {
			return;
/* ======================================================================== */
		} else if (label.equals("Conf. OTF Filter")) {
			showOTFFilterParametersDialog(OTF_FILTER);
			showOTFFilterParametersDialog(OTF_FILTER, OTF_FILTER_LWIR); // second may be null
			return;
/* ======================================================================== */
		} else if (label.equals("Conf. Interpolation")) {
@@ -9168,7 +9177,8 @@ if (MORE_BUTTONS) {
//					FFT_OVERLAP, ////int            fft_overlap,
//					FFT_SIZE, //int               fft_size,
					PSF_SUBPIXEL, // //int           PSF_subpixel,
					OTF_FILTER, // //OTFFilterParameters otfFilterParameters,
					OTF_FILTER,      // OTFFilterParameters otfFilterParameters,
					OTF_FILTER_LWIR, //OTFFilterParameters otfFilterParameters_lwir,
					PSF_PARS, //PSFParameters psfParameters,
					INVERSE.dSize, //int          PSFKernelSize, // size of square used in the new map (should be multiple of map step)
@@ -15516,6 +15526,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
    	boolean select_INVERSE=!select;
    	boolean select_PSF_PARS=!select;
    	boolean select_OTF_FILTER=!select;
    	boolean select_OTF_FILTER_LWIR=!select;
    	boolean select_PATTERN_DETECT=!select;
    	boolean select_COMPONENTS=!select;
    	boolean select_SHOW_RESULTS=!select;
@@ -15557,6 +15568,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
        	gd.addCheckbox("INVERSE",select_INVERSE);
        	gd.addCheckbox("PSF_PARS",select_PSF_PARS);
        	gd.addCheckbox("OTF_FILTER",select_OTF_FILTER);
        	gd.addCheckbox("OTF_FILTER_LWIR",select_OTF_FILTER_LWIR);
        	gd.addCheckbox("PATTERN_DETECT",select_PATTERN_DETECT);
        	gd.addCheckbox("COMPONENTS",select_COMPONENTS);
        	gd.addCheckbox("SHOW_RESULTS",select_SHOW_RESULTS);
@@ -15599,6 +15611,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
        	select_INVERSE=gd.getNextBoolean();
        	select_PSF_PARS=gd.getNextBoolean();
        	select_OTF_FILTER=gd.getNextBoolean();
        	select_OTF_FILTER_LWIR=gd.getNextBoolean();
        	select_PATTERN_DETECT=gd.getNextBoolean();
        	select_COMPONENTS=gd.getNextBoolean();
        	select_SHOW_RESULTS=gd.getNextBoolean();
@@ -15639,6 +15652,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
        if (select_INVERSE) INVERSE.setProperties(           "INVERSE.", properties);
        if (select_PSF_PARS) PSF_PARS.setProperties(          "PSF_PARS.", properties);
        if (select_OTF_FILTER) OTF_FILTER.setProperties(         "OTF_FILTER.", properties);
        if (select_OTF_FILTER) OTF_FILTER_LWIR.setProperties(    "OTF_FILTER_LWIR.", properties);
        if (select_PATTERN_DETECT) PATTERN_DETECT.setProperties(    "PATTERN_DETECT.", properties);
        if (select_COMPONENTS) COMPONENTS.setProperties(        "COMPONENTS.", properties);
        if (select_SHOW_RESULTS) SHOW_RESULTS.setProperties(      "SHOW_RESULTS.", properties);
@@ -15682,6 +15696,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
       INVERSE.getProperties("INVERSE.", properties);
       PSF_PARS.getProperties("PSF_PARS.", properties);
       OTF_FILTER.getProperties("OTF_FILTER.", properties);
       OTF_FILTER_LWIR.getProperties("OTF_FILTER_LWIR.", properties);
       PATTERN_DETECT.getProperties("PATTERN_DETECT.", properties);
       COMPONENTS.getProperties("COMPONENTS.", properties);
       SHOW_RESULTS.getProperties("SHOW_RESULTS.", properties);
@@ -20391,13 +20406,29 @@ use the result to create a rejectiobn mask - if the energy was high, (multiplica
/* ======================================================================== */
/* ======================================================================== */
/**TODO: add variable gaussian filter to direct psf */
	public boolean showOTFFilterParametersDialog(EyesisAberrations.OTFFilterParameters otfFilterParameters) {
	public boolean showOTFFilterParametersDialog(
			EyesisAberrations.OTFFilterParameters otfFilterParameters,
			EyesisAberrations.OTFFilterParameters otfFilterParameters_lwir) {
		GenericDialog gd = new GenericDialog("OTF Filter parameters");
		if (otfFilterParameters_lwir!=null) {
			gd.addMessage("EO (high-res color) sensors:");
		}
		gd.addNumericField("Invert deconvolution if less than",                           otfFilterParameters.deconvInvert, 3);
		gd.addNumericField("OTF zero frequency size on power spectrum ",                  otfFilterParameters.zerofreqSize, 3); //2.0;
		gd.addNumericField("OTF smouth PS to generate alias rejection mask (0 - none)",   otfFilterParameters.smoothPS,      3); //2.5 - smooth model PS for rejecting aliases (0 - no smouth, >0 additional Gauss )
		gd.addNumericField("OTF relative high value of PS for rejection mask ",           otfFilterParameters.thresholdHigh, 3); //0.1
		gd.addNumericField("OTF relative low  value of PS for rejection mask ",           otfFilterParameters.thresholdLow,  3); //0.01; // when FFT component is less than this fraction of the maximal value, replace 1/z with Z
		if (otfFilterParameters_lwir!=null) {
			gd.addMessage("LWIR (low-res mono) sensors:");
			gd.addNumericField("Invert deconvolution if less than",                           otfFilterParameters_lwir.deconvInvert, 3);
			gd.addNumericField("OTF zero frequency size on power spectrum ",                  otfFilterParameters_lwir.zerofreqSize, 3); //2.0;
			gd.addNumericField("OTF smouth PS to generate alias rejection mask (0 - none)",   otfFilterParameters_lwir.smoothPS,      3); //2.5 - smooth model PS for rejecting aliases (0 - no smouth, >0 additional Gauss )
			gd.addNumericField("OTF relative high value of PS for rejection mask ",           otfFilterParameters_lwir.thresholdHigh, 3); //0.1
			gd.addNumericField("OTF relative low  value of PS for rejection mask ",           otfFilterParameters_lwir.thresholdLow,  3); //0.01; // when FFT component is less than this fraction of the maximal value, replace 1/z with Z
		}
		gd.showDialog();
		if (gd.wasCanceled()) return false;
		otfFilterParameters.deconvInvert=        gd.getNextNumber();
@@ -20405,6 +20436,13 @@ use the result to create a rejectiobn mask - if the energy was high, (multiplica
		otfFilterParameters.smoothPS=            gd.getNextNumber();
		otfFilterParameters.thresholdHigh=       gd.getNextNumber();
		otfFilterParameters.thresholdLow=        gd.getNextNumber();
		if (otfFilterParameters_lwir!=null) {
			otfFilterParameters_lwir.deconvInvert=        gd.getNextNumber();
			otfFilterParameters_lwir.zerofreqSize=        gd.getNextNumber();
			otfFilterParameters_lwir.smoothPS=            gd.getNextNumber();
			otfFilterParameters_lwir.thresholdHigh=       gd.getNextNumber();
			otfFilterParameters_lwir.thresholdLow=        gd.getNextNumber();
		}
		return true;
	}
/* ======================================================================== */
+143 −69

File changed.

Preview size limit exceeded, changes collapsed.

+0 −2
Original line number Diff line number Diff line
@@ -4807,8 +4807,6 @@ public class MatchSimulatedPattern {
							}
						}
						//							if (nowDebugCell)correctedPatternCrossLocationAverage4(
						double [] centerXY=correctedPatternCrossLocation(
								lwirReaderParameters, // LwirReaderParameters lwirReaderParameters, // null is OK
								patternGrid[iUV[1]][iUV[0]][0], // initial coordinates of the pattern cross point
+22 −2
Original line number Diff line number Diff line
@@ -1009,14 +1009,32 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
				y0);
	}

	public double [] extractSimulMono ( // TODO: can use twice smaller barray
			double [] localbArray,
			SimulParameters  simulParameters,
			int outSubdiv,  // subdivide output pixels - now 4
			int size,    // number of Bayer cells in width of the square selection (half number of pixels)
			double x0,    // selection center, X (in pixels)
			double y0) {
		return extractSimulMono ( // TODO: can use twice smaller barray
				localbArray,
				false, // boolean invert,
				simulParameters,
				outSubdiv,  // subdivide output pixels - now 4
				size,    // number of Bayer cells in width of the square selection (half number of pixels)
				x0,    // selection center, X (in pixels)
				y0);
	}

	public double [] extractSimulMono ( // TODO: can use twice smaller barray
			double [] localbArray,
			boolean invert,
			SimulParameters  simulParameters,
			int outSubdiv,  // subdivide output pixels - now 4
			int size,    // number of Bayer cells in width of the square selection (half number of pixels)
			double x0,    // selection center, X (in pixels)
			double y0) {
		double pattern_sign = invert? -1.0 : 1.0;
		int sampleWidth=(int) (Math.sqrt(simulParameters.fill)*simulParameters.subdiv);
		int sampleN=sampleWidth*sampleWidth;
		if      (sampleWidth<1)     sampleWidth=1;
@@ -1043,7 +1061,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
						return null;
					}
				}
				simul_pixels[iy*size+ix]= (s-sampleAverage)/sampleAverage;
				simul_pixels[iy*size+ix]= pattern_sign * (s - sampleAverage) / sampleAverage;
			}
		}
		if (this.debugLevel>2) {
@@ -1069,6 +1087,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
		return rslt;
	}

	// colorComp == -1 = mono, positive, colorComp == -2 - mono, negative
	public double[] extractBayerSim (
			float [][] spixels, // [0] - regular pixels, [1] - shifted by 1/2 diagonally, for checker greens
			int full_width,
@@ -1106,6 +1125,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
			}
		} else { // components 0..3
			int ser;
			double pattern_sign = (colorComp == -2)? -1.0: 1.0;
			if (colorComp < 0) {
				ser = 1; // offset by 1/2 pix? should it be so? // FIXME: verify and fix if needed - compare to extractSimulMono()
			} else {
@@ -1125,7 +1145,7 @@ Cv=(Cy*x-Cx*y)+(-Cy*Dx+Cx*Dy)
				else if (iy >= full_height) iy = full_height - 1;
				if (ix < 0) ix = 0;
				else if (ix >= full_width) iy = full_width - 1;
				result[index] = spixels[ser][iy * full_width + ix];
				result[index] = pattern_sign * spixels[ser][iy * full_width + ix];
			}
		}
		return result;
+22 −18
Original line number Diff line number Diff line
@@ -171,7 +171,7 @@ public class DoubleGaussianBlur {
	        if (kRadius > maxRadius) kRadius = maxRadius;
	        double[][] kernel = new double[2][kRadius];
	        for (int i=0; i<kRadius; i++)               // Gaussian function
	            kernel[0][i] = (double)(Math.exp(-0.5*i*i/sigma/sigma));
	            kernel[0][i] = (Math.exp(-0.5*i*i/sigma/sigma));
	        if (kRadius < maxRadius && kRadius > 3) {   // edge correction
	            double sqrtSlope = Double.MAX_VALUE;
	            int r = kRadius;
@@ -184,7 +184,7 @@ public class DoubleGaussianBlur {
	                    break;
	            }
	            for (int r1 = r+2; r1 < kRadius; r1++)
	                kernel[0][r1] = (double)((kRadius-r1)*(kRadius-r1)*sqrtSlope*sqrtSlope);
	                kernel[0][r1] = (kRadius-r1)*(kRadius-r1)*sqrtSlope*sqrtSlope;
	        }
	        double sum;                                 // sum over all kernel elements for normalization
	        if (kRadius < maxRadius) {
@@ -197,9 +197,9 @@ public class DoubleGaussianBlur {
	        double rsum = 0.5 + 0.5*kernel[0][0]/sum;
	        for (int i=0; i<kRadius; i++) {
	            double v = (kernel[0][i]/sum);
	            kernel[0][i] = (double)v;
	            kernel[0][i] = v;
	            rsum -= v;
	            kernel[1][i] = (double)rsum;
	            kernel[1][i] = rsum;
	            //IJ.log("k["+i+"]="+(float)v+" sum="+(float)rsum);
	        }
	        return kernel;
@@ -213,6 +213,10 @@ public class DoubleGaussianBlur {
	     */
	    void downscaleLine(double[] pixels, double[] cache, double[] kernel,
	            int reduceBy, int pixel0, int unscaled0, int length, int pointInc, int newLength) {
	    	if (pixel0 > pixels.length) {
	    		System.out.println("++++++ Error in DoubleGaussianBlur, pixel0="+pixel0+", pixels.length="+(pixels.length));
	    		return;
	    	}
	        double first = pixels[pixel0];
	        double last = pixels[pixel0 + pointInc*(length-1)];
	        int xin = unscaled0 - reduceBy/2;
@@ -241,13 +245,13 @@ public class DoubleGaussianBlur {
	        double[] kernel = new double[3*unitLength];
	        for (int i=0; i<=unitLength/2; i++) {
	            double x = i/(double)unitLength;
	            double v = (double)((0.75-x*x)/unitLength);
	            double v = (0.75-x*x)/unitLength;
	            kernel[mid-i] = v;
	            kernel[mid+i] = v;
	        }
	        for (int i=unitLength/2+1; i<(unitLength*3+1)/2; i++) {
	            double x = i/(double)unitLength;
	            double v = (double)((0.125 + 0.5*(x-1)*(x-2))/unitLength);
	            double v = (0.125 + 0.5*(x-1)*(x-2))/unitLength;
	            kernel[mid-i] = v;
	            kernel[mid+i] = v;
	        }
@@ -284,13 +288,13 @@ public class DoubleGaussianBlur {
	        kernel[0] = 0;
	        for (int i=0; i<unitLength; i++) {
	            double x = i/(double)unitLength;
	            double v = (double)((2./3. -x*x*(1-0.5*x)));
	            double v = ((2./3. -x*x*(1-0.5*x)));
	            kernel[mid+i] = v;
	            kernel[mid-i] = v;
	        }
	        for (int i=unitLength; i<2*unitLength; i++) {
	            double x = i/(double)unitLength;
	            double v = (double)((2.-x)*(2.-x)*(2.-x)/6.);
	            double v = (2.-x)*(2.-x)*(2.-x)/6.;
	            kernel[mid+i] = v;
	            kernel[mid-i] = v;
	        }