From f310836890e56ea95c96f2566bca9563dc73c2b4 Mon Sep 17 00:00:00 2001 From: Desmis Date: Mon, 14 Dec 2020 09:19:27 +0100 Subject: [PATCH] Improve reinforce denoise local contrast using mask --- rtdata/languages/default | 8 +++++--- rtengine/iplocallab.cc | 26 ++++++++++++++++++++------ rtengine/procevents.h | 1 + rtengine/procparams.cc | 4 ++++ rtengine/procparams.h | 1 + rtengine/refreshmap.cc | 3 ++- rtgui/locallabtools.cc | 16 +++++++++++++++- rtgui/locallabtools.h | 1 + rtgui/paramsedited.cc | 7 +++++++ rtgui/paramsedited.h | 1 + 10 files changed, 57 insertions(+), 11 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index c4ae579b4..8be55df83 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1230,6 +1230,7 @@ HISTORY_MSG_982;Local - Equalizer hue HISTORY_MSG_983;Local - denoise threshold mask high HISTORY_MSG_984;Local - denoise threshold mask low HISTORY_MSG_985;Local - denoise use mask +HISTORY_MSG_986;Local - denoise reinforce HISTORY_MSG_BLSHAPE;Blur by level HISTORY_MSG_BLURCWAV;Blur chroma HISTORY_MSG_BLURWAV;Blur luminance @@ -2759,9 +2760,10 @@ TP_LOCALLAB_MASKCOM_TOOLNAME;Common Color Mask - 13 TP_LOCALLAB_MASKCOM_TOOLTIP;A tool in its own right.\nCan be used to adjust the image appearance (chrominance, luminance, contrast) and texture as a function of Scope. TP_LOCALLAB_MASKCURVE_TOOLTIP;The 3 curves are set to 1 (maximum) by default:\nC=f(C) the chroma varies according to the chrominance. You can decrease the chroma to improve the selection. By setting this curve close to zero (with a low value of C to activate the curve) you can desaturate the background in Inverse mode.\nL=f(L) the luminance varies according to the luminance, so you can decrease the brightness to improve the selection.\nL and C = f(H) luminance and chroma vary with hue, so you can decrease luminance and chroma to improve selection TP_LOCALLAB_MASKH;Hue curve -TP_LOCALLAB_MASKLC_TOOLTIP;Allows you to modulate the denoise according to the mask;\n if the mask is very dark - below the threshold 'dark' - denoise will be increased.\n if the mask is clear - above the threshold 'light' - denoise will be almost cancelled.\n between the two, denoise will be maintained at the settings without mask. -TP_LOCALLAB_MASKLCTHR;Threshold luminance mask "light" -TP_LOCALLAB_MASKLCTHRLOW;Threshold luminance mask "dark" +TP_LOCALLAB_MASKLC_TOOLTIP;Allows you to modulate the denoise according to the mask, generated by the module "Mask and Modifications (Blur and Denoise);\n if the mask is very dark - below the threshold 'dark' - denoise will be increased.\n if the mask is clear - above the threshold 'light' - denoise will be almost cancelled.\n between the two, denoise will be maintained at the settings without mask. +TP_LOCALLAB_MASKLCTHR;Threshold luminance "light area mask" +TP_LOCALLAB_MASKLCTHRLOW;Threshold luminance "dark area mask" +TP_LOCALLAB_MASKLNOISELOW;Reinforce denoise in dark area "mask" TP_LOCALLAB_MASK_TOOLTIP;You can enable multiple masks for a tool by activating another tool and using only the mask (set the tool sliders to 0 ).\n\nYou can also duplicate the RT-spot and place it close to the first spot. The small variations in the spot references allows you to make fine adjustments. TP_LOCALLAB_MED;Medium TP_LOCALLAB_MEDIAN;Median Low diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc index c8129b801..38e068a07 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -660,6 +660,7 @@ struct local_params { float thrlow; float thrhigh; bool usemask; + float lnoiselow; }; @@ -780,6 +781,7 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.thrlow = locallab.spots.at(sp).levelthrlow; lp.thrhigh = locallab.spots.at(sp).levelthr; lp.usemask = locallab.spots.at(sp).usemask; + lp.lnoiselow = locallab.spots.at(sp).lnoiselow; // printf("llColorMask=%i lllcMask=%i llExpMask=%i llSHMask=%i llcbMask=%i llretiMask=%i lltmMask=%i llblMask=%i llvibMask=%i\n", llColorMask, lllcMask, llExpMask, llSHMask, llcbMask, llretiMask, lltmMask, llblMask, llvibMask); if (locallab.spots.at(sp).softMethod == "soft") { @@ -8868,19 +8870,24 @@ void ImProcFunctions::DeNoise(int call, float * slidL, float * slida, float * sl if(lp.thrhigh < lp.thrlow) { hig = lp.thrlow + 0.01f; } - + float alow = -lp.lnoiselow / lp.thrlow; + float blow = lp.lnoiselow; + float ahigh = 0.9999f / (hig - 100.f); + float bhigh = 1.f - hig * ahigh; #ifdef _OPENMP #pragma omp parallel for if (multiThread) #endif for (int ir = 0; ir < GH; ir++) for (int jr = 0; jr < GW; jr++) { const float lM = bufmaskblurbl->L[ir][jr]; + const float lmr = lM / 327.68f; + if (lM < 327.68f * lp.thrlow) { - noisevarlum[(ir >> 1) * GW2 + (jr >> 1)] *= 3.f; + noisevarlum[(ir >> 1) * GW2 + (jr >> 1)] *= alow * lmr + blow; //3.f;//increase denoise } else if (lM < 327.68f * hig) { - // do nothing + // do nothing - denoise not change } else { - noisevarlum[(ir >> 1) * GW2 + (jr >> 1)] *= 0.01f; + noisevarlum[(ir >> 1) * GW2 + (jr >> 1)] *= ahigh * lmr + bhigh; //0.01f;//quasi suppress denoise } } } @@ -9462,18 +9469,25 @@ void ImProcFunctions::DeNoise(int call, float * slidL, float * slida, float * sl hig = lp.thrlow + 0.01f; } + float alow = -lp.lnoiselow / lp.thrlow; + float blow = lp.lnoiselow; + float ahigh = 0.9999f / (hig - 100.f); + float bhigh = 1.f - hig * ahigh; + + #ifdef _OPENMP #pragma omp parallel for if (multiThread) #endif for (int ir = 0; ir < bfh; ir++) for (int jr = 0; jr < bfw; jr++) { const float lM = bufmaskblurbl->L[ir + ystart][jr + xstart]; + const float lmr = lM / 327.68f; if (lM < 327.68f * lp.thrlow) { - noisevarlum[(ir >> 1) * bfw2 + (jr >> 1)] *= 3.f; + noisevarlum[(ir >> 1) * bfw2 + (jr >> 1)] *= alow * lmr + blow; } else if (lM < 327.68f * hig) { // do nothing } else { - noisevarlum[(ir >> 1) * bfw2 + (jr >> 1)] *= 0.01f; + noisevarlum[(ir >> 1) * bfw2 + (jr >> 1)] *= ahigh * lmr + bhigh; } } } diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 159ab9835..ce98e3fd5 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -1008,6 +1008,7 @@ enum ProcEventCode { Evlocallablevelthr = 982, Evlocallablevelthrlow = 983, Evlocallabusemask1 = 984, + Evlocallablnoiselow = 985, NUMOFEVENTS }; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 567dff805..8b08f6c1b 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -3309,6 +3309,7 @@ LocallabParams::LocallabSpot::LocallabSpot() : medMethod("33"), usemask(false), levelthr(50.), + lnoiselow(3.), levelthrlow(25.), activlum(true), noiselumf(0.), @@ -4351,6 +4352,7 @@ bool LocallabParams::LocallabSpot::operator ==(const LocallabSpot& other) const && blurMethod == other.blurMethod && usemask == other.usemask && levelthr == other.levelthr + && lnoiselow == other.lnoiselow && levelthrlow == other.levelthrlow && medMethod == other.medMethod && activlum == other.activlum @@ -5936,6 +5938,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || spot_edited->blurMethod, "Locallab", "BlurMethod_" + index_str, spot.blurMethod, keyFile); saveToKeyfile(!pedited || spot_edited->usemask, "Locallab", "Usemaskb_" + index_str, spot.usemask, keyFile); saveToKeyfile(!pedited || spot_edited->levelthr, "Locallab", "Levelthr_" + index_str, spot.levelthr, keyFile); + saveToKeyfile(!pedited || spot_edited->lnoiselow, "Locallab", "Lnoiselow_" + index_str, spot.lnoiselow, keyFile); saveToKeyfile(!pedited || spot_edited->levelthrlow, "Locallab", "Levelthrlow_" + index_str, spot.levelthrlow, keyFile); saveToKeyfile(!pedited || spot_edited->medMethod, "Locallab", "MedMethod_" + index_str, spot.medMethod, keyFile); saveToKeyfile(!pedited || spot_edited->activlum, "Locallab", "activlum_" + index_str, spot.activlum, keyFile); @@ -7737,6 +7740,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Locallab", "BlurMethod_" + index_str, pedited, spot.blurMethod, spotEdited.blurMethod); assignFromKeyfile(keyFile, "Locallab", "Usemaskb_" + index_str, pedited, spot.usemask, spotEdited.usemask); assignFromKeyfile(keyFile, "Locallab", "Levelthr_" + index_str, pedited, spot.levelthr, spotEdited.levelthr); + assignFromKeyfile(keyFile, "Locallab", "Lnoiselow_" + index_str, pedited, spot.lnoiselow, spotEdited.lnoiselow); assignFromKeyfile(keyFile, "Locallab", "Levelthrlow_" + index_str, pedited, spot.levelthrlow, spotEdited.levelthrlow); assignFromKeyfile(keyFile, "Locallab", "MedMethod_" + index_str, pedited, spot.medMethod, spotEdited.medMethod); assignFromKeyfile(keyFile, "Locallab", "activlum_" + index_str, pedited, spot.activlum, spotEdited.activlum); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 79d7ad0f5..b5e241f51 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1216,6 +1216,7 @@ struct LocallabParams { Glib::ustring medMethod; // none, 33, 55, 77, 99 bool usemask; double levelthr; + double lnoiselow; double levelthrlow; bool activlum; double noiselumf; diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 7cd1c2547..129afdca9 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -1011,7 +1011,8 @@ int refreshmap[rtengine::NUMOFEVENTS] = { LUMINANCECURVE, //EvlocallabwavCurvehue LUMINANCECURVE, // Evlocallablevelthr LUMINANCECURVE, // Evlocallablevelthrlow - LUMINANCECURVE //Evlocallabusemask1 + LUMINANCECURVE, //Evlocallabusemask1 + LUMINANCECURVE // Evlocallablnoiselow }; diff --git a/rtgui/locallabtools.cc b/rtgui/locallabtools.cc index c55ecf817..2c8a25606 100644 --- a/rtgui/locallabtools.cc +++ b/rtgui/locallabtools.cc @@ -5762,7 +5762,8 @@ LocallabBlur::LocallabBlur(): wavshapeden(static_cast(LocalcurveEditorwavden->addCurve(CT_Flat, "", nullptr, false, false))), expdenoise1(Gtk::manage(new MyExpander(false, M("TP_LOCALLAB_DENOI1_EXP")))), usemask(Gtk::manage(new Gtk::CheckButton(M("TP_LOCALLAB_USEMASK")))), - levelthr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_MASKLCTHR"), 0., 100., 1., 50.))), + lnoiselow(Gtk::manage(new Adjuster(M("TP_LOCALLAB_MASKLNOISELOW"), 0.5, 10., 0.1, 3.))), + levelthr(Gtk::manage(new Adjuster(M("TP_LOCALLAB_MASKLCTHR"), 1., 100., 1., 50.))), levelthrlow(Gtk::manage(new Adjuster(M("TP_LOCALLAB_MASKLCTHRLOW"), 0., 100., 1., 25.))), noiselumf0(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMFINEZERO"), MINCHRO, MAXCHRO, 0.01, 0.))), noiselumf(Gtk::manage(new Adjuster(M("TP_LOCALLAB_NOISELUMFINE"), MINCHRO, MAXCHRO, 0.01, 0.))), @@ -5891,6 +5892,7 @@ LocallabBlur::LocallabBlur(): setExpandAlignProperties(expdenoise1, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); levelthr->setAdjusterListener(this); + lnoiselow->setAdjusterListener(this); levelthrlow->setAdjusterListener(this); @@ -6044,6 +6046,7 @@ LocallabBlur::LocallabBlur(): wavBox->pack_start(*LocalcurveEditorwavhue, Gtk::PACK_SHRINK, 4); ToolParamBlock* const wavBox1 = Gtk::manage(new ToolParamBlock()); wavBox1->pack_start(*usemask, Gtk::PACK_SHRINK, 0); + wavBox1->pack_start(*lnoiselow, Gtk::PACK_SHRINK, 0); wavBox1->pack_start(*levelthrlow, Gtk::PACK_SHRINK, 0); wavBox1->pack_start(*levelthr, Gtk::PACK_SHRINK, 0); expdenoise1->add(*wavBox1, false); @@ -6349,6 +6352,7 @@ void LocallabBlur::read(const rtengine::procparams::ProcParams* pp, const Params noiselumc->setValue(spot.noiselumc); noiselumdetail->setValue(spot.noiselumdetail); levelthr->setValue(spot.levelthr); + lnoiselow->setValue(spot.lnoiselow); levelthrlow->setValue(spot.levelthrlow); noiselequal->setValue((double)spot.noiselequal); noisechrof->setValue(spot.noisechrof); @@ -6473,6 +6477,7 @@ void LocallabBlur::write(rtengine::procparams::ProcParams* pp, ParamsEdited* ped spot.noiselumc = noiselumc->getValue(); spot.noiselumdetail = noiselumdetail->getValue(); spot.levelthr = levelthr->getValue(); + spot.lnoiselow = lnoiselow->getValue(); spot.levelthrlow = levelthrlow->getValue(); spot.noiselequal = noiselequal->getIntValue(); spot.noisechrof = noisechrof->getValue(); @@ -6538,6 +6543,7 @@ void LocallabBlur::setDefaults(const rtengine::procparams::ProcParams* defParams noiselumc->setDefault(defSpot.noiselumc); noiselumdetail->setDefault(defSpot.noiselumdetail); levelthr->setDefault(defSpot.levelthr); + lnoiselow->setDefault(defSpot.lnoiselow); levelthrlow->setDefault(defSpot.levelthrlow); noiselequal->setDefault((double)defSpot.noiselequal); noisechrof->setDefault(defSpot.noisechrof); @@ -6684,6 +6690,13 @@ void LocallabBlur::adjusterChanged(Adjuster* a, double newval) } } + if (a == lnoiselow) { + if (listener) { + listener->panelChanged(Evlocallablnoiselow, + lnoiselow->getTextValue() + " (" + escapeHtmlChars(spotName) + ")"); + } + } + if (a == levelthrlow) { if (listener) { listener->panelChanged(Evlocallablevelthrlow, @@ -6937,6 +6950,7 @@ void LocallabBlur::convertParamToSimple() slomaskbl->setValue(defSpot.slomaskbl); Lmaskblshape->setCurve(defSpot.Lmasklccurve); levelthr->setValue(defSpot.levelthr); + lnoiselow->setValue(defSpot.lnoiselow); levelthrlow->setValue(defSpot.levelthrlow); usemask->set_active(defSpot.usemask); diff --git a/rtgui/locallabtools.h b/rtgui/locallabtools.h index ad100baae..b711eae9e 100644 --- a/rtgui/locallabtools.h +++ b/rtgui/locallabtools.h @@ -665,6 +665,7 @@ private: FlatCurveEditor* const wavshapeden; MyExpander* const expdenoise1; Gtk::CheckButton* const usemask; + Adjuster* const lnoiselow; Adjuster* const levelthr; Adjuster* const levelthrlow; Adjuster* const noiselumf0; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 59a97234b..6cd2c93e5 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -1286,6 +1286,7 @@ void ParamsEdited::initFrom(const std::vector& locallab.spots.at(j).blurMethod = locallab.spots.at(j).blurMethod && pSpot.blurMethod == otherSpot.blurMethod; locallab.spots.at(j).usemask = locallab.spots.at(j).usemask && pSpot.usemask == otherSpot.usemask; locallab.spots.at(j).levelthr = locallab.spots.at(j).levelthr && pSpot.levelthr == otherSpot.levelthr; + locallab.spots.at(j).lnoiselow = locallab.spots.at(j).lnoiselow && pSpot.lnoiselow == otherSpot.lnoiselow; locallab.spots.at(j).levelthrlow = locallab.spots.at(j).levelthrlow && pSpot.levelthrlow == otherSpot.levelthrlow; locallab.spots.at(j).medMethod = locallab.spots.at(j).medMethod && pSpot.medMethod == otherSpot.medMethod; locallab.spots.at(j).activlum = locallab.spots.at(j).activlum && pSpot.activlum == otherSpot.activlum; @@ -4063,6 +4064,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.locallab.spots.at(i).levelthr = mods.locallab.spots.at(i).levelthr; } + if (locallab.spots.at(i).lnoiselow) { + toEdit.locallab.spots.at(i).lnoiselow = mods.locallab.spots.at(i).lnoiselow; + } + if (locallab.spots.at(i).levelthrlow) { toEdit.locallab.spots.at(i).levelthrlow = mods.locallab.spots.at(i).levelthrlow; } @@ -6584,6 +6589,7 @@ LocallabParamsEdited::LocallabSpotEdited::LocallabSpotEdited(bool v) : quamethod(v), usemask(v), levelthr(v), + lnoiselow(v), levelthrlow(v), blurMethod(v), medMethod(v), @@ -7102,6 +7108,7 @@ void LocallabParamsEdited::LocallabSpotEdited::set(bool v) quamethod = v; usemask = v; levelthr = v; + lnoiselow = v; levelthrlow = v; blurMethod = v; medMethod = v; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index e035b2b13..41406e3ea 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -622,6 +622,7 @@ public: bool quamethod; bool usemask; bool levelthr; + bool lnoiselow; bool levelthrlow; bool blurMethod; bool medMethod;