00001
00002
00027 #include <hugin_config.h>
00028 #include <hugin_version.h>
00029 #include <fstream>
00030 #include <sstream>
00031
00032 #include <algorithms/optimizer/PhotometricOptimizer.h>
00033 #include "ExtractPoints.h"
00034
00035 #ifdef WIN32
00036 #include <getopt.h>
00037 #else
00038 #include <unistd.h>
00039 #endif
00040
00041 #include <hugin_basic.h>
00042 #include <nona/Stitcher.h>
00043
00044 #include <tiff.h>
00045
00046 using namespace std;
00047 using namespace vigra;
00048 using namespace vigra_ext;
00049 using namespace AppBase;
00050 using namespace HuginBase;
00051
00052
00053
00054 static void usage(const char * name)
00055 {
00056 cerr << name << ": Try to determine the radial vignetting" << std::endl
00057 << "vig_optimize version " << DISPLAY_VERSION << endl
00058 << std::endl
00059 << "Usage: " << name << " [options] -o output.pto input.pto" << std::endl
00060 << "Valid options are:" << std::endl
00061 << " -o file write results to output project" << std::endl
00062 << " -v Verbose, print progress messages" << std::endl
00063 << " -p n Number of points to extract" << std::endl
00064
00065
00066 << " -s level Work on downscaled images, every step halves width and height" << std::endl
00067 << " -h Display help (this text)" << std::endl
00068 << std::endl
00069 << " Expert and debugging options:" << std::endl
00070 << " -i file Read corresponding points from file" << std::endl
00071 << " -w file Dump corresponding points to file" << std::endl;
00072 }
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 void loadPointsC(FILE *f, std::vector<PointPairRGB> & vec)
00087 {
00088 double dummy1, dummy2;
00089 PointPairRGB point;
00090 double i1, i2;
00091
00092 int n=0;
00093 do {
00094 n = fscanf(f, " %lf %lf %lf %lf %lf %lf %f %f %f %f %f %f %lf %f %f %lf",
00095 &i1, &i2, &(point.p1.x), &(point.p1.y),
00096 &(point.p2.x), &(point.p2.y),
00097 &(point.i1.red()), &(point.i1.green()), &(point.i1.blue()),
00098 &(point.i2.red()), &(point.i2.green()), &(point.i2.blue()),
00099
00100 &dummy1,
00101 &(point.r1), &(point.r2),
00102
00103 &(dummy2) );
00104
00105
00106 point.imgNr1 = hugin_utils::roundi(i1);
00107 point.imgNr2 = hugin_utils::roundi(i2);
00108 if (n==16) {
00109 vec.push_back(point);
00110 }
00111 } while (n == 16);
00112 }
00113
00114 void loadPoints(istream & i, std::vector<PointPairRGB> & vec )
00115 {
00116 while(!i.eof() && i.good()) {
00117 double dummy1, dummy2;
00118 PointPairRGB point;
00119 double i1, i2;
00120 i >> i1 >> i2
00121 >> point.p1.x >> point.p1.y
00122 >> point.p2.x >> point.p2.y
00123 >> point.i1.red() >> point.i1.green() >> point.i1.blue()
00124 >> point.i2.red() >> point.i2.green() >> point.i2.blue()
00125
00126 >> dummy1
00127 >> point.r1 >> point.r2
00128
00129 >> dummy2;
00130 point.imgNr1 = hugin_utils::roundi(i1);
00131 point.imgNr2 = hugin_utils::roundi(i2);
00132 if (i.good()) {
00133 vec.push_back(point);
00134 }
00135 }
00136 }
00137
00138 bool hasphotometricParams(Panorama &pano)
00139 {
00140 OptimizeVector vars=pano.getOptimizeVector();
00141
00142 for (OptimizeVector::const_iterator it=vars.begin(); it != vars.end(); ++it)
00143 {
00144 std::set<std::string> cvars;
00145 for (std::set<std::string>::const_iterator itv = (*it).begin();
00146 itv != (*it).end(); ++itv)
00147 {
00148 if ((*itv)[0] == 'E' || (*itv)[0] == 'R' || (*itv)[0] == 'V') {
00149 return true;
00150 }
00151 }
00152 }
00153 return false;
00154 }
00155
00156
00157 int main(int argc, char *argv[])
00158 {
00159 StreamProgressDisplay progressDisplay(std::cout);
00160
00161
00162 const char * optstring = "hi:o:p:s:vw:";
00163 int c;
00164
00165 opterr = 0;
00166
00167 int pyrLevel=3;
00168 int verbose = 0;
00169 int nPoints = 200;
00170 bool randomPoints = true;
00171 std::string outputFile;
00172 std::string outputPointsFile;
00173 std::string inputPointsFile;
00174 string basename;
00175 while ((c = getopt (argc, argv, optstring)) != -1)
00176 switch (c) {
00177 case 'i':
00178 inputPointsFile = optarg;
00179 break;
00180 case 'o':
00181 outputFile = optarg;
00182 break;
00183 case 'p':
00184 nPoints = atoi(optarg);
00185 break;
00186
00187
00188
00189 case 's':
00190 pyrLevel=atoi(optarg);
00191 break;
00192 case 'v':
00193 verbose++;
00194 break;
00195 case 'h':
00196 usage(argv[0]);
00197 return 1;
00198 case 'w':
00199 outputPointsFile = optarg;
00200 break;
00201 default:
00202 cerr << "Invalid parameter: " << optarg << std::endl;
00203 usage(argv[0]);
00204 return 1;
00205 }
00206
00207 unsigned nFiles = argc - optind;
00208 if (nFiles != 1) {
00209 std::cerr << std::endl << "Error: one pto file needs to be specified" << std::endl <<std::endl;
00210 usage(argv[0]);
00211 return 1;
00212 }
00213
00214 const char * scriptFile = argv[optind];
00215 Panorama pano;
00216 ifstream prjfile(scriptFile);
00217 if (!prjfile.good()) {
00218 cerr << "could not open script : " << scriptFile << endl;
00219 return 1;
00220 }
00221 pano.setFilePrefix(hugin_utils::getPathPrefix(scriptFile));
00222 DocumentData::ReadWriteError err = pano.readData(prjfile);
00223 if (err != DocumentData::SUCCESSFUL) {
00224 cerr << "error while parsing panos tool script: " << scriptFile << endl;
00225 cerr << "DocumentData::ReadWriteError code: " << err << endl;
00226 return 1;
00227 }
00228
00229
00230 if (!hasphotometricParams(pano)) {
00231 cerr << "ERROR:no photometric parameters were selected for optimization" << endl;
00232 cerr << "please update 'v' line in .pto script and try again." << endl;
00233 return 1;
00234 }
00235
00236
00237 TIFFSetWarningHandler(0);
00238
00239
00240 try {
00241 std::vector<vigra_ext::PointPairRGB> points;
00242
00243 if (inputPointsFile != "" ) {
00244
00245
00246 FILE * f = fopen(inputPointsFile.c_str(), "r");
00247 if (f == 0) {
00248 perror("Could not open input point file");
00249 return 1;
00250 }
00251 loadPointsC(f, points);
00252 fclose(f);
00253 } else {
00254 loadImgsAndExtractPoints(pano, nPoints, pyrLevel, randomPoints, progressDisplay, points, verbose);
00255 }
00256 if (verbose)
00257 cout << "\rSelected " << points.size() << " points" << std::endl;
00258 if (points.size() == 0) {
00259 std::cerr << "Error: no overlapping points found, exiting" << std::endl;
00260 return 1;
00261 }
00262
00263 if (outputPointsFile.size() > 0) {
00264 ofstream of(outputPointsFile.c_str());
00265 for (std::vector<PointPairRGB>::iterator it = points.begin(); it != points.end(); ++it) {
00266 of << (*it).imgNr1 << " " << (*it).imgNr2 << " "
00267 << (*it).p1.x << " " << (*it).p1.y<< " "
00268 << (*it).p2.x << " " << (*it).p2.y<< " "
00269 << (*it).i1.red() << " " << (*it).i1.green() << " " << (*it).i1.blue() << " "
00270 << (*it).i2.red() << " " << (*it).i2.green() << " " << (*it).i2.blue() << " "
00271
00272 << 0 << " "
00273 << (*it).r1 << " " << (*it).r2 << " "
00274
00275 << 0 << std::endl;
00276 }
00277 }
00278
00279
00280 progressDisplay.startSubtask("Vignetting Optimization", 0.0);
00281 PhotometricOptimizer photoopt(pano, &progressDisplay, pano.getOptimizeVector(), points);
00282 photoopt.run();
00283
00284
00285 progressDisplay.finishSubtask();
00286
00287 UIntSet allImgs;
00288 fill_set(allImgs,0, pano.getNrOfImages()-1);
00289
00290 if (outputFile == "" || outputFile == "-") {
00291 pano.printPanoramaScript(std::cout, pano.getOptimizeVector(), pano.getOptions(), allImgs, false, hugin_utils::getPathPrefix(scriptFile));
00292 } else {
00293 ofstream of(outputFile.c_str());
00294 pano.printPanoramaScript(of, pano.getOptimizeVector(), pano.getOptions(), allImgs, false, hugin_utils::getPathPrefix(scriptFile));
00295 }
00296
00297 } catch (std::exception & e) {
00298 cerr << "caught exception: " << e.what() << std::endl;
00299 return 1;
00300 }
00301 return 0;
00302 }