Bugfix for Directional Pyramid Denoising. Adding a Directional Pyramid Equalizer tool. This one serves the same function as the existing Wavelet Equalizer, but has much less artifacting; though it is a little slower to execute and has not yet been adapted for OpenMP implementation. There are also fewer levels on which the tool operates, though of course if there was a demand that could be altered. The controls are similar, though have been given separate luma and chroma controls. Each slider adjusts the factor by which a given detail band is amplified; factors larger than one increase contrast, while values smaller than one decrease contrast. The luma control alters contrast on various scales, each successive one twice as large as the previous one. The chroma control is similar, but does less since there is typically less chroma contrast on fine scales. One might use this to restore some of the color contrast lost in NR, or to remove color fringing by making the fine scale enhancement factor much less than one.
This commit is contained in:
@@ -341,7 +341,7 @@ namespace rtengine {
|
||||
//float eps = 0.0;
|
||||
double wtdsum[3], norm;
|
||||
float hipass[3], hpffluct[3], tonefactor, nrfactor;
|
||||
int i1, j1;
|
||||
int i, j, ix, jx;
|
||||
|
||||
// c[0] noise_L
|
||||
// c[1] noise_ab (relative to noise_L)
|
||||
@@ -366,9 +366,7 @@ namespace rtengine {
|
||||
}*/
|
||||
//float domker[5][5] = {{1,1,1,1,1},{1,2,2,2,1},{1,2,4,2,1},{1,2,2,2,1},{1,1,1,1,1}};
|
||||
|
||||
LabImage* smooth;
|
||||
|
||||
smooth = new LabImage(width, height);
|
||||
|
||||
// for coarsest level, take non-subsampled lopass image and subtract from lopass_fine to generate hipass image
|
||||
|
||||
@@ -386,28 +384,64 @@ namespace rtengine {
|
||||
|
||||
// step (1)
|
||||
|
||||
|
||||
for(int i = 0, i1=0; i < height; i+=pitch, i1++)
|
||||
for(int j = 0, j1=0; j < width; j+=pitch, j1++) {
|
||||
|
||||
//copy common pixels
|
||||
smooth->L[i][j] = data_coarse->L[i1][j1];
|
||||
smooth->a[i][j] = data_coarse->a[i1][j1];
|
||||
smooth->b[i][j] = data_coarse->b[i1][j1];
|
||||
}
|
||||
|
||||
if (pitch>1) {//pitch=2; expand coarse image, fill in missing data
|
||||
if (pitch==1) {
|
||||
|
||||
for(int i = 0; i < height-1; i+=2)
|
||||
for(int j = 0; j < width-1; j+=2) {
|
||||
// step (1-2-3-4)
|
||||
for( i = 0; i < height; i++)
|
||||
for( j = 0; j < width; j++) {
|
||||
|
||||
tonefactor = ((NRWT_L(data_coarse->L[i][j])));
|
||||
|
||||
//Wiener filter
|
||||
//luma
|
||||
if (level<2) {
|
||||
hipass[0] = data_fine->L[i][j]-data_coarse->L[i][j];
|
||||
hpffluct[0]=SQR(hipass[0])+0.001;
|
||||
hipass[0] *= hpffluct[0]/(hpffluct[0]+noisevar_L);
|
||||
data_fine->L[i][j] = CLIP(hipass[0]+data_coarse->L[i][j]);
|
||||
}
|
||||
|
||||
//chroma
|
||||
hipass[1] = data_fine->a[i][j]-data_coarse->a[i][j];
|
||||
hipass[2] = data_fine->b[i][j]-data_coarse->b[i][j];
|
||||
hpffluct[1]=SQR(hipass[1]*tonefactor)+0.001;
|
||||
hpffluct[2]=SQR(hipass[2]*tonefactor)+0.001;
|
||||
nrfactor = (hpffluct[1]+hpffluct[2]) /((hpffluct[1]+hpffluct[2]) + noisevar_ab * NRWT_AB);
|
||||
|
||||
hipass[1] *= nrfactor;
|
||||
hipass[2] *= nrfactor;
|
||||
|
||||
data_fine->a[i][j] = hipass[1]+data_coarse->a[i][j];
|
||||
data_fine->b[i][j] = hipass[2]+data_coarse->b[i][j];
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
LabImage* smooth;
|
||||
|
||||
smooth = new LabImage(width, height);
|
||||
|
||||
for( i = 0, ix=0; i < height; i+=pitch, ix++)
|
||||
for( j = 0, jx=0; j < width; j+=pitch, jx++) {
|
||||
|
||||
//copy common pixels
|
||||
smooth->L[i][j] = data_coarse->L[ix][jx];
|
||||
smooth->a[i][j] = data_coarse->a[ix][jx];
|
||||
smooth->b[i][j] = data_coarse->b[ix][jx];
|
||||
}
|
||||
|
||||
//if (pitch>1) {//pitch=2; step (1) expand coarse image, fill in missing data
|
||||
|
||||
for( i = 0; i < height-1; i+=2)
|
||||
for( j = 0; j < width-1; j+=2) {
|
||||
//do midpoint first
|
||||
norm=0;
|
||||
wtdsum[0]=wtdsum[1]=wtdsum[2]=0.0;
|
||||
for(i1=i; i1<MIN(height,i+3); i1+=2)
|
||||
for (j1=j; j1<MIN(width,j+3); j1+=2) {
|
||||
wtdsum[0] += smooth->L[i1][j1];
|
||||
wtdsum[1] += smooth->a[i1][j1];
|
||||
wtdsum[2] += smooth->b[i1][j1];
|
||||
for( ix=i; ix<MIN(height,i+3); ix+=2)
|
||||
for ( jx=j; jx<MIN(width,j+3); jx+=2) {
|
||||
wtdsum[0] += smooth->L[ix][jx];
|
||||
wtdsum[1] += smooth->a[ix][jx];
|
||||
wtdsum[2] += smooth->b[ix][jx];
|
||||
norm++;
|
||||
}
|
||||
norm = 1/norm;
|
||||
@@ -416,22 +450,22 @@ namespace rtengine {
|
||||
smooth->b[i+1][j+1]=wtdsum[2]*norm;
|
||||
}
|
||||
|
||||
for(int i = 0; i < height-1; i+=2)
|
||||
for(int j = 0; j < width-1; j+=2) {
|
||||
for( i = 0; i < height-1; i+=2)
|
||||
for( j = 0; j < width-1; j+=2) {
|
||||
//now right neighbor
|
||||
if (j+1==width) continue;
|
||||
norm=0;
|
||||
wtdsum[0]=wtdsum[1]=wtdsum[2]=0.0;
|
||||
for (j1=j; j1<MIN(width,j+3); j1+=2) {
|
||||
wtdsum[0] += smooth->L[i][j1];
|
||||
wtdsum[1] += smooth->a[i][j1];
|
||||
wtdsum[2] += smooth->b[i][j1];
|
||||
for (jx=j; jx<MIN(width,j+3); jx+=2) {
|
||||
wtdsum[0] += smooth->L[i][jx];
|
||||
wtdsum[1] += smooth->a[i][jx];
|
||||
wtdsum[2] += smooth->b[i][jx];
|
||||
norm++;
|
||||
}
|
||||
for (i1=MAX(0,i-1); i1<MIN(height,i+2); i1+=2) {
|
||||
wtdsum[0] += smooth->L[i1][j+1];
|
||||
wtdsum[1] += smooth->a[i1][j+1];
|
||||
wtdsum[2] += smooth->b[i1][j+1];
|
||||
for (ix=MAX(0,i-1); ix<MIN(height,i+2); ix+=2) {
|
||||
wtdsum[0] += smooth->L[ix][j+1];
|
||||
wtdsum[1] += smooth->a[ix][j+1];
|
||||
wtdsum[2] += smooth->b[ix][j+1];
|
||||
norm++;
|
||||
}
|
||||
norm = 1/norm;
|
||||
@@ -443,16 +477,16 @@ namespace rtengine {
|
||||
if (i+1==height) continue;
|
||||
norm=0;
|
||||
wtdsum[0]=wtdsum[1]=wtdsum[2]=0.0;
|
||||
for (i1=i; i1<MIN(height,i+3); i1+=2) {
|
||||
wtdsum[0] += smooth->L[i1][j];
|
||||
wtdsum[1] += smooth->a[i1][j];
|
||||
wtdsum[2] += smooth->b[i1][j];
|
||||
for (ix=i; ix<MIN(height,i+3); ix+=2) {
|
||||
wtdsum[0] += smooth->L[ix][j];
|
||||
wtdsum[1] += smooth->a[ix][j];
|
||||
wtdsum[2] += smooth->b[ix][j];
|
||||
norm++;
|
||||
}
|
||||
for (j1=j-1; j1<MIN(width,j+2); j1+=2) {
|
||||
wtdsum[0] += smooth->L[i+1][j1];
|
||||
wtdsum[1] += smooth->a[i+1][j1];
|
||||
wtdsum[2] += smooth->b[i+1][j1];
|
||||
for (jx=MAX(0,j-1); jx<MIN(width,j+2); jx+=2) {
|
||||
wtdsum[0] += smooth->L[i+1][jx];
|
||||
wtdsum[1] += smooth->a[i+1][jx];
|
||||
wtdsum[2] += smooth->b[i+1][jx];
|
||||
norm++;
|
||||
}
|
||||
norm=1/norm;
|
||||
@@ -461,42 +495,40 @@ namespace rtengine {
|
||||
smooth->b[i+1][j]=wtdsum[2]*norm;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// step (2-3-4)
|
||||
for(int i = 0; i < height; i++)
|
||||
for(int j = 0; j < width; j++) {
|
||||
|
||||
tonefactor = ((NRWT_L(smooth->L[i][j])));
|
||||
|
||||
//Wiener filter
|
||||
//luma
|
||||
if (level<2) {
|
||||
hipass[0] = data_fine->L[i][j]-smooth->L[i][j];
|
||||
hpffluct[0]=SQR(hipass[0])+0.001;
|
||||
hipass[0] *= hpffluct[0]/(hpffluct[0]+noisevar_L);
|
||||
data_fine->L[i][j] = CLIP(hipass[0]+smooth->L[i][j]);
|
||||
|
||||
|
||||
// step (2-3-4)
|
||||
for( i = 0; i < height; i++)
|
||||
for( j = 0; j < width; j++) {
|
||||
|
||||
tonefactor = ((NRWT_L(smooth->L[i][j])));
|
||||
|
||||
//Wiener filter
|
||||
//luma
|
||||
if (level<2) {
|
||||
hipass[0] = data_fine->L[i][j]-smooth->L[i][j];
|
||||
hpffluct[0]=SQR(hipass[0])+0.001;
|
||||
hipass[0] *= hpffluct[0]/(hpffluct[0]+noisevar_L);
|
||||
data_fine->L[i][j] = CLIP(hipass[0]+smooth->L[i][j]);
|
||||
}
|
||||
|
||||
//chroma
|
||||
hipass[1] = data_fine->a[i][j]-smooth->a[i][j];
|
||||
hipass[2] = data_fine->b[i][j]-smooth->b[i][j];
|
||||
hpffluct[1]=SQR(hipass[1]*tonefactor)+0.001;
|
||||
hpffluct[2]=SQR(hipass[2]*tonefactor)+0.001;
|
||||
nrfactor = (hpffluct[1]+hpffluct[2]) /((hpffluct[1]+hpffluct[2]) + noisevar_ab * NRWT_AB);
|
||||
|
||||
hipass[1] *= nrfactor;
|
||||
hipass[2] *= nrfactor;
|
||||
|
||||
data_fine->a[i][j] = hipass[1]+smooth->a[i][j];
|
||||
data_fine->b[i][j] = hipass[2]+smooth->b[i][j];
|
||||
}
|
||||
|
||||
//chroma
|
||||
hipass[1] = data_fine->a[i][j]-smooth->a[i][j];
|
||||
hipass[2] = data_fine->b[i][j]-smooth->b[i][j];
|
||||
hpffluct[1]=SQR(hipass[1]*tonefactor)+0.001;
|
||||
hpffluct[2]=SQR(hipass[2]*tonefactor)+0.001;
|
||||
nrfactor = (hpffluct[1]+hpffluct[2]) /((hpffluct[1]+hpffluct[2]) + noisevar_ab * NRWT_AB);
|
||||
//nrfactor *= resaturate;
|
||||
/*if (level) {
|
||||
hipass[0] *= recontrast;
|
||||
nrfactor *= resaturate;
|
||||
}*/
|
||||
hipass[1] *= nrfactor;
|
||||
hipass[2] *= nrfactor;
|
||||
|
||||
data_fine->a[i][j] = hipass[1]+smooth->a[i][j];
|
||||
data_fine->b[i][j] = hipass[2]+smooth->b[i][j];
|
||||
}
|
||||
|
||||
delete smooth;
|
||||
}//end of pitch>1
|
||||
|
||||
delete smooth;
|
||||
};
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user