int main(int argc, char* argv[]) { // Exit with usage unless filename given as argument if (argc < 2) { usage(); } unsigned int i = 1, mask = 0; double threshold = 0.5; vector<string> images_to_mask; string pto_file = (""),output_pto = (""); string mask_format = ("PNG"); string model_file = ("celeste.model"); int course_fine = 0; int resize_dimension=800; // Deal with arguments // parse arguments int c; const char * optstring = "i:o:d:s:t:m:f:r:h"; while ((c = getopt (argc, argv, optstring)) != -1) { switch(c) { case 'h': usage(); break; case 'i': pto_file=optarg; break; case 'o': output_pto=optarg; break; case 't': threshold = atof(optarg); if(threshold<=0 || threshold>1) { cerr << "Invalid parameter: threshold (-t) should be between 0 and 1" << std::endl; return 1; }; break; case 'm': mask = atoi(optarg); if(mask<0 || mask>1) { cerr << "Invalid parameter: mask parameter (-m) can only be 0 or 1" << std::endl; return 1; }; break; case 'f': mask_format = optarg; break; case 'd': model_file = optarg; break; case 'r': course_fine = atoi(optarg); break; case 's': resize_dimension = atoi(optarg); if(resize_dimension<100) { cerr << "Invalid parameter: maximum dimension (-s) should be bigger than 100" << std::endl; return 1; }; break; case ':': cerr <<"Missing parameter for parameter " << argv[optind] << endl; return 1; break; case '?': /* invalid parameter */ return 1; break; default: /* unknown */ usage(); }; }; while(optind<argc) { images_to_mask.push_back(argv[optind]); optind++; }; if(images_to_mask.size()==0 && pto_file.empty()) { cout << "No project file or image files given."<< endl; return 1; }; // Check model file if (!fileexists(model_file)){ #if _WINDOWS char buffer[MAX_PATH];//always use MAX_PATH for filepaths GetModuleFileName(NULL,buffer,sizeof(buffer)); string working_path=(buffer); string install_path_model=""; //remove filename std::string::size_type pos=working_path.rfind("\\"); if(pos!=std::string::npos) { working_path.erase(pos); //remove last dir: should be bin pos=working_path.rfind("\\"); if(pos!=std::string::npos) { working_path.erase(pos); //append path delimiter and path working_path.append("\\share\\hugin\\data\\"); install_path_model=working_path; } } #elif defined MAC_SELF_CONTAINED_BUNDLE char path[PATH_MAX + 1]; uint32_t size = sizeof(path); string install_path_model(""); if (_NSGetExecutablePath(path, &size) == 0) { install_path_model=dirname(path); install_path_model.append("/../Resources/xrc/"); } #else string install_path_model = (INSTALL_DATA_DIR); #endif install_path_model.append(model_file); if (!fileexists(install_path_model)){ cout << endl << "Couldn't open SVM model file " << model_file << endl; cout << "Also tried " << install_path_model << endl << endl; exit(1); }else{ model_file = install_path_model; } } // Set output .pto filename if not given if (output_pto == ("") && pto_file != ("")){ output_pto = pto_file.substr(0,pto_file.length()-4).append("_celeste.pto"); } // Convert mask format to upper case transform(mask_format.begin(), mask_format.end(), mask_format.begin(),(int(*)(int)) toupper); if (mask_format == ("JPG")){ mask_format = ("JPEG"); } if (mask_format != ("PNG") &&mask_format != ("BMP") && mask_format != ("GIF") && mask_format != ("JPEG") && mask_format != ("TIFF")){ mask_format = ("TIFF"); } // Print some stuff out cout << endl << "Celeste: Removes cloud-like control points from Hugin project files and creates image masks" << endl; cout << "using Support Vector Machines." << endl; cout << endl << "Version " << DISPLAY_VERSION << endl << endl; cout << "Arguments:" << endl; cout << "Input Hugin file:\t" << pto_file << endl; cout << "Output Hugin file:\t" << output_pto << endl; cout << "SVM model file:\t\t" << model_file << endl; cout << "Max dimension:\t\t" << resize_dimension << endl; cout << "SVM threshold:\t\t" << threshold << endl; cout << "Create PTO masks:\t"; if (mask){ cout << "Yes" << endl; }else{ cout << "No" << endl; } cout << "Mask format:\t\t" << mask_format << endl; cout << "Filter radius:\t\t"; // Mask resolution int radius; if (course_fine) { radius = 10; cout << "Small" << endl << endl; } else { radius=20; cout << "Large" << endl << endl; } // Convert mask format to lower case cout << "Converting mask format to lower case..." << endl; transform(mask_format.begin(), mask_format.end(), mask_format.begin(),(int(*)(int)) tolower); // Vectors to store SVM responses and PTO file info etc vector<string> images,pto_file_top,pto_file_cps,pto_file_end; vector<double> svm_responses; cout << "Loading SVMmodel..." << endl; struct celeste::svm_model* model; if(!celeste::loadSVMmodel(model,model_file)) { cerr << "Could not load SVMmodel" << endl; return 1; }; // Mask images if (images_to_mask.size()) { cout << "Masking images..." << endl << endl; for (unsigned int l = 0; l < images_to_mask.size(); l++) { std::string imagefile=images_to_mask[l]; try { cout << "Opening image file:\t" << imagefile << endl; // Read image given and convert to UInt16 vigra::UInt16RGBImage in=loadAndConvertImage(imagefile); if(in.width()==0 || in.height()==0) { continue; }; // Create mask file name string mask_name = generateMaskName(imagefile,mask_format); cout << "Generating mask:\t" << mask_name << endl; // Create mask vigra::BImage mask=celeste::getCelesteMask(model,in,radius,threshold,resize_dimension); exportImage(srcImageRange(mask), vigra::ImageExportInfo(mask_name.c_str()).setPixelType("UINT8")); } catch (vigra::StdException & e) { // catch any errors that might have occured and print their reason cout << "Unable to open file:\t" << imagefile << endl << endl; cout << e.what() << endl << endl; }; }; }; // Process PTO file if (pto_file != ("")) { cout << "Parsing Hugin project file " << pto_file << endl << endl; Panorama pano; ifstream prjfile(pto_file.c_str()); if (!prjfile.good()) { cerr << "could not open script : " << pto_file << endl; celeste::destroySVMmodel(model); return 1; } pano.setFilePrefix(hugin_utils::getPathPrefix(pto_file)); DocumentData::ReadWriteError err = pano.readData(prjfile); if (err != DocumentData::SUCCESSFUL) { cerr << "error while parsing panos tool script: " << pto_file << endl; cerr << "DocumentData::ReadWriteError code: " << err << endl; celeste::destroySVMmodel(model); return 1; } cout << "Done parsing Hugin step 1" << endl; for(unsigned int i=0;i<pano.getNrOfImages();i++) { CPointVector cps=pano.getCtrlPointsVectorForImage(i); if(cps.size()>0 || mask) { try { string imagefile=pano.getImage(i).getFilename(); vigra::UInt16RGBImage in=loadAndConvertImage(imagefile); if(in.width()==0 || in.height()==0) { continue; }; if(cps.size()>0) { UIntSet cloudCP=celeste::getCelesteControlPoints(model,in,cps,radius,threshold,resize_dimension); if(cloudCP.size()>0) { for(UIntSet::reverse_iterator it=cloudCP.rbegin();it!=cloudCP.rend();++it) { pano.removeCtrlPoint(*it); }; }; }; if(mask) { string mask_name = generateMaskName(imagefile,mask_format); // Create mask vigra::BImage mask=celeste::getCelesteMask(model,in,radius,threshold,resize_dimension); exportImage(srcImageRange(mask), vigra::ImageExportInfo(mask_name.c_str()).setPixelType("UINT8")); }; } catch (vigra::StdException & e) { // catch any errors that might have occured and print their reason cout << "Unable to open file:\t" << pano.getImage(i).getFilename() << endl << endl; cout << e.what() << endl << endl; }; }; }; cout << "about to write new pto file" << endl; // write new pto file ofstream of(output_pto.c_str()); UIntSet imgs; cout << "fill_set..." << endl; fill_set(imgs,0, pano.getNrOfImages()-1); cout << "printing..." << endl; pano.printPanoramaScript(of, pano.getOptimizeVector(), pano.getOptions(), imgs, false, hugin_utils::getPathPrefix(pto_file)); cout << endl << "Written file " << output_pto << endl << endl; } celeste::destroySVMmodel(model); return(0); }
int main(int argc, char *argv[]) { // parse arguments const char * optstring = "o:hn:pws"; int c; string output; bool onlyPair = false; bool wholePano = false; bool skipOptimisation = false; double n = 2.0; while ((c = getopt (argc, argv, optstring)) != -1) { switch (c) { case 'o': output = optarg; break; case 'h': usage(argv[0]); return 0; case 'n': n = atof(optarg); if(n==0) { cerr <<"Invalid parameter: " << optarg << " is not valid real number" << endl; return 1; }; if (n<1.0) { cerr << "Invalid parameter: n must be at least 1" << endl; return 1; }; break; case 'p': onlyPair= true; break; case 'w': wholePano = true; break; case 's': skipOptimisation = true; break; case ':': cerr <<"Option -n requires a number" << endl; return 1; break; case '?': break; default: abort (); } } if (argc - optind != 1) { usage(argv[0]); return 1; }; if (onlyPair && wholePano) { cerr << "Options -p and -w can't used together" << endl; return 1; }; string input=argv[optind]; Panorama pano; ifstream prjfile(input.c_str()); if (!prjfile.good()) { cerr << "could not open script : " << input << endl; return 1; } pano.setFilePrefix(hugin_utils::getPathPrefix(input)); DocumentData::ReadWriteError err = pano.readData(prjfile); if (err != DocumentData::SUCCESSFUL) { cerr << "error while parsing panos tool script: " << input << endl; cerr << "DocumentData::ReadWriteError code: " << err << endl; return 1; } size_t nrImg=pano.getNrOfImages(); if (nrImg < 2) { cerr << "Panorama should consist of at least two images" << endl; return 1; } if (pano.getNrOfCtrlPoints() < 3) { cerr << "Panorama should contain at least 3 control point" << endl; }; size_t cpremoved1=0; UIntSet CPtoRemove; // step 1 with pairwise optimisation if(!wholePano) { CPtoRemove=getCPoutsideLimit_pair(pano,n); if (CPtoRemove.size()>0) for(UIntSet::reverse_iterator it = CPtoRemove.rbegin(); it != CPtoRemove.rend(); ++it) pano.removeCtrlPoint(*it); cpremoved1=CPtoRemove.size(); }; // step 2 with optimisation of whole panorama bool unconnected=false; if(!onlyPair) { //check for unconnected images CPGraph graph; createCPGraph(pano, graph); CPComponents comps; int parts=findCPComponents(graph, comps); if (parts > 1) { unconnected=true; } else { CPtoRemove.clear(); if(skipOptimisation) { std::cout << endl << "Skipping optimisation, current image positions will be used." << endl; }; CPtoRemove=getCPoutsideLimit(pano,n,skipOptimisation); if (CPtoRemove.size()>0) for(UIntSet::reverse_iterator it = CPtoRemove.rbegin(); it != CPtoRemove.rend(); ++it) pano.removeCtrlPoint(*it); }; }; cout << endl; if(!wholePano) cout << "Removed " << cpremoved1 << " control points in step 1" << endl; if(!onlyPair) if(unconnected) cout <<"Skipped step 2 because of unconnected image pairs" << endl; else cout << "Removed " << CPtoRemove.size() << " control points in step 2" << endl; //write output OptimizeVector optvec = pano.getOptimizeVector(); UIntSet imgs; fill_set(imgs,0, pano.getNrOfImages()-1); // Set output .pto filename if not given if (output=="") { output=input.substr(0,input.length()-4).append("_clean.pto"); } ofstream of(output.c_str()); pano.printPanoramaScript(of, optvec, pano.getOptions(), imgs, false, hugin_utils::getPathPrefix(input)); cout << endl << "Written output to " << output << endl; return 0; }