Improvment Denoise -- how to deal with yellow noise and others quality improvment issue2131

This commit is contained in:
jdc
2013-12-21 07:46:28 +01:00
parent a90ae2a455
commit c3e790563f
13 changed files with 200 additions and 96 deletions

View File

@@ -435,8 +435,8 @@ HISTORY_MSG_197;CAM02 - Color curve
HISTORY_MSG_198;CAM02 - Color curve
HISTORY_MSG_199;CAM02 - Show CIECAM02 output histograms in curves
HISTORY_MSG_200;CAM02 - Tone mapping using CIECAM02 Q
HISTORY_MSG_201;NR - Delta Chrominance red
HISTORY_MSG_202;NR - Delta Chrominance blue
HISTORY_MSG_201;NR - Delta Chrominance red-green
HISTORY_MSG_202;NR - Delta Chrominance blue-yellow
HISTORY_MSG_203;NR - Method
HISTORY_MSG_204;LMMSE Enhancement Steps
HISTORY_MSG_205;CAM02 hot/bad pixels
@@ -483,6 +483,7 @@ HISTORY_MSG_246;"CL" curve
HISTORY_MSG_247;"LH" curve
HISTORY_MSG_248;"HH" curve
HISTORY_MSG_249;Contrast by Detail Levels Threshold
HISTORY_MSG_250;NR enhance
HISTORY_NEWSNAPSHOTAS;As...
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: <b>Alt-s</b>
@@ -1144,7 +1145,9 @@ TP_DARKFRAME_LABEL;Dark Frame
TP_DEFRINGE_LABEL;Defringe
TP_DEFRINGE_RADIUS;Radius
TP_DEFRINGE_THRESHOLD;Threshold
TP_DIRPYRDENOISE_BLUE;Delta chrominance Blue
TP_DIRPYRDENOISE_BLUE;Delta chrominance Blue & Yellow
TP_DIRPYRDENOISE_ENH;Enhanced mode
TP_DIRPYRDENOISE_ENH_TOOLTIP;Increases the quality of denoise, but increases processing time approximately 20%
TP_DIRPYRDENOISE_CHROMA;Chrominance (Master)
TP_DIRPYRDENOISE_ENABLED_TOOLTIP;Can be used on raw and non-raw images.\n\nFor non-raw images noise reduction of luminance depends on gamma of the input color profile. Gamma of sRGB is assumed, thus if input image is in color profile of a different gamma, luminance noise reduction will vary.
TP_DIRPYRDENOISE_GAMMA;Gamma
@@ -1156,7 +1159,7 @@ TP_DIRPYRDENOISE_LUMA;Luminance
TP_DIRPYRDENOISE_METHOD;Method
TP_DIRPYRDENOISE_METHOD_TOOLTIP;For raw images either RGB or Lab methods can be used.\n\nFor non-raw images Lab method will be used, regardless of the selection.
TP_DIRPYRDENOISE_PERF;RGB mode (raw images)
TP_DIRPYRDENOISE_RED;Delta chrominance Red
TP_DIRPYRDENOISE_RED;Delta chrominance Red & Green
TP_DIRPYRDENOISE_RGB;RGB
TP_DIRPYREQUALIZER_LABEL;Contrast by Detail Levels
TP_DIRPYREQUALIZER_LUMACOARSEST;Coarsest

View File

