27 #include <hugin_config.h> 
   36 #include <vigra/error.hxx> 
   37 #include <vigra/functorexpression.hxx> 
   38 #include <vigra/transformimage.hxx> 
   48 #include "../deghosting/deghosting.h" 
   49 #include "../deghosting/khan.h" 
   64 bool mergeWeightedAverage(std::vector<std::string> inputFiles, vigra::FRGBImage& output, vigra::BImage& alpha, vigra::Rect2D& outputROI)
 
   67     std::vector<ImagePtr> images;
 
   68     std::vector<deghosting::BImagePtr> weightImages;
 
   69     std::vector<vigra::ImageImportInfo> imageInfo;
 
   72     for (
size_t i = 0; i < inputFiles.size(); i++)
 
   74         vigra::ImageImportInfo 
info(inputFiles[i].c_str());
 
   75         imageInfo.push_back(info);
 
   78             outputROI = vigra::Rect2D(vigra::Point2D(info.getPosition()), info.size());
 
   82             outputROI |= vigra::Rect2D(vigra::Point2D(info.getPosition()), info.size());
 
   86     for (
size_t i=0; i < imageInfo.size(); i++)
 
   93             std::cout << 
"Loading image: " << inputFiles[i] << std::endl;
 
   96         vigra::Point2D offset = vigra::Point2D(imageInfo[i].getPosition());
 
   97         offset -= outputROI.upperLeft();
 
   99         img->resize(outputROI.size());
 
  100         weight->resize(img->size().width(), img->size().height(), 0);
 
  101         if (imageInfo[i].numBands() == 4)
 
  107             importImage(imageInfo[i], 
destImage(*img, offset));
 
  110         images.push_back(img);
 
  111         weightImages.push_back(weight);
 
  114     output.resize(outputROI.size());
 
  115     alpha.resize(output.width(), output.height(), 0);
 
  118         std::cout << 
"Calculating weighted average " << std::endl;
 
  125     for (
int y=0; y < output.height(); y++)
 
  127         for (
int x=0; x < output.width(); x++)
 
  131             bool hasValues = 
false;
 
  132             for (
unsigned imgNr=0; imgNr < images.size(); imgNr++)
 
  135                 const vigra::UInt8 weight = (*weightImages[imgNr])(x, y);
 
  136                 waverage( (*images[imgNr])(x,y), weight);
 
  137                 hasValues |= (weight > 0);
 
  142                 output(x,y) = waverage();
 
  152                                  const std::vector<deghosting::FImagePtr>& weights,
 
  153                                  vigra::FRGBImage& output,
 
  154                                  vigra::BImage& alpha,
 
  155                                  const vigra::Rect2D outputROI)
 
  159         std::cout << 
"Merging input images" << std::endl;
 
  161     int width = (weights[0])->width();
 
  162     int height = (weights[0])->height();
 
  164     assert(inputFiles.size() == weights.size());
 
  166     vigra::BasicImage<vigra::NumericTraits<vigra::FRGBImage::PixelType>::Promote> weightedImg(width, height);
 
  167     vigra::BasicImage<vigra::NumericTraits<vigra::FImage::PixelType>::Promote> weightAdded(width, height);
 
  168     for(
unsigned i = 0; i < inputFiles.size(); i++)
 
  170         vigra::ImageImportInfo inputInfo(inputFiles[i].c_str());
 
  171         vigra::BasicImage<vigra::NumericTraits<vigra::FRGBImage::PixelType>::Promote> tmpImg(outputROI.size());
 
  174         vigra::Point2D offset = vigra::Point2D(inputInfo.getPosition());
 
  175         offset -= outputROI.upperLeft();
 
  176         if (inputInfo.numBands() == 4)
 
  178             vigra::BImage tmpMask(tmpImg.size());
 
  190     output.resize(width, height);
 
  191     alpha.resize(width, height, 0);
 
  194         vigra::Threshold<vigra::FImage::PixelType, vigra::BImage::PixelType>(1e-7f, FLT_MAX, 0, 255));
 
  200     std::cout << name << 
": merge overlapping images" << std::endl
 
  204          << 
"Usage: " << name  << 
" [options] -o output.exr <input-files>" << std::endl
 
  205          << 
"Valid options are:" << std::endl
 
  206          << 
"  -o|--output prefix output file" << std::endl
 
  207          << 
"  -m mode   merge mode, can be one of: avg (default), avg_slow, khan, if avg, no" << std::endl
 
  208          << 
"            -i and -s options apply" << std::endl
 
  209          << 
"  -i iter   number of iterations to execute (default is 4). Khan only" << std::endl
 
  210          << 
"  -s sigma  standard deviation of Gaussian weighting" << std::endl
 
  211          << 
"            function (sigma > 0); default: 30. Khan only" << std::endl
 
  212          << 
"  -a set    advanced settings. Possible options are:" << std::endl
 
  213          << 
"              f   use gray images for computation. It's about two times faster" << std::endl
 
  214          << 
"                  but it usually returns worse results." << std::endl
 
  215          << 
"              g   use gamma 2.2 correction instead of logarithm" << std::endl
 
  216          << 
"              m   do not scale image, NOTE: slows down process" << std::endl
 
  217          << 
"  -c        Only consider pixels that are defined in all images (avg mode only)" << std::endl
 
  218          << 
"  -v|--verbose   Verbose, print progress messages, repeat for" << std::endl
 
  219          << 
"                 even more verbose output" << std::endl
 
  220          << 
"  -h|help   Display help (this text)" << std::endl
 
  225 int main(
int argc, 
char* argv[])
 
  229     const char* optstring = 
