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[])