26 #ifndef _NONA_STITCHER_H
27 #define _NONA_STITCHER_H
30 #include <vigra/windows.h>
39 #include <vigra/stdimage.hxx>
40 #include <vigra/rgbvalue.hxx>
41 #include <vigra/tiff.hxx>
43 #include <vigra/impex.hxx>
45 #include <vigra/copyimage.hxx>
69 template <
typename ImageType,
typename AlphaType>
86 const UIntSet & images,
const std::string & file,
103 std::vector<vigra::Rect2D>::iterator itr =
m_rois.begin();
105 if (! itr->isEmpty()) {
127 template<
typename ImageType,
typename AlphaType>
129 unsigned int imgNr,
unsigned int nImg,
131 const std::string& basename,
132 const bool useBigTIFF,
136 AlphaType * alpha_img = 0;
148 std::ostringstream greyname;
149 greyname << basename << std::setfill(
'0') << std::setw(4) << imgNr <<
"_gray.pgm";
150 vigra::ImageExportInfo exinfo1(greyname.str().c_str());
153 alpha.resize(opts.
getROI().size());
155 vigra::Rect2D newOutArea(newOutRect);
156 newOutRect.moveBy(-opts.
getROI().upperLeft());
165 exinfo1.setPosition(remapped.
boundingBox().upperLeft());
179 complete.resize(opts.
getROI().size());
180 alpha.resize(opts.
getROI().size());
182 vigra::Rect2D newOutArea(newOutRect);
183 newOutRect.moveBy(-opts.
getROI().upperLeft());
193 final_img = &complete;
199 alpha_img = &remapped.
m_mask;
203 std::ostringstream filename;
204 filename << basename << std::setfill(
'0') << std::setw(4) << imgNr <<
"." + ext;
208 vigra::ImageExportInfo exinfo(filename.str().c_str(), useBigTIFF ?
"w8" :
"w");
209 exinfo.setXResolution(150);
210 exinfo.setYResolution(150);
214 exinfo.setPosition(remapped.
boundingBox().upperLeft());
219 exinfo.setPosition(opts.
getROI().upperLeft());
226 bool supportsAlpha =
true;
235 std::ostringstream quality;
236 quality <<
"JPEG QUALITY=" << opts.
quality;
237 exinfo.setCompression(quality.str().c_str());
238 supportsAlpha =
false;
254 template <
typename ImageType,
typename AlphaType>
272 const std::string & basename,
291 for (UIntSet::const_iterator it = images.begin();
292 it != images.end(); ++it)
306 }
catch (vigra::PreconditionViolation & e) {
309 std::cerr << e.what();
327 unsigned int imgNr,
unsigned int nImg,
334 vigra::UInt16Image xImg;
335 vigra::UInt16Image yImg;
340 vigra::UInt16Image dist;
346 std::ostringstream filename2;
347 filename2 <<
m_basename << std::setfill(
'0') << std::setw(4) << imgNr <<
"_x.tif";
349 vigra::ImageExportInfo exinfo(filename2.str().c_str());
350 exinfo.setXResolution(150);
351 exinfo.setYResolution(150);
359 std::ostringstream filename3;
360 filename3 <<
m_basename << std::setfill(
'0') << std::setw(4) << imgNr <<
"_y.tif";
362 vigra::ImageExportInfo exinfo2(filename3.str().c_str());
363 exinfo2.setXResolution(150);
364 exinfo2.setYResolution(150);
368 std::ostringstream filename2;
369 filename2 <<
m_basename << std::setfill(
'0') << std::setw(4) << imgNr <<
"_x.tif";
370 vigra::ImageExportInfo exinfo(filename2.str().c_str());
371 exinfo.setXResolution(150);
372 exinfo.setYResolution(150);
375 std::ostringstream filename3;
376 filename3 <<
m_basename << std::setfill(
'0') << std::setw(4) << imgNr <<
"_y.tif";
377 vigra::ImageExportInfo exinfo2(filename3.str().c_str());
378 exinfo2.setXResolution(150);
379 exinfo2.setYResolution(150);
398 template <
typename ImageType,
typename AlphaImageType>
417 DEBUG_DEBUG(
"Layering image into a multi image tif file " << filename);
425 unsigned int imgNr,
unsigned int nImg,
441 vigra::maskImage(remapped.
m_mask),
459 template <
typename ImageType,
typename AlphaType>
474 const std::string & filename,
480 const unsigned int nImg = imgSet.size();
490 std::copy(imgSet.begin(), imgSet.end(), std::back_inserter(images));
496 for (UIntVector::const_iterator it = images.begin(); it != images.end(); ++it)
518 const std::string suffix(
GetAdvancedOption(advOptions,
"saveIntermediateImagesSuffix"));
521 finalFilename.append(suffix);
528 vigra_ext::MergeImages<ImageType, AlphaType>(panoImage, alpha, remapped->
m_image, remapped->
m_mask, vigra::Diff2D(remapped->
boundingBox().upperLeft()), wrap, hardSeam);
531 }
catch (vigra::PreconditionViolation & e) {
532 DEBUG_ERROR(
"exception during stitching" << e.what());
549 const std::string & filename,
555 std::string basename = filename;
561 stitch(opts, imgSet, filename, pano, panoMask, remapper, advOptions);
565 std::transform(cext.begin(),cext.end(), cext.begin(), (int(*)(int))
std::tolower);
571 std::string outputfile(basename);
573 const std::string suffix =
GetAdvancedOption(advOptions,
"saveFinalImageSuffix", std::string());
576 outputfile.append(suffix);
578 outputfile.append(
"." + ext);
583 vigra::ImageExportInfo exinfo(outputfile.c_str(),
GetAdvancedOption(advOptions,
"useBigTIFF",
false) ?
"w8" :
"w");
584 exinfo.setXResolution(150);
585 exinfo.setYResolution(150);
593 std::ostringstream quality;
594 quality <<
"JPEG QUALITY=" << opts.
quality;
595 exinfo.setCompression(quality.str().c_str());
599 exinfo.setPixelType(
"UINT8");
603 exinfo.setCanvasSize(pano.size());
604 exinfo.setPosition(
m_panoROI.upperLeft());
608 exinfo.setPixelType(
"FLOAT");
630 vigra::ImageImportInfo::ICCProfile
iccProfile;
636 template<
class VALUETYPE>
641 typedef typename vigra::NumericTraits<argument_type>
Traits;
652 sum = vigra::NumericTraits<float_type>::zero();
656 template<
class T,
class M>
668 typedef typename std::vector<float_type>::const_iterator Iter;
671 float_type error = vigra::NumericTraits<float_type>::zero();
672 for (Iter it=
values.begin(); it !=
values.end(); ++it) {
673 error += vigra::abs(*it-mean);
688 template <
typename ImageType,
typename AlphaType>
703 template <
class FUNCTOR>
705 const std::string & filename,
712 std::string basename = filename;
728 std::string outputfile = basename +
"." + ext;
732 vigra::ImageExportInfo exinfo(outputfile.c_str(),
GetAdvancedOption(advOptions,
"useBigTIFF",
false) ?
"w8" :
"w");
736 exinfo.setXResolution(150);
737 exinfo.setYResolution(150);
741 std::ostringstream quality;
742 quality <<
"JPEG QUALITY=" << opts.
quality;
743 exinfo.setCompression(quality.str().c_str());
763 template<
class ImgIter,
class ImgAccessor,
764 class AlphaIter,
class AlphaAccessor,
767 vigra::triple<ImgIter, ImgIter, ImgAccessor> pano,
768 std::pair<AlphaIter, AlphaAccessor> alpha,
772 typedef typename vigra::NumericTraits<typename ImageType::value_type> Traits;
773 typedef typename AlphaAccessor::value_type MaskType;
778 typedef std::vector<RemappedPanoImage<ImageType, AlphaType> *> RemappedVector;
779 unsigned int nImg = imgSet.size();
785 RemappedVector remapped(nImg);
789 for (UIntSet::const_iterator it = imgSet.begin();
790 it != imgSet.end(); ++it)
803 vigra::Diff2D size = pano.second - pano.first;
804 ImgIter output = pano.first;
807 for (
int y=0; y < size.y; y++) {
808 for (
int x=0; x < size.x; x++) {
811 for (
unsigned int i=0; i< nImg; i++) {
812 MaskType a = remapped[i]->getMask(x,y);
815 reduce(remapped[i]->
operator()(x,y), a);
818 pano.third.set(Traits::fromRealPromote(
reduce()), output, vigra::Diff2D(x,y));
819 alpha.second.set(maskRes, alpha.first, vigra::Diff2D(x,y));
823 for (
typename RemappedVector::iterator it=remapped.begin();
824 it != remapped.end(); ++it)
836 template <
typename ImageType,
typename AlphaType>
851 template<
class ImgIter,
class ImgAccessor,
852 class AlphaIter,
class AlphaAccessor,
855 vigra::triple<ImgIter, ImgIter, ImgAccessor> pano,
856 std::pair<AlphaIter, AlphaAccessor> alpha,
858 BlendFunctor & blend)
865 vigra::Rect2D panoROI;
869 for (UIntSet::reverse_iterator it = imgSet.rbegin();
870 it != imgSet.rend(); ++it)
883 blend(*remapped, pano, alpha, panoROI);
886 }
catch (vigra::PreconditionViolation & e) {
889 std::cerr << e.what();
898 template <
class BlendFunctor>
900 const std::string & filename,
902 BlendFunctor & blend)
904 std::string basename = filename;
919 std::string outputfile = basename +
"." + ext;
923 vigra::ImageExportInfo exinfo(outputfile.c_str());
924 exinfo.setXResolution(150);
925 exinfo.setYResolution(150);
929 std::ostringstream quality;
930 quality <<
"JPEG QUALITY=" << opts.
quality;
931 exinfo.setCompression(quality.str().c_str());
934 exinfo.setCompression(
"DEFLATE");
964 template <
typename ImageType,
typename AlphaType,
965 typename PanoIter,
typename PanoAccessor,
966 typename AlphaIter,
typename AlphaAccessor>
968 vigra::triple<PanoIter, PanoIter, PanoAccessor> pano,
969 std::pair<AlphaIter, AlphaAccessor> alpha,
970 const vigra::Rect2D & panoROI)
976 DEBUG_DEBUG(
"size of panorama: " << pano.second - pano.first);
979 vigra::Rect2D fullPano(vigra::Size2D(pano.second-pano.first));
981 vigra::Rect2D overlap = fullPano & img.
boundingBox();
993 template<
typename ImageType,
typename AlphaType>
997 const std::string & basename,
1013 stitcher.
stitch(opts, imgs, basename, m, hdrmerge, advOptions);
1017 stitcher.
stitch(opts, imgs, basename, m, advOptions);
1029 stitcher.
stitch(opts, imgs, basename, m, advOptions);
1035 stitcher.
stitch(opts, imgs, basename, m, advOptions);
1040 DEBUG_ERROR(
"multi mask stitching not implemented!");
1057 const std::string & basename,
1067 const std::string & basename,
1069 const char * pixelType,
1075 const std::string & basename,
1077 const char * pixelType,
1084 const std::string & basename,
1086 const char * pixelType,
1092 const std::string & basename,
1094 const char * pixelType,
Mask m_mask
corresponding alpha channel
vigra::triple< ImgIter, ImgIter, ImgAcc > applyRect(vigra::Rect2D &r, vigra::triple< ImgIter, ImgIter, ImgAcc > img)
apply a roi to an image area
virtual void stitch(const PanoramaOptions &opts, const UIntSet &images, const std::string &basename, SingleImageRemapper< ImageType, AlphaType > &remapper, const AdvancedOptions &advOptions)
static void stitchPanoIntern(const PanoramaData &pano, const PanoramaOptions &opts, AppBase::ProgressDisplay *progress, const std::string &basename, UIntSet imgs, const AdvancedOptions &advOptions)
virtual void release(RemappedPanoImage< ImageType, AlphaType > *d)=0
declaration of functions to handle stacks and layers
virtual void saveRemapped(RemappedPanoImage< ImageType, AlphaImageType > &remapped, unsigned int imgNr, unsigned int nImg, const PanoramaOptions &opts, const AdvancedOptions &advOptions)
save the remapped image in a partial tiff layer
bool GetAdvancedOption(const AdvancedOptions &opts, const std::string &name, const bool defaultValue)
check if given option is saved and return its boolean value, otherwise return defaultValue ...
double outputRangeCompression
void operator()(RemappedPanoImage< ImageType, AlphaType > &img, vigra::triple< PanoIter, PanoIter, PanoAccessor > pano, std::pair< AlphaIter, AlphaAccessor > alpha, const vigra::Rect2D &panoROI)
blend img into pano, using alpha mask and panoROI
vigra::ImageImportInfo::ICCProfile GetICCProfile() const
virtual RemappedPanoImage< ImageType, AlphaType > * getRemapped(const PanoramaData &pano, const PanoramaOptions &opts, unsigned int imgNr, vigra::Rect2D outputROI, AppBase::ProgressDisplay *progress)=0
create a remapped pano image.
void stitch(const PanoramaOptions &opts, const UIntSet &imgSet, const std::string &filename, ImageType &panoImage, AlphaType &alpha, SingleImageRemapper< ImageType, AlphaType > &remapper, const AdvancedOptions &advOptions)
Traits::RealPromote float_type
implements a stitching algorithm
virtual ~ReduceStitcher()
blend images, by simply stacking them, without soft blending or boundary calculation ...
void copyImageIf(SrcImageIterator src_upperleft, SrcImageIterator src_lowerright, SrcAccessor src_acc, MaskImageIterator mask_upperleft, MaskAccessor mask_acc, DestImageIterator dest_upperleft, DestAccessor dest_acc)
void stitch(const PanoramaOptions &opts, const UIntSet &imgSet, const std::string &filename, SingleImageRemapper< ImageType, AlphaType > &remapper, BlendFunctor &blend)
float_type operator()() const
return the result
Some functions to create tiff images with masks.
unsigned int getHeight() const
get panorama height
void stitchPanoRGB_8_16(const PanoramaData &pano, const PanoramaOptions &opts, AppBase::ProgressDisplay *progress, const std::string &basename, const UIntSet &usedImgs, const char *pixelType, const AdvancedOptions &advOptions)
void reduce(bool wraparound, SrcImageIterator src_upperleft, SrcImageIterator src_lowerright, SrcAccessor sa, AlphaIterator alpha_upperleft, AlphaAccessor aa, DestImageIterator dest_upperleft, DestImageIterator dest_lowerright, DestAccessor da, DestAlphaIterator dest_alpha_upperleft, DestAlphaIterator dest_alpha_lowerright, DestAlphaAccessor daa)
The Burt & Adelson Reduce operation.
create a panorama using the reduce operation on all overlapping pixels.
Stitcher< ImageType, AlphaType > Base
Contains functions to transform whole images.
remap a set of images, and store the individual remapped files.
#define DEBUG_ASSERT(cond)
vigra::Rect2D GetPanoROI() const
Difference reduce functor.
void exportImageAlpha(ImageIterator image_upper_left, ImageIterator image_lower_right, ImageAccessor image_accessor, AlphaIterator alpha_upper_left, AlphaAccessor alpha_accessor, const ImageExportInfo &export_info)
Write the image and its alpha channel to a file.
vigra::pair< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImage(const ROIImage< Image, Mask > &img)
void stitchPanoGray_8_16(const PanoramaData &pano, const PanoramaOptions &opts, AppBase::ProgressDisplay *progress, const std::string &basename, const UIntSet &usedImgs, const char *pixelType, const AdvancedOptions &advOptions)
unsigned int colorReferenceImage
void stitch(const PanoramaOptions &opts, const UIntSet &imgSet, vigra::triple< ImgIter, ImgIter, ImgAccessor > pano, std::pair< AlphaIter, AlphaAccessor > alpha, SingleImageRemapper< ImageType, AlphaType > &remapper, FUNCTOR &reduce)
void saveRemapped(RemappedPanoImage< ImageType, AlphaType > &remapped, unsigned int imgNr, unsigned int nImg, const PanoramaOptions &opts, const std::string &basename, const bool useBigTIFF, AppBase::ProgressDisplay *progress)
void init(const PanoramaOptions &opts, const UIntSet &images)
UIntVector getEstimatedBlendingOrder(const PanoramaData &pano, const UIntSet &images, const unsigned int referenceImage)
returns vector of image numbers for blending in approbiate order
std::set< unsigned int > UIntSet
virtual void prepareOutputFile(const PanoramaOptions &opts, const AdvancedOptions &advOptions)
prepare the output file (setup file structures etc.)
SimpleStitcher(const PanoramaData &pano, AppBase::ProgressDisplay *progress)
static const std::string & getFormatName(FileFormat f)
return string name of output file format
const vigra::Rect2D & getROI() const
vigra::Rect2D & boundingBox()
void calcSrcCoordImgs(DistImgType &imgX, DistImgType &imgY)
calculate distance map.
void taskFinished()
call when a task has finished and the status message should be cleared
virtual void finalizeOutputFile(const PanoramaOptions &opts)
virtual UIntSet getUsedImages()
void stitch(const PanoramaOptions &opts, const UIntSet &imgSet, const std::string &filename, SingleImageRemapper< ImageType, AlphaType > &remapper, FUNCTOR &reduce, const AdvancedOptions &advOptions)
vigra::TiffImage * m_tiff
Stitcher(const PanoramaData &pano, AppBase::ProgressDisplay *progress)
create a stitcher for the given panorama
std::string getExtension(const std::string &basename2)
Get extension of a filename.
std::vector< unsigned int > UIntVector
AppBase::ProgressDisplay * m_progress
vigra::FRGBImage ImageType
virtual void calcOutputROIS(const PanoramaOptions &opts, const UIntSet &images)
virtual ~WeightedStitcher()
Stitcher< ImageType, AlphaType > Base
Image m_image
remapped image
const PanoramaData & m_pano
vigra::ImageExportInfo::ICCProfile iccProfile
MultiImageRemapper(const PanoramaData &pano, AppBase::ProgressDisplay *progress)
Helper class for storing different options.
vigra::ImageImportInfo::ICCProfile m_ICCProfile
ReduceToDifferenceFunctor()
void createAlphaTiffImage(ImageIterator upperleft, ImageIterator lowerright, ImageAccessor a, AlphaIterator alphaUpperleft, AlphaAccessor alphaA, vigra::TiffImage *tiff)
void setMessage(const std::string &message, const std::string &filename="")
sets the message to given string
std::string stripExtension(const std::string &basename2)
remove extension of a filename
functor to create a remapped image
virtual const SrcPanoImage & getImage(std::size_t nr) const =0
get a panorama image, counting starts with 0
static std::vector< vigra::Rect2D > computeROIS(const PanoramaData &panorama, const PanoramaOptions &opts, const UIntSet &images)
virtual void saveRemapped(RemappedPanoImage< ImageType, AlphaType > &remapped, unsigned int imgNr, unsigned int nImg, const PanoramaOptions &opts, const AdvancedOptions &advOptions)
save a remapped image, or layer
virtual void finalizeOutputFile(const PanoramaOptions &opts)
close the tiff file
vigra::pair< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImage(ROIImage< Image, Alpha > &img)
void stitchPanorama(const PanoramaData &pano, const PanoramaOptions &opt, AppBase::ProgressDisplay *progress, const std::string &basename, const UIntSet &usedImgs, const AdvancedOptions &advOptions)
The main stitching function.
MultiImageRemapper< ImageType, AlphaImageType > Base
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
void createTiffDirectory(vigra::TiffImage *tiff, const std::string &pagename, const std::string &documentname, const std::string comp, uint16_t page, uint16_t nImg, vigra::Diff2D offset, vigra::Size2D fullSize, const vigra::ImageExportInfo::ICCProfile &icc)
write a new Tiff directory, for a new layer
void stitchPanoGray_32_float(const PanoramaData &pano, const PanoramaOptions &opts, AppBase::ProgressDisplay *progress, const std::string &basename, const UIntSet &usedImgs, const char *pixelType, const AdvancedOptions &advOptions)
std::string tiffCompression
const std::string & getOutputExtension() const
return the extension used by the current output format
ReduceStitcher(const PanoramaData &pano, AppBase::ProgressDisplay *progress)
unsigned int getWidth() const
TiffMultiLayerRemapper(const PanoramaData &pano, AppBase::ProgressDisplay *progress)
A stitcher without seaming, just copies the images over each other.
virtual ~MultiImageRemapper()
vigra::triple< typename ROIImage< Image, Alpha >::mask_const_traverser, typename ROIImage< Image, Alpha >::mask_const_traverser, typename ROIImage< Image, Alpha >::MaskConstAccessor > srcMaskRange(const ROIImage< Image, Alpha > &img)
void setAdvancedOptions(const HuginBase::Nona::AdvancedOptions advancedOptions)
void stitchPanoRGB_32_float(const PanoramaData &pano, const PanoramaOptions &opts, AppBase::ProgressDisplay *progress, const std::string &basename, const UIntSet &usedImgs, const char *pixelType, const AdvancedOptions &advOptions)
vigra::ImageImportInfo::ICCProfile iccProfile
virtual ~SimpleStitcher()
void stitch(const PanoramaOptions &opts, const UIntSet &imgSet, const std::string &filename, SingleImageRemapper< ImageType, AlphaType > &remapper, const AdvancedOptions &advOptions)
vigra::pair< typename ROIImage< Image, Alpha >::mask_const_traverser, typename ROIImage< Image, Alpha >::MaskConstAccessor > srcMask(const ROIImage< Image, Alpha > &img)
virtual void prepareOutputFile(const PanoramaOptions &opts, const AdvancedOptions &advOptions)
prepare the output file (setup file structures etc.)
std::map< std::string, std::string > AdvancedOptions
vigra::triple< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImageRange(ROIImage< Image, Alpha > &img)
std::string outputPixelType
virtual void stitch(const PanoramaOptions &opts, const UIntSet &images, const std::string &file, SingleImageRemapper< ImageType, AlphaType > &remapper)
Stitch some images into a panorama file.
void copyImage(SrcImageIterator src_upperleft, SrcImageIterator src_lowerright, SrcAccessor src_acc, DestImageIterator dest_upperleft, DestAccessor dest_acc)
void calcAlpha()
calculate only the alpha channel.
void stitch(const PanoramaOptions &opts, const UIntSet &imgSet, vigra::triple< ImgIter, ImgIter, ImgAccessor > pano, std::pair< AlphaIter, AlphaAccessor > alpha, SingleImageRemapper< ImageType, AlphaType > &remapper, BlendFunctor &blend)
vigra::NumericTraits< argument_type > Traits
vigra::ImageImportInfo::ICCProfile iccProfile
WeightedStitcher(const PanoramaData &pano, AppBase::ProgressDisplay *progress)
std::vector< vigra::Rect2D > m_rois
functor to create a remapped image, loads image from disk
void ConvertTo8Bit(ImageType &image)
converts to given image to fit into 0..255
std::vector< float_type > values
Stitcher< ImageType, AlphaType > Base
Stitcher< ImageType, AlphaType > Base
std::string tolower(const std::string &s)
convert a string to lowercase
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames)
virtual ~TiffMultiLayerRemapper()
double outputExposureValue