"chvo:m:i:s:a:el";
 
  230     static struct option longOptions[] =
 
  232         { 
"output", required_argument, NULL, 
'o' },
 
  233         { 
"verbose", no_argument, NULL, 
'v' },
 
  234         { 
"help", no_argument, NULL, 
'h' },
 
  240     std::string outputFile = 
"merged.exr";
 
  241     std::string mode = 
"avg";
 
  242     bool onlyCompleteOverlap = 
false;
 
  248     while ((c = getopt_long(argc, argv, optstring, longOptions, 
nullptr)) != -1)
 
  256                 iterations = atoi(optarg);
 
  259                 sigma = atof(optarg);
 
  262                 for(
char* c = optarg; *c; c++)
 
  281                 onlyCompleteOverlap = 
true;
 
  303     unsigned nFiles = argc - optind;
 
  309     else if (nFiles == 1)
 
  311         std::cout << std::endl << 
"Only one input image given. Copying input image to output image." << std::endl;
 
  313         std::ifstream infile(argv[optind], std::ios_base::binary);
 
  314         std::ofstream outfile(outputFile.c_str(), std::ios_base::binary);
 
  315         outfile << infile.rdbuf();
 
  320     std::vector<std::string> inputFiles;
 
  321     for (
size_t i=optind; i < (size_t)argc; i++)
 
  323         inputFiles.push_back(argv[i]);
 
  330         if (mode == 
"avg_slow")
 
  336                 std::cout << 
"Running simple weighted avg algorithm" << std::endl;
 
  339             vigra::Rect2D outputROI;
 
  344                 std::cout << 
"Writing " << outputFile << std::endl;
 
  346             vigra::ImageExportInfo exinfo(outputFile.c_str());
 
  347             exinfo.setPixelType(
"FLOAT");
 
  348             exinfo.setPosition(outputROI.upperLeft());
 
  349             exinfo.setCanvasSize(vigra::Size2D(outputROI.lowerRight().x, outputROI.lowerRight().y));
 
  352         else if (mode == 
"avg")
 
  360         else if (mode == 
"khan")
 
  364                 std::cout << 
"Running Khan deghosting algorithm" << std::endl;
 
  366             vigra::Rect2D outputROI;
 
  367             std::vector<deghosting::FImagePtr> weights;
 
  385                 std::cout << 
"Writing " << outputFile << std::endl;
 
  387             vigra::ImageExportInfo exinfo(outputFile.c_str());
 
  388             exinfo.setPixelType(
"FLOAT");
 
  389             exinfo.setPosition(outputROI.upperLeft());
 
  390             exinfo.setCanvasSize(vigra::Size2D(outputROI.lowerRight().x, outputROI.lowerRight().y));
 
  395             std::cerr << 
"Unknown merge mode, see help for a list of possible modes" << std::endl;
 
  399     catch (std::exception& e)
 
  401         std::cerr << 
"caught exception: " << e.what() << std::endl;
 
const uint16_t ADV_MULTIRES
std::shared_ptr< vigra::BImage > BImagePtr
void transformImage(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
Transform an image into the panorama. 
bool mergeWeightedAverage(std::vector< std::string > inputFiles, vigra::FRGBImage &output, vigra::BImage &alpha, vigra::Rect2D &outputROI)
bool weightedAverageOfImageFiles(const std::vector< std::string > &inputFiles, const std::vector< deghosting::FImagePtr > &weights, vigra::FRGBImage &output, vigra::BImage &alpha, const vigra::Rect2D outputROI)
compute output image when given source images 
void exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor, AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor, const ImageExportInfo &export_info)
Write the image and its alpha channel to a file. 
vigra::pair< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImage(const ROIImage< Image, Mask > &img)
const uint16_t OTHER_GRAY
virtual std::vector< FImagePtr > createWeightMasks() override
create weight masks create weight masks for masking out ghosting regions 
void combineThreeImages(SrcImageIterator1 src1_upperleft, SrcImageIterator1 src1_lowerright, SrcAccessor1 src1_acc, SrcImageIterator2 src2_upperleft, SrcAccessor2 src2_acc, SrcImageIterator3 src3_upperleft, SrcAccessor3 src3_acc, DestImageIterator dest_upperleft, DestAccessor dest_acc, const Functor &func)
void combineTwoImages(SrcImageIterator1 src1_upperleft, SrcImageIterator1 src1_lowerright, SrcAccessor1 src1_acc, SrcImageIterator2 src2_upperleft, SrcAccessor2 src2_acc, DestImageIterator dest_upperleft, DestAccessor dest_acc, const Functor &func)
void importImageAlpha(const ImageImportInfo &import_info, ImageIterator image_iterator, ImageAccessor image_accessor, AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor, VigraTrueType)
vigra::FRGBImage ImageType
std::shared_ptr< ImageType > ImagePtr
vigra::pair< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImage(ROIImage< Image, Alpha > &img)
vigra::triple< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImageRange(const ROIImage< Image, Mask > &img)
helper function for ROIImages 
void importImageAlpha(const ImageImportInfo &import_info, ImageIterator image_iterator, ImageAccessor image_accessor, AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor)
Read the image specified by the given vigra::ImageImportInfo object including its alpha channel...
static uint16_t otherFlags
std::string GetHuginVersion()
return a string with version numbers 
vigra::triple< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImageRange(ROIImage< Image, Alpha > &img)
static void info(const char *fmt,...)
vigra::Rect2D getOutputROI() const 
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames) 
void reduceFilesToHDR(std::vector< std::string > input, std::string output, bool onlyCompleteOverlap, Functor &reduce)
int main(int argc, char *argv[])