Preliminary cleanup for LCPModelCommon
This commit is contained in:
166
rtengine/lcp.cc
166
rtengine/lcp.cc
@@ -16,6 +16,8 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#include "lcp.h"
|
||||
@@ -31,29 +33,33 @@ using namespace std;
|
||||
using namespace rtengine;
|
||||
|
||||
|
||||
LCPModelCommon::LCPModelCommon()
|
||||
LCPModelCommon::LCPModelCommon() :
|
||||
foc_len_x(-1.0f),
|
||||
foc_len_y(-1.0f),
|
||||
img_center_x(0.5f),
|
||||
img_center_y(0.5f),
|
||||
param{{}},
|
||||
scale_factor(1.0f),
|
||||
mean_error(0.0),
|
||||
bad_error(false),
|
||||
x0(0.0f),
|
||||
y0(0.0f),
|
||||
fx(0.0f),
|
||||
fy(0.0f),
|
||||
rfx(0.0f),
|
||||
rfy(0.0f),
|
||||
vign_param{{}}
|
||||
{
|
||||
focLenX = focLenY = -1;
|
||||
imgXCenter = imgYCenter = 0.5;
|
||||
x0 = y0 = fx = fy = rfx = rfy = meanErr = 0;
|
||||
|
||||
badErr = false;
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
param[i] = 0;
|
||||
}
|
||||
|
||||
scaleFac = 1;
|
||||
}
|
||||
|
||||
bool LCPModelCommon::empty() const
|
||||
{
|
||||
return param[0] == 0 && param[1] == 0 && param[2] == 0;
|
||||
return param[0] == 0.0f && param[1] == 0.0f && param[2] == 0.0f;
|
||||
}
|
||||
|
||||
void LCPModelCommon::print() const
|
||||
{
|
||||
printf("focLen %g/%g; imgCenter %g/%g; scale %g; err %g\n", focLenX, focLenY, imgXCenter, imgYCenter, scaleFac, meanErr);
|
||||
printf("focLen %g/%g; imgCenter %g/%g; scale %g; err %g\n", foc_len_x, foc_len_y, img_center_x, img_center_y, scale_factor, mean_error);
|
||||
printf("xy0 %g/%g fxy %g/%g\n", x0, y0, fx, fy);
|
||||
printf("param: %g/%g/%g/%g/%g\n", param[0], param[1], param[2], param[3], param[4]);
|
||||
}
|
||||
@@ -61,60 +67,56 @@ void LCPModelCommon::print() const
|
||||
// weighted merge two parameters
|
||||
void LCPModelCommon::merge(const LCPModelCommon& a, const LCPModelCommon& b, float facA)
|
||||
{
|
||||
float facB = 1 - facA;
|
||||
const float facB = 1.0f - facA;
|
||||
|
||||
focLenX = facA * a.focLenX + facB * b.focLenX;
|
||||
focLenY = facA * a.focLenY + facB * b.focLenY;
|
||||
imgXCenter = facA * a.imgXCenter + facB * b.imgXCenter;
|
||||
imgYCenter = facA * a.imgYCenter + facB * b.imgYCenter;
|
||||
scaleFac = facA * a.scaleFac + facB * b.scaleFac;
|
||||
meanErr = facA * a.meanErr + facB * b.meanErr;
|
||||
foc_len_x = facA * a.foc_len_x + facB * b.foc_len_x;
|
||||
foc_len_y = facA * a.foc_len_y + facB * b.foc_len_y;
|
||||
img_center_x = facA * a.img_center_x + facB * b.img_center_x;
|
||||
img_center_y = facA * a.img_center_y + facB * b.img_center_y;
|
||||
scale_factor = facA * a.scale_factor + facB * b.scale_factor;
|
||||
mean_error = facA * a.mean_error + facB * b.mean_error;
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
param[i] = facA * a.param[i] + facB * b.param[i];
|
||||
}
|
||||
|
||||
double param0Sqr = param[0] * param[0];
|
||||
const float param0Sqr = param[0] * param[0];
|
||||
|
||||
vignParam[0] = - param[0];
|
||||
vignParam[1] = param0Sqr - param[1];
|
||||
vignParam[2] = param0Sqr * param[0] - 2. * param[0] * param[1] + param[2];
|
||||
vignParam[3] = param0Sqr * param0Sqr + param[1] * param[1] + 2. * param[0] * param[2] - 3. * param0Sqr * param[1];
|
||||
vign_param[0] = -param[0];
|
||||
vign_param[1] = param0Sqr - param[1];
|
||||
vign_param[2] = param0Sqr * param[0] - 2.0f * param[0] * param[1] + param[2];
|
||||
vign_param[3] = param0Sqr * param0Sqr + param[1] * param[1] + 2.0f * param[0] * param[2] - 3.0f * param0Sqr * param[1];
|
||||
|
||||
}
|
||||
|
||||
void LCPModelCommon::prepareParams(int fullWidth, int fullHeight, float focalLength, float focalLength35mm, float sensorFormatFactor, bool swapXY, bool mirrorX, bool mirrorY)
|
||||
{
|
||||
// Mention that the Adobe technical paper has a bug here, the DMAX is handled differently for focLen and imgCenter
|
||||
int Dmax = fullWidth;
|
||||
|
||||
if (fullHeight > fullWidth) {
|
||||
Dmax = fullHeight;
|
||||
}
|
||||
const int Dmax = std::max(fullWidth, fullHeight);
|
||||
|
||||
// correct focLens
|
||||
if (focLenX < 0) { // they may not be given
|
||||
if (foc_len_x < 0.0f) { // they may not be given
|
||||
// and 35mm may not be given either
|
||||
if (focalLength35mm < 1) {
|
||||
if (focalLength35mm < 1.0f) {
|
||||
focalLength35mm = focalLength * sensorFormatFactor;
|
||||
}
|
||||
|
||||
focLenX = focLenY = focalLength / ( 35 * focalLength / focalLength35mm); // focLen must be calculated in pixels
|
||||
foc_len_x = foc_len_y = focalLength / (35.0f * focalLength / focalLength35mm); // focLen must be calculated in pixels
|
||||
}
|
||||
|
||||
if (swapXY) {
|
||||
x0 = (mirrorX ? 1. - imgYCenter : imgYCenter) * fullWidth;
|
||||
y0 = (mirrorY ? 1. - imgXCenter : imgXCenter) * fullHeight;
|
||||
fx = focLenY * Dmax;
|
||||
fy = focLenX * Dmax;
|
||||
x0 = (mirrorX ? 1.0f - img_center_y : img_center_y) * fullWidth;
|
||||
y0 = (mirrorY ? 1.0f - img_center_x : img_center_x) * fullHeight;
|
||||
fx = foc_len_y * Dmax;
|
||||
fy = foc_len_x * Dmax;
|
||||
} else {
|
||||
x0 = (mirrorX ? 1. - imgXCenter : imgXCenter) * fullWidth;
|
||||
y0 = (mirrorY ? 1. - imgYCenter : imgYCenter) * fullHeight;
|
||||
fx = focLenX * Dmax;
|
||||
fy = focLenY * Dmax;
|
||||
x0 = (mirrorX ? 1.0f - img_center_x : img_center_x) * fullWidth;
|
||||
y0 = (mirrorY ? 1.0f - img_center_y : img_center_y) * fullHeight;
|
||||
fx = foc_len_x * Dmax;
|
||||
fy = foc_len_y * Dmax;
|
||||
}
|
||||
rfx = 1.0 / fx;
|
||||
rfy = 1.0 / fy;
|
||||
rfx = 1.0f / fx;
|
||||
rfy = 1.0f / fy;
|
||||
|
||||
//printf("FW %i /X0 %g FH %i /Y0 %g %g\n",fullWidth,x0,fullHeight,y0, imgYCenter);
|
||||
}
|
||||
@@ -127,9 +129,9 @@ LCPPersModel::LCPPersModel()
|
||||
// mode: 0=distortion, 1=vignette, 2=CA
|
||||
bool LCPPersModel::hasModeData(int mode) const
|
||||
{
|
||||
return (mode == 0 && !vignette.empty() && !vignette.badErr) || (mode == 1 && !base.empty() && !base.badErr)
|
||||
return (mode == 0 && !vignette.empty() && !vignette.bad_error) || (mode == 1 && !base.empty() && !base.bad_error)
|
||||
|| (mode == 2 && !chromRG.empty() && !chromG.empty() && !chromBG.empty() &&
|
||||
!chromRG.badErr && !chromG.badErr && !chromBG.badErr);
|
||||
!chromRG.bad_error && !chromG.bad_error && !chromBG.bad_error);
|
||||
}
|
||||
|
||||
void LCPPersModel::print() const
|
||||
@@ -202,7 +204,7 @@ void LCPMapper::correctDistortion(double& x, double& y) const
|
||||
{
|
||||
double xd = (x - mc.x0) / mc.fx, yd = (y - mc.y0) / mc.fy;
|
||||
|
||||
const float* aDist = mc.param;
|
||||
const LCPModelCommon::Param aDist = mc.param;
|
||||
double rsqr = xd * xd + yd * yd;
|
||||
double xfac = aDist[swapXY ? 3 : 4], yfac = aDist[swapXY ? 4 : 3];
|
||||
|
||||
@@ -230,7 +232,7 @@ void LCPMapper::correctCA(double& x, double& y, int channel) const
|
||||
|
||||
// Green contains main distortion, just like base
|
||||
if (useCADist) {
|
||||
const float* aDist = chrom[1].param;
|
||||
const LCPModelCommon::Param aDist = chrom[1].param;
|
||||
double rsqr = xd * xd + yd * yd;
|
||||
double xfac = aDist[swapXY ? 3 : 4], yfac = aDist[swapXY ? 4 : 3];
|
||||
|
||||
@@ -254,12 +256,12 @@ void LCPMapper::correctCA(double& x, double& y, int channel) const
|
||||
yd = ygreen;
|
||||
rsqr = xd * xd + yd * yd;
|
||||
|
||||
const float* aCA = chrom[channel].param;
|
||||
const LCPModelCommon::Param aCA = chrom[channel].param;
|
||||
double xfac = aCA[swapXY ? 3 : 4], yfac = aCA[swapXY ? 4 : 3];
|
||||
double commonSum = 1. + rsqr * (aCA[0] + rsqr * (aCA[1] + aCA[2] * rsqr)) + 2. * (yfac * yd + xfac * xd);
|
||||
|
||||
x = (chrom[channel].scaleFac * ( xd * commonSum + xfac * rsqr )) * chrom[channel].fx + chrom[channel].x0;
|
||||
y = (chrom[channel].scaleFac * ( yd * commonSum + yfac * rsqr )) * chrom[channel].fy + chrom[channel].y0;
|
||||
x = (chrom[channel].scale_factor * ( xd * commonSum + xfac * rsqr )) * chrom[channel].fx + chrom[channel].x0;
|
||||
y = (chrom[channel].scale_factor * ( yd * commonSum + yfac * rsqr )) * chrom[channel].fy + chrom[channel].y0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +270,7 @@ float LCPMapper::calcVignetteFac(int x, int y) const
|
||||
// No need for swapXY, since vignette is in RAW and always before rotation
|
||||
float xd = ((float)x - mc.x0) * mc.rfx, yd = ((float)y - mc.y0) * mc.rfy;
|
||||
|
||||
const float* vignParam = mc.vignParam;
|
||||
const LCPModelCommon::VignParam vignParam = mc.vign_param;
|
||||
float rsqr = xd * xd + yd * yd;
|
||||
|
||||
return rsqr * (vignParam[0] + rsqr * ((vignParam[1]) - (vignParam[2]) * rsqr + (vignParam[3]) * rsqr * rsqr));
|
||||
@@ -284,10 +286,10 @@ SSEFUNCTION void LCPMapper::processVignetteLine(int width, int y, float *line) c
|
||||
const vfloat fourv = F2V(4.f);
|
||||
const vfloat zerov = F2V(0.f);
|
||||
const vfloat ydv = F2V(yd);
|
||||
const vfloat p0 = F2V(mc.vignParam[0]);
|
||||
const vfloat p1 = F2V(mc.vignParam[1]);
|
||||
const vfloat p2 = F2V(mc.vignParam[2]);
|
||||
const vfloat p3 = F2V(mc.vignParam[3]);
|
||||
const vfloat p0 = F2V(mc.vign_param[0]);
|
||||
const vfloat p1 = F2V(mc.vign_param[1]);
|
||||
const vfloat p2 = F2V(mc.vign_param[2]);
|
||||
const vfloat p3 = F2V(mc.vign_param[3]);
|
||||
const vfloat x0v = F2V(mc.x0);
|
||||
const vfloat rfxv = F2V(mc.rfx);
|
||||
|
||||
@@ -305,7 +307,7 @@ SSEFUNCTION void LCPMapper::processVignetteLine(int width, int y, float *line) c
|
||||
for (; x < width; x++) {
|
||||
if (line[x] > 0) {
|
||||
float xd = ((float)x - mc.x0) * mc.rfx;
|
||||
const float* vignParam = mc.vignParam;
|
||||
const LCPModelCommon::VignParam vignParam = mc.vign_param;
|
||||
float rsqr = xd * xd + yd;
|
||||
line[x] += line[x] * rsqr * (vignParam[0] + rsqr * ((vignParam[1]) - (vignParam[2]) * rsqr + (vignParam[3]) * rsqr * rsqr));
|
||||
}
|
||||
@@ -317,7 +319,7 @@ SSEFUNCTION void LCPMapper::processVignetteLine3Channels(int width, int y, float
|
||||
// No need for swapXY, since vignette is in RAW and always before rotation
|
||||
float yd = ((float)y - mc.y0) * mc.rfy;
|
||||
yd *= yd;
|
||||
const float* vignParam = mc.vignParam;
|
||||
const LCPModelCommon::VignParam vignParam = mc.vign_param;
|
||||
for (int x = 0; x < width; x++) {
|
||||
float xd = ((float)x - mc.x0) * mc.rfx;
|
||||
float rsqr = xd * xd + yd;
|
||||
@@ -391,17 +393,17 @@ int LCPProfile::filterBadFrames(double maxAvgDevFac, int minFramesLeft)
|
||||
|
||||
for (int pm = 0; pm < MaxPersModelCount && aPersModel[pm]; pm++) {
|
||||
if (aPersModel[pm]->hasModeData(0)) {
|
||||
errVignette += aPersModel[pm]->vignette.meanErr;
|
||||
errVignette += aPersModel[pm]->vignette.mean_error;
|
||||
vignetteCount++;
|
||||
}
|
||||
|
||||
if (aPersModel[pm]->hasModeData(1)) {
|
||||
errBase += aPersModel[pm]->base.meanErr;
|
||||
errBase += aPersModel[pm]->base.mean_error;
|
||||
baseCount++;
|
||||
}
|
||||
|
||||
if (aPersModel[pm]->hasModeData(2)) {
|
||||
errChrom += std::max(std::max(aPersModel[pm]->chromRG.meanErr, aPersModel[pm]->chromG.meanErr), aPersModel[pm]->chromBG.meanErr);
|
||||
errChrom += std::max(std::max(aPersModel[pm]->chromRG.mean_error, aPersModel[pm]->chromG.mean_error), aPersModel[pm]->chromBG.mean_error);
|
||||
chromCount++;
|
||||
}
|
||||
}
|
||||
@@ -424,20 +426,20 @@ int LCPProfile::filterBadFrames(double maxAvgDevFac, int minFramesLeft)
|
||||
|
||||
// Now mark all the bad ones as bad, and hasModeData will return false;
|
||||
for (int pm = 0; pm < MaxPersModelCount && aPersModel[pm]; pm++) {
|
||||
if (aPersModel[pm]->hasModeData(0) && aPersModel[pm]->vignette.meanErr > maxAvgDevFac * errVignette) {
|
||||
aPersModel[pm]->vignette.badErr = true;
|
||||
if (aPersModel[pm]->hasModeData(0) && aPersModel[pm]->vignette.mean_error > maxAvgDevFac * errVignette) {
|
||||
aPersModel[pm]->vignette.bad_error = true;
|
||||
filtered++;
|
||||
}
|
||||
|
||||
if (aPersModel[pm]->hasModeData(1) && aPersModel[pm]->base.meanErr > maxAvgDevFac * errBase) {
|
||||
aPersModel[pm]->base.badErr = true;
|
||||
if (aPersModel[pm]->hasModeData(1) && aPersModel[pm]->base.mean_error > maxAvgDevFac * errBase) {
|
||||
aPersModel[pm]->base.bad_error = true;
|
||||
filtered++;
|
||||
}
|
||||
|
||||
if (aPersModel[pm]->hasModeData(2) &&
|
||||
(aPersModel[pm]->chromRG.meanErr > maxAvgDevFac * errChrom || aPersModel[pm]->chromG.meanErr > maxAvgDevFac * errChrom
|
||||
|| aPersModel[pm]->chromBG.meanErr > maxAvgDevFac * errChrom)) {
|
||||
aPersModel[pm]->chromRG.badErr = aPersModel[pm]->chromG.badErr = aPersModel[pm]->chromBG.badErr = true;
|
||||
(aPersModel[pm]->chromRG.mean_error > maxAvgDevFac * errChrom || aPersModel[pm]->chromG.mean_error > maxAvgDevFac * errChrom
|
||||
|| aPersModel[pm]->chromBG.mean_error > maxAvgDevFac * errChrom)) {
|
||||
aPersModel[pm]->chromRG.bad_error = aPersModel[pm]->chromG.bad_error = aPersModel[pm]->chromBG.bad_error = true;
|
||||
filtered++;
|
||||
}
|
||||
}
|
||||
@@ -493,48 +495,48 @@ void LCPProfile::calcParams(int mode, float focalLength, float focusDist, float
|
||||
|
||||
if (aPersModel[pm]->hasModeData(mode)) {
|
||||
if (mode == 0) {
|
||||
meanErr = aPersModel[pm]->vignette.meanErr;
|
||||
meanErr = aPersModel[pm]->vignette.mean_error;
|
||||
|
||||
// by aperture (vignette), and max out focus distance
|
||||
// tests showed doing this by log(aperture) is not as advisable
|
||||
if (aPersModel[pm]->focLen == bestFocLenLow && (
|
||||
(aper == aperture && pLow->vignette.meanErr > meanErr)
|
||||
(aper == aperture && pLow->vignette.mean_error > meanErr)
|
||||
|| (aper >= aperture && aper < pLow->aperture && pLow->aperture > aperture)
|
||||
|| (aper <= aperture && (pLow->aperture > aperture || fabs(aperture - aper) < fabs(aperture - pLow->aperture))))) {
|
||||
pLow = aPersModel[pm];
|
||||
}
|
||||
|
||||
if (aPersModel[pm]->focLen == bestFocLenHigh && (
|
||||
(aper == aperture && pHigh->vignette.meanErr > meanErr)
|
||||
(aper == aperture && pHigh->vignette.mean_error > meanErr)
|
||||
|| (aper <= aperture && aper > pHigh->aperture && pHigh->aperture < aperture)
|
||||
|| (aper >= aperture && (pHigh->aperture < aperture || fabs(aperture - aper) < fabs(aperture - pHigh->aperture))))) {
|
||||
pHigh = aPersModel[pm];
|
||||
}
|
||||
} else {
|
||||
meanErr = (mode == 1 ? aPersModel[pm]->base.meanErr : aPersModel[pm]->chromG.meanErr);
|
||||
meanErr = (mode == 1 ? aPersModel[pm]->base.mean_error : aPersModel[pm]->chromG.mean_error);
|
||||
|
||||
if (focusDist > 0) {
|
||||
// by focus distance
|
||||
if (aPersModel[pm]->focLen == bestFocLenLow && (
|
||||
(focDist == focusDist && (mode == 1 ? pLow->base.meanErr : pLow->chromG.meanErr) > meanErr)
|
||||
(focDist == focusDist && (mode == 1 ? pLow->base.mean_error : pLow->chromG.mean_error) > meanErr)
|
||||
|| (focDist >= focusDist && focDist < pLow->focDist && pLow->focDist > focusDist)
|
||||
|| (focDist <= focusDist && (pLow->focDist > focusDist || fabs(focusDistLog - focDistLog) < fabs(focusDistLog - (log(pLow->focDist) + euler)))))) {
|
||||
pLow = aPersModel[pm];
|
||||
}
|
||||
|
||||
if (aPersModel[pm]->focLen == bestFocLenHigh && (
|
||||
(focDist == focusDist && (mode == 1 ? pHigh->base.meanErr : pHigh->chromG.meanErr) > meanErr)
|
||||
(focDist == focusDist && (mode == 1 ? pHigh->base.mean_error : pHigh->chromG.mean_error) > meanErr)
|
||||
|| (focDist <= focusDist && focDist > pHigh->focDist && pHigh->focDist < focusDist)
|
||||
|| (focDist >= focusDist && (pHigh->focDist < focusDist || fabs(focusDistLog - focDistLog) < fabs(focusDistLog - (log(pHigh->focDist) + euler)))))) {
|
||||
pHigh = aPersModel[pm];
|
||||
}
|
||||
} else {
|
||||
// no focus distance available, just error
|
||||
if (aPersModel[pm]->focLen == bestFocLenLow && (mode == 1 ? pLow->base.meanErr : pLow->chromG.meanErr) > meanErr) {
|
||||
if (aPersModel[pm]->focLen == bestFocLenLow && (mode == 1 ? pLow->base.mean_error : pLow->chromG.mean_error) > meanErr) {
|
||||
pLow = aPersModel[pm];
|
||||
}
|
||||
|
||||
if (aPersModel[pm]->focLen == bestFocLenHigh && (mode == 1 ? pHigh->base.meanErr : pHigh->chromG.meanErr) > meanErr) {
|
||||
if (aPersModel[pm]->focLen == bestFocLenHigh && (mode == 1 ? pHigh->base.mean_error : pHigh->chromG.mean_error) > meanErr) {
|
||||
pHigh = aPersModel[pm];
|
||||
}
|
||||
}
|
||||
@@ -770,17 +772,17 @@ void XMLCALL LCPProfile::XmlTextHandler(void *pLCPProfile, const XML_Char *s, in
|
||||
|
||||
// Section depended
|
||||
if (!strcmp("FocalLengthX", tag)) {
|
||||
pProf->pCurCommon->focLenX = atof(raw);
|
||||
pProf->pCurCommon->foc_len_x = atof(raw);
|
||||
} else if (!strcmp("FocalLengthY", tag)) {
|
||||
pProf->pCurCommon->focLenY = atof(raw);
|
||||
pProf->pCurCommon->foc_len_y = atof(raw);
|
||||
} else if (!strcmp("ImageXCenter", tag)) {
|
||||
pProf->pCurCommon->imgXCenter = atof(raw);
|
||||
pProf->pCurCommon->img_center_x = atof(raw);
|
||||
} else if (!strcmp("ImageYCenter", tag)) {
|
||||
pProf->pCurCommon->imgYCenter = atof(raw);
|
||||
pProf->pCurCommon->img_center_y = atof(raw);
|
||||
} else if (!strcmp("ScaleFactor", tag)) {
|
||||
pProf->pCurCommon->scaleFac = atof(raw);
|
||||
pProf->pCurCommon->scale_factor = atof(raw);
|
||||
} else if (!strcmp("ResidualMeanError", tag)) {
|
||||
pProf->pCurCommon->meanErr = atof(raw);
|
||||
pProf->pCurCommon->mean_error = atof(raw);
|
||||
} else if (!strcmp("RadialDistortParam1", tag) || !strcmp("VignetteModelParam1", tag)) {
|
||||
pProf->pCurCommon->param[0] = atof(raw);
|
||||
} else if (!strcmp("RadialDistortParam2", tag) || !strcmp("VignetteModelParam2", tag)) {
|
||||
|
||||
Reference in New Issue
Block a user