Fix blur radius when using the Fourier method

Fix the formula, adapt old pp3s, and change the maximum blur radius
where applicable.
This commit is contained in:
Lawrence Lee 2024-10-27 18:45:58 -07:00
parent ca329d9013
commit 9b16f407aa
No known key found for this signature in database
GPG Key ID: 048FF2B76A63895F
7 changed files with 58 additions and 23 deletions

View File

@ -52,21 +52,8 @@ void ImProcFunctions::localContrast(LabImage *lab, float **destination, const rt
#endif #endif
gaussianBlur(lab->L, buf, width, height, sigma); gaussianBlur(lab->L, buf, width, height, sigma);
} else { } else {
float kr = 1.f;
//emprical adjustment between FFTW radius and Gaussainblur
//under 50 ==> 10.f
//above 400 ==> 1.f
if(settings->fftwsigma == false) {//empirical formula
float ak = -9.f / 350.f;
float bk = 10.f - 50.f * ak;
kr = ak * sigma + bk;
if(sigma < 50.f) kr = 10.f;
if(sigma > 400.f) kr = 1.f;
} else {//sigma *= sigma
kr = sigma;
}
//OPENMP disabled //OPENMP disabled
ImProcFunctions::fftw_convol_blur2(lab->L, buf, width, height, kr * sigma, 0, 0); ImProcFunctions::fftw_convol_blur2(lab->L, buf, width, height, sigma, 0, 0);
} }
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp parallel for if(multiThread) #pragma omp parallel for if(multiThread)

View File

@ -9523,8 +9523,8 @@ void ImProcFunctions::fftw_convol_blur(float * input, float * output, int bfw, i
/*define the gaussian constants for the convolution kernel*/ /*define the gaussian constants for the convolution kernel*/
if (algo == 0) { if (algo == 0) {
n_x = rtengine::RT_PI / (double) bfw; //ipol n_x = rtengine::RT_PI / (double) bfw / std::sqrt(2.); //ipol
n_y = rtengine::RT_PI / (double) bfh; n_y = rtengine::RT_PI / (double) bfh / std::sqrt(2.);
} else if (algo == 1) { } else if (algo == 1) {
n_x = 1.f / bfw; //gauss n_x = 1.f / bfw; //gauss
n_y = 1.f / bfh; n_y = 1.f / bfh;
@ -9547,7 +9547,7 @@ void ImProcFunctions::fftw_convol_blur(float * input, float * output, int bfw, i
for (int i = 0; i < bfw; i++) for (int i = 0; i < bfw; i++)
if (algo == 0) { if (algo == 0) {
kern[ i + index] = exp((float)(-radius) * (n_x * i * i + n_y * j * j)); //calculate Gauss kernel Ipol formula kern[ i + index] = exp((float)(-radius * radius) * (n_x * i * i + n_y * j * j)); //calculate Gauss kernel Ipol formula
} else if (algo == 1) { } else if (algo == 1) {
kern[ i + index] = radsig * exp((float)(-(n_x * i * i + n_y * j * j) / (2.f * radius * radius))); //calculate Gauss kernel with Gauss formula kern[ i + index] = radsig * exp((float)(-(n_x * i * i + n_y * j * j) / (2.f * radius * radius))); //calculate Gauss kernel with Gauss formula
} }
@ -9585,7 +9585,7 @@ void ImProcFunctions::fftw_convol_blur(float * input, float * output, int bfw, i
int index = j * bfw; int index = j * bfw;
for (int i = 0; i < bfw; i++) { for (int i = 0; i < bfw; i++) {
out[i + index] *= exp((float)(-radius) * (n_x * i * i + n_y * j * j)); //apply Gauss kernel without FFT - some authors says radius*radius but differences with Gaussianblur out[i + index] *= exp((float)(-radius * radius) * (n_x * i * i + n_y * j * j)); //apply Gauss kernel without FFT - some authors says radius*radius but differences with Gaussianblur
} }
} }
} else if (algo == 1) { } else if (algo == 1) {

View File

@ -1314,14 +1314,26 @@ void ImProcFunctions::MSRLocal(int call, int sp, bool fftw, int lum, float** red
if (settings->fftwsigma == false) { //empirical formula if (settings->fftwsigma == false) { //empirical formula
ImProcFunctions::fftw_convol_blur2(src, out, bfwr, bfhr, (kr * RetinexScales[scale]), 0, 0); ImProcFunctions::fftw_convol_blur2(src, out, bfwr, bfhr, (kr * RetinexScales[scale]), 0, 0);
} else { } else {
ImProcFunctions::fftw_convol_blur2(src, out, bfwr, bfhr, (SQR(RetinexScales[scale])), 0, 0); // FFT blur radius fixed in 5.12, resulting in different
// blur amount. Here we preserve the original behavior by
// multiplying the original sigma SQR(RetinexScales[scale])
// with 2 then taking the square root.
const auto gaussianSigma = std::sqrt(2.f) * RetinexScales[scale];
ImProcFunctions::fftw_convol_blur2(src, out, bfwr, bfhr, gaussianSigma, 0, 0);
} }
} else { // reuse result of last iteration } else { // reuse result of last iteration
// out was modified in last iteration => restore it // out was modified in last iteration => restore it
if (settings->fftwsigma == false) { //empirical formula if (settings->fftwsigma == false) { //empirical formula
ImProcFunctions::fftw_convol_blur2(out, out, bfwr, bfhr, sqrtf(SQR(kr * RetinexScales[scale]) - SQR(kr * RetinexScales[scale + 1])), 0, 0); ImProcFunctions::fftw_convol_blur2(out, out, bfwr, bfhr, sqrtf(SQR(kr * RetinexScales[scale]) - SQR(kr * RetinexScales[scale + 1])), 0, 0);
} else { } else {
ImProcFunctions::fftw_convol_blur2(out, out, bfwr, bfhr, (SQR(RetinexScales[scale]) - SQR(RetinexScales[scale + 1])), 0, 0); // FFT blur radius fixed in 5.12, resulting in different
// blur amount. Here we preserve the original behavior by
// multiplying the original sigma
// SQR(RetinexScales[scale]) - SQR(RetinexScales[scale + 1])
// with 2 then taking the square root.
const auto gaussianSigma =
std::sqrt(2 * (SQR(RetinexScales[scale]) - SQR(RetinexScales[scale + 1])));
ImProcFunctions::fftw_convol_blur2(out, out, bfwr, bfhr, gaussianSigma, 0, 0);
} }
} }
} }

