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         int c;
00142 
00143         std::string outputPrefix = "weight";
00144 
00145         enum optionArgumentKind {
00146             NoArgument,
00147             StringArgument,
00148             DoubleArgument,
00149             IntegerArgument,
00150             ArrayArgument
00151         };
00152 
00153         enum optionId {
00154             outputID,
00155             iterationsID,
00156             sigmaID,
00157             responseID,
00158             thresholdID,
00159             contrastID,
00160             advancedID,
00161             saveID,
00162             helpID,
00163             verboseID
00164         };
00165 
00166         static struct option longOptions[] = {
00167             { "output", 1, 0, StringArgument },
00168             { "iterations", 1, 0, IntegerArgument },
00169             { "sigma", 1, 0, DoubleArgument },
00170             { "response", 1, 0, ArrayArgument },
00171             { "threshold", 1, 0, DoubleArgument },
00172             { "contrast", 1, 0, DoubleArgument },
00173             { "advanced", 1, 0, StringArgument },
00174             { "save", 1, 0, StringArgument },
00175             { "help", 0, 0, NoArgument },
00176             { "verbose", 0, 0, NoArgument },
00177             { 0, 0, 0, 0 }
00178         };
00179 
00180         // TEST
00181         // response for testing
00182         response.resize(5);
00183         response[0] = -3.59f;
00184         response[1] = -0.93f;
00185         response[2] = 0.11f;
00186         response[3] = -0.22f;
00187         response[4] = 0.34f;
00188 
00189         int optionIndex = 0;
00190 
00191         while ((c = getopt_long(argc, argv, optstring, longOptions, &optionIndex)) != -1) {
00192             switch (c) {
00193                 case NoArgument: {
00194                         if (longOptions[optionIndex].flag != 0) break;
00195                         switch (optionIndex) {
00196                             case helpID:
00197                                 usage();
00198                                 return 0;
00199                             case verboseID:
00200                                 verbosity++;
00201                                 break;
00202                             default:
00203                                 std::cerr << "There's a problem with parsing options" << std::endl;
00204                                 return 1;
00205                         }
00206                         break;
00207                     }
00208 
00209                 case StringArgument: {
00210                         if (longOptions[optionIndex].flag != 0) break;
00211                         switch (optionIndex) {
00212                             case outputID:
00213                                 outputPrefix = optarg;
00214                                 break;
00215                             case advancedID:
00216                                 parseOptions_advanced(optarg);
00217                                 break;
00218                             case saveID:
00219                                 parseOptions_save(optarg);
00220                                 break;
00221                             default:
00222                                 std::cerr << "There's a problem with parsing options" << std::endl;
00223                                 return 1;
00224                         }
00225                         break;
00226                     }
00227 
00228                 case IntegerArgument: {
00229                         if (longOptions[optionIndex].flag != 0) break;
00230                         switch (optionIndex) {
00231                             case iterationsID:
00232                                 iterations = atoi(optarg);
00233                                 break;
00234                             default:
00235                                 std::cerr << "There's a problem with parsing options" << std::endl;
00236                                 return 1;
00237                         }
00238                         break;
00239                     }
00240 
00241                 case DoubleArgument: {
00242                         if (longOptions[optionIndex].flag != 0) break;
00243                         switch (optionIndex) {
00244                             case sigmaID:
00245                                 sigma = atof(optarg);
00246                                 break;
00247                             case thresholdID:
00248                                 thresholdLim = atof(optarg);
00249                                 break;
00250                             case contrastID:
00251                                 contrast = atof(optarg);
00252                                 break;
00253                         }
00254                         break;
00255                     }
00256 
00257                 case ArrayArgument: {
00258                         if (longOptions[optionIndex].flag != 0) break;
00259                         switch (optionIndex) {
00260                             case responseID:
00261                                 // TODO
00262                                 break;
00263                         }
00264                         break;
00265                     }
00266 
00267                 case 'o':
00268                     outputPrefix = optarg;
00269                     break;
00270                 case 'i':
00271                     iterations = atoi(optarg);
00272                     break;
00273                 case 's':
00274                     sigma = atof(optarg);
00275                     break;
00276                 case 'r':
00277                     // TODO
00278                     break;
00279                 case 't':
00280                     thresholdLim = atof(optarg);
00281                     break;
00282                 case 'c':
00283                     contrast = atof(optarg);
00284                     break;
00285                 case 'a':
00286                     parseOptions_advanced(optarg);
00287                     break;
00288                 case 'w':
00289                     parseOptions_save(optarg);
00290                     break;
00291                 case 'h':
00292                     usage();
00293                     return 0;
00294                 case 'v':
00295                     verbosity++;
00296                     break;
00297                 case ':':
00298                 case '?':
00299                     // missing argument or invalid switch
00300                     return 1;
00301                     break;
00302                 default:
00303                     // this should not happen
00304                     abort();
00305             }
00306         }
00307 
00308         std::cout << std::endl;
00309 
00310         unsigned nFiles = argc - optind;
00311         if (nFiles < 3)
00312         {
00313             std::cerr << hugin_utils::stripPath(argv[0]) << ": at least three input images needed" << std::endl;
00314             return 1;
00315         };
00316 
00317         // load all images
00318         std::vector<std::string> inputFiles;
00319         for (size_t i = optind; i < (size_t)argc; i++)
00320         {
00321             inputFiles.push_back(argv[i]);
00322         }
00323 
00324         deghosting::Deghosting* deghoster = NULL;
00325 
00326         std::vector<deghosting::FImagePtr> weights;
00327         if (otherFlags & OTHER_GRAY)
00328         {
00329             deghosting::Khan<float> khanDeghoster(inputFiles, flags, debugFlags, iterations, sigma, verbosity);
00330             deghoster = &khanDeghoster;
00331             weights = deghoster->createWeightMasks();
00332         }
00333         else
00334         {
00335             deghosting::Khan<vigra::RGBValue<float> > khanDeghoster(inputFiles, flags, debugFlags, iterations, sigma, verbosity);
00336             deghoster = &khanDeghoster;
00337             weights = deghoster->createWeightMasks();
00338         }
00339 
00340         //deghoster->setCameraResponse(response);
00341 
00342         // save weights
00343         if (otherFlags & SAVE_GENWEIGHTS)
00344         {
00345             for (unsigned int i = 0; i<weights.size(); ++i)
00346             {
00347                 char tmpfn[100];
00348                 snprintf(tmpfn, 99, "%s_%u.tif", outputPrefix.c_str(), i);
00349                 vigra::ImageExportInfo exWeights(tmpfn);
00350                 vigra::exportImage(srcImageRange(*weights[i]), exWeights.setPixelType("UINT8"));
00351             }
00352         }
00353 
00354         // apply contrast functor
00355         for (unsigned int i = 0; i < weights.size(); ++i)
00356         {
00357             vigra::transformImage(vigra::srcImageRange(*(weights[i])), vigra::destImage(*(weights[i])), vigra::BrightnessContrastFunctor<vigra::FImage::PixelType>(1, contrast, 0, 255));
00358         }
00359 
00360         std::vector<deghosting::BImagePtr> thresholded = threshold(weights, thresholdLim, otherThresholdFlags);
00361 
00362         // save masks with treshold applied
00363         for (unsigned int i = 0; i<weights.size(); ++i)
00364         {
00365             char tmpfn[100];
00366             std::string fileName = hugin_utils::stripExtension(inputFiles[i]);
00367             fileName = hugin_utils::stripPath(fileName);
00368             snprintf(tmpfn, 99, "%s_mask.tif", fileName.c_str());
00369             vigra::ImageExportInfo exWeights(tmpfn);
00370             vigra::BImage outImg = vigra::BImage((*thresholded[i]).size());
00371             simpleDenoise(vigra::srcImageRange(*thresholded[i]), destImage(outImg));
00372             vigra::exportImage(vigra::srcImageRange(outImg), exWeights.setPixelType("UINT8"));
00373         }
00374     }
00375     catch (const std::exception & e)
00376     {
00377         std::cerr << "caught exception: " << e.what() << std::endl;
00378         return 1;
00379     } catch (...)
00380     {
00381         std::cerr << "caught unknown exception" << std::endl;
00382         return 1;
00383     }
00384     return 0;
00385 }

Generated on 2 Dec 2016 for Hugintrunk by  doxygen 1.4.7