27#include <hugin_config.h>
32#include <vigra/error.hxx>
34#include <vigra/cornerdetection.hxx>
35#include <vigra/localminmax.hxx>
39#include "vigra/stdimage.hxx"
40#include "vigra/stdimagefunctions.hxx"
41#include "vigra/functorexpression.hxx"
42#include "vigra/transformimage.hxx"
54#include <foreign/levmar/levmar.h>
65#define DEFAULT_OPTIMISATION_PARAMETER "abcvde"
129 for (
unsigned int i = 0;
i<3;
i++)
131 const std::set<std::string> vars =
m_optvars[
i];
132 for (std::set<std::string>::const_iterator
it = vars.begin();
it != vars.end(); ++
it)
134 const char var = (*it)[0];
135 if ((var >=
'a') && (var <=
'c'))
139 else if ((var ==
'd') || (var ==
'e'))
149 std::cerr <<
"Unknown parameter detected, ignoring!" << std::endl;
175 for (
unsigned int i = 0;
i < 3;
i++)
179 m_dist[
i][0] = img.getRadialDistortion()[0];
180 m_dist[
i][1] = img.getRadialDistortion()[1];
181 m_dist[
i][2] = img.getRadialDistortion()[2];
184 m_shift[0] = img.getRadialDistortionCenterShift().x;
185 m_shift[1] = img.getRadialDistortionCenterShift().y;
186 m_center[0] = img.getSize().width() / 2.0;
187 m_center[1] = img.getSize().height() / 2.0;
193 for (
unsigned int i = 0;
i < 3;
i++)
213 optvars.push_back(vars);
214 optvars.push_back(std::set<std::string>());
219 optvars.push_back(vars);
267 for (
unsigned int i = 0;
i<3;
i++)
269 double scale =
dat->m_hfov[1] /
dat->m_hfov[
i];
270 for (
unsigned int j = 0;
j<3;
j++)
272 dist[
i][
j] =
dat->m_dist[
i][
j] * pow(scale, (
int)(4 -
j));
274 dist[
i][3] = scale*(1 -
dat->m_dist[
i][0] -
dat->m_dist[
i][1] -
dat->m_dist[
i][2]);
278 center[0] =
dat->m_center[0] +
dat->m_shift[0];
279 center[1] =
dat->m_center[1] +
dat->m_shift[1];
285 unsigned int noPts =
dat->m_pano.getNrOfCtrlPoints();
291 double dist_p1 = vigra::hypot(
cp.x1 - center[0],
cp.y1 - center[1]);
292 double dist_p2 = vigra::hypot(
cp.x2 - center[0],
cp.y2 - center[1]);
294 if (
cp.image1Nr == 1)
321 if (
dat->huberSigma > 0)
327 dat->m_pano.updateCtrlPointErrors(
newCPs);
357 vigra::ArrayVector<double> p(m, 0.0);
361 vigra::ArrayVector<double> x(
n, 0.0);
367 for (
int i = 0;
i<m; ++
i)
374 ret =
dlevmar_dif(&
optGetError, &
optVis, &(p[0]), &(x[0]), m,
n,
nMaxIter,
NULL, info,
NULL,
NULL, &data);
381 for (
int i = 0;
i<
n;
i++)
383 error += x[
i] * x[
i];
385 error =
sqrt(error /
n);
389 fprintf(
stderr,
"Levenberg-Marquardt returned %d in %g iter, reason %g\nSolution: ",
ret, info[5], info[6]);
390 for (
int i = 0;
i<m; ++
i)
405 std::cout << name <<
": Parameter estimation of transverse chromatic abberations" << std::endl
408 <<
"Usage: " << name <<
" [options] <inputfile>" << std::endl
409 <<
" option are: " << std::endl
410 <<
" -h Display help (this text)" << std::endl
411 <<
" -l input file is PTO file instead of image" << std::endl
412 <<
" -m method optimization method (0 normal, 1 newfit)" << std::endl
413 <<
" -o optvars string of variables to optimize (\"abcvde\")" << std::endl
414 <<
" -r reset values (this will zero a,b,c,d,e params and set v to 10)" << std::endl
415 <<
" makes sense only with -l option" << std::endl
416 <<
" -s <scale> Scale for corner detection" << std::endl
417 <<
" -n <number> number of points per grid cell (default: 10)" << std::endl
418 <<
" -g <number> divide image in <number>x<number> grid cells (default: 10)" << std::endl
419 <<
" -t num Remove all control points with an error higher than num pixels (default: 1.5)" << std::endl
420 <<
" -v Verbose" << std::endl
421 <<
" --save-into-database Saves the tca data into Hugin lens database" << std::endl
422 <<
" -w filename write PTO file" << std::endl
423 <<
" -R <r> Use this file as red channel" << std::endl
424 <<
" -G <g> Use this file as green channel" << std::endl
425 <<
" -B <b> Use this file as blue channel" << std::endl
427 <<
" <inputfile> is the base name of 4 image files:" << std::endl
428 <<
" <inputfile> Colour file to compute TCA parameters" << std::endl
429 <<
" red_<inputfile> Red channel of <inputfile>" << std::endl
430 <<
" green_<inputfile> Green channel of <inputfile>" << std::endl
431 <<
" blue_<inputfile> Blue channel of <inputfile>" << std::endl
432 <<
" The channel images must be colour images with 3 identical channels." << std::endl
433 <<
" If any of -R, -G, or -B is given, this file name is used instead of the derived name." << std::endl
435 <<
" Output:" << std::endl
436 <<
" commandline arguments for fulla" << std::endl;
442template <
class ImageType>
445 vigra::BasicImage<vigra::RGBValue<vigra::UInt8> >
img8(img.size());
448 transformImage(srcImageRange(img), destImage(
img8),
449 vigra::functor::Arg1()*vigra::functor::Param(
ratio));
452 std::cout <<
"image8 size:" <<
img8.size() << std::endl;
459 std::cout <<
"Finding control points... " << std::endl;
462 const long sWidth = 29 + 11;
465 vigra::Size2D size(
img8.width(),
img8.height());
466 std::vector<vigra::Rect2D>
rects;
473 (
partx + 1)*size.x / grid, (
party + 1)*size.y / grid);
474 rect &= vigra::Rect2D(size);
475 if (
rect.width()>0 &&
rect.height()>0)
482 #pragma omp parallel for schedule(dynamic)
483 for (
int i = 0;
i <
rects.size(); ++
i)
492 for (MapPoints::const_reverse_iterator
it =
points.rbegin();
it !=
points.rend(); ++
it)
494 if (cps.size() >= nPoints)
506 img8, vigra::GreenAccessor<vigra::RGBValue<vigra::UInt8> >(),
508 img8, vigra::RedAccessor<vigra::RGBValue<vigra::UInt8> >(),
550 std::ostringstream
buf;
551 buf <<
"Number of good matches: " << cps.size() <<
", bad matches: " <<
nBad << std::endl;
552 std::cout <<
buf.str();
557 for (HuginBase::CPVector::const_iterator
it = cps.begin();
it != cps.end(); ++
it)
567template <
class PixelType>
570 typedef vigra::BasicImage<PixelType>
ImageType;
574 vigra::ImageImportInfo
imgInfo(filename);
577 const int bands =
imgInfo.numBands();
580 if (!(bands == 3 || (bands == 4 &&
extraBands == 1)))
582 std::cerr <<
"Unsupported number of bands!";
592 vigra::BImage alpha(
imgInfo.size());
600 std::string red_name;
607 red_name=std::string(
"red_")+filename;
617 lenses.updatePartNumbers();
620 std::string green_name;
627 green_name=std::string(
"green_")+filename;
637 lenses.updatePartNumbers();
640 std::string blue_name;
647 blue_name=std::string(
"blue_")+filename;
657 lenses.updatePartNumbers();
662 lenses.unlinkVariablePart(HuginBase::ImageVariableGroup::IVE_HFOV, 0);
663 lenses.unlinkVariablePart(HuginBase::ImageVariableGroup::IVE_RadialDistortion, 0);
683 catch (std::exception& e)
685 std::cerr <<
"ERROR: caught exception: " << e.what() << std::endl;
706 for (
unsigned int i=0;
i < 3;
i++)
731 for (
unsigned int i=0;
i < 3;
i++)
734 hfov[
i] = img.getHFOV();
735 dist[
i][0] = img.getRadialDistortion()[0];
736 dist[
i][1] = img.getRadialDistortion()[1];
737 dist[
i][2] = img.getRadialDistortion()[2];
740 shift[0] = img.getRadialDistortionCenterShift().x;
741 shift[1] = img.getRadialDistortionCenterShift().y;
747 for (
unsigned int i=0 ;
i<3 ;
i++)
749 double scale = hfov[1] / hfov[
i];
750 for (
unsigned int j=0 ;
j<3 ;
j++)
760 "-b %.7f:%.7f:%.7f:%.7f ",
767 "-b %.7f:%.7f:%.7f:%.7f "
784 std::cout << std::endl <<
"For saving information tca data into database no suitable information" << std::endl
785 <<
"found in EXIF data." << std::endl
786 <<
"For fixed lens cameras leave lensname empty." << std::endl << std::endl <<
"Lensname: ";
788 std::cin.getline(
input, 255);
794 std::cout <<
"Camera maker: ";
797 std::cin.getline(
input, 255);
800 std::cout <<
"Camera model: ";
803 std::cin.getline(
input, 255);
809 double focal = img.getExifFocalLength();
812 std::cout <<
"Real focal length (in mm): ";
832 std::cout << std::endl << std::endl <<
"TCA data for " <<
lensname <<
" @ " <<
focal <<
" mm successful saved into database." << std::endl;
836 std::cout << std::endl << std::endl <<
"Could not save data into database." << std::endl;
849 for (
int i = 0;
i < 10;
i++)
861 std::cerr <<
"Unknown optimizer strategy." << std::endl
862 <<
"Using newfit method." << std::endl;
869 for (HuginBase::CPVector::const_iterator
it = cps.begin();
it != cps.end(); ++
it)
878 std::cerr <<
"Ctrl points before pruning: " << cps.size() <<
", after: " <<
newCPs.size() << std::endl;
882 if (cps.size() ==
newCPs.size())
906 const char*
optstring =
"hlm:o:rt:vw:R:G:B:s:g:n:";
956 std::cerr <<
hugin_utils::stripPath(
argv[0]) <<
": Invalid parameter: control point error threshold (-t) must be greater than 0" << std::endl;
1048 std::cerr <<
" ERROR: unsupported pixel type: " <<
pixelType << std::endl;
std::multimap< double, vigra::Diff2D > MapPoints
class to access Hugins camera and lens database
!! from PTOptimise.h 1951
Somewhere to specify what variables belong to what.
Contains various routines used for stitching panoramas.
represents a control point
Same as above, but use a non const panorama.
static void Clean()
cleanup the static LensDB instance, must be called at the end of the program
static LensDB & GetSingleton()
returns the static LensDB instance
virtual std::size_t getNrOfCtrlPoints() const =0
number of control points
virtual void setSrcImage(unsigned int nr, const SrcPanoImage &img)=0
set input image parameters TODO: Propagate changes to linked images.
virtual SrcPanoImage getSrcImage(unsigned imgNr) const =0
get a complete description of a source image
virtual std::size_t getNrOfImages() const =0
number of images.
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
void setHeight(unsigned int h)
set panorama height
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
const PanoramaOptions & getOptions() const
returns the options for this panorama
void setOptimizeVector(const OptimizeVector &optvec)
set optimize setting
void setCtrlPoints(const CPVector &points)
set all control points (Ippei: Is this supposed to be 'add' method?)
bool ReadPTOFile(const std::string &filename, const std::string &prefix="")
read pto file from the given filename into Panorama object it does some checks on the file and issues...
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
unsigned int addCtrlPoint(const ControlPoint &point)
add a new control point.
void printPanoramaScript(std::ostream &o, const OptimizeVector &optvars, const PanoramaOptions &options, const UIntSet &imgs, bool forPTOptimizer, const std::string &stripPrefix="") const
create an optimizer script
unsigned int addImage(const SrcPanoImage &img)
the the number for a specific image
void setOptions(const PanoramaOptions &opt)
set new output settings This is not used directly for optimizing/stiching, but it can be feed into ru...
void setSrcImage(unsigned int nr, const SrcPanoImage &img)
set input image parameters
const CPVector & getCtrlPoints() const
get all control point of this Panorama
std::size_t getNrOfImages() const
number of images.
All variables of a source image.
std::string getDBLensName() const
constructs the lens name for the database it is the lensname if known, for compact cameras it is cons...
void setSize(vigra::Size2D val)
Set the image size in pixels.
bool readEXIF()
try to fill out information about the image, by examining the exif data
class AlphaIterator class AlphaAccessor inline void importImageAlpha(const ImageImportInfo &import_info, ImageIterator image_iterator, ImageAccessor image_accessor, AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor)
vigra::FRGBImage ImageType
misc math function & classes used by other parts of the program
std::vector< ControlPoint > CPVector
std::vector< std::set< std::string > > OptimizeVector
std::set< unsigned int > UIntSet
std::string StrTrim(const std::string &str)
remove trailing and leading white spaces and tabs
std::string GetHuginVersion()
return a string with version numbers
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames)
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
void findInterestPointsPartial(vigra::triple< ImageIter, ImageIter, ImageAcc > img, const vigra::Rect2D &rect, double scale, unsigned nPoints, std::multimap< double, vigra::Diff2D > &points)
CorrelationResult PointFineTune(const IMAGET &templImg, ACCESSORT access_t, vigra::Diff2D templPos, int templSize, const IMAGES &searchImg, ACCESSORS access_s, vigra::Diff2D searchPos, int sWidth)
fine tune a point with normalized cross correlation
void fill_set(_Container &c, typename _Container::key_type begin, typename _Container::key_type end)
HuginBase::PanoramaData & m_pano
const HuginBase::OptimizeVector & m_optvars
void FromX(double *x)
copy new values from x to internal optimization variables
OptimData(HuginBase::PanoramaData &pano, const HuginBase::OptimizeVector &optvars, double mEstimatorSigma, int maxIter)
std::vector< double * > m_mapping
void ToX(double *x)
copy internal optimization variables into x
std::set< std::string > optvars
std::string alignedPrefix
std::string ptoOutputFile
Maximum of correlation, position and value.
hugin_utils::FDiff2D maxpos
void optimize_new(HuginBase::PanoramaData &pano)
static int ptProgress(int command, char *argument)
int main(int argc, char *argv[])
#define DEFAULT_OPTIMISATION_PARAMETER
static int ptinfoDlg(int command, char *argument)
void get_optvars(HuginBase::OptimizeVector &_retval)
int main2(HuginBase::Panorama &pano)
int optimize_old(HuginBase::Panorama &pano)
int processPTO(const char *filename)
void createCtrlPoints(HuginBase::Panorama &pano, const ImageType &img, int imgRedNr, int imgGreenNr, int imgBlueNr, double scale, int nPoints, unsigned grid)
void resetValues(HuginBase::Panorama &pano)
void print_result(HuginBase::Panorama &pano)
void optGetError(double *p, double *x, int m, int n, void *data)
std::multimap< double, vigra::Diff2D > MapPoints
int optVis(double *p, double *x, int m, int n, int iter, double sqerror, void *data)
static hugin_omp::Lock lock
double weightHuber(double x, double sigma)
int processImg(const char *filename)
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
functions to manage ROI's