From b39529f7c0620d3c247a6908b2fd3b7c461661e2 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Mon, 5 Jun 2017 14:21:52 +0200 Subject: [PATCH 1/3] LCP: new experimental logic for finding the correct distortion coefficients --- rtengine/dcrop.cc | 4 +- rtengine/improccoordinator.cc | 4 +- rtengine/improcfun.h | 2 +- rtengine/iptransform.cc | 4 +- rtengine/lcp.cc | 83 ++++++++++++++++++++--------------- rtengine/rtthumbnail.cc | 2 +- rtengine/simpleprocess.cc | 4 +- 7 files changed, 59 insertions(+), 44 deletions(-) diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 351ce1f08..4247d5780 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -702,7 +702,9 @@ void Crop::update (int todo) if (needstransform) parent->ipf.transform (baseCrop, transCrop, cropx / skip, cropy / skip, trafx / skip, trafy / skip, skips(parent->fw, skip), skips(parent->fh, skip), parent->getFullWidth(), parent->getFullHeight(), parent->imgsrc->getMetaData()->getFocalLen(), parent->imgsrc->getMetaData()->getFocalLen35mm(), - parent->imgsrc->getMetaData()->getFocusDist(), parent->imgsrc->getRotateDegree(), false); + parent->imgsrc->getMetaData()->getFocusDist(), + parent->imgsrc->getMetaData()->getFNumber(), + parent->imgsrc->getRotateDegree(), false); else baseCrop->copyData(transCrop); diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index f9bbda301..237af8436 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -398,7 +398,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) oprevi = new Imagefloat (pW, pH); if (needstransform) ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH, fw, fh, imgsrc->getMetaData()->getFocalLen(), - imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), false); + imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), imgsrc->getMetaData()->getFNumber(), imgsrc->getRotateDegree(), false); else orig_prev->copyData(oprevi); } @@ -1212,7 +1212,7 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool if (ipf.needsTransform()) { Imagefloat* trImg = new Imagefloat (fW, fH); ipf.transform (im, trImg, 0, 0, 0, 0, fW, fH, fW, fH, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), - imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), true); + imgsrc->getMetaData()->getFocusDist(), imgsrc->getMetaData()->getFNumber(), imgsrc->getRotateDegree(), true); delete im; im = trImg; } diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 028e55a33..547815eb5 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -236,7 +236,7 @@ public: void sharpening (LabImage* lab, float** buffer, SharpeningParams &sharpenParam); void sharpeningcam (CieImage* ncie, float** buffer); void transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, - double focalLen, double focalLen35mm, float focusDist, int rawRotationDeg, bool fullImage); + double focalLen, double focalLen35mm, float focusDist, double fNumber, int rawRotationDeg, bool fullImage); float resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh); void lab2monitorRgb (LabImage* lab, Image8* image); void resize (Image16* src, Image16* dst, float dScale); diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index d01049774..b446fde51 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -307,7 +307,7 @@ bool ImProcFunctions::transCoord (int W, int H, int x, int y, int w, int h, int& } void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, - double focalLen, double focalLen35mm, float focusDist, int rawRotationDeg, bool fullImage) + double focalLen, double focalLen35mm, float focusDist, double fNumber, int rawRotationDeg, bool fullImage) { LCPMapper *pLCPMap = nullptr; @@ -317,7 +317,7 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, if (pLCPProf) { pLCPMap = new LCPMapper (pLCPProf, focalLen, focalLen35mm, - focusDist, 0, false, + focusDist, fNumber, false, params->lensProf.useDist, oW, oH, params->coarse, rawRotationDeg); } diff --git a/rtengine/lcp.cc b/rtengine/lcp.cc index 821194afe..dc209f2e2 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -407,9 +407,9 @@ LCPProfile::LCPProfile(const Glib::ustring &fname) } // Two phase filter: first filter out the very rough ones, that distord the average a lot // force it, even if there are few frames (community profiles) - filterBadFrames(2.0, 0); +// filterBadFrames(2.0, 0); // from the non-distorded, filter again on new average basis, but only if there are enough frames left - filterBadFrames(1.5, 100); +// filterBadFrames(1.5, 100); } // from all frames not marked as bad already, take average and filter out frames with higher deviation than this if there are enough values @@ -522,55 +522,66 @@ void LCPProfile::calcParams(int mode, float focalLength, float focusDist, float float focDist = aPersModel[pm]->focDist; float focDistLog = log(focDist) + euler; double meanErr; - if (aPersModel[pm]->hasModeData(mode)) { - if (mode == 0) { + double lowMeanErr, highMeanErr; + switch (mode) { + case 0: meanErr = aPersModel[pm]->vignette.mean_error; + lowMeanErr = pLow->vignette.mean_error; + highMeanErr = pHigh->vignette.mean_error; + break; + case 1: + meanErr = aPersModel[pm]->base.mean_error; + lowMeanErr = pLow->base.mean_error; + highMeanErr = pHigh->base.mean_error; + break; + default: //case 2: + meanErr = aPersModel[pm]->chromG.mean_error; + lowMeanErr = pLow->chromG.mean_error; + highMeanErr = pHigh->chromG.mean_error; + break; + } - // by aperture (vignette), and max out focus distance - // tests showed doing this by log(aperture) is not as advisable + if (aperture > 0 && mode != 2) { if (aPersModel[pm]->focLen == bestFocLenLow && ( - (aper == aperture && pLow->vignette.mean_error > meanErr) - || (aper >= aperture && aper < pLow->aperture && pLow->aperture > aperture) + (aper == aperture && lowMeanErr > 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.mean_error > meanErr) - || (aper <= aperture && aper > pHigh->aperture && pHigh->aperture < aperture) - || (aper >= aperture && (pHigh->aperture < aperture || fabs(aperture - aper) < fabs(aperture - pHigh->aperture))))) { + (aper == aperture && highMeanErr > 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 if (focusDist > 0 && mode != 0) { + // by focus distance + if (aPersModel[pm]->focLen == bestFocLenLow && ( + (focDist == focusDist && lowMeanErr > 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 && highMeanErr > 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 { - meanErr = (mode == 1 ? aPersModel[pm]->base.mean_error : aPersModel[pm]->chromG.mean_error); + // no focus distance available, just error + if (aPersModel[pm]->focLen == bestFocLenLow && lowMeanErr > meanErr) { + pLow = aPersModel[pm]; + } - if (focusDist > 0) { - // by focus distance - if (aPersModel[pm]->focLen == bestFocLenLow && ( - (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.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.mean_error : pLow->chromG.mean_error) > meanErr) { - pLow = aPersModel[pm]; - } - - if (aPersModel[pm]->focLen == bestFocLenHigh && (mode == 1 ? pHigh->base.mean_error : pHigh->chromG.mean_error) > meanErr) { - pHigh = aPersModel[pm]; - } + if (aPersModel[pm]->focLen == bestFocLenHigh && highMeanErr > meanErr) { + pHigh = aPersModel[pm]; } } + } } } diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 2854df91a..a9dd1689b 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -1065,7 +1065,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei int origFH; double tscale = 0.0; getDimensions(origFW, origFH, tscale); - ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, origFW * tscale + 0.5, origFH * tscale + 0.5, focalLen, focalLen35mm, focusDist, 0, true); // Raw rotate degree not detectable here + ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, origFW * tscale + 0.5, origFH * tscale + 0.5, focalLen, focalLen35mm, focusDist, fnumber, 0, true); // Raw rotate degree not detectable here delete baseImg; baseImg = trImg; } diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index efbba78d1..37e6d4b5d 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -814,7 +814,9 @@ private: if (ipf.needsTransform()) { Imagefloat* trImg = new Imagefloat (fw, fh); ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, fw, fh, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), - imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), true); + imgsrc->getMetaData()->getFocusDist(), + imgsrc->getMetaData()->getFNumber(), + imgsrc->getRotateDegree(), true); delete baseImg; baseImg = trImg; } From 84ff861934963bc4684d587180471dbc603d5db1 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Thu, 8 Jun 2017 17:40:05 +0200 Subject: [PATCH 2/3] further tweaks to the LCP matching logic for distortion correction Now based on the one used by the lensfun-convert-lcp tool of Lensfun --- rtengine/lcp.cc | 163 +++++++++++++++++++++++++----------------------- 1 file changed, 85 insertions(+), 78 deletions(-) diff --git a/rtengine/lcp.cc b/rtengine/lcp.cc index dc209f2e2..d7bee4b6d 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -492,96 +492,103 @@ void LCPProfile::calcParams(int mode, float focalLength, float focusDist, float float focalLengthLog = log(focalLength); //, apertureLog=aperture>0 ? log(aperture) : 0; float focusDistLog = focusDist > 0 ? log(focusDist) + euler : 0; - // Pass 1: determining best focal length, if possible different focusDistances (for the focDist is not given case) - for (int pm = 0; pm < persModelCount; pm++) { - float f = aPersModel[pm]->focLen; - - if (aPersModel[pm]->hasModeData(mode)) { - if (f <= focalLength && (pLow == nullptr || f > pLow->focLen || (focusDist == 0 && f == pLow->focLen && pLow->focDist > aPersModel[pm]->focDist))) { - pLow = aPersModel[pm]; - } - - if (f >= focalLength && (pHigh == nullptr || f < pHigh->focLen || (focusDist == 0 && f == pHigh->focLen && pHigh->focDist < aPersModel[pm]->focDist))) { - pHigh = aPersModel[pm]; + if (mode > 0) { + // matching logic taken from lensfun-convert-lcp + // see https://github.com/lensfun/lensfun + std::map m; + for (int pm = 0; pm < persModelCount; pm++) { + auto cur = aPersModel[pm]; + if (cur->hasModeData(mode)) { + float f = cur->focLen; + auto it = m.find(f); + if (it == m.end()) { + m[f] = cur; + } else { + auto prev = it->second; + float curdist = cur->focDist ? cur->focDist : -1; + float prevdist = prev->focDist ? prev->focDist : -2; + if (curdist > prevdist) { + float curaper = cur->aperture > 0 ? cur->aperture : 1000; + float prevaper = prev->aperture > 0 ? prev->aperture : 1000; + if (std::abs(curaper - 8) < std::abs(prevaper - 8)) { + m[f] = cur; + } + } + } } } - } - - if (!pLow) { - pLow = pHigh; - } else if (!pHigh) { - pHigh = pLow; + auto it = m.lower_bound(focalLength); + if (it != m.end()) { + pLow = it->second; + } + it = m.upper_bound(focalLength); + if (it != m.end()) { + pHigh = it->second; + } + if ((pLow == nullptr) != (pHigh == nullptr)) { + pLow = pHigh; + } } else { - // Pass 2: We have some, so take the best aperture for vignette and best focus for CA and distortion - // there are usually several frame per focal length. In the end pLow will have both flen and apterure/focdis below the target, - // and vice versa pHigh - float bestFocLenLow = pLow->focLen, bestFocLenHigh = pHigh->focLen; - + // Pass 1: determining best focal length, if possible different focusDistances (for the focDist is not given case) for (int pm = 0; pm < persModelCount; pm++) { - float aper = aPersModel[pm]->aperture; // float aperLog=log(aper); - float focDist = aPersModel[pm]->focDist; - float focDistLog = log(focDist) + euler; - double meanErr; + float f = aPersModel[pm]->focLen; + if (aPersModel[pm]->hasModeData(mode)) { - double lowMeanErr, highMeanErr; - switch (mode) { - case 0: - meanErr = aPersModel[pm]->vignette.mean_error; - lowMeanErr = pLow->vignette.mean_error; - highMeanErr = pHigh->vignette.mean_error; - break; - case 1: - meanErr = aPersModel[pm]->base.mean_error; - lowMeanErr = pLow->base.mean_error; - highMeanErr = pHigh->base.mean_error; - break; - default: //case 2: - meanErr = aPersModel[pm]->chromG.mean_error; - lowMeanErr = pLow->chromG.mean_error; - highMeanErr = pHigh->chromG.mean_error; - break; + if (f <= focalLength && (pLow == nullptr || f > pLow->focLen || (focusDist == 0 && f == pLow->focLen && pLow->focDist > aPersModel[pm]->focDist))) { + pLow = aPersModel[pm]; } - if (aperture > 0 && mode != 2) { - if (aPersModel[pm]->focLen == bestFocLenLow && ( - (aper == aperture && lowMeanErr > meanErr) - || (aper >= aperture && aper < pLow->aperture && pLow->aperture > aperture) + if (f >= focalLength && (pHigh == nullptr || f < pHigh->focLen || (focusDist == 0 && f == pHigh->focLen && pHigh->focDist < aPersModel[pm]->focDist))) { + pHigh = aPersModel[pm]; + } + } + } + + if (!pLow) { + pLow = pHigh; + } else if (!pHigh) { + pHigh = pLow; + } else { + // Pass 2: We have some, so take the best aperture for vignette and best focus for CA and distortion + // there are usually several frame per focal length. In the end pLow will have both flen and apterure/focdis below the target, + // and vice versa pHigh + float bestFocLenLow = pLow->focLen, bestFocLenHigh = pHigh->focLen; + + for (int pm = 0; pm < persModelCount; pm++) { + float aper = aPersModel[pm]->aperture; // float aperLog=log(aper); + // float focDist = aPersModel[pm]->focDist; + // float focDistLog = log(focDist) + euler; + if (aPersModel[pm]->hasModeData(mode)) { + double meanErr = aPersModel[pm]->vignette.mean_error; + double lowMeanErr = pLow->vignette.mean_error; + double highMeanErr = pHigh->vignette.mean_error; + + if (aperture > 0) { + if (aPersModel[pm]->focLen == bestFocLenLow && ( + (aper == aperture && lowMeanErr > meanErr) + || (aper >= aperture && aper < pLow->aperture && pLow->aperture > aperture) || (aper <= aperture && (pLow->aperture > aperture || fabs(aperture - aper) < fabs(aperture - pLow->aperture))))) { - pLow = aPersModel[pm]; - } + pLow = aPersModel[pm]; + } - if (aPersModel[pm]->focLen == bestFocLenHigh && ( - (aper == aperture && highMeanErr > 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 if (focusDist > 0 && mode != 0) { - // by focus distance - if (aPersModel[pm]->focLen == bestFocLenLow && ( - (focDist == focusDist && lowMeanErr > 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 && ( + (aper == aperture && highMeanErr > 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 { + // no focus distance available, just error + if (aPersModel[pm]->focLen == bestFocLenLow && lowMeanErr > meanErr) { + pLow = aPersModel[pm]; + } - if (aPersModel[pm]->focLen == bestFocLenHigh && ( - (focDist == focusDist && highMeanErr > 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]; + if (aPersModel[pm]->focLen == bestFocLenHigh && highMeanErr > meanErr) { + pHigh = aPersModel[pm]; + } } - } else { - // no focus distance available, just error - if (aPersModel[pm]->focLen == bestFocLenLow && lowMeanErr > meanErr) { - pLow = aPersModel[pm]; - } - - if (aPersModel[pm]->focLen == bestFocLenHigh && highMeanErr > meanErr) { - pHigh = aPersModel[pm]; - } - } + } } } } From dd14de75f6fc691eb45bfea50c78d8be17696138 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Fri, 9 Jun 2017 08:45:57 +0200 Subject: [PATCH 3/3] Backed out changeset ec2a74c86e53 --- rtengine/lcp.cc | 167 +++++++++++++++++++++++------------------------- 1 file changed, 80 insertions(+), 87 deletions(-) diff --git a/rtengine/lcp.cc b/rtengine/lcp.cc index d7bee4b6d..dc209f2e2 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -492,103 +492,96 @@ void LCPProfile::calcParams(int mode, float focalLength, float focusDist, float float focalLengthLog = log(focalLength); //, apertureLog=aperture>0 ? log(aperture) : 0; float focusDistLog = focusDist > 0 ? log(focusDist) + euler : 0; - if (mode > 0) { - // matching logic taken from lensfun-convert-lcp - // see https://github.com/lensfun/lensfun - std::map m; - for (int pm = 0; pm < persModelCount; pm++) { - auto cur = aPersModel[pm]; - if (cur->hasModeData(mode)) { - float f = cur->focLen; - auto it = m.find(f); - if (it == m.end()) { - m[f] = cur; - } else { - auto prev = it->second; - float curdist = cur->focDist ? cur->focDist : -1; - float prevdist = prev->focDist ? prev->focDist : -2; - if (curdist > prevdist) { - float curaper = cur->aperture > 0 ? cur->aperture : 1000; - float prevaper = prev->aperture > 0 ? prev->aperture : 1000; - if (std::abs(curaper - 8) < std::abs(prevaper - 8)) { - m[f] = cur; - } - } - } + // Pass 1: determining best focal length, if possible different focusDistances (for the focDist is not given case) + for (int pm = 0; pm < persModelCount; pm++) { + float f = aPersModel[pm]->focLen; + + if (aPersModel[pm]->hasModeData(mode)) { + if (f <= focalLength && (pLow == nullptr || f > pLow->focLen || (focusDist == 0 && f == pLow->focLen && pLow->focDist > aPersModel[pm]->focDist))) { + pLow = aPersModel[pm]; + } + + if (f >= focalLength && (pHigh == nullptr || f < pHigh->focLen || (focusDist == 0 && f == pHigh->focLen && pHigh->focDist < aPersModel[pm]->focDist))) { + pHigh = aPersModel[pm]; } } - auto it = m.lower_bound(focalLength); - if (it != m.end()) { - pLow = it->second; - } - it = m.upper_bound(focalLength); - if (it != m.end()) { - pHigh = it->second; - } - if ((pLow == nullptr) != (pHigh == nullptr)) { - pLow = pHigh; - } + } + + if (!pLow) { + pLow = pHigh; + } else if (!pHigh) { + pHigh = pLow; } else { - // Pass 1: determining best focal length, if possible different focusDistances (for the focDist is not given case) + // Pass 2: We have some, so take the best aperture for vignette and best focus for CA and distortion + // there are usually several frame per focal length. In the end pLow will have both flen and apterure/focdis below the target, + // and vice versa pHigh + float bestFocLenLow = pLow->focLen, bestFocLenHigh = pHigh->focLen; + for (int pm = 0; pm < persModelCount; pm++) { - float f = aPersModel[pm]->focLen; - + float aper = aPersModel[pm]->aperture; // float aperLog=log(aper); + float focDist = aPersModel[pm]->focDist; + float focDistLog = log(focDist) + euler; + double meanErr; if (aPersModel[pm]->hasModeData(mode)) { - if (f <= focalLength && (pLow == nullptr || f > pLow->focLen || (focusDist == 0 && f == pLow->focLen && pLow->focDist > aPersModel[pm]->focDist))) { - pLow = aPersModel[pm]; + double lowMeanErr, highMeanErr; + switch (mode) { + case 0: + meanErr = aPersModel[pm]->vignette.mean_error; + lowMeanErr = pLow->vignette.mean_error; + highMeanErr = pHigh->vignette.mean_error; + break; + case 1: + meanErr = aPersModel[pm]->base.mean_error; + lowMeanErr = pLow->base.mean_error; + highMeanErr = pHigh->base.mean_error; + break; + default: //case 2: + meanErr = aPersModel[pm]->chromG.mean_error; + lowMeanErr = pLow->chromG.mean_error; + highMeanErr = pHigh->chromG.mean_error; + break; } - if (f >= focalLength && (pHigh == nullptr || f < pHigh->focLen || (focusDist == 0 && f == pHigh->focLen && pHigh->focDist < aPersModel[pm]->focDist))) { - pHigh = aPersModel[pm]; - } - } - } - - if (!pLow) { - pLow = pHigh; - } else if (!pHigh) { - pHigh = pLow; - } else { - // Pass 2: We have some, so take the best aperture for vignette and best focus for CA and distortion - // there are usually several frame per focal length. In the end pLow will have both flen and apterure/focdis below the target, - // and vice versa pHigh - float bestFocLenLow = pLow->focLen, bestFocLenHigh = pHigh->focLen; - - for (int pm = 0; pm < persModelCount; pm++) { - float aper = aPersModel[pm]->aperture; // float aperLog=log(aper); - // float focDist = aPersModel[pm]->focDist; - // float focDistLog = log(focDist) + euler; - if (aPersModel[pm]->hasModeData(mode)) { - double meanErr = aPersModel[pm]->vignette.mean_error; - double lowMeanErr = pLow->vignette.mean_error; - double highMeanErr = pHigh->vignette.mean_error; - - if (aperture > 0) { - if (aPersModel[pm]->focLen == bestFocLenLow && ( - (aper == aperture && lowMeanErr > meanErr) - || (aper >= aperture && aper < pLow->aperture && pLow->aperture > aperture) + if (aperture > 0 && mode != 2) { + if (aPersModel[pm]->focLen == bestFocLenLow && ( + (aper == aperture && lowMeanErr > 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 && highMeanErr > 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 { - // no focus distance available, just error - if (aPersModel[pm]->focLen == bestFocLenLow && lowMeanErr > meanErr) { - pLow = aPersModel[pm]; - } - - if (aPersModel[pm]->focLen == bestFocLenHigh && highMeanErr > meanErr) { - pHigh = aPersModel[pm]; - } + pLow = aPersModel[pm]; + } + + if (aPersModel[pm]->focLen == bestFocLenHigh && ( + (aper == aperture && highMeanErr > 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 if (focusDist > 0 && mode != 0) { + // by focus distance + if (aPersModel[pm]->focLen == bestFocLenLow && ( + (focDist == focusDist && lowMeanErr > 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 && highMeanErr > 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 && lowMeanErr > meanErr) { + pLow = aPersModel[pm]; + } + + if (aPersModel[pm]->focLen == bestFocLenHigh && highMeanErr > meanErr) { + pHigh = aPersModel[pm]; } - } + } } }