From fa39d8bf2a682335208ccff1dc9606872645874a Mon Sep 17 00:00:00 2001 From: Oliver Duis Date: Tue, 12 Jun 2012 22:48:34 +0200 Subject: [PATCH] Improved LCP error correction see issue 1408 --- rtengine/lcp.cc | 67 +++++++++++++++++++++++++++++++++++++------------ rtengine/lcp.h | 5 +++- 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/rtengine/lcp.cc b/rtengine/lcp.cc index df7e413df..4284e52a7 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -235,7 +235,7 @@ LCPProfile::LCPProfile(Glib::ustring fname) { isFisheye=inCamProfiles=firstLIDone=inPerspect=inAlternateLensID=false; sensorFormatFactor=1; - for (int i=0;i<2000;i++) aPersModel[i]=NULL; + for (int i=0;ihasModeData(0)) { errVignette+=aPersModel[pm]->vignette.meanErr; vignetteCount++; @@ -273,35 +283,37 @@ LCPProfile::LCPProfile(Glib::ustring fname) { } // Only if we have enough frames, filter out errors - if (baseCount+chromCount+vignetteCount>=100) { + int filtered=0; + + if (baseCount+chromCount+vignetteCount>=minFramesLeft) { if (baseCount>0) errBase/=(double)baseCount; if (chromCount>0) errChrom/=(double)chromCount; if (vignetteCount>0) errVignette/=(double)vignetteCount; // Now mark all the bad ones as bad, and hasModeData will return false; - const double MaxDeviation=2; - int filtered=0; - for (int pm=0;pm<2000 && aPersModel[pm];pm++) { - if (aPersModel[pm]->hasModeData(0) && aPersModel[pm]->vignette.meanErr > MaxDeviation * errVignette) { + for (int pm=0;pmhasModeData(0) && aPersModel[pm]->vignette.meanErr > maxAvgDevFac * errVignette) { aPersModel[pm]->vignette.badErr=true; filtered++; } - if (aPersModel[pm]->hasModeData(1) && aPersModel[pm]->base.meanErr > MaxDeviation * errBase) { + if (aPersModel[pm]->hasModeData(1) && aPersModel[pm]->base.meanErr > maxAvgDevFac * errBase) { aPersModel[pm]->base.badErr=true; filtered++; } if (aPersModel[pm]->hasModeData(2) && - (aPersModel[pm]->chromRG.meanErr > MaxDeviation * errChrom || aPersModel[pm]->chromG.meanErr > MaxDeviation * errChrom || aPersModel[pm]->chromBG.meanErr > MaxDeviation * errChrom)) { + (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; filtered++; } } - //printf("Filtered %i frames from %i profile %s\n", filtered, baseCount+chromCount+vignetteCount, fname.c_str()); + //printf("Filtered %.1f%% frames for maxAvgDevFac %g leaving %i\n", filtered*100./(baseCount+chromCount+vignetteCount), maxAvgDevFac, baseCount+chromCount+vignetteCount-filtered); } + return filtered; } @@ -333,7 +345,7 @@ void LCPProfile::calcParams(int mode, float focalLength, float focusDist, float pLow=pHigh; else if (!pHigh) pHigh=pLow; - else if (mode==0 || focusDist>0) { + 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 @@ -342,29 +354,52 @@ void LCPProfile::calcParams(int mode, float focalLength, float focusDist, float for (int pm=0;pmaperture; // float aperLog=log(aper); float focDist=aPersModel[pm]->focDist; float focDistLog=log(focDist)+euler; + double meanErr; if (aPersModel[pm]->hasModeData(mode)) { if (mode==0) { - // by aperture, and max out focus distance + meanErr=aPersModel[pm]->vignette.meanErr; + + // 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 && aperaperture && pLow->aperture > aperture) + if (aPersModel[pm]->focLen==bestFocLenLow && ( + (aper==aperture && pLow->vignette.meanErr>meanErr) + || (aper>=aperture && aperaperture && pLow->aperture > aperture) || (aper<=aperture && (pLow->aperture>aperture || fabs(aperture-aper)aperture))))) { pLow=aPersModel[pm]; } - if (aPersModel[pm]->focLen==bestFocLenHigh && ((aper<=aperture && aper>pHigh->aperture && pHigh->aperture < aperture) + if (aPersModel[pm]->focLen==bestFocLenHigh && ( + (aper==aperture && pHigh->vignette.meanErr>meanErr) + || (aper<=aperture && aper>pHigh->aperture && pHigh->aperture < aperture) || (aper>=aperture && (pHigh->apertureaperture))))) { pHigh=aPersModel[pm]; } } else { + meanErr = (mode==1 ? aPersModel[pm]->base.meanErr : aPersModel[pm]->chromG.meanErr); + + if (focusDist>0) { // by focus distance - if (aPersModel[pm]->focLen==bestFocLenLow && ((focDist>=focusDist && focDistfocDist && pLow->focDist > focusDist) + if (aPersModel[pm]->focLen==bestFocLenLow && ( + (focDist==focusDist && (mode==1 ? pLow->base.meanErr : pLow->chromG.meanErr)>meanErr) + || (focDist>=focusDist && focDistfocDist && pLow->focDist > focusDist) || (focDist<=focusDist && (pLow->focDist>focusDist || fabs(focusDistLog-focDistLog)focDist)+euler)))))) { pLow=aPersModel[pm]; } - if (aPersModel[pm]->focLen==bestFocLenHigh && ((focDist<=focusDist && focDist>pHigh->focDist && pHigh->focDist < focusDist) + if (aPersModel[pm]->focLen==bestFocLenHigh && ( + (focDist==focusDist && (mode==1 ? pHigh->base.meanErr : pHigh->chromG.meanErr)>meanErr) + || (focDist<=focusDist && focDist>pHigh->focDist && pHigh->focDist < focusDist) || (focDist>=focusDist && (pHigh->focDistfocDist)+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) { + pLow=aPersModel[pm]; + } + if (aPersModel[pm]->focLen==bestFocLenHigh && (mode==1 ? pHigh->base.meanErr : pHigh->chromG.meanErr)>meanErr) { + pHigh=aPersModel[pm]; + } + } } } } diff --git a/rtengine/lcp.h b/rtengine/lcp.h index 4986094dc..e17db1b78 100644 --- a/rtengine/lcp.h +++ b/rtengine/lcp.h @@ -71,6 +71,8 @@ namespace rtengine { static void XMLCALL XmlTextHandler (void *pLCPProfile, const XML_Char *s, int len); static void XMLCALL XmlEndHandler (void *pLCPProfile, const char *el); + int filterBadFrames(double maxAvgDevFac, int minFramesLeft); + public: // Common data Glib::ustring profileName, lensPrettyName, cameraPrettyName, lens, camera; // lens/camera(=model) can be auto-matched with DNG @@ -79,7 +81,8 @@ namespace rtengine { int persModelCount; // The correction frames - LCPPersModel* aPersModel[2000]; // Do NOT use std::list or something, it's buggy in GCC! + static const int MaxPersModelCount=3000; + LCPPersModel* aPersModel[MaxPersModelCount]; // Do NOT use std::list or something, it's buggy in GCC! LCPProfile(Glib::ustring fname);