28 #include <hugin_config.h>
42 #include "vigra/impexalpha.hxx"
44 static void usage(
const char* name)
46 std::cout << name <<
": report the number of image groups in a project" << std::endl
49 <<
"Usage: " << name <<
" input.pto" << std::endl
51 << name <<
" examines the connections between images in a project and" << std::endl
52 <<
"reports back the number of parts or image groups in that project" << std::endl
54 <<
"Further switches:" << std::endl
55 <<
" --print-output-info Print more information about the output" << std::endl
56 <<
" --print-lens-info Print more information about lenses" << std::endl
57 <<
" --print-stack-info Print more information about assigned stacks" << std::endl
58 <<
" --print-image-info Print information about image files" << std::endl
59 <<
" --create-missing-images Creates placeholder images for non-existing" << std::endl
60 <<
" images in same directory as the pto file" << std::endl
62 << name <<
" is used by the assistant" << std::endl
66 void PrintImageGroup(
const std::vector<HuginBase::UIntSet>& imageGroup,
const std::string& prefix=std::string())
68 for (
size_t i=0; i < imageGroup.size(); i++)
72 std::cout << prefix <<
" " << i <<
": ";
76 for (HuginBase::UIntSet::const_iterator it = imageGroup[i].begin(); it != imageGroup[i].end(); ++it)
79 if (c+1 != imageGroup[i].size())
86 if (prefix.empty() && (i+1 != imageGroup.size()))
90 std::cout << std::endl;
96 vigra::FindMinMax<float> minmax;
97 vigra::inspectImage(
srcImageRange(image, vigra::RedAccessor<vigra::RGBValue<float>>()), minmax);
98 std::cout <<
" Red channel: " << minmax.min <<
" - " << minmax.max << std::endl;
100 vigra::inspectImage(
srcImageRange(image, vigra::GreenAccessor<vigra::RGBValue<float>>()), minmax);
101 std::cout <<
" Green channel: " << minmax.min <<
" - " << minmax.max << std::endl;
103 vigra::inspectImage(
srcImageRange(image, vigra::BlueAccessor<vigra::RGBValue<float>>()), minmax);
104 std::cout <<
" Blue channel: " << minmax.min <<
" - " << minmax.max << std::endl;
109 vigra::FindMinMax<float> minmax;
111 std::cout <<
" " << text <<
": " << minmax.min <<
" - " << minmax.max << std::endl;
117 std::cout << std::endl;
120 const std::string filename = pano.
getImage(imgNr).getFilename();
121 std::cout <<
"Image " << imgNr <<
": " << filename << std::endl;
124 if (vigra::isImage(filename.c_str()))
126 vigra::ImageImportInfo
info(filename.c_str());
127 std::filesystem::path file(filename);
128 std::cout <<
" File type: " <<
info.getFileType() << std::endl;
129 const auto fileSize = std::filesystem::file_size(file);
130 std::cout <<
" File size: ";
133 std::cout << fileSize / 1000 <<
" kB" << std::endl;
137 std::cout << fileSize <<
" B" << std::endl;
139 std::cout <<
" Pixel type: " <<
info.getPixelType() << std::endl
140 <<
" Pixel size: " <<
info.width() <<
"x" <<
info.height() << std::endl
141 <<
" Resolution: " <<
info.getXResolution() <<
"/" <<
info.getYResolution() << std::endl
142 <<
" Offset: " <<
info.getPosition() << std::endl
143 <<
" Canvas size: " <<
info.getCanvasSize() << std::endl
145 <<
" Bands: " <<
info.numBands() << std::endl
146 <<
" Extra bands: " <<
info.numExtraBands() << std::endl;
147 if (
info.numImages() > 1)
149 std::cout <<
" Subimages: " <<
info.numImages() <<
" (reading index " <<
info.getImageIndex() <<
")" << std::endl;
151 if (
info.numExtraBands() == 0)
154 if (
info.numBands() == 3)
157 vigra::FRGBImage image(
info.size());
163 if (
info.numBands() == 1)
166 vigra::FImage image(
info.size());
172 std::cout <<
" Only RGB or grayscale images supported" << std::endl;
175 std::cout << std::endl;
179 if (
info.numExtraBands() == 1)
182 if (
info.numBands() == 4)
185 vigra::FRGBImage image(
info.size());
186 vigra::FImage mask(
info.size());
193 if (
info.numBands() == 2)
196 vigra::FImage image(
info.size());
197 vigra::FImage mask(
info.size());
204 std::cout <<
" Only RGB or grayscale images supported" << std::endl;
207 std::cout << std::endl;
211 std::cout <<
" Only images with one or no alpha channel supported" << std::endl;
218 std::filesystem::path file(filename);
219 std::cout << std::endl <<
" not recognized by vigra as image file" << std::endl
220 <<
" File size: " << std::filesystem::file_size(file) / 1024 <<
" kiB" << std::endl << std::endl;
226 std::cout <<
" does not exists." << std::endl <<std::endl;
235 std::uniform_int_distribution<> distribIndex(0, 128);
236 auto randIndex = std::bind(distribIndex, rng);
238 bool requiresPTOrewrite =
false;
241 const std::filesystem::path imagePath(ptoPath);
245 std::filesystem::path srcFile(pano.
getImage(imgNr).getFilename());
246 std::cout <<
"Image " << imgNr <<
": " << srcFile.string();
247 if (std::filesystem::exists(srcFile))
249 std::cout <<
" exists." << std::endl;
254 srcFile = std::filesystem::absolute(srcFile);
255 std::filesystem::path newImage(imagePath);
256 newImage /= srcFile.filename();
258 if (newImage != srcFile)
260 requiresPTOrewrite =
true;
263 std::cout <<
" does not exist. Creating " << newImage.filename() << std::endl;
266 vigra::RGBValue<vigra::UInt8>(64 + randIndex(), 64 + randIndex(), 64 + randIndex()));
267 vigra::ImageExportInfo imgExportInfo(newImage.string().c_str());
271 if (requiresPTOrewrite)
276 std::cout <<
"Written output to " << output << std::endl;
281 int main(
int argc,
char* argv[])
284 const char* optstring =
"h";
287 PRINT_OUTPUT_INFO=1000,
288 PRINT_LENS_INFO=1004,
289 PRINT_STACK_INFO=1005,
290 CREATE_DUMMY_IMAGES=1006,
293 static struct option longOptions[] =
295 {
"print-output-info", no_argument, NULL, PRINT_OUTPUT_INFO },
296 {
"print-lens-info", no_argument, NULL, PRINT_LENS_INFO },
297 {
"print-stack-info", no_argument, NULL, PRINT_STACK_INFO },
298 {
"print-image-info", no_argument, NULL, PRINT_IMAGE_INFO },
299 {
"create-missing-images", no_argument, NULL, CREATE_DUMMY_IMAGES },
300 {
"help", no_argument, NULL,
'h' },
305 bool printOutputInfo=
false;
306 bool printLensInfo =
false;
307 bool printStackInfo =
false;
308 bool printImageInfo =
false;
309 bool createDummyImages =
false;
311 while ((c = getopt_long (argc, argv, optstring, longOptions,
nullptr)) != -1)
318 case PRINT_OUTPUT_INFO:
319 printOutputInfo=
true;
321 case PRINT_LENS_INFO:
322 printLensInfo =
true;
324 case PRINT_STACK_INFO:
325 printStackInfo =
true;
327 case PRINT_IMAGE_INFO:
328 printImageInfo =
true;
330 case CREATE_DUMMY_IMAGES:
331 createDummyImages =
true;
344 if (argc - optind != 1)
346 if (argc - optind < 1)
358 std::string input=argv[optind];
361 if (createDummyImages)
373 std::cout << std::endl
374 <<
"Opened project " << input << std::endl << std::endl
375 <<
"Project contains" << std::endl
391 std::ios oldstate(
nullptr);
392 oldstate.copyfmt(std::cout);
393 std::cout <<
"Control points statistics" << std::endl
394 << std::fixed << std::setprecision(2)
395 <<
"\tMean error : " << mean << std::endl
396 <<
"\tStandard deviation: " << sqrt(var) << std::endl
397 <<
"\tMinimum : " << min << std::endl
398 <<
"\tMaximum : " << max << std::endl;
399 std::cout.copyfmt(oldstate);
407 std::cout <<
"All images are connected." << std::endl;
413 std::cout <<
"Found unconnected images!" << std::endl
414 <<
"There are " << comps.size() <<
" image groups." << std::endl;
416 std::cout <<
"Image groups: " << std::endl;
417 for (
size_t i=0; i < comps.size(); i++)
420 HuginGraph::ImageGraph::Components::value_type::const_iterator it;
422 for (it = comps[i].begin(); it != comps[i].end(); ++it)
425 if (c+1 != comps[i].size())
432 if (i+1 != comps.size())
434 std::cout <<
", " << std::endl;
437 returnValue=comps.size();
439 std::cout << std::endl;
442 std::cout << std::endl <<
"Lenses:" << std::endl;
447 std::cout << std::endl <<
"Stacks:" << std::endl;
454 std::cout << std::endl <<
"Output contains" << std::endl
455 << stacks.size() <<
" images stacks:" << std::endl;
458 std::cout << std::endl << std::endl <<
"and " << layers.size() <<
" exposure layers:" << std::endl;
463 std::cout <<
"Supported file formats: " << vigra::impexListFormats() << std::endl
464 <<
"Supported extensions: " << vigra::impexListExtensions() << std::endl;
467 if (createDummyImages)
std::string GetICCDesc(const vigra::ImageImportInfo::ICCProfile &iccProfile)
returns description of given icc profile
void InspectGrayscaleImage(const vigra::FImage &image, const std::string text)
std::vector< UIntSet > getHDRStacks(const PanoramaData &pano, UIntSet allImgs, PanoramaOptions opts)
returns vector of set of output stacks
bool FileExists(const std::string &filename)
checks if file exists
declaration of functions to handle stacks and layers
std::vector< UIntSet > getExposureLayers(const PanoramaData &pano, UIntSet allImgs, PanoramaOptions opts)
returns vector of set of output exposure layers
void InspectRGBImage(const vigra::FRGBImage &image)
std::string GetOutputFilename(const std::string &out, const std::string &in, const std::string &suffix)
construct output filename, if ouput is known return this value otherwise use the input filename and a...
ConstImageVariableGroup & getStacks()
Get the ImageVariableGroup representing the group of stack variables.
Somewhere to specify what variables belong to what.
static void calcCtrlPntsErrorStats(const PanoramaData &pano, double &min, double &max, double &mean, double &var, const int &imgNr=-1, const bool onlyActive=false, const bool ignoreLineCp=false)
UIntSet getImagesinROI(const PanoramaData &pano, const UIntSet activeImages)
returns set of images which are visible in output ROI
void PrintImageInfo(const HuginBase::Panorama &pano)
std::size_t getNrOfCtrlPoints() const
number of control points
int getHeight() const
Get the height of the image in pixels.
std::vector< HuginBase::UIntSet > Components
stores the components of the graph
void PrintImageGroup(const std::vector< HuginBase::UIntSet > &imageGroup, const std::string &prefix=std::string())
void CreateMissingImages(HuginBase::Panorama &pano, const std::string &output)
std::set< unsigned int > UIntSet
ConstImageVariableGroup & getLenses()
Get the ImageVariableGroup representing the group of lens variables.
UIntSetVector getPartsSet() const
return a vector which contains a HuginBase::UIntSet for each group with the corresponding images numb...
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
std::string GetAbsoluteFilename(const std::string &filename)
returns the full absolute filename
std::size_t getNrOfImages() const
number of images.
int getWidth() const
Get the width of the image in pixels.
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...
Make an ImageVariableGroup for lenses and other common concepts.
void setImageFilename(unsigned int img, const std::string &fname)
set a new image filename
vigra::pair< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImage(ROIImage< Image, Alpha > &img)
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
UIntSet getActiveImages() const
get active 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...
const PanoramaOptions & getOptions() const
returns the options for this panorama
Components GetComponents()
find all connected components
std::string GetHuginVersion()
return a string with version numbers
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
std::size_t getNumberOfParts() const
get the number of parts.
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[])
class to work with images graphs created from a HuginBase::Panorama class it creates a graph based on...