deghosting_mask.cpp

Go to the documentation of this file.
00001 
00021 #include <iostream>
00022 #include <string>
00023 #include <cstring>
00024 #include <cstdio>
00025 
00026 #include <hugin_config.h>
00027 // for stripExtension
00028 #include <hugin_utils/utils.h>
00029 // for exportImage
00030 #include <vigra/impex.hxx>
00031 
00032 #include "deghosting.h"
00033 #include "support.h"
00034 #include "threshold.h"
00035 #include "denoise.h"
00036 
00037 // deghosting algorithms
00038 #include "khan.h"
00039 
00040 #include <getopt.h>
00041 #ifdef _WIN32
00042     #define snprintf _snprintf
00043 #endif
00044 
00045 // options for otherFlags
00046 static const uint16_t SAVE_GENWEIGHTS = 1;
00047 static const uint16_t OTHER_GRAY = 2;
00048 
00049 // globals containing settings
00050 static int iterations = 4;
00051 static double sigma = 30;
00052 static uint16_t flags = deghosting::ADV_ONLYP + deghosting::ADV_MULTIRES;
00053 static uint16_t otherFlags = 0;
00054 static uint16_t otherThresholdFlags = 0;
00055 static uint16_t debugFlags = 0;
00056 static deghosting::EMoR response(0.0f);
00057 static int verbosity = 0;
00058 static double thresholdLim = 150;
00059 static double contrast = 1.3;
00060 
00063 void parseOptions_advanced(char* optarg) {
00064     for(char *c = optarg; *c; c++) {
00065         switch(*c) {
00066             case 'f':
00067                 otherFlags += OTHER_GRAY;
00068                 break;
00069             case 'g':
00070                 flags += deghosting::ADV_GAMMA;
00071                 break;
00072             case 'm':
00073                 flags -= deghosting::ADV_MULTIRES;
00074                 break;
00075             case 't':
00076                 otherThresholdFlags += THRESHOLD_DONTCARE;
00077                 break;
00078             case 'w':
00079                 flags -= deghosting::ADV_ONLYP;
00080                 break;
00081             default:
00082                 std::cerr<< "Error: unknown option" << std::endl;
00083                 exit(1);
00084         }
00085     }
00086 }
00087 
00090 void parseOptions_save(char* optarg) {
00091     for(char *c = optarg; *c; c++) {
00092         switch(*c) {
00093             case 'i':
00094                 debugFlags += deghosting::SAVE_INITWEIGHTS;
00095                 break;
00096             case 'w':
00097                 otherFlags += SAVE_GENWEIGHTS;
00098                 break;
00099             default:
00100                 std::cerr<< "Error: unknown option" << std::endl;
00101                 exit(1);
00102         }
00103     }
00104 }
00105 
00106 static void usage()
00107 {
00108     std::cerr << "deghosting_mask: creates mask for removing ghosting in images" << std::endl
00109          << "deghosting_mask version " << hugin_utils::GetHuginVersion() << std::endl
00110          << std::endl
00111          << "Usage: deghosting_mask [options] inputfile(s) " << std::endl
00112          << "   option are: " << std::endl
00113          << "     -o, --output=PREFIX       prefix for output masks" << std::endl
00114          << "     -i, --iterations=ITER     number of iterations, default is (ITER > 0)" << std::endl
00115          << "                               default: " << iterations << std::endl
00116          << "     -s, --sigma=SIGMA         standard deviation of Gaussian weighting" << std::endl
00117          << "                               function (SIGMA > 0); default: " << sigma << std::endl
00118          //<< "     -r, --response=E:M:o:R    use camera response specified in EMoR format" << std::endl
00119          << "     -t, --threshold=THRESH    threshold; default: " << thresholdLim << std::endl
00120          << "     -c, --contrast=CONTR      change contrast before applying threshold;" << std::endl
00121          << "                               default: " << contrast << std::endl
00122          << "     -a, --advanced=SET        advanced settings. Possible options are:" << std::endl
00123          << "                               f   use gray images for computation. It's about two times faster" << std::endl
00124          << "                                   but it usually returns worse results." << std::endl
00125          << "                                   You also have to change threshold to smaller value (around 100)" << std::endl
00126          << "                               g   use gamma 2.2 correction instead of logarithm if input images are HDR" << std::endl
00127          << "                               m   do not scale image, NOTE: slows down process" << std::endl
00128          << "                               t   use simple threshold, may result in holes in images" << std::endl
00129          << "                               w   compute \"complete\" weights, not only probabilities" << std::endl
00130          << "     -w, --save=SET            advanced save settings" << std::endl
00131          << "                               i   save initial weights" << std::endl
00132          << "                               w   save generated weights" << std::endl
00133          << "     -h, --help                display this help" << std::endl
00134          << "     -v, --verbose             verbose, repeat for more verbose output" << std::endl;
00135 }
00136 
00137 int main(int argc, char *argv[]) {
00138     try
00139     {
00140         const char * optstring = "o:i:s:r:t:c:a:w:hv";
00141         opterr = 0;
00142         int c;
00143 
00144         std::string outputPrefix = "weight";
00145 
00146         enum optionArgumentKind {
00147             NoArgument,
00148             StringArgument,
00149             DoubleArgument,
00150             IntegerArgument,
00151             ArrayArgument
00152         };
00153 
00154         enum optionId {
00155             outputID,
00156             iterationsID,
00157             sigmaID,
00158             responseID,
00159             thresholdID,
00160             contrastID,
00161             advancedID,
00162             saveID,
00163             helpID,
00164             verboseID
00165         };
00166 
00167         static struct option longOptions[] = {
00168             { "output", 1, 0, StringArgument },
00169             { "iterations", 1, 0, IntegerArgument },
00170             { "sigma", 1, 0, DoubleArgument },
00171             { "response", 1, 0, ArrayArgument },
00172             { "threshold", 1, 0, DoubleArgument },
00173             { "contrast", 1, 0, DoubleArgument },
00174             { "advanced", 1, 0, StringArgument },
00175             { "save", 1, 0, StringArgument },
00176             { "help", 0, 0, NoArgument },
00177             { "verbose", 0, 0, NoArgument },
00178             { 0, 0, 0, 0 }
00179         };
00180 
00181         // TEST
00182         // response for testing
00183         response.resize(5);
00184         response[0] = -3.59f;
00185         response[1] = -0.93f;
00186         response[2] = 0.11f;
00187         response[3] = -0.22f;
00188         response[4] = 0.34f;
00189 
00190         int optionIndex = 0;
00191 
00192         while ((c = getopt_long(argc, argv, optstring, longOptions, &optionIndex)) != -1) {
00193             switch (c) {
00194                 case NoArgument: {
00195                         if (longOptions[optionIndex].flag != 0) break;
00196                         switch (optionIndex) {
00197                             case helpID:
00198                                 usage();
00199                                 return 0;
00200                             case verboseID:
00201                                 verbosity++;
00202                                 break;
00203                             default:
00204                                 std::cerr << "There's a problem with parsing options" << std::endl;
00205                                 return 1;
00206                         }
00207                         break;
00208                     }
00209 
00210                 case StringArgument: {
00211                         if (longOptions[optionIndex].flag != 0) break;
00212                         switch (optionIndex) {
00213                             case outputID:
00214                                 outputPrefix = optarg;
00215                                 break;
00216                             case advancedID:
00217                                 parseOptions_advanced(optarg);
00218                                 break;
00219                             case saveID:
00220                                 parseOptions_save(optarg);
00221                                 break;
00222                             default:
00223                                 std::cerr << "There's a problem with parsing options" << std::endl;
00224                                 return 1;
00225                         }
00226                         break;
00227                     }
00228 
00229                 case IntegerArgument: {
00230                         if (longOptions[optionIndex].flag != 0) break;
00231                         switch (optionIndex) {
00232                             case iterationsID:
00233                                 iterations = atoi(optarg);
00234                                 break;
00235                             default:
00236                                 std::cerr << "There's a problem with parsing options" << std::endl;
00237                                 return 1;
00238                         }
00239                         break;
00240                     }
00241 
00242                 case DoubleArgument: {
00243                         if (longOptions[optionIndex].flag != 0) break;
00244                         switch (optionIndex) {
00245                             case sigmaID:
00246                                 sigma = atof(optarg);
00247                                 break;
00248                             case thresholdID:
00249                                 thresholdLim = atof(optarg);
00250                                 break;
00251                             case contrastID:
00252                                 contrast = atof(optarg);
00253                                 break;
00254                         }
00255                         break;
00256                     }
00257 
00258                 case ArrayArgument: {
00259                         if (longOptions[optionIndex].flag != 0) break;
00260                         switch (optionIndex) {
00261                             case responseID:
00262                                 // TODO
00263                                 break;
00264                         }
00265                         break;
00266                     }
00267 
00268                 case 'o':
00269                     outputPrefix = optarg;
00270                     break;
00271                 case 'i':
00272                     iterations = atoi(optarg);
00273                     break;
00274                 case 's':
00275                     sigma = atof(optarg);
00276                     break;
00277                 case 'r':
00278                     // TODO
00279                     break;
00280                 case 't':
00281                     thresholdLim = atof(optarg);
00282                     break;
00283                 case 'c':
00284                     contrast = atof(optarg);
00285                     break;
00286                 case 'a':
00287                     parseOptions_advanced(optarg);
00288                     break;
00289                 case 'w':
00290                     parseOptions_save(optarg);
00291                     break;
00292                 case 'h':
00293                     usage();
00294                     return 0;
00295                 case 'v':
00296                     verbosity++;
00297                     break;
00298             }
00299         }
00300 
00301         std::cout << std::endl;
00302 
00303         unsigned nFiles = argc - optind;
00304         if (nFiles == 0)
00305         {
00306             std::cerr << std::endl << "Error: at least three input images needed" << std::endl << std::endl;
00307             usage();
00308             return 1;
00309         }
00310         else
00311         {
00312             if (nFiles < 3)
00313             {
00314                 std::cout << std::endl << "Error: You have to specify at least three images." << std::endl;
00315                 return 1;
00316             }
00317         }
00318 
00319         // load all images
00320         std::vector<std::string> inputFiles;
00321         for (size_t i = optind; i < (size_t)argc; i++)
00322         {
00323             inputFiles.push_back(argv[i]);
00324         }
00325 
00326         deghosting::Deghosting* deghoster = NULL;
00327 
00328         std::vector<deghosting::FImagePtr> weights;
00329         if (otherFlags & OTHER_GRAY)
00330         {
00331             deghosting::Khan<float> khanDeghoster(inputFiles, flags, debugFlags, iterations, sigma, verbosity);
00332             deghoster = &khanDeghoster;
00333             weights = deghoster->createWeightMasks();
00334         }
00335         else
00336         {
00337             deghosting::Khan<vigra::RGBValue<float> > khanDeghoster(inputFiles, flags, debugFlags, iterations, sigma, verbosity);
00338             deghoster = &khanDeghoster;
00339             weights = deghoster->createWeightMasks();
00340         }
00341 
00342         //deghoster->setCameraResponse(response);
00343 
00344         // save weights
00345         if (otherFlags & SAVE_GENWEIGHTS)
00346         {
00347             for (unsigned int i = 0; i<weights.size(); ++i)
00348             {
00349                 char tmpfn[100];
00350                 snprintf(tmpfn, 99, "%s_%u.tif", outputPrefix.c_str(), i);
00351                 vigra::ImageExportInfo exWeights(tmpfn);
00352                 vigra::exportImage(srcImageRange(*weights[i]), exWeights.setPixelType("UINT8"));
00353             }
00354         }
00355 
00356         // apply contrast functor
00357         for (unsigned int i = 0; i < weights.size(); ++i)
00358         {
00359             vigra::transformImage(vigra::srcImageRange(*(weights[i])), vigra::destImage(*(weights[i])), vigra::BrightnessContrastFunctor<vigra::FImage::PixelType>(1, contrast, 0, 255));
00360         }
00361 
00362         std::vector<deghosting::BImagePtr> thresholded = threshold(weights, thresholdLim, otherThresholdFlags);
00363 
00364         // save masks with treshold applied
00365         for (unsigned int i = 0; i<weights.size(); ++i)
00366         {
00367             char tmpfn[100];
00368             std::string fileName = hugin_utils::stripExtension(inputFiles[i]);
00369             fileName = hugin_utils::stripPath(fileName);
00370             snprintf(tmpfn, 99, "%s_mask.tif", fileName.c_str());
00371             vigra::ImageExportInfo exWeights(tmpfn);
00372             vigra::BImage outImg = vigra::BImage((*thresholded[i]).size());
00373             simpleDenoise(vigra::srcImageRange(*thresholded[i]), destImage(outImg));
00374             vigra::exportImage(vigra::srcImageRange(outImg), exWeights.setPixelType("UINT8"));
00375         }
00376     }
00377     catch (const std::exception & e)
00378     {
00379         std::cerr << "caught exception: " << e.what() << std::endl;
00380         return 1;
00381     } catch (...)
00382     {
00383         std::cerr << "caught unknown exception" << std::endl;
00384         return 1;
00385     }
00386     return 0;
00387 }

Generated on 28 Sep 2016 for Hugintrunk by  doxygen 1.4.7