24 #include "hugin_config.h"  
   35         std::cout << std::endl << 
"Celeste: Removes cloud-like control points from Hugin project files and creates image masks" << std::endl;
 
   36         std::cout << 
"using Support Vector Machines." << std::endl;
 
   38         std::cout << std::endl << 
"Usage: celeste_standalone [options] image1 image2 [..]" << std::endl << std::endl;
 
   39         std::cout << 
"Options:" << std::endl << std::endl;
 
   40         std::cout << 
"  -i <filename>   Input Hugin PTO file. Control points over SVM threshold will" << std::endl;
 
   41         std::cout << 
"                  be removed before being written to the output file. If -m is" << std::endl;
 
   42         std::cout << 
"                  set to 1, images in the file will be also be masked." << std::endl;
 
   43         std::cout << 
"  -o <filename>   Output Hugin PTO file. Default: '<filename>_celeste.pto'" << std::endl;
 
   44         std::cout << 
"  -d <filename>   SVM model file. Default: 'data/celeste.model'" << std::endl;
 
   45         std::cout << 
"  -s <int>        Maximum dimension for re-sized image prior to processing. A" << std::endl;
 
   46         std::cout << 
"                  higher value will increase the resolution of the mask but is" << std::endl;
 
   47         std::cout << 
"                  significantly slower. Default: 800" << std::endl;
 
   48         std::cout << 
"  -t <float>      SVM threshold. Raise this value to remove fewer control points," << std::endl;
 
   49         std::cout << 
"                  lower it to remove more. Range 0 to 1. Default: 0.5" << std::endl;
 
   50         std::cout << 
"  -m <1|0>        Create masks when processing Hugin PTO file. Default: 0" << std::endl;
 
   51         std::cout << 
"  -f <std::string>     Mask file format. Options are PNG, JPEG, BMP, GIF and TIFF." << std::endl;
 
   52         std::cout << 
"                  Default: PNG" << std::endl;
 
   53         std::cout << 
"  -r <1|0>        Filter radius. 0 = large (more accurate), 1 = small (higher" << std::endl;
 
   54         std::cout << 
"                  resolution mask, slower, less accurate). Default: 0" << std::endl;
 
   55         std::cout << 
"  -h|--help       Print usage." << std::endl; 
 
   56         std::cout << 
"  image1 image2.. Image files to be masked." << std::endl << std::endl;
 
   63     vigra::ImageImportInfo 
info(imagefile.c_str());
 
   64     std::string pixelType=
info.getPixelType();
 
   65     vigra::UInt16RGBImage image;
 
   68         std::cerr << 
"Celeste works only on colour images, " << std::endl 
 
   69             << 
"but image " << imagefile << 
" has  " << 
info.numBands() << 
" channels." << std::endl 
 
   70             << 
"Skipping this image." << std::endl;
 
   73     if(pixelType==
"UINT8" || pixelType==
"INT16")
 
   75         vigra::UInt16RGBImage imageIn(
info.width(),
info.height());
 
   76         if(
info.numExtraBands()==1)
 
   78             vigra::BImage mask(
info.size());
 
   90         if(pixelType==
"UINT16")
 
   92             image.resize(
info.width(),
info.height());
 
   93             if(
info.numExtraBands()==1)
 
   95                 vigra::BImage mask(
info.size());
 
  105             if(pixelType==
"INT32" || pixelType==
"UINT32")
 
  107                 vigra::UInt32RGBImage imageIn(
info.width(),
info.height());
 
  108                 if(
info.numExtraBands()==1)
 
  110                     vigra::BImage mask(
info.size());
 
  122                 if(pixelType==
"FLOAT" || pixelType==
"DOUBLE")
 
  124                     vigra::FRGBImage imagefloat(
info.width(),
info.height());
 
  125                     if(
info.numExtraBands()==1)
 
  127                         vigra::BImage mask(
info.size());
 
  136                     imagefloat.resize(0,0);
 
  140                     std::cerr << 
