From: <da...@us...> - 2007-06-19 20:54:57
|
Revision: 2119 http://hugin.svn.sourceforge.net/hugin/?rev=2119&view=rev Author: dangelo Date: 2007-06-19 13:54:56 -0700 (Tue, 19 Jun 2007) Log Message: ----------- much faster and reliable align_image_stack. - Interest point detection on downscaled images, always select a given number of points. - can directly output hdr or aligned images Modified Paths: -------------- hugin/trunk/src/tools/align_image_stack.cpp Modified: hugin/trunk/src/tools/align_image_stack.cpp =================================================================== --- hugin/trunk/src/tools/align_image_stack.cpp 2007-06-19 18:04:35 UTC (rev 2118) +++ hugin/trunk/src/tools/align_image_stack.cpp 2007-06-19 20:54:56 UTC (rev 2119) @@ -67,28 +67,36 @@ << std::endl << "Usage: " << name << " [options] input files" << std::endl << "Valid options are:" << std::endl - << " -o prefix save aligned images as prefix0000.tif and so on (default: aligned_)" << std::endl + << " -a align images, do not output final HDR image" << std::endl + << " -o output filename (for HDR image) default (output.hdr)," << std::endl + << " or prefix for aligned images (-a option)" << std::endl << " -p file Output .pto file (useful for debugging, or further refinement)" << std::endl << " -v Verbose, print progress messages" << std::endl << " -t num Remove all control points with an error higher than num (default: 3)" << std::endl << " -f HFOV approximate horizontal field of view of input images, uses if EXIF info not complete" << std::endl - << " -c num Harris corner threshold (default: 5)" << std::endl + << " -c num number of control points to create between adjectant images (default: 200)" << std::endl << " -h Display help (this text)" << std::endl << std::endl; } template <class ImageType> -void createCtrlPoints(Panorama & pano, int img1, const ImageType & leftImg, int img2, const ImageType & rightImg, double scale, double cornerThreshold) +void createCtrlPoints(Panorama & pano, int img1, const ImageType & leftImg, int img2, const ImageType & rightImg, int pyrLevel, double scale, int nPoints) { ////////////////////////////////////////////////// // find interesting corners using harris corner detector + double scaleFactor = 1<<pyrLevel; + BImage leftCorners(leftImg.size(), vigra::UInt8(0)); FImage leftCornerResponse(leftImg.size()); - DEBUG_DEBUG("running corner detector threshold: " << cornerThreshold << " scale: " << scale ); + DEBUG_DEBUG("running corner detector. nPoints: " << nPoints << ", scale: " << scale ); + if (g_verbose > 1) { + std::cout << "Trying to find " << nPoints << " corners... "; + } + // find corner response at scale scale vigra::cornerResponseFunction(srcImageRange(leftImg, GreenAccessor<typename ImageType::value_type>()), destImage(leftCornerResponse), @@ -102,6 +110,42 @@ if (g_verbose > 5) exportImage(srcImageRange(leftCorners), vigra::ImageExportInfo("corner_response_maxima.png")); + + DEBUG_DEBUG("selecting points"); + // select the nPoints with the highest response + // some distribution criteria might be useful, too + // to avoid clustering all points on a single object. + double minResponse = 0; + std::multimap<double, vigra::Diff2D> points; + // sample grid on img1 and try to add ctrl points + for (int x=0; x < leftImg.size().x; x++ ) { + for (int y=0; y < leftImg.size().y; y++ ) { + if (leftCorners(x,y) == 0) { + continue; + } + double resp = leftCornerResponse(x,y); + if (resp > minResponse) { + // add to point map + points.insert(make_pair(resp,Diff2D(x,y))); + // if we have reached the maximum + // number of points, increase the threshold, to avoid + // growing the points map too much. + // extract more than nPoints, because some might be bad + // and cannot be matched with the other image. + if (points.size() > 5*nPoints) { + // remove the point with the lowest corner response. + points.erase(points.begin()); + // use new threshold for next selection. + minResponse = points.begin()->first; + } + } + } + } + if (g_verbose > 1) { + std::cout << " found " << points.size() << " candidates" << std::endl; + } + +/* DEBUG_DEBUG("thresholding corner response"); // threshold corner response to keep only strong corners (above 400.0) transformImage(srcImageRange(leftCornerResponse), destImage(leftCornerResponse), @@ -113,50 +157,50 @@ if (g_verbose > 5) exportImage(srcImageRange(leftCorners), vigra::ImageExportInfo("corner_response_threshold.png")); +*/ - int nGood = 0; int nBad = 0; - // sample grid on img1 and try to add ctrl points - for (int x=0; x < leftImg.size().x; x++ ) { - for (int y=0; y < leftImg.size().y; y++ ) { - if (leftCorners(x,y) > 0) { - // we found a corner. correlate with second image + // loop over all points, starting with the highest corner score + for (multimap<double, Diff2D>::reverse_iterator it = points.rbegin(); + it != points.rend(); + ++it) + { + if (nGood >= nPoints) { + // we have enough points, stop + break; + } - // load parameters + long templWidth = 20; + long sWidth = 100; + double corrThresh = 0.9; + double curvThresh = 0.0; - long templWidth = 20; - long sWidth = 100; - double corrThresh = 0.9; - double curvThresh = 0.0; + vigra_ext::CorrelationResult res; - vigra_ext::CorrelationResult res; - vigra::Diff2D roundP1(x, y); - vigra::Diff2D roundP2(x, y); - - res = vigra_ext::PointFineTune(leftImg, - roundP1, - templWidth, - rightImg, - roundP2, - sWidth - ); - - if (g_verbose > 1) { - cout << "corr coeff: " << res.maxi << " curv:" << res.curv.x << " " << res.curv.y << std::endl; - } - if (res.maxi < corrThresh ) - { - nBad++; - DEBUG_DEBUG("low correlation: " << res.maxi << " curv: " << res.curv); - } else { - nGood++; - // add control point - ControlPoint p(img1, roundP1.x, roundP1.y, img2, res.maxpos.x, res.maxpos.y); - pano.addCtrlPoint(p); - } - } + res = vigra_ext::PointFineTune(leftImg, + (*it).second, + templWidth, + rightImg, + (*it).second, + sWidth + ); + if (g_verbose > 2) { + cout << (*it).second.x << "," << (*it).second.y << " -> " << res.maxpos.x << "," << res.maxpos.x << ": corr coeff: " << res.maxi << " curv:" << res.curv.x << " " << res.curv.y << std::endl; } + if (res.maxi < corrThresh ) + { + nBad++; + DEBUG_DEBUG("low correlation: " << res.maxi << " curv: " << res.curv); + } else { + nGood++; + // add control point + ControlPoint p(img1, (*it).second.x * scaleFactor, + (*it).second.y * scaleFactor, + img2, res.maxpos.x * scaleFactor, + res.maxpos.y * scaleFactor); + pano.addCtrlPoint(p); + } } if (g_verbose > 0) { cout << "Number of good matches: " << nGood << ", bad matches: " << nBad << std::endl; @@ -167,23 +211,30 @@ int main(int argc, char *argv[]) { // parse arguments - const char * optstring = "f:hp:vo:t:c:o:"; + const char * optstring = "af:hp:vo:t:c:o:"; int c; opterr = 0; g_verbose = 0; - int nPoints = 100; double cpErrorThreshold = 3; - double cornerThreshold = 5; + int nPoints; double hfov = 0; - std::string outputPrefix = "aligned_"; + int pyrLevel = 2; + std::string outputPrefix; std::string ptoFile; string basename; + nPoints = 200; +// // use to override exposure value on the command line? +// std::map<std::string, double> exposureValueMap; + bool outputLayers = false; while ((c = getopt (argc, argv, optstring)) != -1) switch (c) { + case 'a': + outputLayers = true; + break; case 'c': - cornerThreshold = atof(optarg); + nPoints = atoi(optarg); break; case 'f': hfov = atof(optarg); @@ -216,6 +267,14 @@ return 1; } + if (outputPrefix.length() == 0) { + if (outputLayers) { + outputPrefix = "aligned_"; + } else { + outputPrefix = "output.hdr"; + } + } + // extract file names std::vector<std::string> files; for (size_t i=0; i < nFiles; i++) @@ -231,11 +290,16 @@ try { // load first image vigra::ImageImportInfo firstImgInfo(files[0].c_str()); - ImageType * leftImg = new BRGBImage(firstImgInfo.size()); - vigra::importImage(firstImgInfo, destImage(*leftImg)); + ImageType leftImgOrig(firstImgInfo.size()); - ImageType * rightImg = new BRGBImage(firstImgInfo.size()); + // rescale image + ImageType * leftImg = new BRGBImage(); + { + vigra::importImage(firstImgInfo, destImage(leftImgOrig)); + reduceNTimes(leftImgOrig, *leftImg, pyrLevel); + } + Panorama pano; Lens l; pano.addLens(l); @@ -285,6 +349,8 @@ // optimize nothing in the first image OptimizeVector optvars(1); + ImageType * rightImg = new BRGBImage(leftImg->size()); + // loop to add images and control points between them. for (int i = 1; i < (int) nFiles; i++) { if (g_verbose > 0) { @@ -304,12 +370,16 @@ // load the actual image data of the next image vigra::ImageImportInfo nextImgInfo(files[i].c_str()); assert(nextImgInfo.size() == firstImgInfo.size()); - vigra::importImage(nextImgInfo, destImage(*rightImg)); + { + ImageType rightImgOrig(nextImgInfo.size()); + vigra::importImage(nextImgInfo, destImage(rightImgOrig)); + reduceNTimes(rightImgOrig, *rightImg, pyrLevel); + } // add control points. // TODO: work on smaller images, or use a fast descriptor, based on // integral images. - createCtrlPoints(pano, i-1, *leftImg, i, *rightImg, 8, cornerThreshold); + createCtrlPoints(pano, i-1, *leftImg, i, *rightImg, pyrLevel, 3, nPoints); // swap images; delete leftImg; @@ -345,7 +415,31 @@ pano.setCtrlPoints(newCPs); // reoptimize PTools::optimize(pano); + if (!outputLayers) { + // TODO: photometric alignment (HDR, fixed white balance) + //utils::StreamProgressReporter progress(2.0); + //loadImgsAndExtractPoints(pano, nPoints, pyrLevel, randomPoints, progress, points); + //smartOptimizePhotometric + // switch to HDR output mode + PanoramaOptions opts = pano.getOptions(); + opts.outputFormat = PanoramaOptions::HDR; + opts.outputPixelType = "FLOAT"; + opts.outputMode = PanoramaOptions::OUTPUT_HDR; + pano.setOptions(opts); + } else { + // disable all exposure compensation stuff. + PanoramaOptions opts = pano.getOptions(); + opts.outputExposureValue = 0; + opts.outputMode = PanoramaOptions::OUTPUT_LDR; + for (int i=0; i < pano.getNrOfImages(); i++) { + SrcPanoImage img = pano.getSrcImage(i); + img.setExposureValue(0); + img.setResponseType(SrcPanoImage::RESPONSE_LINEAR); + pano.setSrcImage(i, img); + } + pano.setOptions(opts); + } UIntSet imgs = pano.getActiveImages(); if (ptoFile.size() > 0) { @@ -356,7 +450,7 @@ // remap all images utils::StreamMultiProgressDisplay progress(cout); - PT::stitchPanorama(pano, opts, + PT::stitchPanorama(pano, pano.getOptions(), progress, opts.outfile, imgs); } catch (std::exception & e) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <da...@us...> - 2007-06-20 15:50:46
|
Revision: 2129 http://hugin.svn.sourceforge.net/hugin/?rev=2129&view=rev Author: dangelo Date: 2007-06-20 08:50:42 -0700 (Wed, 20 Jun 2007) Log Message: ----------- fixed problems with -a, ignore EXIF rotation tag. Modified Paths: -------------- hugin/trunk/src/tools/align_image_stack.cpp Modified: hugin/trunk/src/tools/align_image_stack.cpp =================================================================== --- hugin/trunk/src/tools/align_image_stack.cpp 2007-06-20 14:00:29 UTC (rev 2128) +++ hugin/trunk/src/tools/align_image_stack.cpp 2007-06-20 15:50:42 UTC (rev 2129) @@ -314,6 +314,8 @@ SrcPanoImage srcImg; srcImg.setFilename(files[0]); initImageFromFile(srcImg, focalLength, cropFactor); + // disable autorotate + srcImg.setRoll(0); if (srcImg.getSize().x == 0 || srcImg.getSize().y == 0) { cerr << "Could not decode image: " << files[0] << "Unsupported image file format"; return 1; @@ -334,8 +336,13 @@ // setup output to be exactly similar to input image PanoramaOptions opts; opts.setHFOV(srcImg.getHFOV(), false); - opts.setWidth(srcImg.getSize().x, false); - opts.setHeight(srcImg.getSize().y); + if (srcImg.getRoll() == 0.0 || srcImg.getRoll() == 180.0) { + opts.setWidth(srcImg.getSize().x, false); + opts.setHeight(srcImg.getSize().y); + } else { + opts.setWidth(srcImg.getSize().y, false); + opts.setHeight(srcImg.getSize().x); + } opts.setProjection(PanoramaOptions::RECTILINEAR); // output to tiff format opts.outputFormat = PanoramaOptions::TIFF_m; @@ -432,13 +439,14 @@ PanoramaOptions opts = pano.getOptions(); opts.outputExposureValue = 0; opts.outputMode = PanoramaOptions::OUTPUT_LDR; + opts.outputFormat = PanoramaOptions::TIFF_m; + pano.setOptions(opts); for (int i=0; i < pano.getNrOfImages(); i++) { SrcPanoImage img = pano.getSrcImage(i); img.setExposureValue(0); - img.setResponseType(SrcPanoImage::RESPONSE_LINEAR); +// img.setResponseType(SrcPanoImage::RESPONSE_LINEAR); pano.setSrcImage(i, img); } - pano.setOptions(opts); } UIntSet imgs = pano.getActiveImages(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <da...@us...> - 2007-12-07 12:42:53
|
Revision: 2554 http://hugin.svn.sourceforge.net/hugin/?rev=2554&view=rev Author: dangelo Date: 2007-12-07 04:42:52 -0800 (Fri, 07 Dec 2007) Log Message: ----------- added align_image_stack, enabled processing of 16 bit images Added Paths: ----------- hugin/trunk/src/tools/align_image_stack.cpp Added: hugin/trunk/src/tools/align_image_stack.cpp =================================================================== --- hugin/trunk/src/tools/align_image_stack.cpp (rev 0) +++ hugin/trunk/src/tools/align_image_stack.cpp 2007-12-07 12:42:52 UTC (rev 2554) @@ -0,0 +1,367 @@ +// -*- c-basic-offset: 4 -*- + +/** @file align_image_stack.cpp + * + * @brief program to align a set of well overlapping images (~90%) + * + * @author Pablo d'Angelo <pab...@we...> + * + * $Id: align_image_stack.cpp 2510 2007-10-28 22:24:11Z dangelo $ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <hugin_config.h> +#include <fstream> +#include <sstream> + +#include <vigra/error.hxx> +#include <vigra/impex.hxx> +#include <vigra/cornerdetection.hxx> +#include <vigra/localminmax.hxx> +#include <hugin_utils/utils.h> + +#include <vigra_ext/Pyramid.h> +#include <vigra_ext/Correlation.h> + +#include <panodata/Panorama.h> +#include <panotools/PanoToolsOptimizerWrapper.h> +#include <algorithms/optimizer/PTOptimizer.h> +#include <nona/Stitcher.h> + +#ifdef WIN32 + #include <getopt.h> +#else + #include <unistd.h> +#endif + + +#include <tiff.h> + +using namespace vigra; +using namespace HuginBase; +using namespace AppBase; +using namespace std; +using namespace vigra_ext; +using namespace HuginBase::PTools; +using namespace HuginBase::Nona; + +int g_verbose = 0; + +static void usage(const char * name) +{ + cerr << name << ": align overlapping images for HDR creation" << std::endl + << std::endl + << "Usage: " << name << " [options] input files" << std::endl + << "Valid options are:" << std::endl + << " -o prefix save aligned images as prefix0000.tif and so on (default: aligned_)" << std::endl + << " -p file Output .pto file (useful for debugging, or further refinement)" << std::endl + << " -v Verbose, print progress messages" << std::endl + << " -t num Remove all control points with an error higher than num (default: 3)" << std::endl + << " -f HFOV approximate horizontal field of view of input images, uses if EXIF info not complete" << std::endl + << " -c num Harris corner threshold (default: 5)" << std::endl + << " -h Display help (this text)" << std::endl + << std::endl; +} + + +template <class ImageType> +void createCtrlPoints(Panorama & pano, int img1, const ImageType & leftImg, int img2, const ImageType & rightImg, double scale, double cornerThreshold) +{ + ////////////////////////////////////////////////// + // find interesting corners using harris corner detector + + BImage leftCorners(leftImg.size(), vigra::UInt8(0)); + FImage leftCornerResponse(leftImg.size()); + + DEBUG_DEBUG("running corner detector threshold: " << cornerThreshold << " scale: " << scale ); + + // find corner response at scale scale + vigra::cornerResponseFunction(srcImageRange(leftImg, GreenAccessor<typename ImageType::value_type>()), + destImage(leftCornerResponse), + scale); + + //saveScaledImage(leftCornerResponse,"corner_response.png"); + DEBUG_DEBUG("finding local maxima"); + // find local maxima of corner response, mark with 1 + vigra::localMaxima(srcImageRange(leftCornerResponse), destImage(leftCorners), 255); + + if (g_verbose > 5) + exportImage(srcImageRange(leftCorners), vigra::ImageExportInfo("corner_response_maxima.png")); + + DEBUG_DEBUG("thresholding corner response"); + // threshold corner response to keep only strong corners (above 400.0) + transformImage(srcImageRange(leftCornerResponse), destImage(leftCornerResponse), + vigra::Threshold<double, double>( + cornerThreshold, DBL_MAX, 0.0, 1.0)); + + vigra::combineTwoImages(srcImageRange(leftCorners), srcImage(leftCornerResponse), + destImage(leftCorners), std::multiplies<float>()); + + if (g_verbose > 5) + exportImage(srcImageRange(leftCorners), vigra::ImageExportInfo("corner_response_threshold.png")); + + + int nGood = 0; + int nBad = 0; + // sample grid on img1 and try to add ctrl points + for (int x=0; x < leftImg.size().x; x++ ) { + for (int y=0; y < leftImg.size().y; y++ ) { + if (leftCorners(x,y) > 0) { + // we found a corner. correlate with second image + + // load parameters + + long templWidth = 20; + long sWidth = 100; + double corrThresh = 0.9; + double curvThresh = 0.0; + + vigra_ext::CorrelationResult res; + vigra::Diff2D roundP1(x, y); + vigra::Diff2D roundP2(x, y); + + res = vigra_ext::PointFineTune(leftImg, + roundP1, + templWidth, + rightImg, + roundP2, + sWidth + ); + + if (g_verbose > 1) { + cout << "corr coeff: " << res.maxi << " curv:" << res.curv.x << " " << res.curv.y << std::endl; + } + if (res.maxi < corrThresh ) + { + nBad++; + DEBUG_DEBUG("low correlation: " << res.maxi << " curv: " << res.curv); + } else { + nGood++; + // add control point + ControlPoint p(img1, roundP1.x, roundP1.y, img2, res.maxpos.x, res.maxpos.y); + pano.addCtrlPoint(p); + } + } + } + } + if (g_verbose > 0) { + cout << "Number of good matches: " << nGood << ", bad matches: " << nBad << std::endl; + } +}; + + +int main(int argc, char *argv[]) +{ + // parse arguments + const char * optstring = "f:hp:vo:t:c:o:"; + int c; + + opterr = 0; + + g_verbose = 0; + int nPoints = 100; + double cpErrorThreshold = 3; + double cornerThreshold = 5; + double hfov = 0; + std::string outputPrefix = "aligned_"; + std::string ptoFile; + string basename; + while ((c = getopt (argc, argv, optstring)) != -1) + switch (c) { + case 'c': + cornerThreshold = atof(optarg); + break; + case 'f': + hfov = atof(optarg); + break; + case 't': + cpErrorThreshold = atof(optarg); + break; + case 'p': + ptoFile = optarg; + break; + case 'o': + outputPrefix = optarg; + break; + case 'v': + g_verbose++; + break; + case 'h': + usage(argv[0]); + return 1; + default: + cerr << "Invalid parameter: " << optarg << std::endl; + usage(argv[0]); + return 1; + } + + unsigned nFiles = argc - optind; + if (nFiles < 2) { + std::cerr << std::endl << "Error: at least two files need to be specified" << std::endl <<std::endl; + usage(argv[0]); + return 1; + } + + // extract file names + std::vector<std::string> files; + for (size_t i=0; i < nFiles; i++) + files.push_back(argv[optind+i]); + + // suppress tiff warnings + //TIFFSetWarningHandler(0); + +// utils::StreamMultiProgressDisplay pdisp(cout); + //utils::MultiProgressDisplay pdisp; + + typedef vigra::UInt16RGBImage ImageType; + try { + // load first image + vigra::ImageImportInfo firstImgInfo(files[0].c_str()); + ImageType * leftImg = new UInt16RGBImage(firstImgInfo.size()); + vigra::importImage(firstImgInfo, destImage(*leftImg)); + + ImageType * rightImg = new UInt16RGBImage(firstImgInfo.size()); + + Panorama pano; + Lens l; + pano.addLens(l); + + // add the first image.to the panorama object + // default settings + double focalLength = 50; + double cropFactor = 0; + VariableMap defaultVars; + fillVariableMap(defaultVars); + + SrcPanoImage srcImg; + srcImg.setFilename(files[0]); + SrcPanoImage::initImageFromFile(srcImg, focalLength, cropFactor); + if (srcImg.getSize().x == 0 || srcImg.getSize().y == 0) { + cerr << "Could not decode image: " << files[0] << "Unsupported image file format"; + return 1; + } + + // use hfov specified by user. + if (hfov > 0) { + srcImg.setHFOV(hfov); + } else if (cropFactor == 0) { + // could not read HFOV, assuming default: 50 + srcImg.setHFOV(50); + } + + PanoImage panoImg(files[0], srcImg.getSize().x, srcImg.getSize().y, 0); + int imgNr = pano.addImage(panoImg, defaultVars); + pano.setSrcImage(imgNr, srcImg); + + // setup output to be exactly similar to input image + PanoramaOptions opts; + opts.setHFOV(srcImg.getHFOV(), false); + opts.setWidth(srcImg.getSize().x, false); + opts.setHeight(srcImg.getSize().y); + opts.setProjection(PanoramaOptions::RECTILINEAR); + // output to tiff format + opts.outputFormat = PanoramaOptions::TIFF_m; + opts.tiff_saveROI = false; + opts.outfile = outputPrefix; + // m estimator, to be more robust against points on moving objects + opts.huberSigma = 2; + pano.setOptions(opts); + + // variables that should be optimized + // optimize nothing in the first image + OptimizeVector optvars(1); + + // loop to add images and control points between them. + for (int i = 1; i < (int) nFiles; i++) { + if (g_verbose > 0) { + cout << "Creating control points between " << files[i-1] << " and " << files[i] << endl; + } + // add next image. + srcImg.setFilename(files[i]); + SrcPanoImage::initImageFromFile(srcImg, focalLength, cropFactor); + if (srcImg.getSize().x == 0 || srcImg.getSize().y == 0) { + cerr << "Could not decode image: " << files[i] << "Unsupported image file format"; + return 1; + } + PanoImage panoImg(files[i], srcImg.getSize().x, srcImg.getSize().y, 0); + int imgNr = pano.addImage(panoImg, defaultVars); + pano.setSrcImage(imgNr, srcImg); + + // load the actual image data of the next image + vigra::ImageImportInfo nextImgInfo(files[i].c_str()); + assert(nextImgInfo.size() == firstImgInfo.size()); + vigra::importImage(nextImgInfo, destImage(*rightImg)); + + // add control points. + // TODO: work on smaller images, or use a fast descriptor, based on + // integral images. + createCtrlPoints(pano, i-1, *leftImg, i, *rightImg, 8, cornerThreshold); + + // swap images; + delete leftImg; + leftImg = rightImg; + rightImg = new ImageType(leftImg->size()); + + // optimize yaw, roll, pitch + std::set<std::string> vars; + vars.insert("y"); + vars.insert("p"); + vars.insert("r"); + optvars.push_back(vars); + } + delete leftImg; + delete rightImg; + + // optimize everything. + pano.setOptimizeVector(optvars); + PTools::optimize(pano); + + // need to do some basic outlier pruning. + // remove all points with error higher than a specified threshold + CPVector cps = pano.getCtrlPoints(); + CPVector newCPs; + for (int i=0; i < (int)cps.size(); i++) { + if (cps[i].error < cpErrorThreshold) { + newCPs.push_back(cps[i]); + } + } + if (g_verbose > 0) { + cout << "Ctrl points before pruning: " << cps.size() << ", after: " << newCPs.size() << std::endl; + } + pano.setCtrlPoints(newCPs); + // reoptimize + PTools::optimize(pano); + + UIntSet imgs = pano.getActiveImages(); + + if (ptoFile.size() > 0) { + std::ofstream script(ptoFile.c_str()); + pano.printPanoramaScript(script, optvars, pano.getOptions(), imgs, false, ""); + } + + // remap all images + StreamMultiProgressDisplay progress(cout); + + stitchPanorama(pano, opts, + progress, opts.outfile, imgs); + + } catch (std::exception & e) { + cerr << "caught exception: " << e.what() << std::endl; + return 1; + } + return 0; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <da...@us...> - 2007-12-11 17:08:32
|
Revision: 2560 http://hugin.svn.sourceforge.net/hugin/?rev=2560&view=rev Author: dangelo Date: 2007-12-11 09:08:27 -0800 (Tue, 11 Dec 2007) Log Message: ----------- unlink HFOV, if -m option is given Modified Paths: -------------- hugin/trunk/src/tools/align_image_stack.cpp Modified: hugin/trunk/src/tools/align_image_stack.cpp =================================================================== --- hugin/trunk/src/tools/align_image_stack.cpp 2007-12-09 20:44:06 UTC (rev 2559) +++ hugin/trunk/src/tools/align_image_stack.cpp 2007-12-11 17:08:27 UTC (rev 2560) @@ -281,8 +281,16 @@ PanoImage panoImg(files[0], srcImg.getSize().x, srcImg.getSize().y, 0); int imgNr = pano.addImage(panoImg, defaultVars); + // unlink HFOV? + if (param.optHFOV) { + l = pano.getLens(0); + LensVariable lv = map_get(l.variables, "v"); + lv.setLinked(true); + pano.updateLensVariable(0, lv); + } pano.setSrcImage(imgNr, srcImg); + // setup output to be exactly similar to input image PanoramaOptions opts; opts.setProjection(PanoramaOptions::RECTILINEAR); @@ -327,6 +335,7 @@ } PanoImage panoImg(files[i], srcImg.getSize().x, srcImg.getSize().y, 0); + pano.addLens(l); int imgNr = pano.addImage(panoImg, defaultVars); pano.setSrcImage(imgNr, srcImg); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <da...@us...> - 2007-12-11 17:19:27
|
Revision: 2562 http://hugin.svn.sourceforge.net/hugin/?rev=2562&view=rev Author: dangelo Date: 2007-12-11 09:19:20 -0800 (Tue, 11 Dec 2007) Log Message: ----------- really unlink HFOV Modified Paths: -------------- hugin/trunk/src/tools/align_image_stack.cpp Modified: hugin/trunk/src/tools/align_image_stack.cpp =================================================================== --- hugin/trunk/src/tools/align_image_stack.cpp 2007-12-11 17:17:59 UTC (rev 2561) +++ hugin/trunk/src/tools/align_image_stack.cpp 2007-12-11 17:19:20 UTC (rev 2562) @@ -285,7 +285,7 @@ if (param.optHFOV) { l = pano.getLens(0); LensVariable lv = map_get(l.variables, "v"); - lv.setLinked(true); + lv.setLinked(false); pano.updateLensVariable(0, lv); } pano.setSrcImage(imgNr, srcImg); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bto...@us...> - 2008-01-21 23:42:55
|
Revision: 2682 http://hugin.svn.sourceforge.net/hugin/?rev=2682&view=rev Author: btownshend Date: 2008-01-21 15:42:52 -0800 (Mon, 21 Jan 2008) Log Message: ----------- Added -l option to signal linear response input files. Modified Paths: -------------- hugin/trunk/src/tools/align_image_stack.cpp Modified: hugin/trunk/src/tools/align_image_stack.cpp =================================================================== --- hugin/trunk/src/tools/align_image_stack.cpp 2008-01-21 23:40:51 UTC (rev 2681) +++ hugin/trunk/src/tools/align_image_stack.cpp 2008-01-21 23:42:52 UTC (rev 2682) @@ -81,6 +81,7 @@ << " -m Optimize field of view for all images, execpt for first." << std::endl << " Useful for aligning focus stacks with slightly different magnification." << std::endl << " -c num number of control points to create between adjectant images (default: 200)" << std::endl + << " -l Assume linear input files" << std::endl << " -h Display help (this text)" << std::endl << std::endl; } @@ -222,6 +223,7 @@ nPoints = 200; hfov = 0; pyrLevel = 2; + linear = false; // Assume linear input files if true optHFOV = false; fisheye = false; } @@ -229,6 +231,7 @@ double cpErrorThreshold; int nPoints; double hfov; + bool linear; bool optHFOV; bool fisheye; int pyrLevel; @@ -297,6 +300,12 @@ lv.setLinked(false); pano.updateLensVariable(0, lv); } + if (param.linear) { + srcImg.setResponseType(SrcPanoImage::RESPONSE_LINEAR); + if (g_verbose>0) { + cout << "Using linear response" << std::endl; + } + } pano.setSrcImage(imgNr, srcImg); // setup output to be exactly similar to input image @@ -445,7 +454,6 @@ for (unsigned i=0; i < pano.getNrOfImages(); i++) { SrcPanoImage img = pano.getSrcImage(i); img.setExposureValue(0); -// img.setResponseType(SrcPanoImage::RESPONSE_LINEAR); pano.setSrcImage(i, img); } // remap all images @@ -464,7 +472,7 @@ int main(int argc, char *argv[]) { // parse arguments - const char * optstring = "a:ef:hmp:vo:t:c:o:"; + const char * optstring = "a:ef:hlmp:vo:t:c:o:"; int c; opterr = 0; @@ -488,6 +496,8 @@ case 'f': param.hfov = atof(optarg); break; + case 'l': + param.linear = true; case 'm': param.optHFOV = true; break; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <da...@us...> - 2008-01-28 09:54:58
|
Revision: 2713 http://hugin.svn.sourceforge.net/hugin/?rev=2713&view=rev Author: dangelo Date: 2008-01-28 01:54:56 -0800 (Mon, 28 Jan 2008) Log Message: ----------- fixed: [ 1880623 ] align_image_stack crashes on certain TIFFs support images with alpha channels (currently alpha channels will be simply ignored during image matching). Modified Paths: -------------- hugin/trunk/src/tools/align_image_stack.cpp Modified: hugin/trunk/src/tools/align_image_stack.cpp =================================================================== --- hugin/trunk/src/tools/align_image_stack.cpp 2008-01-28 08:41:03 UTC (rev 2712) +++ hugin/trunk/src/tools/align_image_stack.cpp 2008-01-28 09:54:56 UTC (rev 2713) @@ -248,12 +248,19 @@ try { // load first image vigra::ImageImportInfo firstImgInfo(files[0].c_str()); - ImageType leftImgOrig(firstImgInfo.size()); // rescale image ImageType * leftImg = new ImageType(); { - vigra::importImage(firstImgInfo, destImage(leftImgOrig)); + ImageType leftImgOrig(firstImgInfo.size()); + if(firstImgInfo.numExtraBands() == 1) { + vigra::BImage alpha(firstImgInfo.size()); + vigra::importImageAlpha(firstImgInfo, destImage(leftImgOrig), destImage(alpha)); + } else if (firstImgInfo.numExtraBands() == 0) { + vigra::importImage(firstImgInfo, destImage(leftImgOrig)); + } else { + vigra_fail("Images with multiple extra (alpha) channels not supported"); + } reduceNTimes(leftImgOrig, *leftImg, param.pyrLevel); } @@ -367,8 +374,15 @@ assert(nextImgInfo.size() == firstImgInfo.size()); { ImageType rightImgOrig(nextImgInfo.size()); - vigra::importImage(nextImgInfo, destImage(rightImgOrig)); - reduceNTimes(rightImgOrig, *rightImg, param.pyrLevel); + if (nextImgInfo.numExtraBands() == 1) { + vigra::BImage alpha(nextImgInfo.size()); + vigra::importImageAlpha(nextImgInfo, destImage(rightImgOrig), destImage(alpha)); + } else if (nextImgInfo.numExtraBands() == 0) { + vigra::importImage(nextImgInfo, destImage(rightImgOrig)); + reduceNTimes(rightImgOrig, *rightImg, param.pyrLevel); + } else { + vigra_fail("Images with multiple extra (alpha) channels not supported"); + } } // add control points. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <da...@us...> - 2008-01-28 10:22:14
|
Revision: 2714 http://hugin.svn.sourceforge.net/hugin/?rev=2714&view=rev Author: dangelo Date: 2008-01-28 02:22:13 -0800 (Mon, 28 Jan 2008) Log Message: ----------- fixed a stupid bug that slipped through the last commit Modified Paths: -------------- hugin/trunk/src/tools/align_image_stack.cpp Modified: hugin/trunk/src/tools/align_image_stack.cpp =================================================================== --- hugin/trunk/src/tools/align_image_stack.cpp 2008-01-28 09:54:56 UTC (rev 2713) +++ hugin/trunk/src/tools/align_image_stack.cpp 2008-01-28 10:22:13 UTC (rev 2714) @@ -379,10 +379,10 @@ vigra::importImageAlpha(nextImgInfo, destImage(rightImgOrig), destImage(alpha)); } else if (nextImgInfo.numExtraBands() == 0) { vigra::importImage(nextImgInfo, destImage(rightImgOrig)); - reduceNTimes(rightImgOrig, *rightImg, param.pyrLevel); } else { vigra_fail("Images with multiple extra (alpha) channels not supported"); } + reduceNTimes(rightImgOrig, *rightImg, param.pyrLevel); } // add control points. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bto...@us...> - 2008-01-28 23:42:14
|
Revision: 2721 http://hugin.svn.sourceforge.net/hugin/?rev=2721&view=rev Author: btownshend Date: 2008-01-28 15:42:13 -0800 (Mon, 28 Jan 2008) Log Message: ----------- Added -g option to create a uniform grid over which control points are distributed Fixed bug that caused -l option to also trigger -m Added -s option to specify prescaling of image (default is -s 2 which is 4x downsampling) Added more debugging files for corner detection when verbose==5 Fixed bug in display of selected control points Cleaned up usage summary Modified Paths: -------------- hugin/trunk/src/tools/align_image_stack.cpp Modified: hugin/trunk/src/tools/align_image_stack.cpp =================================================================== --- hugin/trunk/src/tools/align_image_stack.cpp 2008-01-28 23:13:19 UTC (rev 2720) +++ hugin/trunk/src/tools/align_image_stack.cpp 2008-01-28 23:42:13 UTC (rev 2721) @@ -72,23 +72,26 @@ << " Modes of operation:" << std::endl << " -p file Output .pto file (useful for debugging, or further refinement)" << std::endl << " -a prefix align images, output as prefix_xxxx.tif" << std::endl - << " -o output merge images to HDR, generate output.hdr)," << std::endl + << " -o output merge images to HDR, generate output.hdr" << std::endl << " Modifiers" << std::endl - << " -v Verbose, print progress messages" << std::endl + << " -v Verbose, print progress messages. Repeat for higher verbosity" << std::endl << " -e Assume input images are full frame fish eye (default: rectilinear)" << std::endl << " -t num Remove all control points with an error higher than num pixels (default: 3)" << std::endl << " -f HFOV approximate horizontal field of view of input images, use if EXIF info not complete" << std::endl - << " -m Optimize field of view for all images, execpt for first." << std::endl + << " -m Optimize field of view for all images, except for first." << std::endl << " Useful for aligning focus stacks with slightly different magnification." << std::endl - << " -c num number of control points to create between adjectant images (default: 200)" << std::endl + << " -c num number of control points (per grid) to create between adjacent images (default: 200)" << std::endl << " -l Assume linear input files" << std::endl + << " -s scale Scale down image by 2^scale (default: 2 [4x downsampling])" << std::endl + << " -g gsize Break image into a rectangular grid (gsize x gsize) and attempt to find " << std::endl + << " num control points in each section (default: 1 [no grid] )" << std::endl << " -h Display help (this text)" << std::endl << std::endl; } template <class ImageType> -void createCtrlPoints(Panorama & pano, int img1, const ImageType & leftImg, int img2, const ImageType & rightImg, int pyrLevel, double scale, unsigned nPoints) +void createCtrlPoints(Panorama & pano, int img1, const ImageType & leftImg, int img2, const ImageType & rightImg, int pyrLevel, double scale, unsigned nPoints, unsigned grid) { ////////////////////////////////////////////////// // find interesting corners using harris corner detector @@ -109,7 +112,10 @@ destImage(leftCornerResponse), scale); - //saveScaledImage(leftCornerResponse,"corner_response.png"); + if (g_verbose > 5) + // saveScaledImage(leftCornerResponse,"corner_response.png"); + exportImage(srcImageRange(leftCornerResponse), vigra::ImageExportInfo("corner_response.tif")); + DEBUG_DEBUG("finding local maxima"); // find local maxima of corner response, mark with 1 vigra::localMaxima(srcImageRange(leftCornerResponse), destImage(leftCorners), 255); @@ -117,101 +123,113 @@ if (g_verbose > 5) exportImage(srcImageRange(leftCorners), vigra::ImageExportInfo("corner_response_maxima.png")); + for (int partx=0;partx<grid;partx++) { + for (int party=0;party<grid;party++) { + if (g_verbose>1) { + std::cout << "selecting points for grid partition (" << partx << ", " << party << ")" << std::endl; + } + // select the nPoints with the highest response + // some distribution criteria might be useful, too + // to avoid clustering all points on a single object. + double minResponse = 0; + std::multimap<double, vigra::Diff2D> points; + // sample grid on img1 and try to add ctrl points + for (int x=partx*leftImg.size().x/grid; x < (partx+1)*leftImg.size().x/grid; x++ ) { + for (int y=party*leftImg.size().y/grid; y < (party+1)*leftImg.size().y/grid; y++ ) { + if (leftCorners(x,y) == 0) { + continue; + } + double resp = leftCornerResponse(x,y); + if (resp > minResponse) { + // add to point map + points.insert(make_pair(resp,Diff2D(x,y))); + // if we have reached the maximum + // number of points, increase the threshold, to avoid + // growing the points map too much. + // extract more than nPoints, because some might be bad + // and cannot be matched with the other image. + if (points.size() > 5*nPoints) { + // remove the point with the lowest corner response. + leftCorners(points.begin()->second.x,points.begin()->second.y)=0; + points.erase(points.begin()); + // use new threshold for next selection. + minResponse = points.begin()->first; + } + } else + // Remove from list for debug purposes + leftCorners(x,y)=0; + } + } + if (g_verbose > 1) { + std::cout << " found " << points.size() << " candidates" << std::endl; + } - DEBUG_DEBUG("selecting points"); - // select the nPoints with the highest response - // some distribution criteria might be useful, too - // to avoid clustering all points on a single object. - double minResponse = 0; - std::multimap<double, vigra::Diff2D> points; - // sample grid on img1 and try to add ctrl points - for (int x=0; x < leftImg.size().x; x++ ) { - for (int y=0; y < leftImg.size().y; y++ ) { - if (leftCorners(x,y) == 0) { - continue; - } - double resp = leftCornerResponse(x,y); - if (resp > minResponse) { - // add to point map - points.insert(make_pair(resp,Diff2D(x,y))); - // if we have reached the maximum - // number of points, increase the threshold, to avoid - // growing the points map too much. - // extract more than nPoints, because some might be bad - // and cannot be matched with the other image. - if (points.size() > 5*nPoints) { - // remove the point with the lowest corner response. - points.erase(points.begin()); - // use new threshold for next selection. - minResponse = points.begin()->first; - } - } - } - } - if (g_verbose > 1) { - std::cout << " found " << points.size() << " candidates" << std::endl; - } + /* + DEBUG_DEBUG("thresholding corner response"); + // threshold corner response to keep only strong corners (above 400.0) + transformImage(srcImageRange(leftCornerResponse), destImage(leftCornerResponse), + vigra::Threshold<double, double>( + cornerThreshold, DBL_MAX, 0.0, 1.0)); -/* - DEBUG_DEBUG("thresholding corner response"); - // threshold corner response to keep only strong corners (above 400.0) - transformImage(srcImageRange(leftCornerResponse), destImage(leftCornerResponse), - vigra::Threshold<double, double>( - cornerThreshold, DBL_MAX, 0.0, 1.0)); + vigra::combineTwoImages(srcImageRange(leftCorners), srcImage(leftCornerResponse), + destImage(leftCorners), std::multiplies<float>()); - vigra::combineTwoImages(srcImageRange(leftCorners), srcImage(leftCornerResponse), - destImage(leftCorners), std::multiplies<float>()); + if (g_verbose > 5) + exportImage(srcImageRange(leftCorners), vigra::ImageExportInfo("corner_response_threshold.png")); + */ - if (g_verbose > 5) - exportImage(srcImageRange(leftCorners), vigra::ImageExportInfo("corner_response_threshold.png")); -*/ + unsigned nGood = 0; + unsigned nBad = 0; + // loop over all points, starting with the highest corner score + for (multimap<double, Diff2D>::reverse_iterator it = points.rbegin(); + it != points.rend(); + ++it) + { + if (nGood >= nPoints) { + // we have enough points, stop + break; + } - unsigned nGood = 0; - unsigned nBad = 0; - // loop over all points, starting with the highest corner score - for (multimap<double, Diff2D>::reverse_iterator it = points.rbegin(); - it != points.rend(); - ++it) - { - if (nGood >= nPoints) { - // we have enough points, stop - break; - } + long templWidth = 20; + long sWidth = 100; + double corrThresh = 0.9; + //double curvThresh = 0.0; - long templWidth = 20; - long sWidth = 100; - double corrThresh = 0.9; - //double curvThresh = 0.0; + vigra_ext::CorrelationResult res; - vigra_ext::CorrelationResult res; - - res = vigra_ext::PointFineTune(leftImg, - (*it).second, - templWidth, - rightImg, - (*it).second, - sWidth - ); - if (g_verbose > 2) { - cout << (*it).second.x << "," << (*it).second.y << " -> " << res.maxpos.x << "," << res.maxpos.x << ": corr coeff: " << res.maxi << " curv:" << res.curv.x << " " << res.curv.y << std::endl; - } - if (res.maxi < corrThresh ) - { - nBad++; - DEBUG_DEBUG("low correlation: " << res.maxi << " curv: " << res.curv); - } else { - nGood++; - // add control point - ControlPoint p(img1, (*it).second.x * scaleFactor, - (*it).second.y * scaleFactor, - img2, res.maxpos.x * scaleFactor, - res.maxpos.y * scaleFactor); - pano.addCtrlPoint(p); - } + res = vigra_ext::PointFineTune(leftImg, + (*it).second, + templWidth, + rightImg, + (*it).second, + sWidth + ); + if (g_verbose > 2) { + cout << (*it).second.x << "," << (*it).second.y << " -> " + << res.maxpos.x << "," << res.maxpos.y << ": corr coeff: " << res.maxi + << " curv:" << res.curv.x << " " << res.curv.y << std::endl; + } + if (res.maxi < corrThresh ) + { + nBad++; + DEBUG_DEBUG("low correlation: " << res.maxi << " curv: " << res.curv); + } else { + nGood++; + // add control point + ControlPoint p(img1, (*it).second.x * scaleFactor, + (*it).second.y * scaleFactor, + img2, res.maxpos.x * scaleFactor, + res.maxpos.y * scaleFactor); + pano.addCtrlPoint(p); + } + } + if (g_verbose > 0) { + cout << "Number of good matches: " << nGood << ", bad matches: " << nBad << std::endl; + } + } } - if (g_verbose > 0) { - cout << "Number of good matches: " << nGood << ", bad matches: " << nBad << std::endl; - } + if (g_verbose > 5) + exportImage(srcImageRange(leftCorners), vigra::ImageExportInfo("corner_response_chosen.png")); }; @@ -221,6 +239,7 @@ { cpErrorThreshold = 3; nPoints = 200; + grid = 1; hfov = 0; pyrLevel = 2; linear = false; // Assume linear input files if true @@ -230,6 +249,7 @@ double cpErrorThreshold; int nPoints; + int grid; // Partition images into grid x grid subregions, each with npoints double hfov; bool linear; bool optHFOV; @@ -388,7 +408,7 @@ // add control points. // work on smaller images // TODO: or use a fast interest point operator. - createCtrlPoints(pano, i-1, *leftImg, i, *rightImg, param.pyrLevel, 2, param.nPoints); + createCtrlPoints(pano, i-1, *leftImg, i, *rightImg, param.pyrLevel, 2, param.nPoints, param.grid); // swap images; delete leftImg; @@ -486,7 +506,7 @@ int main(int argc, char *argv[]) { // parse arguments - const char * optstring = "a:ef:hlmp:vo:t:c:o:"; + const char * optstring = "a:ef:g:hlmp:vo:s:t:c:"; int c; opterr = 0; @@ -510,8 +530,12 @@ case 'f': param.hfov = atof(optarg); break; + case 'g': + param.grid = atoi(optarg); + break; case 'l': param.linear = true; + break; case 'm': param.optHFOV = true; break; @@ -530,6 +554,9 @@ case 'h': usage(argv[0]); return 1; + case 's': + param.pyrLevel = atoi(optarg); + break; default: cerr << "Invalid parameter: " << optarg << std::endl; usage(argv[0]); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <da...@us...> - 2008-01-31 18:04:34
|
Revision: 2748 http://hugin.svn.sourceforge.net/hugin/?rev=2748&view=rev Author: dangelo Date: 2008-01-31 10:04:27 -0800 (Thu, 31 Jan 2008) Log Message: ----------- fixed unsigned vs signed warnings Modified Paths: -------------- hugin/trunk/src/tools/align_image_stack.cpp Modified: hugin/trunk/src/tools/align_image_stack.cpp =================================================================== --- hugin/trunk/src/tools/align_image_stack.cpp 2008-01-31 17:57:05 UTC (rev 2747) +++ hugin/trunk/src/tools/align_image_stack.cpp 2008-01-31 18:04:27 UTC (rev 2748) @@ -123,8 +123,8 @@ if (g_verbose > 5) exportImage(srcImageRange(leftCorners), vigra::ImageExportInfo("corner_response_maxima.png")); - for (int partx=0;partx<grid;partx++) { - for (int party=0;party<grid;party++) { + for (unsigned partx=0;partx<grid;partx++) { + for (unsigned party=0;party<grid;party++) { if (g_verbose>1) { std::cout << "selecting points for grid partition (" << partx << ", " << party << ")" << std::endl; } @@ -134,8 +134,8 @@ double minResponse = 0; std::multimap<double, vigra::Diff2D> points; // sample grid on img1 and try to add ctrl points - for (int x=partx*leftImg.size().x/grid; x < (partx+1)*leftImg.size().x/grid; x++ ) { - for (int y=party*leftImg.size().y/grid; y < (party+1)*leftImg.size().y/grid; y++ ) { + for (unsigned x=partx*leftImg.size().x/grid; x < (partx+1)*leftImg.size().x/grid; x++ ) { + for (unsigned y=party*leftImg.size().y/grid; y < (party+1)*leftImg.size().y/grid; y++ ) { if (leftCorners(x,y) == 0) { continue; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bto...@us...> - 2008-02-02 22:49:45
|
Revision: 2774 http://hugin.svn.sourceforge.net/hugin/?rev=2774&view=rev Author: btownshend Date: 2008-02-02 14:49:25 -0800 (Sat, 02 Feb 2008) Log Message: ----------- Changed defaults to '-s 1 -g 5 -c 8' from '-s 2 -g 1 -c 200' Added some sanity checks on option values Modified Paths: -------------- hugin/trunk/src/tools/align_image_stack.cpp Modified: hugin/trunk/src/tools/align_image_stack.cpp =================================================================== --- hugin/trunk/src/tools/align_image_stack.cpp 2008-02-02 21:58:38 UTC (rev 2773) +++ hugin/trunk/src/tools/align_image_stack.cpp 2008-02-02 22:49:25 UTC (rev 2774) @@ -80,11 +80,11 @@ << " -f HFOV approximate horizontal field of view of input images, use if EXIF info not complete" << std::endl << " -m Optimize field of view for all images, except for first." << std::endl << " Useful for aligning focus stacks with slightly different magnification." << std::endl - << " -c num number of control points (per grid) to create between adjacent images (default: 200)" << std::endl + << " -c num number of control points (per grid) to create between adjacent images (default: 8)" << std::endl << " -l Assume linear input files" << std::endl - << " -s scale Scale down image by 2^scale (default: 2 [4x downsampling])" << std::endl + << " -s scale Scale down image by 2^scale (default: 1 [2x downsampling])" << std::endl << " -g gsize Break image into a rectangular grid (gsize x gsize) and attempt to find " << std::endl - << " num control points in each section (default: 1 [no grid] )" << std::endl + << " num control points in each section (default: 10 [5x5 grid] )" << std::endl << " -h Display help (this text)" << std::endl << std::endl; } @@ -238,10 +238,10 @@ Parameters() { cpErrorThreshold = 3; - nPoints = 200; - grid = 1; + nPoints = 8; + grid = 5; hfov = 0; - pyrLevel = 2; + pyrLevel = 1; linear = false; // Assume linear input files if true optHFOV = false; fisheye = false; @@ -368,7 +368,7 @@ // loop to add images and control points between them. for (int i = 1; i < (int) files.size(); i++) { if (g_verbose > 0) { - cout << "Creating control points between " << files[i-1] << " and " << files[i] << endl; + cout << "Creating control points between " << files[i-1] << " and " << files[i] << std::endl; } // add next image. srcImg.setFilename(files[i]); @@ -523,15 +523,27 @@ break; case 'c': param.nPoints = atoi(optarg); + if (param.nPoints<1) { + cerr << "Invalid parameter: Number of points/grid (-c) must be at least 1" << std::endl; + return 1; + } break; case 'e': param.fisheye = true; break; case 'f': param.hfov = atof(optarg); + if (param.hfov<=0) { + cerr << "Invalid parameter: HFOV (-f) must be greater than 0" << std::endl; + return 1; + } break; case 'g': param.grid = atoi(optarg); + if (param.grid <1 || param.grid>50) { + cerr << "Invalid parameter: number of grid cells (-g) should be between 1 and 50" << std::endl; + return 1; + } break; case 'l': param.linear = true; @@ -541,6 +553,10 @@ break; case 't': param.cpErrorThreshold = atof(optarg); + if (param.cpErrorThreshold <= 0) { + cerr << "Invalid parameter: control point error threshold (-t) must be greater than 0" << std::endl; + return 1; + } break; case 'p': param.ptoFile = optarg; @@ -556,6 +572,10 @@ return 1; case 's': param.pyrLevel = atoi(optarg); + if (param.pyrLevel<0 || param.pyrLevel >8) { + cerr << "Invalid parameter: scaling (-s) should be between 0 and 8" << std::endl; + return 1; + } break; default: cerr << "Invalid parameter: " << optarg << std::endl; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <bto...@us...> - 2008-02-02 23:54:39
|
Revision: 2775 http://hugin.svn.sourceforge.net/hugin/?rev=2775&view=rev Author: btownshend Date: 2008-02-02 15:54:37 -0800 (Sat, 02 Feb 2008) Log Message: ----------- Fixed typo in usage message. Modified Paths: -------------- hugin/trunk/src/tools/align_image_stack.cpp Modified: hugin/trunk/src/tools/align_image_stack.cpp =================================================================== --- hugin/trunk/src/tools/align_image_stack.cpp 2008-02-02 22:49:25 UTC (rev 2774) +++ hugin/trunk/src/tools/align_image_stack.cpp 2008-02-02 23:54:37 UTC (rev 2775) @@ -84,7 +84,7 @@ << " -l Assume linear input files" << std::endl << " -s scale Scale down image by 2^scale (default: 1 [2x downsampling])" << std::endl << " -g gsize Break image into a rectangular grid (gsize x gsize) and attempt to find " << std::endl - << " num control points in each section (default: 10 [5x5 grid] )" << std::endl + << " num control points in each section (default: 5 [5x5 grid] )" << std::endl << " -h Display help (this text)" << std::endl << std::endl; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |