From 1faa7d7d0891590b392938883c7dd0d40a0f69a3 Mon Sep 17 00:00:00 2001 From: Desmis Date: Fri, 15 Dec 2017 15:48:35 +0100 Subject: [PATCH] Clean and optimize local chroma denoise --- rtengine/FTblockDN.cc | 11 ++- rtengine/improcfun.h | 2 +- rtengine/iplocallab.cc | 150 ++++++++++++++++++++++++++--------------- 3 files changed, 105 insertions(+), 58 deletions(-) diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc index 848d7dd11..0de589f58 100644 --- a/rtengine/FTblockDN.cc +++ b/rtengine/FTblockDN.cc @@ -1172,6 +1172,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef } else { madL[lvl][dir - 1] = SQR(MadRgb(WavCoeffs_L[dir], Wlvl_L * Hlvl_L)); } + } } } @@ -2531,7 +2532,7 @@ bool ImProcFunctions::WaveletDenoiseAllL(wavelet_decomposition &WaveletCoeffs_L, int maxlvl = min(WaveletCoeffs_L.maxlevel(), 5); if (edge == 1 || edge == 3) { - maxlvl = 4; //for refine denoise edge wavelet + maxlvl = 4; //for refine denoise edge wavelet } if (edge == 2) { @@ -2744,7 +2745,7 @@ SSEFUNCTION void ImProcFunctions::ShrinkAllL(wavelet_decomposition &WaveletCoeff SSEFUNCTION void ImProcFunctions::ShrinkAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir, - float *noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch, + float *noisevarchrom, float noisevar_ab, bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, float * madL, float * variC, int local, float * madaab, bool madCalculated) { @@ -2777,14 +2778,18 @@ SSEFUNCTION void ImProcFunctions::ShrinkAllAB(wavelet_decomposition &WaveletCoef madab = SQR(MadRgb(WavCoeffs_ab[dir], W_ab * H_ab)); } } + float noisevarfc; + if ((local == 2 || local == 3) && variC) { + useNoiseCCurve = true; noisevarfc = variC[level]; } else { noisevarfc = noisevar_ab; } + if (noisevarfc > 0.001f) {//noisevar_ab - // madab = useNoiseCCurve ? madab : madab * noisevar_ab; + //madab = useNoiseCCurve ? madab : madab * noisevar_ab; madab = useNoiseCCurve ? madab : madab * noisevarfc; #ifdef __SSE2__ __m128 onev = _mm_set1_ps(1.f); diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 0ab0669f0..69fa24304 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -369,7 +369,7 @@ public: const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb); void ShrinkAllL(wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir, float *noisevarlum, float * madL, float * vari, int edge); void ShrinkAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir, - float *noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, float * madL, float * variC, int local, float * madaab = nullptr, bool madCalculated = false); + float *noisevarchrom, float noisevar_ab, bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, float * madL, float * variC, int local, float * madaab = nullptr, bool madCalculated = false); void ShrinkAll_info(float ** WavCoeffs_a, float ** WavCoeffs_b, int W_ab, int H_ab, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, int schoice, int lvl, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb); diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc index 3868a572d..46a5ce070 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -1861,6 +1861,7 @@ void ImProcFunctions::addGaNoise(LabImage *lab, LabImage *dst, const float mean, void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, LabImage* original, LabImage* transformed, const LabImage &tmp1, int cx, int cy) { // local denoise + //simple algo , perhaps we can improve as the others, but noise is here and not good for hue detection // BENCHFUN const float ach = (float)lp.trans / 100.f; @@ -1888,6 +1889,7 @@ void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, Lab calcTransition(lox, loy, ach, lp, zone, localFactor); int begx = int (lp.xc - lp.lxL); int begy = int (lp.yc - lp.lyT); + float factnoise = (1.f + (lp.noisecf + lp.noisecc) / 300.f); switch (zone) { case 0: { // outside selection and outside transition zone => no effect, keep original values @@ -1914,10 +1916,10 @@ void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, Lab difL *= factorx; difa *= factorx; - difb *= factorx; + difb *= factorx ; transformed->L[y][x] = original->L[y][x] + difL; - transformed->a[y][x] = original->a[y][x] + difa; - transformed->b[y][x] = original->b[y][x] + difb; + transformed->a[y][x] = original->a[y][x] + difa * factnoise; + transformed->b[y][x] = original->b[y][x] + difb * factnoise; break; } @@ -1936,8 +1938,8 @@ void ImProcFunctions::DeNoise_Local(int call, const struct local_params& lp, Lab } transformed->L[y][x] = original->L[y][x] + difL; - transformed->a[y][x] = original->a[y][x] + difa; - transformed->b[y][x] = original->b[y][x] + difb; + transformed->a[y][x] = original->a[y][x] + difa * factnoise; + transformed->b[y][x] = original->b[y][x] + difb * factnoise; } } } @@ -8572,7 +8574,7 @@ void ImProcFunctions::Lab_Local(int call, float** shbuffer, LabImage * original, wavelet_decomposition bdecomp(tmp1.b[0], tmp1.W, tmp1.H, levwavL, 1, skip, numThreads, DaubLen); float madL[8][3]; - // float madC[8][3]; + // float madC[8][3]; int edge = 2; if (!Ldecomp.memoryAllocationFailed) { @@ -8653,23 +8655,6 @@ void ImProcFunctions::Lab_Local(int call, float** shbuffer, LabImage * original, float variC[levred]; if (!adecomp.memoryAllocationFailed && !bdecomp.memoryAllocationFailed) { - /* - #pragma omp parallel for collapse(2) schedule(dynamic,1) - - for (int lvl = 0; lvl < levred; ++lvl) { - // compute median absolute deviation (MAD) of detail coefficients as robust noise estimator - for (int dir = 1; dir < 4; ++dir) { - - int Wlvl_ab = adecomp.level_W(lvl);//approximation with only "a" (better than L - int Hlvl_ab = adecomp.level_H(lvl); - - float ** WavCoeffs_ab = adecomp.level_coeffs(lvl); - madC[lvl][dir - 1] = SQR(Mad(WavCoeffs_ab[dir], Wlvl_ab * Hlvl_ab)); - } - - } - */ - if (levred == 7) { edge = 2; @@ -8703,17 +8688,51 @@ void ImProcFunctions::Lab_Local(int call, float** shbuffer, LabImage * original, variC[3] = max(minic, variC[3]); if (levred == 7) { - + float k6 = 0.f; variC[4] = max(0.0001f, variC[4]); variC[5] = max(0.0001f, variC[5]); - variC[6] = max(0.0001f, variC[6]); + + if (lp.noisecc < 20.f) { + k6 = 0.f; + } else if (lp.noisecc < 50.f) { + k6 = 0.4f; + } else if (lp.noisecc < 70.f) { + k6 = 0.7f; + } else { + k6 = 1.f; + } + + variC[6] = max(0.0001f, k6 * variC[6]); } float* noisevarchrom = new float[GH * GW]; + //noisevarchrom in function chroma + int GW2 = (GW + 1) / 2; + float nvch = 50.f;//high value + float nvcl = 8.f;//low value + float seuil = 3000.f;//low + float seuil2 = 20000.f;//high + //ac and bc for transition + float ac = (nvch - nvcl) / (seuil - seuil2); + float bc = nvch - seuil * ac; +#ifdef _OPENMP + #pragma omp parallel for + +#endif + + for (int ir = 0; ir < GH; ir++) + for (int jr = 0; jr < GW; jr++) { + float cN = sqrt(SQR(tmp1.a[ir][jr]) + SQR(tmp1.b[ir][jr])); + + if (cN < seuil) { + noisevarchrom[(ir >> 1)*GW2 + (jr >> 1)] = 1.f * SQR(nvch); + } else if (cN < seuil2) { + noisevarchrom[(ir >> 1)*GW2 + (jr >> 1)] = 1.f * SQR(ac * cN + bc); + } else { + noisevarchrom[(ir >> 1)*GW2 + (jr >> 1)] = 1.f * SQR(nvcl); + } + } - for (int q = 0; q < GH * GW; q++) { - noisevarchrom[q] = 50.f; - } float noisevarab_r = 100.f; //SQR(lp.noisecc / 10.0); WaveletDenoiseAllAB(Ldecomp, adecomp, noisevarchrom, madL, variC, edge, noisevarab_r, false, false, false, numThreads); @@ -8725,6 +8744,10 @@ void ImProcFunctions::Lab_Local(int call, float** shbuffer, LabImage * original, if (!Ldecomp.memoryAllocationFailed) { Lin = new array2D(GW, GH); +#ifdef _OPENMP + #pragma omp parallel for + +#endif for (int i = 0; i < GH; ++i) { for (int j = 0; j < GW; ++j) { @@ -8754,7 +8777,7 @@ void ImProcFunctions::Lab_Local(int call, float** shbuffer, LabImage * original, int masterThread = omp_get_thread_num(); #endif #ifdef _OPENMP - #pragma omp parallel //num_threads(denoiseNestedLevels) if (denoiseNestedLevels>1) + #pragma omp parallel #endif { #ifdef _OPENMP @@ -9081,23 +9104,6 @@ void ImProcFunctions::Lab_Local(int call, float** shbuffer, LabImage * original, float variC[levred]; if (!adecomp.memoryAllocationFailed && !bdecomp.memoryAllocationFailed) { - /* - float madC[8][3]; - #pragma omp parallel for collapse(2) schedule(dynamic,1) - - for (int lvl = 0; lvl < levred; ++lvl) { - // compute median absolute deviation (MAD) of detail coefficients as robust noise estimator - for (int dir = 1; dir < 4; ++dir) { - - int Wlvl_ab = adecomp.level_W(lvl);//approximation with only "a" (better than L - int Hlvl_ab = adecomp.level_H(lvl); - - float ** WavCoeffs_ab = adecomp.level_coeffs(lvl); - madC[lvl][dir - 1] = SQR(Mad(WavCoeffs_ab[dir], Wlvl_ab * Hlvl_ab)); - } - - } - */ if (levred == 7) { edge = 2; variC[0] = SQR(lp.noisecf / 10.0); @@ -9129,17 +9135,50 @@ void ImProcFunctions::Lab_Local(int call, float** shbuffer, LabImage * original, variC[3] = max(minic, variC[3]); if (levred == 7) { - + float k6 = 0.f; variC[4] = max(0.0001f, variC[4]); variC[5] = max(0.0001f, variC[5]); - variC[6] = max(0.0001f, variC[6]); + + if (lp.noisecc < 20.f) { + k6 = 0.f; + } else if (lp.noisecc < 50.f) { + k6 = 0.4f; + } else if (lp.noisecc < 70.f) { + k6 = 0.7f; + } else { + k6 = 1.f; + } + + variC[6] = max(0.0001f, k6 * variC[6]); } float* noisevarchrom = new float[bfh * bfw]; + int bfw2 = (bfw + 1) / 2; + float nvch = 50.f;//high value + float nvcl = 8.f;//low value + float seuil = 3000.f;//low + float seuil2 = 20000.f;//high + //ac and bc for transition + float ac = (nvch - nvcl) / (seuil - seuil2); + float bc = nvch - seuil * ac; +#ifdef _OPENMP + #pragma omp parallel for + +#endif + + for (int ir = 0; ir < bfh; ir++) + for (int jr = 0; jr < bfw; jr++) { + float cN = sqrt(SQR(bufwv.a[ir][jr]) + SQR(bufwv.b[ir][jr])); + + if (cN < seuil) { + noisevarchrom[(ir >> 1)*bfw2 + (jr >> 1)] = 0.5f * SQR(nvch); + } else if (cN < seuil2) { + noisevarchrom[(ir >> 1)*bfw2 + (jr >> 1)] = 0.5f * SQR(ac * cN + bc); + } else { + noisevarchrom[(ir >> 1)*bfw2 + (jr >> 1)] = 0.5f * SQR(nvcl); + } + } - for (int q = 0; q < bfh * bfw; q++) { - noisevarchrom[q] = 50.f; - } float noisevarab_r = 100.f; //SQR(lp.noisecc / 10.0); @@ -9152,8 +9191,11 @@ void ImProcFunctions::Lab_Local(int call, float** shbuffer, LabImage * original, if (!Ldecomp.memoryAllocationFailed) { Lin = new array2D(bfw, bfh); - // #pragma omp parallel for num_threads(numThreads) if (numThreads>1) +#ifdef _OPENMP + #pragma omp parallel for + +#endif for (int i = 0; i < bfh; ++i) { for (int j = 0; j < bfw; ++j) { @@ -9185,7 +9227,7 @@ void ImProcFunctions::Lab_Local(int call, float** shbuffer, LabImage * original, int masterThread = omp_get_thread_num(); #endif #ifdef _OPENMP - #pragma omp parallel //num_threads(denoiseNestedLevels) if (denoiseNestedLevels>1) + #pragma omp parallel #endif { #ifdef _OPENMP @@ -9302,7 +9344,7 @@ void ImProcFunctions::Lab_Local(int call, float** shbuffer, LabImage * original, //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #ifdef _OPENMP - #pragma omp parallel for //num_threads(denoiseNestedLevels) if (denoiseNestedLevels>1) + #pragma omp parallel for #endif for (int i = 0; i < bfh; ++i) {