"Unsupported pixel type" << std::endl;
 
  143     if (!
info.getICCProfile().empty())
 
  152     std::string mask_name = (
"");
 
  153     if (imagefile.substr(imagefile.length()-4,1)==(
"."))
 
  155         mask_name.append(imagefile.substr(0,imagefile.length()-4));
 
  159         mask_name.append(imagefile.substr(0,imagefile.length()-4));
 
  161     mask_name.append(
"_mask.");
 
  162     mask_name.append(mask_format);
 
  167 int main(
int argc, 
char* argv[])
 
  171     std::vector<std::string> images_to_mask;
 
  172     std::string pto_file = (
""),output_pto = (
"");
 
  173     std::string mask_format = (
"PNG");
 
  174     std::string model_file = (
"celeste.model");
 
  176     int resize_dimension=800;
 
  181     const char * optstring = 
"i:o:d:s:t:m:f:r:h";
 
  182     static struct option longOptions[] =
 
  184         { 
"output", required_argument, NULL, 
'o' },
 
  185         { 
"help", no_argument, NULL, 
'h' },
 
  189     while ((c = getopt_long(argc, argv, optstring, longOptions, 
nullptr)) != -1)
 
  203                 threshold = atof(optarg);
 
  204                 if(threshold<=0 || threshold>1)
 
  206                     std::cerr << 
hugin_utils::stripPath(argv[0]) << 
": Invalid parameter: threshold (-t) should be between 0 and 1" << std::endl;
 
  214                     std::cerr << 
hugin_utils::stripPath(argv[0]) << 
": Invalid parameter: mask parameter (-m) can only be 0 or 1" << std::endl;
 
  219                 mask_format = optarg; 
 
  225                 course_fine = atoi(optarg);
 
  228                 resize_dimension = atoi(optarg);
 
  229                 if(resize_dimension<100)
 
  231                     std::cerr << 
hugin_utils::stripPath(argv[0]) << 
": Invalid parameter: maximum dimension (-s) should be bigger than 100" << std::endl;
 
  248         images_to_mask.push_back(argv[optind]);
 
  252     if(images_to_mask.empty() && pto_file.empty())
 
  263                 install_path_model.append(model_file);
 
  267             std::cerr << std::endl << 
"Couldn't open SVM model file " << model_file << std::endl
 
  268                 << 