View File

@ -10084,6 +10084,40 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Locallab", "shadmaskcie_" + index_str, spot.shadmaskcie, spotEdited.shadmaskcie); assignFromKeyfile(keyFile, "Locallab", "shadmaskcie_" + index_str, spot.shadmaskcie, spotEdited.shadmaskcie);
assignFromKeyfile(keyFile, "Locallab", "LLmaskcieCurvewav_" + index_str, spot.LLmaskciecurvewav, spotEdited.LLmaskciecurvewav); assignFromKeyfile(keyFile, "Locallab", "LLmaskcieCurvewav_" + index_str, spot.LLmaskciecurvewav, spotEdited.LLmaskciecurvewav);
if (ppVersion < 352) {
// FFT Gaussian blur fixed in 5.12. Converts old radii to
// the equivalent new radii if FFT mode is enabled. The
// fixed blur radius has a factor of radius / 2 compared to
// the original, so the base conversion is sqrt(2 * radius).
// Derivation: old_radius = new_radius * new_radius / 2
// 2 * old_radius = new_radius * new_radius
// sqrt(2 * old_radius) = new_radius
if (spot.fftColorMask) {
spot.blurcol = std::sqrt(2 * spot.blurcol);
spotEdited.blurcol = true;
}
if (spot.fftwbl || spot.radius > 30.) {
// Internally, the radius is divided by 1.4, so the
// factor is actually radius / 1.4 / 2.
spot.radius = std::sqrt(2.8 * spot.radius);
spotEdited.radius = true;
}
if (spot.fftwlc) {
// Internally, the radius was squared, so replace
// old_radius with old_radius^2 before solving.
spot.lcradius = std::sqrt(2.) * spot.lcradius;
spotEdited.lcradius = true;
}
if (spot.fftmask) {
spot.blurmask = std::sqrt(2 * spot.blurmask);
spotEdited.blurmask = true;
}
if (spot.fftcieMask) {
spot.blurcie = std::sqrt(2 * spot.blurcie);
spotEdited.blurcie = true;
}
}
if (keyFile.has_key("Locallab", "CSThresholdcie_" + index_str)) { if (keyFile.has_key("Locallab", "CSThresholdcie_" + index_str)) {
const std::vector<int> thresh = keyFile.get_integer_list("Locallab", "CSThresholdcie_" + index_str); const std::vector<int> thresh = keyFile.get_integer_list("Locallab", "CSThresholdcie_" + index_str);

View File

@ -28,7 +28,7 @@ fft *
#include "../rtengine/color.h" #include "../rtengine/color.h"
#define MINRAD 1.5 #define MINRAD 1.5
#define MAXRAD 10000 #define MAXRAD 1000
#define CENTERRAD 100 #define CENTERRAD 100
#define MINCHRO 0. #define MINCHRO 0.
#define MAXCHRO 150. #define MAXCHRO 150.

View File

@ -4660,7 +4660,7 @@ void LocallabContrast::updateContrastGUI3()
const double temp = lcradius->getValue(); const double temp = lcradius->getValue();
if (fftwlc->get_active()) { if (fftwlc->get_active()) {
lcradius->setLimits(20, 1000, 1, 80); lcradius->setLimits(20, 1500, 1, 80);
} else { } else {
lcradius->setLimits(20, 100, 1, 80); lcradius->setLimits(20, 100, 1, 80);
} }

View File

@ -1,11 +1,13 @@
#pragma once #pragma once
// This number has to be incremented whenever the PP3 file format is modified or the behaviour of a tool changes // This number has to be incremented whenever the PP3 file format is modified or the behaviour of a tool changes
#define PPVERSION 351 #define PPVERSION 352
#define PPVERSION_AEXP 301 //value of PPVERSION when auto exposure algorithm was modified #define PPVERSION_AEXP 301 //value of PPVERSION when auto exposure algorithm was modified
/* /*
Log of version changes Log of version changes
352 2024-10-27
FFT Gaussian blur radius fixed
351 2024-06-19 351 2024-06-19
take into account Global in selective editing take into account Global in selective editing
350 2023-03-05 350 2023-03-05