@@ -39,10 +39,11 @@
#include "iccmatrices.h"
#include "boxblur.h"
#include "rt_math.h"
#include "mytime.h"
#include "sleef.c"
#ifdef __SSE2__
#include "sleefsseavx.c"
#endif
#ifdef __SSE2__
#include "sleefsseavx.c"
#endif
#ifdef _OPENMP
#include <omp.h>
@@ -82,15 +83,21 @@ namespace rtengine {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
extern const Settings* settings;
void ImProcFunctions::RGB_denoise(Imagefloat * src, Imagefloat * dst, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const procparams::DefringeParams & defringe, const double expcomp)
{
{
//#ifdef _DEBUG
// MyTime t1e,t2e;
// t1e.set();
//#endif
static MyMutex FftwMutex;
MyMutex::MyLock lock(FftwMutex);
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/*if (plistener) {
@@ -158,15 +165,15 @@ namespace rtengine {
const float gain = pow (2.0f, float(expcomp));
float incr=1.f;
float noisevar_Ldetail = SQR((SQR(100.f-dnparams.Ldetail) + 50.f*(100.f-dnparams.Ldetail)) * TS * 0.5f * incr);
bool enhance_denoise = dnparams.enhance;
noisered=1.f;//chroma red
if(dnparams.redchro<-0.1f) {noisered=0.001f+SQR((100.f + dnparams.redchro)/100.0f);}
else if(dnparams.redchro>0.1f) {noisered=1.f+SQR((dnparams.redchro));}
else if (dnparams.redchro>= -0.1f && dnparams.redchro<=0.1f) noisered=0.f;
noisered=1.f;//chroma red
if(dnparams.redchro<-0.1f) {noisered=0.001f+SQR((100.f + dnparams.redchro)/100.0f);}
else if(dnparams.redchro>0.1f) {noisered=1.f+SQR((dnparams.redchro));}
else if (dnparams.redchro>= -0.1f && dnparams.redchro<=0.1f) noisered=0.f;
noiseblue=1.f;//chroma blue
if(dnparams.bluechro<-0.1f) {noiseblue=0.001f+SQR((100.f + dnparams.bluechro)/100.0f);}
else if(dnparams.bluechro>0.1f) {noiseblue=1.f+SQR((dnparams.bluechro));}
noiseblue=1.f;//chroma blue
if(dnparams.bluechro<-0.1f) {noiseblue=0.001f+SQR((100.f + dnparams.bluechro)/100.0f);}
else if(dnparams.bluechro>0.1f) {noiseblue=1.f+SQR((dnparams.bluechro));}
else if (dnparams.bluechro>= -0.1f && dnparams.bluechro<=0.1f) noiseblue=0.f;
array2D<float> tilemask_in(TS,TS);
@@ -261,9 +268,9 @@ namespace rtengine {
// Calculate number of tiles. If less than omp_get_max_threads(), then limit num_threads to number of tiles
int numtiles = numtiles_W * numtiles_H;
int numthreads = MIN(numtiles,omp_get_max_threads());
if(options.rgbDenoiseThreadLimit > 0) numthreads = MIN(numthreads,options.rgbDenoiseThreadLimit);
// Issue 1887, overide setting of 1, if more than one thread is available. This way the inner omp-directives should become inactive
if(numthreads == 1 && omp_get_max_threads() > 1)
if(options.rgbDenoiseThreadLimit > 0) numthreads = MIN(numthreads,options.rgbDenoiseThreadLimit);
// Issue 1887, overide setting of 1, if more than one thread is available. This way the inner omp-directives should become inactive
if(numthreads == 1 && omp_get_max_threads() > 1)
numthreads = 2;
#pragma omp parallel num_threads(numthreads)
#endif
@@ -434,23 +441,43 @@ namespace rtengine {
//binary 1 or 0 for each level, eg subsampling = 0 means no subsampling, 1 means subsample
//the first level only, 7 means subsample the first three levels, etc.
float noisevarL = SQR((dnparams.luma/125.0f)*(1+ dnparams.luma/25.0f));
float noisevarab = SQR(dnparams.chroma/10.0f);
float interm_med= dnparams.chroma/10.0f;
float intermred, intermblue;
if(dnparams.redchro > 0.f) intermred=0.0014f*SQR(dnparams.redchro); else intermred= dnparams.redchro/7.0f;//increase slower than linear for more sensit
float intermred2=dnparams.redchro/7.0f;
if(dnparams.bluechro > 0.f) intermblue=0.0014f*SQR(dnparams.bluechro); else intermblue= dnparams.bluechro/7.0f;//increase slower than linear
float intermblue2=dnparams.bluechro/7.0f;
//adjust noise ab in function of sliders red and blue
float realred = interm_med + intermred; if (realred < 0.f) realred=0.01f;
float realred2 = interm_med + intermred2; if (realred2 < 0.f) realred2=0.01f;
float noisevarab_r = SQR(realred);
float realblue = interm_med + intermblue; if (realblue < 0.f) realblue=0.01f;
float realblue2 = interm_med + intermblue2; if (realblue2 < 0.f) realblue2=0.01f;
float noisevarab_b = SQR(realblue);
{ // enclosing this code in a block frees about 120 MB before allocating 20 MB after this block (measured with D700 NEF)
wavelet_decomposition* Ldecomp;
wavelet_decomposition* adecomp;
wavelet_decomposition* bdecomp;
int levwav=5;
// if(xxxx) levwav=7;
float maxreal = max(realred2, realblue2);
//increase the level of wavelet if user increase much or very much sliders
if( maxreal < 8.f) levwav=5;
else if( maxreal < 10.f)levwav=6;
else if( maxreal < 15.f)levwav=7;
else levwav=8;//maximum ==> I have increase Maxlevel in cplx_wavelet_dec.h from 8 to 9
// if (settings->verbose) printf("levwavelet=%i noisevarA=%f noisevarB=%f \n",levwav, noisevarab_r, noisevarab_b );
Ldecomp = new wavelet_decomposition (labdn->data, labdn->W, labdn->H, levwav/*maxlevels*/, 0/*subsampling*/ );
adecomp = new wavelet_decomposition (labdn->data+datalen, labdn->W, labdn->H,levwav, 1 );
bdecomp = new wavelet_decomposition (labdn->data+2*datalen, labdn->W, labdn->H, levwav, 1 );
//WaveletDenoiseAll_BiShrink(Ldecomp, adecomp, bdecomp, noisevarL, noisevarab);
WaveletDenoiseAll(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarab, labdn);//mod JD
if(enhance_denoise) WaveletDenoiseAll_BiShrink(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarab_r, noisevarab_b,labdn);//enhance mode
else; WaveletDenoiseAll(*Ldecomp, *adecomp, *bdecomp, noisevarL, noisevarab_r, noisevarab_b,labdn);//
Ldecomp->reconstruct(labdn->data);
delete Ldecomp;
@@ -744,7 +771,13 @@ namespace rtengine {
fftwf_destroy_plan( plan_forward_blox[1] );
fftwf_destroy_plan( plan_backward_blox[1] );
fftwf_cleanup();
//#ifdef _DEBUG
// if (settings->verbose) {
// t2e.set();
// printf("Denoise performed in %d usec:\n", t2e.etime(t1e));
// }
//#endif
}//end of main RGB_denoise
@@ -753,26 +786,26 @@ namespace rtengine {
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#if defined( __SSE2__ ) && defined( WIN32 )
__attribute__((force_align_arg_pointer)) void ImProcFunctions::RGBtile_denoise (float * fLblox, int vblproc, int hblproc, int numblox_H, int numblox_W, float noisevar_Ldetail ) //for DCT
#else
void ImProcFunctions::RGBtile_denoise (float * fLblox, int vblproc, int hblproc, int numblox_H, int numblox_W, float noisevar_Ldetail ) //for DCT
#if defined( __SSE2__ ) && defined( WIN32 )
__attribute__((force_align_arg_pointer)) void ImProcFunctions::RGBtile_denoise (float * fLblox, int vblproc, int hblproc, int numblox_H, int numblox_W, float noisevar_Ldetail ) //for DCT
#else
void ImProcFunctions::RGBtile_denoise (float * fLblox, int vblproc, int hblproc, int numblox_H, int numblox_W, float noisevar_Ldetail ) //for DCT
#endif
{
float * nbrwt = new float[TS*TS]; //for DCT
int blkstart = hblproc*TS*TS;
boxabsblur(fLblox+blkstart, nbrwt, 3, 3, TS, TS);//blur neighbor weights for more robust estimation //for DCT
boxabsblur(fLblox+blkstart, nbrwt, 3, 3, TS, TS);//blur neighbor weights for more robust estimation //for DCT
#ifdef __SSE2__
__m128 tempv;
__m128 noisevar_Ldetailv = _mm_set1_ps( noisevar_Ldetail );
__m128 onev = _mm_set1_ps( 1.0f );
for (int n=0; n<TS*TS; n+=4) { //for DCT
tempv = onev - xexpf( -SQRV( LVFU(nbrwt[n]))/noisevar_Ldetailv);
#ifdef __SSE2__
__m128 tempv;
__m128 noisevar_Ldetailv = _mm_set1_ps( noisevar_Ldetail );
__m128 onev = _mm_set1_ps( 1.0f );
for (int n=0; n<TS*TS; n+=4) { //for DCT
tempv = onev - xexpf( -SQRV( LVFU(nbrwt[n]))/noisevar_Ldetailv);
_mm_storeu_ps( &fLblox[blkstart+n], LVFU(fLblox[blkstart+n]) * tempv );
}//output neighbor averaged result
#else
#pragma omp parallel for
for (int n=0; n<TS*TS; n++) { //for DCT
@@ -868,7 +901,7 @@ __attribute__((force_align_arg_pointer)) void ImProcFunctions::RGBtile_denoise (
void ImProcFunctions::WaveletDenoiseAll_BiShrink(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a,
wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float noisevar_ab )
wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float noisevar_abr, float noisevar_abb, LabImage * noi)
{
int maxlvl = WaveletCoeffs_L.maxlevel();
const float eps = 0.01f;
@@ -918,7 +951,7 @@ __attribute__((force_align_arg_pointer)) void ImProcFunctions::RGBtile_denoise (
// ShrinkAll(WavCoeffs_L, WavCoeffs_a, WavCoeffs_b, lvl, Wlvl_L, Hlvl_L, Wlvl_ab, Hlvl_ab,10,10,
// skip_L, skip_ab, skip_h, noisevar_L, noisevar_ab, NULL, NULL);//TODO: this implies redundant evaluation of MAD
ShrinkAll(WavCoeffs_L, WavCoeffs_a, WavCoeffs_b, lvl, Wlvl_L, Hlvl_L, Wlvl_ab, Hlvl_ab,
skip_L, skip_ab, noisevar_L, noisevar_ab, NULL);//TODO: this implies redundant evaluation of MAD
skip_L, skip_ab, noisevar_L, noisevar_abr, noisevar_abb, noi);//TODO: this implies redundant evaluation of MAD
} else {
@@ -934,8 +967,8 @@ __attribute__((force_align_arg_pointer)) void ImProcFunctions::RGBtile_denoise (
for (int dir=1; dir<4; dir++) {
float mad_L = madL[lvl][dir-1];
float mad_a = noisevar_ab*mada[lvl][dir-1];
float mad_b = noisevar_ab*madb[lvl][dir-1];
float mad_a = noisevar_abr*mada[lvl][dir-1];
float mad_b = noisevar_abb*madb[lvl][dir-1];
//float mad_Lpar = madL[lvl+1][dir-1];
//float mad_apar = mada[lvl+1][dir-1];
//float mad_bpar = mada[lvl+1][dir-1];
@@ -943,7 +976,7 @@ __attribute__((force_align_arg_pointer)) void ImProcFunctions::RGBtile_denoise (
//float skip_ab_ratio = WaveletCoeffs_a.level_stride(lvl+1)/skip_ab;
float skip_L_ratio = WaveletCoeffs_L.level_stride(lvl+1)/skip_L;
if (noisevar_ab>0.01) {
if (noisevar_abr>0.01) {
//printf(" dir=%d mad_L=%f mad_a=%f mad_b=%f \n",dir,sqrt(mad_L),sqrt(mad_a),sqrt(mad_b));
@@ -1034,7 +1067,7 @@ __attribute__((force_align_arg_pointer)) void ImProcFunctions::RGBtile_denoise (
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void ImProcFunctions::WaveletDenoiseAll(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a,
wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float noisevar_ab, LabImage * noi)//mod JD
wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float noisevar_abr, float noisevar_abb, LabImage * noi)//mod JD
{
int maxlvl = WaveletCoeffs_L.maxlevel();
@@ -1062,7 +1095,7 @@ __attribute__((force_align_arg_pointer)) void ImProcFunctions::RGBtile_denoise (
// printf("Hab : %d\n", Hlvl_ab);
// printf("Wab : %d\n", Wlvl_ab);
ShrinkAll(WavCoeffs_L, WavCoeffs_a, WavCoeffs_b, lvl, Wlvl_L, Hlvl_L, Wlvl_ab, Hlvl_ab,
skip_L, skip_ab, noisevar_L, noisevar_ab, noi);
skip_L, skip_ab, noisevar_L, noisevar_abr, noisevar_abb, noi);
}
//omp_set_nested(false);
@@ -1070,12 +1103,12 @@ __attribute__((force_align_arg_pointer)) void ImProcFunctions::RGBtile_denoise (
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#if defined( __SSE2__ ) && defined( WIN32 )
#if defined( __SSE2__ ) && defined( WIN32 )
__attribute__((force_align_arg_pointer)) void ImProcFunctions::ShrinkAll(float ** WavCoeffs_L, float ** WavCoeffs_a, float ** WavCoeffs_b, int level,
int W_L, int H_L, int W_ab, int H_ab,int skip_L, int skip_ab, float noisevar_L, float noisevar_ab, LabImage * noi)
#else
int W_L, int H_L, int W_ab, int H_ab,int skip_L, int skip_ab, float noisevar_L, float noisevar_abr, float noisevar_abb, LabImage * noi)
#else
void ImProcFunctions::ShrinkAll(float ** WavCoeffs_L, float ** WavCoeffs_a, float ** WavCoeffs_b, int level,
int W_L, int H_L, int W_ab, int H_ab,int skip_L, int skip_ab, float noisevar_L, float noisevar_ab, LabImage * noi)
int W_L, int H_L, int W_ab, int H_ab,int skip_L, int skip_ab, float noisevar_L, float noisevar_abr, float noisevar_abb, LabImage * noi)
#endif
{
@@ -1098,10 +1131,10 @@ __attribute__((force_align_arg_pointer)) void ImProcFunctions::ShrinkAll(float *
// printf(" dir=%d mad_L=%f mad_a=%f mad_b=%f skip_ab=%i \n",dir,sqrt(madL),sqrt(mada),sqrt(madb), skip_ab);
float mad_L = madL*noisevar_L*5/(level+1);
float mad_a = mada*noisevar_ab;
float mad_b = madb*noisevar_ab;
float mad_a = mada*noisevar_abr; // noisevar_abr between 0..2.25=default 100=middle value ==> 582=max
float mad_b = madb*noisevar_abb;
if (noisevar_ab>0.01) {
if (noisevar_abr>0.01 || noisevar_abb>0.01) {
//OpenMP here
#ifdef _OPENMP
@@ -1115,25 +1148,28 @@ __attribute__((force_align_arg_pointer)) void ImProcFunctions::ShrinkAll(float *
int coeffloc_ab = i*W_ab+j;
int coeffloc_L = ((i*skip_L)/skip_ab)*W_L + ((j*skip_L)/skip_ab);
//modification Jacques feb 2013
/*
float reduc=1.f;
float bluuc=1.f;
if(noisered!=0. || noiseblue !=0.) {
float hh=xatan2(noi->b[2*i][2*j],noi->a[2*i][2*j]);
// float hh=xatan2(noi->b[2*i][2*j],noi->a[2*i][2*j]);
float hh =xatan2(WavCoeffs_b[dir][coeffloc_ab],WavCoeffs_a[dir][coeffloc_ab]);
//one can also use L or c (chromaticity) if necessary
if(hh > -0.4f && hh < 1.6f) reduc=noisered;//red from purple to next yellow
if(hh>-2.45f && hh <=-0.4f) bluuc=noiseblue;//blue
// if(hh > -0.4f && hh < 1.6f) reduc=noisered;//red from purple to next yellow
// if(hh>-2.45f && hh <=-0.4f) bluuc=noiseblue;//blue
if(hh>1.3f && hh <=2.2f) bluuc=noiseblue;//blue
}
mad_a*=reduc;
mad_a*=bluuc;
mad_b*=reduc;
mad_b*=bluuc;
*/
float mag_L = SQR(WavCoeffs_L[dir][coeffloc_L ])+eps;
float mag_a = SQR(WavCoeffs_a[dir][coeffloc_ab])+eps;
float mag_b = SQR(WavCoeffs_b[dir][coeffloc_ab])+eps;
sfavea[coeffloc_ab] = (1-xexpf(-(mag_a/mad_a)-(mag_L/(9*madL))));
sfaveb[coeffloc_ab] = (1-xexpf(-(mag_b/mad_b)-(mag_L/(9*madL))));
sfavea[coeffloc_ab] = (1.f-xexpf(-(mag_a/mad_a)-(mag_L/(9.f*madL))));
sfaveb[coeffloc_ab] = (1.f-xexpf(-(mag_b/mad_b)-(mag_L/(9.f*madL))));
mad_a=m_a;
mad_b=m_b;
// 'firm' threshold of chroma coefficients
@@ -1159,25 +1195,31 @@ __attribute__((force_align_arg_pointer)) void ImProcFunctions::ShrinkAll(float *
int coeffloc_ab = i*W_ab+j;
int coeffloc_L = ((i*skip_L)/skip_ab)*W_L + ((j*skip_L)/skip_ab);
//modification Jacques feb 2013
/*
float reduc=1.f;
float bluuc=1.f;
if(noisered!=0. || noiseblue !=0.) {
float hh=xatan2(noi->b[2*i][2*j],noi->a[2*i][2*j]);
if(hh > -0.4f && hh < 1.6f) reduc=noisered;
if(hh>-2.45f && hh <=-0.4f) bluuc=noiseblue;
// float hh=xatan2(noi->b[2*i][2*j],noi->a[2*i][2*j]);
float hh =xatan2(WavCoeffs_b[dir][coeffloc_ab],WavCoeffs_a[dir][coeffloc_ab]);
// if(hh > -0.4f && hh < 1.6f) reduc=noisered;
// if(hh>-2.45f && hh <=-0.4f) bluuc=noiseblue;
if(hh>1.3f && hh <=2.2f) bluuc=noiseblue;//blue
}
mad_a*=reduc;
mad_a*=bluuc;
mad_b*=reduc;
mad_b*=bluuc;
*/
float mag_L = SQR(WavCoeffs_L[dir][coeffloc_L ])+eps;
float mag_a = SQR(WavCoeffs_a[dir][coeffloc_ab])+eps;
float mag_b = SQR(WavCoeffs_b[dir][coeffloc_ab])+eps;
float sfa = (1-xexpf(-(mag_a/mad_a)-(mag_L/(9*madL))));
float sfb = (1-xexpf(-(mag_b/mad_b)-(mag_L/(9*madL))));
float sfa = (1.f-xexpf(-(mag_a/mad_a)-(mag_L/(9.f*madL))));
float sfb = (1.f-xexpf(-(mag_b/mad_b)-(mag_L/(9.f*madL))));
//use smoothed shrinkage unless local shrinkage is much less
WavCoeffs_a[dir][coeffloc_ab] *= (SQR(sfavea[coeffloc_ab])+SQR(sfa))/(sfavea[coeffloc_ab]+sfa+eps);
@@ -1189,20 +1231,20 @@ __attribute__((force_align_arg_pointer)) void ImProcFunctions::ShrinkAll(float *
}
if (noisevar_L>0.01) {
#ifdef __SSE2__
__m128 magv;
__m128 mad_Lv = _mm_set1_ps( mad_L );
__m128 ninev = _mm_set1_ps( 9.0f );
__m128 epsv = _mm_set1_ps( eps );
#ifdef __SSE2__
__m128 magv;
__m128 mad_Lv = _mm_set1_ps( mad_L );
__m128 ninev = _mm_set1_ps( 9.0f );
__m128 epsv = _mm_set1_ps( eps );
for (int i=0; i<W_L*H_L-3; i+=4) {
magv = SQRV(LVFU(WavCoeffs_L[dir][i]));
magv = SQRV(LVFU(WavCoeffs_L[dir][i]));
_mm_storeu_ps( &sfave[i], magv / (magv + mad_Lv*xexpf(-magv/(ninev * mad_Lv)) + epsv));
}
}
for (int i=(W_L*H_L)-((W_L*H_L)%4); i<W_L*H_L; i++) {
float mag = SQR(WavCoeffs_L[dir][i]);
sfave[i] = mag/(mag+mad_L*xexpf(-mag/(9*mad_L))+eps);
}
#else
}
#else
#ifdef _OPENMP
#pragma omp parallel for
#endif
@@ -1213,25 +1255,25 @@ __attribute__((force_align_arg_pointer)) void ImProcFunctions::ShrinkAll(float *
//WavCoeffs_L[dir][i] *= shrinkfactor;
sfave[i] = shrinkfactor;
}
}
#endif
boxblur(sfave, sfave, level+2, level+2, W_L, H_L);//increase smoothness by locally averaging shrinkage
#ifdef __SSE2__
__m128 sfv;
for (int i=0; i<W_L*H_L-3; i+=4) {
magv = SQRV( LVFU(WavCoeffs_L[dir][i]));
sfv = magv/(magv + mad_Lv * xexpf( -magv / (ninev * mad_Lv)) + epsv );
#ifdef __SSE2__
__m128 sfv;
for (int i=0; i<W_L*H_L-3; i+=4) {
magv = SQRV( LVFU(WavCoeffs_L[dir][i]));
sfv = magv/(magv + mad_Lv * xexpf( -magv / (ninev * mad_Lv)) + epsv );
//use smoothed shrinkage unless local shrinkage is much less
_mm_storeu_ps( &WavCoeffs_L[dir][i], _mm_loadu_ps( &WavCoeffs_L[dir][i]) * (SQRV( LVFU(sfave[i] )) + SQRV(sfv)) / (LVFU(sfave[i])+sfv+epsv));
}
}
for (int i=(W_L*H_L)-((W_L*H_L)%4); i<W_L*H_L; i++) {
float mag = SQR(WavCoeffs_L[dir][i]);
float sf = mag/(mag+mad_L*xexpf(-mag/(9*mad_L))+eps);
//use smoothed shrinkage unless local shrinkage is much less
WavCoeffs_L[dir][i] *= (SQR(sfave[i])+SQR(sf))/(sfave[i]+sf+eps);
}//now luminance coefficients are denoised
}//now luminance coefficients are denoised
#else
#ifdef _OPENMP
#pragma omp parallel for
@@ -1245,7 +1287,7 @@ __attribute__((force_align_arg_pointer)) void ImProcFunctions::ShrinkAll(float *
//use smoothed shrinkage unless local shrinkage is much less
WavCoeffs_L[dir][i] *= (SQR(sfave[i])+SQR(sf))/(sfave[i]+sf+eps);
}//now luminance coefficients are denoised
}//now luminance coefficients are denoised
#endif
}

View File

@@ -66,7 +66,8 @@ public:
private:
static const int maxlevels = 8;//should be greater than any conceivable order of decimation
// static const int maxlevels = 8;//should be greater than any conceivable order of decimation
static const int maxlevels = 9;//should be greater than any conceivable order of decimation
int lvltot, subsamp;
size_t m_w, m_h;//dimensions
@@ -306,7 +307,7 @@ public:
private:
static const int maxlevels = 8;//should be greater than any conceivable order of decimation
static const int maxlevels = 9;//should be greater than any conceivable order of decimation
int lvltot, subsamp;
size_t m_w, m_h;//dimensions

View File

@@ -3771,13 +3771,14 @@ fclose(f);*/
//compute clipped white point
int clippable = (int)(sum * clip/100.f );
int somm=sum;
clipped = 0;
int whiteclip = (imax) - 1;
while (whiteclip>1 && histogram[whiteclip]+clipped <= clippable) {
clipped += histogram[whiteclip];
whiteclip--;
}
int clipwh=clipped;
//compute clipped black point
clipped = 0;
int shc = 0;
@@ -3786,6 +3787,8 @@ fclose(f);*/
clipped += histogram[shc];
shc++;
}
int clipbl=clipped;
//rescale to 65535 max
rawmax <<= histcompr;
whiteclip <<= histcompr;
@@ -3857,7 +3860,8 @@ fclose(f);*/
//diagnostics
//printf ("**************** AUTO LEVELS ****************\n");
/* if (settings->verbose) {
/* if (settings->verbose) {
printf("sum=%i clip=%f clippable=%i clipWh=%i clipBl=%i\n",somm, clip, clippable,clipwh, clipbl);
printf ("expcomp1= %f expcomp2= %f gain= %f expcomp=%f\n",expcomp1,expcomp2,gain,expcomp);
printf ("expo=%f\n",expo);
printf ("median: %i average: %f median/average: %f\n",median,ave, median/ave);

View File

@@ -255,10 +255,10 @@ class ImProcFunctions {
// void WaveletDenoiseAll(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a,
// wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float noisevar_ab, wavelet_decomposition &wch, NoiImage * noi );
void WaveletDenoiseAll(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a,
wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float noisevar_ab, LabImage * noi );
wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float noisevar_abr, float noisevar_abb, LabImage * noi );
void WaveletDenoiseAll_BiShrink(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_a,
wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float noisevar_ab );
wavelet_decomposition &WaveletCoeffs_b, float noisevar_L, float noisevar_abr, float noisevar_abb, LabImage * noi);
//void BiShrink(float * ReCoeffs, float * ImCoeffs, float * ReParents, float * ImParents,
// int W, int H, int level, int padding, float noisevar);
//void Shrink(float ** WavCoeffs, int W, int H, int level, float noisevar);
@@ -266,7 +266,7 @@ class ImProcFunctions {
// int W_L, int H_L, int W_ab, int H_ab, int W_h, int H_h, int skip_L, int skip_ab, int skip_h, float noisevar_L, float noisevar_ab, float **WavCoeffs_h, LabImage * noi);
void ShrinkAll(float ** WavCoeffs_L, float ** WavCoeffs_a, float ** WavCoeffs_b, int level,
int W_L, int H_L, int W_ab, int H_ab, int skip_L, int skip_ab, float noisevar_L, float noisevar_ab, LabImage * noi);
int W_L, int H_L, int W_ab, int H_ab, int skip_L, int skip_ab, float noisevar_L, float noisevar_abr, float noisevar_abb,LabImage * noi);
float MadMax(float * HH_Coeffs, int &max, int datalen);

View File

@@ -272,8 +272,9 @@ enum ProcEvent {
EvLLHCurve=246,
EvLHHCurve=247,
EvDirPyrEqualizerThreshold=248,
EvDPDNenhance=249,
NUMOFEVENTS=249
NUMOFEVENTS=250
};
}
#endif

View File

@@ -291,6 +291,7 @@ void ProcParams::setDefaults () {
defringe.huecurve.at(24) = 0.35;
dirpyrDenoise.enabled = false;
dirpyrDenoise.enhance = false;
// dirpyrDenoise.perform = false;
dirpyrDenoise.luma = 0;
dirpyrDenoise.Ldetail = 50;
@@ -870,6 +871,7 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol
// save dirpyrDenoise
if (!pedited || pedited->dirpyrDenoise.enabled) keyFile.set_boolean ("Directional Pyramid Denoising", "Enabled", dirpyrDenoise.enabled);
if (!pedited || pedited->dirpyrDenoise.enhance) keyFile.set_boolean ("Directional Pyramid Denoising", "Enhance", dirpyrDenoise.enhance);
// if (!pedited || pedited->dirpyrDenoise.perform) keyFile.set_boolean ("Directional Pyramid Denoising", "Perform", dirpyrDenoise.perform);
if (!pedited || pedited->dirpyrDenoise.luma) keyFile.set_double ("Directional Pyramid Denoising", "Luma", dirpyrDenoise.luma);
if (!pedited || pedited->dirpyrDenoise.Ldetail) keyFile.set_double ("Directional Pyramid Denoising", "Ldetail", dirpyrDenoise.Ldetail);
@@ -1455,6 +1457,7 @@ if (keyFile.has_group ("Impulse Denoising")) {
// load dirpyrDenoise
if (keyFile.has_group ("Directional Pyramid Denoising")) {//TODO: No longer an accurate description for FT denoise
if (keyFile.has_key ("Directional Pyramid Denoising", "Enabled")) { dirpyrDenoise.enabled = keyFile.get_boolean ("Directional Pyramid Denoising", "Enabled"); if (pedited) pedited->dirpyrDenoise.enabled = true; }
if (keyFile.has_key ("Directional Pyramid Denoising", "Enhance")) { dirpyrDenoise.enhance = keyFile.get_boolean ("Directional Pyramid Denoising", "Enhance"); if (pedited) pedited->dirpyrDenoise.enhance = true; }
// if (keyFile.has_key ("Directional Pyramid Denoising", "Perform")) { dirpyrDenoise.perform = keyFile.get_boolean ("Directional Pyramid Denoising", "Perform"); if (pedited) pedited->dirpyrDenoise.perform = true; }
if (keyFile.has_key ("Directional Pyramid Denoising", "Luma")) { dirpyrDenoise.luma = keyFile.get_double ("Directional Pyramid Denoising", "Luma"); if (pedited) pedited->dirpyrDenoise.luma = true; }
if (keyFile.has_key ("Directional Pyramid Denoising", "Ldetail")) { dirpyrDenoise.Ldetail = keyFile.get_double ("Directional Pyramid Denoising", "Ldetail"); if (pedited) pedited->dirpyrDenoise.Ldetail = true; }
@@ -1873,6 +1876,7 @@ bool ProcParams::operator== (const ProcParams& other) {
&& impulseDenoise.enabled == other.impulseDenoise.enabled
&& impulseDenoise.thresh == other.impulseDenoise.thresh
&& dirpyrDenoise.enabled == other.dirpyrDenoise.enabled
&& dirpyrDenoise.enhance == other.dirpyrDenoise.enhance
// && dirpyrDenoise.perform == other.dirpyrDenoise.perform
&& dirpyrDenoise.luma == other.dirpyrDenoise.luma
&& dirpyrDenoise.Ldetail == other.dirpyrDenoise.Ldetail

View File

@@ -470,6 +470,8 @@ class DirPyrDenoiseParams {
public:
bool enabled;
bool enhance;
bool perform;
double luma;
double Ldetail;

View File

@@ -268,7 +268,8 @@ TRANSFORM, // EvVignettingCenter
LUMINANCECURVE, // EvLCLCurve
LUMINANCECURVE, // EvLLHCurve
LUMINANCECURVE, // EvLHHCurve
DIRPYREQUALIZER // EvDirPyrEqualizerThreshold
DIRPYREQUALIZER, // EvDirPyrEqualizerThreshold
ALLNORAW // EvDPDNenhance
//LUMINANCECURVE // EvCATsharpcie

View File

@@ -84,6 +84,11 @@ DirPyrDenoise::DirPyrDenoise () : Gtk::VBox(), FoldableToolPanel(this) {
// perform->show();
gamma->show();
// perform->set_active (true);
enhance = Gtk::manage (new Gtk::CheckButton (M("TP_DIRPYRDENOISE_ENH")));
enhance->set_active (false);
enhance->set_tooltip_text (M("TP_DIRPYRDENOISE_ENH_TOOLTIP"));
pack_start (*luma);
pack_start (*Ldetail);
@@ -92,7 +97,10 @@ DirPyrDenoise::DirPyrDenoise () : Gtk::VBox(), FoldableToolPanel(this) {
pack_start (*bluechro);
pack_start (*gamma);
pack_start (*enhance);
// pack_start (*perform);
enhanConn = enhance->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrDenoise::enhanceChanged) );
}
@@ -119,14 +127,17 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) {
gamma->setEditedState (pedited->dirpyrDenoise.gamma ? Edited : UnEdited);
enabled->set_inconsistent (!pedited->dirpyrDenoise.enabled);
enhance->set_inconsistent (!pedited->dirpyrDenoise.enhance);
// perform->set_inconsistent (!pedited->dirpyrDenoise.perform);
}
// perfconn.block (true);
enabled->set_active (pp->dirpyrDenoise.enabled);
enhance->set_active (pp->dirpyrDenoise.enhance);
// perform->set_active (pp->dirpyrDenoise.perform);
// perfconn.block (false);
lastEnabled = pp->dirpyrDenoise.enabled;
lastenhance = pp->dirpyrDenoise.enhance;
// lastperform = pp->dirpyrDenoise.perform;
luma->setValue (pp->dirpyrDenoise.luma);
Ldetail->setValue (pp->dirpyrDenoise.Ldetail);
@@ -150,6 +161,7 @@ void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) {
pp->dirpyrDenoise.bluechro = bluechro->getValue ();
pp->dirpyrDenoise.gamma = gamma->getValue ();
pp->dirpyrDenoise.enabled = enabled->get_active();
pp->dirpyrDenoise.enhance = enhance->get_active();
// pp->dirpyrDenoise.perform = perform->get_active();
if (pedited) {
@@ -161,6 +173,7 @@ void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) {
pedited->dirpyrDenoise.bluechro = bluechro->getEditedState ();
pedited->dirpyrDenoise.gamma = gamma->getEditedState ();
pedited->dirpyrDenoise.enabled = !enabled->get_inconsistent();
pedited->dirpyrDenoise.enhance = !enhance->get_inconsistent();
// pedited->dirpyrDenoise.perform = !perform->get_inconsistent();
}
if (dmethod->get_active_row_number()==0)
@@ -248,6 +261,30 @@ void DirPyrDenoise::enabledChanged () {
listener->panelChanged (EvDPDNEnabled, M("GENERAL_DISABLED"));
}
}
void DirPyrDenoise::enhanceChanged () {
if (batchMode) {
if (enhance->get_inconsistent()) {
enhance->set_inconsistent (false);
enhanConn.block (true);
enhance->set_active (false);
enhanConn.block (false);
}
else if (lastenhance)
enhance->set_inconsistent (true);
lastenhance = enhance->get_active ();
}
if (listener) {
if (enhance->get_active ())
listener->panelChanged (EvDPDNenhance, M("GENERAL_ENABLED"));
else
listener->panelChanged (EvDPDNenhance, M("GENERAL_DISABLED"));
}
}
/*
void DirPyrDenoise::perform_toggled () {

View File

@@ -36,6 +36,10 @@ class DirPyrDenoise : public Gtk::VBox, public AdjusterListener, public Foldable
Gtk::CheckButton* enabled;
bool lastEnabled;
sigc::connection enaConn;
Gtk::CheckButton* enhance;
bool lastenhance;
sigc::connection enhanConn;
// Gtk::CheckButton* perform;
// bool lastperform;
// sigc::connection perfconn;
@@ -54,6 +58,7 @@ class DirPyrDenoise : public Gtk::VBox, public AdjusterListener, public Foldable
void adjusterChanged (Adjuster* a, double newval);
void enabledChanged ();
void enhanceChanged ();
// void perform_toggled ();
void dmethodChanged ();

View File

@@ -152,6 +152,7 @@ void ParamsEdited::set (bool v) {
impulseDenoise.enabled = v;
impulseDenoise.thresh = v;
dirpyrDenoise.enabled = v;
dirpyrDenoise.enhance = v;
// dirpyrDenoise.perform = v;
dirpyrDenoise.luma = v;
dirpyrDenoise.Ldetail = v;
@@ -433,6 +434,7 @@ void ParamsEdited::initFrom (const std::vector<rtengine::procparams::ProcParams>
impulseDenoise.thresh = impulseDenoise.thresh && p.impulseDenoise.thresh == other.impulseDenoise.thresh;
dirpyrDenoise.enabled = dirpyrDenoise.enabled && p.dirpyrDenoise.enabled == other.dirpyrDenoise.enabled;
dirpyrDenoise.enhance = dirpyrDenoise.enhance && p.dirpyrDenoise.enhance == other.dirpyrDenoise.enhance;
// dirpyrDenoise.perform = dirpyrDenoise.perform && p.dirpyrDenoise.perform == other.dirpyrDenoise.perform;
dirpyrDenoise.luma = dirpyrDenoise.luma && p.dirpyrDenoise.luma == other.dirpyrDenoise.luma;
dirpyrDenoise.Ldetail = dirpyrDenoise.Ldetail && p.dirpyrDenoise.Ldetail == other.dirpyrDenoise.Ldetail;
@@ -714,6 +716,7 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
if (impulseDenoise.thresh) toEdit.impulseDenoise.thresh = mods.impulseDenoise.thresh;
if (dirpyrDenoise.enabled) toEdit.dirpyrDenoise.enabled = mods.dirpyrDenoise.enabled;
if (dirpyrDenoise.enhance) toEdit.dirpyrDenoise.enhance = mods.dirpyrDenoise.enhance;
if (dirpyrDenoise.luma) toEdit.dirpyrDenoise.luma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMA] ? toEdit.dirpyrDenoise.luma + mods.dirpyrDenoise.luma : mods.dirpyrDenoise.luma;
if (dirpyrDenoise.Ldetail) toEdit.dirpyrDenoise.Ldetail = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMDET] ? toEdit.dirpyrDenoise.Ldetail + mods.dirpyrDenoise.Ldetail : mods.dirpyrDenoise.Ldetail;
if (dirpyrDenoise.chroma) toEdit.dirpyrDenoise.chroma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_CHROMA] ? toEdit.dirpyrDenoise.chroma + mods.dirpyrDenoise.chroma : mods.dirpyrDenoise.chroma;

View File

@@ -233,6 +233,7 @@ class DirPyrDenoiseParamsEdited {
public:
bool enabled;
bool enhance;
bool Ldetail;
bool luma;
bool chroma;