"Also tried " << install_path_model << std::endl << std::endl;
 
  273                 model_file = install_path_model;
 
  278         if (output_pto == (
"") && pto_file != (
"")){
 
  279                 output_pto = pto_file.substr(0,pto_file.length()-4).append(
"_celeste.pto");
 
  284         if (mask_format == (
"JPG")){
 
  285                 mask_format = (
"JPEG");
 
  287         if (mask_format != (
"PNG") &&mask_format != (
"BMP") && mask_format != (
"GIF") && mask_format != (
"JPEG") && mask_format != (
"TIFF")){
 
  288                 mask_format = (
"TIFF");
 
  292         std::cout << std::endl << 
"Celeste: Removes cloud-like control points from Hugin project files and creates image masks" << std::endl;
 
  293         std::cout << 
"using Support Vector Machines." << std::endl;
 
  295         std::cout << 
"Arguments:" << std::endl;
 
  296         std::cout << 
"Input Hugin file:\t" << pto_file << std::endl;
 
  297         std::cout << 
"Output Hugin file:\t" << output_pto << std::endl;
 
  298         std::cout << 
"SVM model file:\t\t" << model_file << std::endl;
 
  299         std::cout << 
"Max dimension:\t\t" << resize_dimension << std::endl;
 
  300         std::cout << 
"SVM threshold:\t\t" << threshold << std::endl;
 
  301         std::cout << 
"Create PTO masks:\t";
 
  303                 std::cout << 
"Yes" << std::endl;
 
  305                 std::cout << 
"No" << std::endl;
 
  307         std::cout << 
"Mask format:\t\t" << mask_format << std::endl;
 
  308         std::cout << 
"Filter radius:\t\t";
 
  315         std::cout << 
"Small" << std::endl << std::endl;
 
  320         std::cout << 
"Large" << std::endl << std::endl;
 
  333         if (images_to_mask.size())
 
  335         std::cout << 
"Masking images..." << std::endl << std::endl;
 
  336         for (
unsigned int l = 0; 
l < images_to_mask.size(); 
l++)
 
  338             std::string imagefile=images_to_mask[
l];
 
  341                 std::cout << 
"Opening image file:\t" << imagefile << std::endl;
 
  344                 if(in.width()==0 || in.height()==0)
 
  352                 std::cout << 
"Generating mask:\t" << mask_name << std::endl;                            
 
  355                 exportImage(
srcImageRange(*mask), vigra::ImageExportInfo(mask_name.c_str()).setPixelType(
"UINT8"));
 
  358             catch (vigra::StdException & e)
 
  361                 std::cout << 
"Unable to open file:\t" << imagefile << std::endl << std::endl;
 
  362                 std::cout << e.what() << std::endl << std::endl;
 
  368     if (pto_file != (
""))
 
  370                 std::cout << 
"Parsing Hugin project file " << pto_file << std::endl << std::endl;
 
  382             if(!cps.empty() || mask)
 
  386                     std::string imagefile=pano.
getImage(i).getFilename();
 
  388                     if(in.width()==0 || in.height()==0)
 
  397                             for (HuginBase::UIntSet::reverse_iterator it = cloudCP.rbegin(); it != cloudCP.rend(); ++it)
 
  408                         exportImage(
srcImageRange(*mask), vigra::ImageExportInfo(mask_name.c_str()).setPixelType(
"UINT8"));
 
  412                 catch (vigra::StdException & e)
 
  415                     std::cout << 
"Unable to open file:\t" << pano.
getImage(i).getFilename() << std::endl << std::endl;
 
  416                     std::cout << e.what() << std::endl << std::endl;
 
  424             std::cout << std::endl << 
"Written output to " << output_pto << std::endl;
 
void destroySVMmodel(struct svm_model *&model)
frees the resource of model 
 
bool FileExists(const std::string &filename)
checks if file exists 
 
vigra::BImage * getCelesteMask(struct svm_model *model, vigra::UInt16RGBImage &input, int radius, float threshold, int resize_dimension, bool adaptThreshold, bool verbose)
calculates the mask using SVM 
 
void convertToUInt16(SrcIMG &src, const std::string &origType, vigra::UInt16RGBImage &dest)
converts the given image to UInt16RGBImage only this image is correctly processed by celeste ...
 
std::string toupper(const std::string &s)
 
std::set< unsigned int > UIntSet
 
vigra::UInt16RGBImage loadAndConvertImage(std::string imagefile)
 
std::string GetDataDir()
returns the full path to the data directory 
 
bool loadSVMmodel(struct svm_model *&model, std::string &model_file)
loads the SVM model from file 
 
std::string getPathPrefix(const std::string &filename)
Get the path to a filename. 
 
std::size_t getNrOfImages() const 
number of images. 
 
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...
 
vigra::pair< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImage(ROIImage< Image, Alpha > &img)
 
CPointVector getCtrlPointsVectorForImage(unsigned int imgNr) const 
return a vector of std::pairs with global ctrl point nr and ControlPoint In the class ControlPoint th...
 
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 
 
std::string generateMaskName(std::string imagefile, std::string mask_format)
 
std::vector< CPoint > CPointVector
 
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. 
 
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...
 
HuginBase::UIntSet getCelesteControlPoints(struct svm_model *model, vigra::UInt16RGBImage &input, HuginBase::CPointVector cps, int radius, float threshold, int resize_dimension, bool verbose)
 
std::string GetHuginVersion()
return a string with version numbers 
 
void removeCtrlPoint(unsigned int pNr)
remove a control point. 
 
bool WritePTOFile(const std::string &filename, const std::string &prefix="")
write data to given pto file 
 
static void info(const char *fmt,...)
 
const SrcPanoImage & getImage(std::size_t nr) const 
get a panorama image, counting starts with 0 
 
functions to handle icc profiles in images 
 
std::string tolower(const std::string &s)
convert a string to lowercase 
 
void ApplyICCProfile(ImageType &image, const vigra::ImageImportInfo::ICCProfile &iccProfile, const cmsUInt32Number imageFormat)
converts given image with iccProfile to sRGB/gray space, need to give pixel type in lcms2 format work...
 
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames) 
 
int main(int argc, char *argv[])