Commit 46faeae7 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

line/edge emphasis after debayer

parent 4648e870
Loading
Loading
Loading
Loading
+34 −8
Original line number Original line Diff line number Diff line
@@ -1805,10 +1805,18 @@ public class EyesisCorrectionParameters {
  		public double vignetting_range  = 5.0; // do not try to correct vignetting less than vignetting_max/vignetting_range
  		public double vignetting_range  = 5.0; // do not try to correct vignetting less than vignetting_max/vignetting_range
  		
  		
  		public boolean color_DCT        = true; // false - use old color processing mode
  		public boolean color_DCT        = true; // false - use old color processing mode
  		public double  sigma_rb =         0.5; // additional (to G) blur for R and B
  		public double  sigma_rb =         0.9; // additional (to G) blur for R and B
  		public double  sigma_y =          0.5; // blur for G contribution to Y
  		public double  sigma_y =          0.7; // blur for G contribution to Y
  		public double  sigma_color =      1.0; // blur for Pb and Pr in addition to that of Y
  		public double  sigma_color =      0.7; // blur for Pb and Pr in addition to that of Y
  		public double  line_thershold =   1.0; // line detection amplitude to apply line enhancement
  		public double  line_thershold =   1.0; // line detection amplitude to apply line enhancement - not used?
  		public double  nonlin_max_y =     1.0; // maximal amount of nonlinear line/edge emphasis for Y component
  		public double  nonlin_max_c =     1.0; // maximal amount of nonlinear line/edge emphasis for C component
  		public double  nonlin_y =         0.1; // amount of nonlinear line/edge emphasis for Y component
  		public double  nonlin_c =         0.01; // amount of nonlinear line/edge emphasis for C component
  		public double  nonlin_corn =      0.5;  // relative weight for nonlinear corner elements
  		

  		public DCTParameters(){}
  		
  		
  		public DCTParameters(
  		public DCTParameters(
  				int dct_size,
  				int dct_size,
@@ -1863,13 +1871,17 @@ public class EyesisCorrectionParameters {
  			properties.setProperty(prefix+"convolve_direct",    this.convolve_direct+"");
  			properties.setProperty(prefix+"convolve_direct",    this.convolve_direct+"");
  			properties.setProperty(prefix+"vignetting_max",   this.vignetting_max+"");
  			properties.setProperty(prefix+"vignetting_max",   this.vignetting_max+"");
  			properties.setProperty(prefix+"vignetting_range",   this.vignetting_range+"");
  			properties.setProperty(prefix+"vignetting_range",   this.vignetting_range+"");

  			properties.setProperty(prefix+"color_DCT",          this.color_DCT+"");
  			properties.setProperty(prefix+"color_DCT",          this.color_DCT+"");
  			properties.setProperty(prefix+"sigma_rb",           this.sigma_rb+"");
  			properties.setProperty(prefix+"sigma_rb",           this.sigma_rb+"");
  			properties.setProperty(prefix+"sigma_y",            this.sigma_y+"");
  			properties.setProperty(prefix+"sigma_y",            this.sigma_y+"");
  			properties.setProperty(prefix+"sigma_color",        this.sigma_color+"");
  			properties.setProperty(prefix+"sigma_color",        this.sigma_color+"");
  			properties.setProperty(prefix+"line_thershold",     this.line_thershold+"");
  			properties.setProperty(prefix+"line_thershold",     this.line_thershold+"");
  			
  			
  			properties.setProperty(prefix+"nonlin_max_y",           this.nonlin_max_y+"");
  			properties.setProperty(prefix+"nonlin_max_c",           this.nonlin_max_c+"");
  			properties.setProperty(prefix+"nonlin_y",           this.nonlin_y+"");
  			properties.setProperty(prefix+"nonlin_c",           this.nonlin_c+"");
  			properties.setProperty(prefix+"nonlin_corn",        this.nonlin_corn+"");
  		}
  		}
  		public void getProperties(String prefix,Properties properties){
  		public void getProperties(String prefix,Properties properties){
  			if (properties.getProperty(prefix+"dct_size")!=null) this.dct_size=Integer.parseInt(properties.getProperty(prefix+"dct_size"));
  			if (properties.getProperty(prefix+"dct_size")!=null) this.dct_size=Integer.parseInt(properties.getProperty(prefix+"dct_size"));
@@ -1912,6 +1924,11 @@ public class EyesisCorrectionParameters {
  			if (properties.getProperty(prefix+"sigma_color")!=null)    this.sigma_color=Double.parseDouble(properties.getProperty(prefix+"sigma_color"));
  			if (properties.getProperty(prefix+"sigma_color")!=null)    this.sigma_color=Double.parseDouble(properties.getProperty(prefix+"sigma_color"));
  			if (properties.getProperty(prefix+"line_thershold")!=null) this.line_thershold=Double.parseDouble(properties.getProperty(prefix+"line_thershold"));
  			if (properties.getProperty(prefix+"line_thershold")!=null) this.line_thershold=Double.parseDouble(properties.getProperty(prefix+"line_thershold"));


  			if (properties.getProperty(prefix+"nonlin_max_y")!=null)       this.nonlin_max_y=Double.parseDouble(properties.getProperty(prefix+"nonlin_max_y"));
  			if (properties.getProperty(prefix+"nonlin_max_c")!=null)       this.nonlin_max_c=Double.parseDouble(properties.getProperty(prefix+"nonlin_max_c"));
  			if (properties.getProperty(prefix+"nonlin_y")!=null)       this.nonlin_y=Double.parseDouble(properties.getProperty(prefix+"nonlin_y"));
  			if (properties.getProperty(prefix+"nonlin_c")!=null)       this.nonlin_c=Double.parseDouble(properties.getProperty(prefix+"nonlin_c"));
  			if (properties.getProperty(prefix+"nonlin_corn")!=null)    this.nonlin_corn=Double.parseDouble(properties.getProperty(prefix+"nonlin_corn"));
  		}
  		}
  		public boolean showDialog() {
  		public boolean showDialog() {
  			GenericDialog gd = new GenericDialog("Set DCT parameters");
  			GenericDialog gd = new GenericDialog("Set DCT parameters");
@@ -1949,12 +1966,17 @@ public class EyesisCorrectionParameters {
  			gd.addCheckbox    ("Convolve directly with symmetrical kernel (debug feature) ",     this.convolve_direct);
  			gd.addCheckbox    ("Convolve directly with symmetrical kernel (debug feature) ",     this.convolve_direct);
  			gd.addNumericField("Value (max) in vignetting data to correspond to 1x in the kernel",this.vignetting_max,      3);
  			gd.addNumericField("Value (max) in vignetting data to correspond to 1x in the kernel",this.vignetting_max,      3);
  			gd.addNumericField("Do not try to correct vignetting smaller than this fraction of max",this.vignetting_range,  3);
  			gd.addNumericField("Do not try to correct vignetting smaller than this fraction of max",this.vignetting_range,  3);
  			
  			gd.addCheckbox    ("Use DCT-base color conversion",                                   this.color_DCT             );
  			gd.addCheckbox    ("Use DCT-base color conversion",                                   this.color_DCT             );
  			gd.addNumericField("Gaussian sigma to apply to R and B (in addition to G), pix",      this.sigma_rb,            3);
  			gd.addNumericField("Gaussian sigma to apply to R and B (in addition to G), pix",      this.sigma_rb,            3);
  			gd.addNumericField("Gaussian sigma to apply to Y in the MDCT domain, pix",            this.sigma_y,             3);
  			gd.addNumericField("Gaussian sigma to apply to Y in the MDCT domain, pix",            this.sigma_y,             3);
  			gd.addNumericField("Gaussian sigma to apply to Pr and Pb in the MDCT domain, pix",    this.sigma_color,         3);
  			gd.addNumericField("Gaussian sigma to apply to Pr and Pb in the MDCT domain, pix",    this.sigma_color,         3);
  			gd.addNumericField("Threshold for line detection",                                    this.line_thershold,      3);
  			gd.addNumericField("Threshold for line detection (not yet used)",                     this.line_thershold,      3);

  			gd.addNumericField("Maximal amount of non-linear emphasis for linear edges for Y component",  this.nonlin_max_y,3);
  			gd.addNumericField("Maximal amount of non-linear emphasis for linear edges for color diffs.", this.nonlin_max_c,3);
  			gd.addNumericField("Sensitivity of non-linear emphasis for linear edges for Y component",  this.nonlin_y,       3);
  			gd.addNumericField("Sensitivity of non-linear emphasis for linear edges for color diffs.", this.nonlin_c,       3);
  			gd.addNumericField("Corretion for diagonal/corner emphasis elements",                 this.nonlin_corn,         3);
  			
  			
  			WindowTools.addScrollBars(gd);
  			WindowTools.addScrollBars(gd);
  			gd.showDialog();
  			gd.showDialog();
@@ -1994,13 +2016,17 @@ public class EyesisCorrectionParameters {
  			this.convolve_direct=       gd.getNextBoolean();
  			this.convolve_direct=       gd.getNextBoolean();
  			this.vignetting_max=        gd.getNextNumber();
  			this.vignetting_max=        gd.getNextNumber();
  			this.vignetting_range=      gd.getNextNumber();
  			this.vignetting_range=      gd.getNextNumber();

  			this.color_DCT=             gd.getNextBoolean();
  			this.color_DCT=             gd.getNextBoolean();
  			this.sigma_rb=              gd.getNextNumber();
  			this.sigma_rb=              gd.getNextNumber();
  			this.sigma_y=               gd.getNextNumber();
  			this.sigma_y=               gd.getNextNumber();
  			this.sigma_color=           gd.getNextNumber();
  			this.sigma_color=           gd.getNextNumber();
  			this.line_thershold=        gd.getNextNumber();
  			this.line_thershold=        gd.getNextNumber();
  			
  			
  			this.nonlin_max_y=          gd.getNextNumber();
  			this.nonlin_max_c=          gd.getNextNumber();
  			this.nonlin_y=              gd.getNextNumber();
  			this.nonlin_c=              gd.getNextNumber();
  			this.nonlin_corn=           gd.getNextNumber();
  			//  	    MASTER_DEBUG_LEVEL= (int) gd.getNextNumber();
  			//  	    MASTER_DEBUG_LEVEL= (int) gd.getNextNumber();
  			return true;
  			return true;
  		}  
  		}  
+182 −1
Original line number Original line Diff line number Diff line
@@ -1200,11 +1200,34 @@ public class EyesisDCT {
	        			debugLevel);
	        			debugLevel);
	        }
	        }
			if (dct_parameters.color_DCT){ // convert RBG -> YPrPb
			if (dct_parameters.color_DCT){ // convert RBG -> YPrPb
				sdfa_instance.showArrays(idct_data,
				sdfa_instance.showArrays(
						idct_data,
						(tilesX + 1) * dct_parameters.dct_size,
						(tilesX + 1) * dct_parameters.dct_size,
						(tilesY + 1) * dct_parameters.dct_size,
						(tilesY + 1) * dct_parameters.dct_size,
						true,
						true,
						result.getTitle()+"-IDCTDC-YPrPb");
						result.getTitle()+"-IDCTDC-YPrPb");
				if ((dct_parameters.nonlin_y != 0.0) || (dct_parameters.nonlin_c != 0.0)) {
			        System.out.println("Applying edge emphasis, nonlin_y="+dct_parameters.nonlin_y+
			        		", nonlin_c="+dct_parameters.nonlin_c+", nonlin_corn="+dct_parameters.nonlin_corn);
			        idct_data = edge_emphasis(
			        		idct_data,                              // final double [][] yPrPb,
			        		(tilesX + 1) * dct_parameters.dct_size, // final int         width,
			        		dct_parameters.dct_size,                // final int         step,  //(does not need to be this)            // just for multi-threading efficiency?
			        		dct_parameters.nonlin_max_y,            // final double      nonlin_max_y =     1.0; // maximal amount of nonlinear line/edge emphasis for Y component
			        		dct_parameters.nonlin_max_c,            // final double      nonlin_max_c =     1.0; // maximal amount of nonlinear line/edge emphasis for C component
			        		dct_parameters.nonlin_y,                // final double      nonlin_y,         //  =        0.01; // amount of nonlinear line/edge emphasis for Y component
			        		dct_parameters.nonlin_c,                // final double      nonlin_c,         //  =        0.01; // amount of nonlinear line/edge emphasis for C component
			        		dct_parameters.nonlin_corn,             // final double      nonlin_corn,      // =     0.5;  // relative weight for nonlinear corner elements
			        		threadsMax,                             // final int         threadsMax,       // maximal number of threads to launch                         
							debugLevel);                            // final int         globalDebugLevel)
					sdfa_instance.showArrays(
							idct_data,
							(tilesX + 1) * dct_parameters.dct_size,
							(tilesY + 1) * dct_parameters.dct_size,
							true,
							result.getTitle()+"-EMPH-"+dct_parameters.nonlin_y+"_"+dct_parameters.nonlin_c+"_"+dct_parameters.nonlin_corn);
				}
				
				// temporary convert back to RGB
				// temporary convert back to RGB
				idct_data = YPrPbToRBG(idct_data,
				idct_data = YPrPbToRBG(idct_data,
						colorProcParameters.kr,        // 0.299;
						colorProcParameters.kr,        // 0.299;
@@ -1467,4 +1490,162 @@ public class EyesisDCT {
			return rbg;
			return rbg;
		}
		}


		
		public double [][] edge_emphasis(
				final double [][] yPrPb,
				final int         width,
				final int         step,             // just for multi-threading efficiency?
				final double      nonlin_max_y, // =     1.0; // maximal amount of nonlinear line/edge emphasis for Y component
				final double      nonlin_max_c, // =     1.0; // maximal amount of nonlinear line/edge emphasis for C component
				final double      nonlin_y,         //  =        0.01; // amount of nonlinear line/edge emphasis for Y component
				final double      nonlin_c,         //  =        0.01; // amount of nonlinear line/edge emphasis for C component
				final double      nonlin_corn,      // =     0.5;  // relative weight for nonlinear corner elements
				final int         threadsMax,       // maximal number of threads to launch                         
				final int         globalDebugLevel)
		{
			final double [][] yPrPb_new = new double [yPrPb.length][yPrPb[0].length];
			final int         height = yPrPb[0].length/width;
			final int tilesY = (height + step - 1) / step;
			final int tilesX = (width +  step - 1) / step;
			final int nTiles=tilesX*tilesY;
			final int    [][] probes =  {{1,7},{3,5},{2,6},{0,8}}; // indices in [012/345/678] 3x3 square to calculate squared sums of differences
			final int    [][] kerns =   {{ 1,  3,  5,   7},  {1,   3,   5,  7},  {0,   2,   6,  8},  {0,   2,  6,   8}};  // indices in [012/345/678] 3x3 square to convolve data
			final double [][] kernsw =  {{-1.0,1.0,1.0,-1.0},{1.0,-1.0,-1.0,1.0},{1.0,-1.0,-1.0,1.0},{-1.0,1.0,1.0,-1.0}}; // weights of kern elements
			final int    []   neib_indices = {-width-1,-width,-width+1,-1,0,1,width-1,width,width+1};       
			final double [][] kernsw_y = new double [kernsw.length][];
			final double [][] kernsw_c = new double [kernsw.length][];
			for (int n = 0; n < kernsw.length; n++){
				kernsw_y[n] = new double [kernsw[n].length];
				kernsw_c[n] = new double [kernsw[n].length];
				for (int i = 0; i < kernsw[n].length; i++){
					double dy = nonlin_y * ((n>=2)? nonlin_corn: 1.0); 
					double dc = nonlin_c * ((n>=2)? nonlin_corn: 1.0); 
					kernsw_y[n][i] = kernsw[n][i] * dy* dy; 
					kernsw_c[n][i] = kernsw[n][i] * dc* dc; 
				}
			}
			if (globalDebugLevel > 0){
		        System.out.println("edge_emphasis(): nonlin_y="+nonlin_y+
		        		", nonlin_c="+nonlin_c+", nonlin_corn="+nonlin_corn);
		        for (int n=0; n<kernsw_y.length; n++){
		        	System.out.print("kernsw_y["+n+"={");
		        	for (int i = 0; i < kernsw_y[n].length; i++){
			        	System.out.print(kernsw_y[n][i]);
			        	if (i == (kernsw_y[n].length - 1)){
			        		System.out.println("}");
			        	} else {
			        		System.out.print(", ");
			        	}
		        		
		        	}
		        }
		        for (int n=0; n<kernsw_c.length; n++){
		        	System.out.print("kernsw_c["+n+"={");
		        	for (int i = 0; i < kernsw_c[n].length; i++){
			        	System.out.print(kernsw_c[n][i]);
			        	if (i == (kernsw_c[n].length - 1)){
			        		System.out.println("}");
			        	} else {
			        		System.out.print(", ");
			        	}
		        	}
		        }
			}
			
			final Thread[] threads = ImageDtt.newThreadArray(threadsMax);
			final AtomicInteger ai = new AtomicInteger(0);

			for (int ithread = 0; ithread < threads.length; ithread++) {
				threads[ithread] = new Thread() {
					public void run() {
						int tileY,tileX;
						double [] neibs =   new double[9]; // pixels around current, first Y, then each color diff
						double [] kern_y =  new double[9]; // weights of neighbors to add to the current for Y
						double [] kern_c =  new double[9]; // weights of neighbors to add to the current for colors diffs
						int center_index = 4;
						for (int nTile = ai.getAndIncrement(); nTile < nTiles; nTile = ai.getAndIncrement()) {
							tileY = nTile/tilesX;
							tileX = nTile - tileY * tilesX;
							int y1 = (tileY +1) * step;
							if (y1 > height) y1 = height;
							int x1 = (tileX +1) * step;
							if (x1 > width) x1 = width;
							for (int y = tileY * step; y < y1; y++) {
								for (int x = tileX * step; x < x1; x++) {
									int indx = y*width + x;
									for (int n  = 0; n < yPrPb.length; n++) {
										yPrPb_new[n][indx] = yPrPb[n][indx]; // default - just copy old value
									}
									if ((y > 0) && (y < (height - 1)) && (x > 0) && (x < (width - 1))) { // only correct those not on the edge
										// read Y pixels around current
										for (int i = 0; i < neibs.length; i++){
											neibs[i] = yPrPb[0][indx+neib_indices[i]];
										}
										for (int i = 0; i < kern_y.length; i++){
											kern_y[i] = 0.0;
											kern_c[i] = 0.0;
										}
										// calculate amount of each pattern
										for (int n = 0; n < probes.length; n++){
											double squared=0.0;
											for (int i = 0; i < probes[n].length; i++){
												squared += neibs[probes[n][i]];
											}
											squared -= probes[n].length * neibs[center_index];
											squared *= squared; // Now it a square of the sum of differences from the center
											for (int i = 0; i < kernsw[n].length; i++){
												int ni = kerns[n][i];
												kern_y[ni]+= squared*kernsw_y[n][i];
												kern_c[ni]+= squared*kernsw_c[n][i];
											}
										}

										if (nonlin_max_y != 0){
											double sum = 0;
											for (int i = 0; i < kern_y.length; i++){
												sum += Math.abs(kern_y[i]);
											}
											if (sum > nonlin_max_y){
												sum = nonlin_max_y/sum;
												for (int i = 0; i < kern_y.length; i++){
													kern_y[i] *= sum;
												}
											}
										}
										
										if (nonlin_max_c != 0){
											double sum = 0;
											for (int i = 0; i < kern_c.length; i++){
												sum += Math.abs(kern_c[i]);
											}
											if (sum > nonlin_max_c){
												sum = nonlin_max_c/sum;
												for (int i = 0; i < kern_c.length; i++){
													kern_c[i] *= sum;
												}
											}
										}
										
										for (int i = 0; i<kern_y.length; i++){
											yPrPb_new[0][indx] += neibs[i]*kern_y[i]; 
										}
										for (int n = 1;n < 3; n++){ //color components
											for (int i = 0; i < neibs.length; i++){
												yPrPb_new[n][indx] += yPrPb[0][indx+neib_indices[i]]*kern_c[i]; 
											}
										}
									}
								}
							}
						}
					}
				};
			}		      
			ImageDtt.startAndJoin(threads);
			return yPrPb_new;
		}
		
		
		
		
}
}