27 #include <foreign/levmar/levmar.h>
32 #define DEBUG_LOG_VIG 1
42 x = sqrt(sigma* (2*x - sigma));
50 const std::vector<vigra_ext::PointPairRGB> &
data,
51 double mEstimatorSigma,
bool symmetric,
53 : m_pano(pano), m_data(data), huberSigma(mEstimatorSigma), symmetricError(symmetric),
54 m_maxIter(maxIter), m_progress(progress)
62 std::vector<std::set<std::string> > usedVars(pano.
getNrOfImages());
65 for (
unsigned i=0; i < optvars.size(); i++)
67 const std::set<std::string> vars = optvars[i];
69 for (std::set<std::string>::const_iterator it = vars.begin();
70 it != vars.end(); ++it)
78 usedVars[i].insert(var.
type);
80 #define CheckLinked(name)\
81 if(img_i.name##isLinked())\
83 for(unsigned j=i+1;j<pano.getNrOfImages();j++)\
84 if(img_i.name##isLinkedWith(pano.getImage(j)))\
87 usedVars[j].insert(var.type);\
111 if(var.
type==
"Vx" || var.
type==
"Vy")
123 for (
size_t i=0; i < m_vars.size(); i++)
125 assert(!m_vars[i].imgs.empty());
127 unsigned j = *(m_vars[i].imgs.begin());
129 x[i] = m_imgs[j].getVar(m_vars[i].type);
137 for (
size_t i=0; i < m_vars.size(); i++)
140 assert(!m_vars[i].imgs.empty());
142 for (std::set<unsigned>::const_iterator it = m_vars[i].imgs.begin();
143 it != m_vars[i].imgs.end(); ++it)
145 m_imgs[*it].setVar(m_vars[i].type, x[i]);
165 std::ostringstream oss;
166 oss <<
"vig_log_" << iter;
168 std::ofstream
log(oss.str().c_str());
169 log <<
"VIGparams = [";
170 for (
int i = 0; i < m; i++) {
173 log <<
" ]; " << std::endl;
175 std::ofstream script(
"vig_test.pto");
181 size_t nImg = dat->
m_imgs.size();
182 std::vector<RespFunc> resp(nImg);
183 std::vector<InvRespFunc> invResp(nImg);
184 for (
size_t i=0; i < nImg; i++) {
185 resp[i] = RespFunc(dat->
m_imgs[i]);
186 invResp[i] = InvRespFunc(dat->
m_imgs[i]);
191 int lutsize = resp[i].m_lutR.size();
192 for (
int j=0; j < lutsize-1; j++)
194 double d = resp[i].m_lutR[j] - resp[i].m_lutR[j+1];
196 monErr += d*d*lutsize;
202 resp[i].enforceMonotonicity();
203 invResp[i].enforceMonotonicity();
211 log <<
"VIGval = [ ";
214 for (std::vector<vigra_ext::PointPairRGB>::const_iterator it = dat->
m_data.begin();
215 it != dat->
m_data.end(); ++it)
217 vigra::RGBValue<double> l2 = invResp[it->imgNr2](it->i2, it->p2);
218 vigra::RGBValue<double> i2ini1 = resp[it->imgNr1](l2, it->p1);
219 vigra::RGBValue<double> error = it->i1 - i2ini1;
224 vigra::RGBValue<double> l1 = invResp[it->imgNr1](it->i1, it->p1);
225 vigra::RGBValue<double> i1ini2 = resp[it->imgNr2](l1, it->p2);
226 vigra::RGBValue<double> error2 = it->i2 - i1ini2;
229 for (
int i=0; i < 3; i++) {
230 sqerror += error[i]*error[i];
231 sqerror += error2[i]*error2[i];
237 for (
int i=0; i < 3; i++) {
251 log << it->i1.green() <<
" "<< l1.green() <<
" " << i1ini2.green() <<
" "
252 << it->i2.green() <<
" "<< l2.green() <<
" " << i2ini1.green() <<
"; " << std::endl;
257 log << std::endl <<
"VIGerr = [";
258 for (
int i = 0; i < n; i++) {
259 log << x[i] << std::endl;
261 log <<
" ]; " << std::endl;
273 double error = sqrt(sqerror/n)*255;
274 snprintf(tmp,199,
"Iteration: %d, error: %f", iter, error);
279 const std::vector<vigra_ext::PointPairRGB> & correspondences,
280 const float imageStepSize,
287 unsigned int optCount=0;
288 for (OptimizeVector::const_iterator it=vars.begin(); it != vars.end(); ++it)
290 std::set<std::string> cvars;
291 for (std::set<std::string>::const_iterator itv = (*it).begin();
292 itv != (*it).end(); ++itv)
294 if ((*itv)[0] ==
'E' || (*itv)[0] ==
'R' || (*itv)[0] ==
'V') {
298 photometricVars.push_back(cvars);
299 optCount+=cvars.size();
308 OptimData data(pano, photometricVars, correspondences, 5 * imageStepSize,
false, nMaxIter, progress);
310 double info[LM_INFO_SZ];
314 vigra::ArrayVector<double> p(m, 0.0);
318 vigra::ArrayVector<double> x(n, 0.0);
322 printf(
"Parameters before optimisation: ");
323 for(
int i=0; i<m; ++i)
324 printf(
"%.7g ", p[i]);
331 optimOpts[0] = LM_INIT_MU;
333 optimOpts[1] = LM_STOP_THRESH;
334 optimOpts[2] = LM_STOP_THRESH;
335 optimOpts[3] =
std::pow(imageStepSize*0.1f, 2);
337 optimOpts[4] = LM_DIFF_DELTA;
339 dlevmar_dif(&
photometricError, &
photometricVis, &(p[0]), &(x[0]), m, n, nMaxIter, optimOpts, info, NULL,NULL, &data);
342 data.
FromX(p.begin());
347 for (
int i=0; i<n; i++) {
350 error = sqrt(error/n);
353 printf(
"Levenberg-Marquardt returned in %g iter, reason %g\nSolution: ", info[5], info[6]);
354 for(
int i=0; i<m; ++i)
355 printf(
"%.7g ", p[i]);
356 printf(
"\n\nMinimization info:\n");
357 for(
int i=0; i<LM_INFO_SZ; ++i)
358 printf(
"%g ", info[i]);
371 srcImage.setRadialVigCorrCoeff(vigCorr);
372 srcImage.
setSize(vigra::Size2D(500, 500));
374 for (
size_t x = 0; x < 250; x += 10)
377 if (vigFactor < 0.2 || vigFactor > 1.1)
389 if(pano.
getImage(i).getWhiteBalanceBlue()>3)
393 if(pano.
getImage(i).getWhiteBalanceRed()>3)
402 const std::vector<vigra_ext::PointPairRGB> & correspondences,
403 const float imageStepSize,
411 const bool singleStack = (stacks.size() == 1);
414 if (mode == OPT_PHOTOMETRIC_LDR || mode == OPT_PHOTOMETRIC_LDR_WB)
420 correspondences, imageStepSize, progress, error);
431 correspondences, imageStepSize, progress, error);
443 if (mode == OPT_PHOTOMETRIC_LDR_WB || mode == OPT_PHOTOMETRIC_HDR_WB)
450 correspondences, imageStepSize, progress, error);
455 if(hasHighVignetting)
463 if(hasHighVignetting || hasHighWB)
471 correspondences, imageStepSize, progress, error);
static int photometricVis(double *p, double *x, int m, int n, int iter, double sqerror, void *data)
std::vector< UIntSet > getHDRStacks(const PanoramaData &pano, UIntSet allImgs, PanoramaOptions opts)
returns vector of set of output stacks
AppBase::ProgressDisplay * m_progress
declaration of functions to handle stacks and layers
static void photometricError(double *p, double *x, int m, int n, void *data)
std::vector< SrcPanoImage > m_imgs
const PanoramaData & m_pano
void FromX(double *x)
copy new values from x to into this->m_imgs
virtual void printPanoramaScript(std::ostream &o, const OptimizeVector &optvars, const PanoramaOptions &options, const UIntSet &imgs, bool forPTOptimizer, const std::string &stripPrefix="") const =0
create an optimizer script
virtual void setSrcImage(unsigned int nr, const SrcPanoImage &img)=0
set input image parameters TODO: Propagate changes to linked images.
std::vector< float > EMoRParams
virtual void cancelAlgorithm()
Call this when the algorithm is cancelled.
bool CheckStrangeWB(PanoramaData &pano)
hugin_utils::FDiff2D RadialVigCorrCenterShift
std::vector< double > RadialVigCorrCoeff
bool IsHighVignetting(std::vector< double > vigCorr)
bool set_contains(const _Container &c, const typename _Container::key_type &key)
PhotometricOptimizeMode
local optimize definition.
bool updateDisplay()
updates the display, return true, if update was successful, false if cancel was pressed ...
vigra::pair< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImage(const ROIImage< Image, Mask > &img)
std::set< unsigned > imgs
double weightHuber(double x, double sigma)
expects the abs(error) values
unsigned int colorReferenceImage
#define CheckLinked(name)
void ToX(double *x)
copy optimisation variables into x
virtual bool wasCancelled() const
std::set< unsigned int > UIntSet
virtual bool runAlgorithm()
implementation of the algorithm.
std::vector< VariableMap > VariableMapVector
empirical model of response
virtual AppBase::ProgressDisplay * getProgressDisplay() const
virtual UIntSet getActiveImages() const =0
get active images
float pow(float a, double b)
static void smartOptimizePhotometric(PanoramaData &pano, PhotometricOptimizeMode mode, const std::vector< vigra_ext::PointPairRGB > &correspondences, const float imageStepSize, AppBase::ProgressDisplay *progress, double &error)
use various heuristics to decide what to optimize.
virtual const PanoramaOptions & getOptions() const =0
returns the options for this panorama
virtual const SrcPanoImage & getImage(std::size_t nr) const =0
get a panorama image, counting starts with 0
static void optimizePhotometric(PanoramaData &pano, const OptimizeVector &vars, const PointPairs &correspondences, const float imageStepSize, AppBase::ProgressDisplay *progress, double &error)
const PointPairs & o_correspondences
vigra::RGBValue< T, RIDX, GIDX, BIDX > log(vigra::RGBValue< T, RIDX, GIDX, BIDX > const &v)
component-wise logarithm
const float o_imageStepSize
virtual bool runAlgorithm()
implementation of the algorithm.
options wxIntPtr wxIntPtr sortData std::vector< PanoInfo > * data
PanoramaData & o_panorama
virtual VariableMapVector getVariables() const =0
get variables of this panorama
void setSize(vigra::Size2D val)
Set the image size in pixels.
static void info(const char *fmt,...)
std::vector< std::set< std::string > > OptimizeVector
void fill_set(_Container &c, typename _Container::key_type begin, typename _Container::key_type end)
std::vector< vigra_ext::PointPairRGB > m_data
virtual SrcPanoImage getSrcImage(unsigned imgNr) const =0
get a complete description of a source image
const OptimizeVector & o_vars
virtual std::size_t getNrOfImages() const =0
number of images.
All variables of a source image.
virtual void updateVariables(const VariableMapVector &vars)=0
Set the variables.
std::vector< VarMapping > m_vars
OptimData(const PanoramaData &pano, const OptimizeVector &optvars, const std::vector< vigra_ext::PointPairRGB > &data, double mEstimatorSigma, bool symmetric, int maxIter, AppBase::ProgressDisplay *progress)