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

line/edge emphasis after debayer

parent 4648e870
......@@ -1805,11 +1805,19 @@ public class EyesisCorrectionParameters {
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 double sigma_rb = 0.5; // additional (to G) blur for R and B
public double sigma_y = 0.5; // 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 line_thershold = 1.0; // line detection amplitude to apply line enhancement
public double sigma_rb = 0.9; // additional (to G) blur for R and B
public double sigma_y = 0.7; // blur for G contribution to 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 - 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(
int dct_size,
int asym_size,
......@@ -1863,13 +1871,17 @@ public class EyesisCorrectionParameters {
properties.setProperty(prefix+"convolve_direct", this.convolve_direct+"");
properties.setProperty(prefix+"vignetting_max", this.vignetting_max+"");
properties.setProperty(prefix+"vignetting_range", this.vignetting_range+"");
properties.setProperty(prefix+"color_DCT", this.color_DCT+"");
properties.setProperty(prefix+"sigma_rb", this.sigma_rb+"");
properties.setProperty(prefix+"sigma_y", this.sigma_y+"");
properties.setProperty(prefix+"sigma_color", this.sigma_color+"");
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){
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+"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() {
GenericDialog gd = new GenericDialog("Set DCT parameters");
......@@ -1949,13 +1966,18 @@ public class EyesisCorrectionParameters {
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("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.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 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);
gd.showDialog();
......@@ -1994,13 +2016,17 @@ public class EyesisCorrectionParameters {
this.convolve_direct= gd.getNextBoolean();
this.vignetting_max= gd.getNextNumber();
this.vignetting_range= gd.getNextNumber();
this.color_DCT= gd.getNextBoolean();
this.sigma_rb= gd.getNextNumber();
this.sigma_y= gd.getNextNumber();
this.sigma_color= 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();
return true;
}
......
......@@ -1200,11 +1200,34 @@ public class EyesisDCT {
debugLevel);
}
if (dct_parameters.color_DCT){ // convert RBG -> YPrPb
sdfa_instance.showArrays(idct_data,
sdfa_instance.showArrays(
idct_data,
(tilesX + 1) * dct_parameters.dct_size,
(tilesY + 1) * dct_parameters.dct_size,
true,
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
idct_data = YPrPbToRBG(idct_data,
colorProcParameters.kr, // 0.299;
......@@ -1467,4 +1490,162 @@ public class EyesisDCT {
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;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment