27 #ifndef _NONA_REMAPPEDPANOIMAGE_H
28 #define _NONA_REMAPPEDPANOIMAGE_H
30 #include <vigra/imageinfo.hxx>
31 #include <vigra/initimage.hxx>
32 #include <vigra/copyimage.hxx>
33 #include <vigra/flatmorphology.hxx>
46 #define NONA_DEFAULT_EXPOSURE_LOWER_CUTOFF 1/255.0f
47 #define NONA_DEFAULT_EXPOSURE_UPPER_CUTOFF 250/255.0f
60 template <
class TRANSFORM>
62 const PanoramaOptions & dest,
64 vigra::Rect2D & imgRect);
67 template <
class TRANSFORM>
69 const PanoramaOptions & dest,
71 vigra::Rect2D & imgRect,
72 vigra::BImage & alpha,
79 template <
class RemapImage,
class AlphaImage>
126 template<
class DistImgType>
140 template <
class ImgIter,
class ImgAccessor>
141 void remapImage(vigra::triple<ImgIter, ImgIter, ImgAccessor> srcImg,
147 template <
class ImgIter,
class ImgAccessor,
148 class AlphaIter,
class AlphaAccessor>
149 void remapImage(vigra::triple<ImgIter, ImgIter, ImgAccessor> srcImg,
150 std::pair<AlphaIter, AlphaAccessor> alphaImg,
171 template <
class SrcImgType,
class FlatImgType,
class DestImgType,
class MaskImgType>
173 const MaskImgType & srcAlpha,
174 const FlatImgType & srcFlat,
177 vigra::Rect2D outputRect,
198 #include <vigra/impex.hxx>
200 #define DEBUG_FILE_PREFIX "C:/temp/"
202 #define DEBUG_FILE_PREFIX "/tmp/"
207 namespace HuginBase {
211 template <
class RemapImage,
class AlphaImage>
219 if (m_destImg.remapUsingGPU) {
221 const int r = roi.width() % 8;
222 if (r != 0) roi.addSize(vigra::Size2D(8 - r, 0));
226 m_transf.createTransform(src, dest);
229 DEBUG_DEBUG(
"m_srcImg size: " << m_srcImg.getSize());
240 template <
class RemapImage,
class AlphaImage>
243 PanoCommand::Lens::LensProjectionFormat srcProj,
244 const PanoCommand::PanoImage & img,
245 const vigra::Diff2D &destSize,
250 m_srcOrigSize.x = img.getWidth();
251 m_srcOrigSize.y = img.getHeight();
252 m_srcProj = m_srcProj;
256 m_destProj = destProj;
257 m_destHFOV = destHFOV;
267 m_transf.createTransform(srcSize, srcVars, srcProj,
268 destSize, destProj, destHFOV,
271 ImageOptions imgOpts = img.getOptions();
274 bool circCrop = srcProj == Lens::CIRCULAR_FISHEYE;
276 imgOpts.docrop, imgOpts.cropRect, circCrop,
285 template <
class RemapImage,
class AlphaImage>
289 const PanoCommand::PanoImage & img = pano.
getImage(imgNr);
293 m_srcOrigSize.y = img.getHeight();
294 m_srcProj = pano.getLens(pano.
getImage(imgNr).getLensNr()).getProjection();
305 m_transf.createTransform(pano, imgNr, opts, m_srcSize);
308 m_srcPanoImg = pano.
getImage(imgNr);
309 ImageOptions imgOpts = pano.
getImage(imgNr).getOptions();
310 vigra::Rect2D imageRect;
312 bool circCrop = pano.getLens(pano.
getImage(imgNr).getLensNr()).getProjection() == Lens::CIRCULAR_FISHEYE;
314 imgOpts.docrop, imgOpts.cropRect, circCrop,
330 template<
class RemapImage,
class AlphaImage>
331 template<
class DistImgType>
334 if (Base::boundingBox().isEmpty())
return;
338 int xstart = Base::boundingBox().left();
339 int xend = Base::boundingBox().right();
340 int ystart = Base::boundingBox().top();
341 int yend = Base::boundingBox().bottom();
344 typename DistImgType::Iterator yImgX(imgX.upperLeft());
345 typename DistImgType::Iterator yImgY(imgY.upperLeft());
346 typename DistImgType::Accessor accX = imgX.accessor();
347 typename DistImgType::Accessor accY = imgY.accessor();
349 for(
int y=ystart; y < yend; ++y, ++yImgX.y, ++yImgY.y)
352 typename DistImgType::Iterator xImgX(yImgX);
353 typename DistImgType::Iterator xImgY(yImgY);
354 for(
int x=xstart; x < xend; ++x, ++xImgY.x, ++xImgX.x)
357 if (m_transf.transformImgCoord(sx, sy, x, y))
377 template<
class RemapImage,
class AlphaImage>
380 if (Base::boundingBox().isEmpty())
383 Base::m_mask.resize(Base::boundingBox().size());
385 int xstart = Base::boundingBox().left();
386 int xend = Base::boundingBox().right();
387 int ystart = Base::boundingBox().top();
388 int yend = Base::boundingBox().bottom();
391 #pragma omp parallel for schedule(dynamic, 10)
392 for(
int y=ystart; y < yend; ++y)
395 typename AlphaImage::Iterator yalpha(Base::m_mask.upperLeft());
396 yalpha.y += y - ystart;
398 typename AlphaImage::Iterator xalpha(yalpha);
399 for(
int x=xstart; x < xend; ++x, ++xalpha.x)
402 if(m_transf.transformImgCoord(sx,sy,x,y))
422 template <
class ImageType>
431 template<
class RemapImage,
class AlphaImage>
432 template<
class ImgIter,
class ImgAccessor>
442 const bool useGPU = m_destImg.remapUsingGPU;
444 if (Base::boundingBox().isEmpty())
447 vigra::Diff2D srcImgSize = srcImg.second - srcImg.first;
449 vigra::Size2D expectedSize = m_srcImg.getSize();
452 const int r = expectedSize.width() % 8;
453 if (r != 0) expectedSize += vigra::Diff2D(8 - r, 0);
456 DEBUG_DEBUG(
"srcImgSize: " << srcImgSize <<
" m_srcImgSize: " << m_srcImg.getSize());
457 vigra_precondition(srcImgSize == expectedSize,
458 "RemappedPanoImage<RemapImage,AlphaImage>::remapImage(): image unexpectedly changed dimensions.");
460 typedef typename ImgAccessor::value_type input_value_type;
470 std::vector<double> outLut;
471 if (!m_destImg.outputEMoRParams.empty())
476 if (!m_destImg.outputPixelType.empty()) {
480 invResponse.
setOutput(1.0/
pow(2.0,m_destImg.outputExposureValue), outLut,
481 maxVal, m_destImg.outputRangeCompression);
483 invResponse.
setHDROutput(
true,1.0/
pow(2.0,m_destImg.outputExposureValue));
490 vigra::BImage alpha(srcImgSize.x, srcImgSize.y);
492 switch (m_srcImg.getCropMode()) {
496 if (srcImgSize != m_srcImg.getSize()) {
500 initImage(alpha.upperLeft(),
501 alpha.upperLeft()+m_srcImg.getSize(),
502 alpha.accessor(),255);
513 vigra::Rect2D cR = m_srcImg.getCropRect();
515 (cR.top() + cR.height()/2.0) );
517 double radius =
std::min(cR.width(), cR.height())/2.0;
526 vigra::Rect2D cR = m_srcImg.getCropRect();
530 cR &= vigra::Rect2D(0,0, srcImgSize.x, srcImgSize.y);
532 initImage(alpha.upperLeft()+cR.upperLeft(),
533 alpha.upperLeft()+cR.lowerRight(),
534 alpha.accessor(),255);
540 if(m_srcImg.hasActiveMasks())
553 Base::boundingBox().upperLeft(),
556 m_srcImg.horizontalWarpNeeded(),
559 if (Base::boundingBox().right() > m_destImg.getROI().right())
563 vigra::Rect2D newBoundingBox = Base::boundingBox() & m_destImg.getROI();
566 Base::m_region = newBoundingBox;
573 Base::boundingBox().upperLeft(),
576 m_srcImg.horizontalWarpNeeded(),
583 if (srcImgSize != m_srcImg.getSize()) {
586 vigra::BImage alpha(srcImgSize.x, srcImgSize.y, vigra::UInt8(0));
587 initImage(alpha.upperLeft(),
588 alpha.upperLeft()+m_srcImg.getSize(),
589 alpha.accessor(),255);
594 Base::boundingBox().upperLeft(),
597 m_srcImg.horizontalWarpNeeded(),
606 Base::boundingBox().upperLeft(),
609 m_srcImg.horizontalWarpNeeded(),
613 if (Base::boundingBox().right() > m_destImg.getROI().right())
617 vigra::Rect2D newBoundingBox = Base::boundingBox() & m_destImg.getROI();
620 Base::m_region = newBoundingBox;
626 Base::boundingBox().upperLeft(),
629 m_srcImg.horizontalWarpNeeded(),
640 template<
class RemapImage,
class AlphaImage>
641 template<
class ImgIter,
class ImgAccessor,
642 class AlphaIter,
class AlphaAccessor>
644 std::pair<AlphaIter, AlphaAccessor> alphaImg,
648 const bool useGPU = m_destImg.remapUsingGPU;
650 if (Base::boundingBox().isEmpty())
655 vigra::Diff2D srcImgSize = srcImg.second - srcImg.first;
657 vigra::Size2D expectedSize = m_srcImg.getSize();
660 const int r = expectedSize.width() % 8;
661 if (r != 0) expectedSize += vigra::Diff2D(8 - r, 0);
663 vigra_precondition(srcImgSize == expectedSize,
664 "RemappedPanoImage<RemapImage,AlphaImage>::remapImage(): image unexpectedly changed dimensions.");
666 typedef typename ImgAccessor::value_type input_value_type;
675 std::vector<double> outLut;
678 if (!m_destImg.outputPixelType.empty()) {
681 if (!m_destImg.outputEMoRParams.empty())
686 invResponse.
setOutput(1.0/
pow(2.0,m_destImg.outputExposureValue), outLut,
687 maxVal, m_destImg.outputRangeCompression);
689 invResponse.
setHDROutput(
true,1.0/
pow(2.0,m_destImg.outputExposureValue));
693 vigra::BImage alpha(srcImgSize);
694 vigra::Rect2D cR = m_srcImg.getCropRect();
695 switch (m_srcImg.getCropMode()) {
700 alphaImg.first + srcImgSize, alphaImg.second),
708 alphaImg.first + srcImgSize, alphaImg.second),
711 (cR.top() + cR.height()/2.0) );
712 double radius =
std::min(cR.width(), cR.height())/2.0;
720 cR &= vigra::Rect2D(0,0, srcImgSize.x, srcImgSize.y);
727 alphaImg.first + cR.lowerRight(),
729 alpha.upperLeft() + cR.upperLeft(),alpha.accessor());
735 if(m_srcImg.hasActiveMasks())
748 Base::boundingBox().upperLeft(),
751 m_srcImg.horizontalWarpNeeded(),
754 if (Base::boundingBox().right() > m_destImg.getROI().right())
758 vigra::Rect2D newBoundingBox = Base::boundingBox() & m_destImg.getROI();
761 Base::m_region = newBoundingBox;
768 Base::boundingBox().upperLeft(),
771 m_srcImg.horizontalWarpNeeded(),
783 Base::boundingBox().upperLeft(),
786 m_srcImg.horizontalWarpNeeded(),
789 if (Base::boundingBox().right() > m_destImg.getROI().right())
793 vigra::Rect2D newBoundingBox = Base::boundingBox() & m_destImg.getROI();
796 Base::m_region = newBoundingBox;
803 Base::boundingBox().upperLeft(),
806 m_srcImg.horizontalWarpNeeded(),
821 template <
class SrcImgType,
class FlatImgType,
class DestImgType,
class MaskImgType>
823 const MaskImgType & srcAlpha,
824 const FlatImgType & srcFlat,
827 vigra::Rect2D outputROI,
834 vigra::ImageExportInfo exi( DEBUG_FILE_PREFIX
"hugin03_BeforeRemap.tif");
838 if (srcAlpha.width() > 0) {
839 vigra::ImageExportInfo exi(DEBUG_FILE_PREFIX
"hugin04_BeforeRemapAlpha.tif");
847 DEBUG_DEBUG(
"setting src image with size: " << src.getSize());
850 if (srcAlpha.size().x > 0) {
860 vigra::ImageExportInfo exi( DEBUG_FILE_PREFIX
"hugin04_AfterRemap.tif");
864 vigra::ImageExportInfo exi(DEBUG_FILE_PREFIX
"hugin04_AfterRemapAlpha.tif");
AlphaImage m_mask
corresponding alpha channel
PTools::Transform m_transf
PanoramaOptions::ProjectionFormat getProjection() const
double getMaxValForPixelType(const std::string &v)
RemappedPanoImage()
create a remapped pano image
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 ...
void applyMask(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > img, HuginBase::MaskPolygonVector masks)
AlphaImage::const_traverser const_mask_traverser
PanoramaOptions m_destImg
void transformImage(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
Transform an image into the panorama.
void setPanoImage(const SrcPanoImage &src, const PanoramaOptions &dest, vigra::Rect2D roi)
void remapImage(SrcImgType &srcImg, const MaskImgType &srcAlpha, const FlatImgType &srcFlat, const SrcPanoImage &src, const PanoramaOptions &dest, vigra::Rect2D outputRect, RemappedPanoImage< DestImgType, MaskImgType > &remapped, AppBase::ProgressDisplay *progress)
remap a single image
AdvancedOptions m_advancedOptions
unsigned int getHeight() const
get panorama height
void estimateImageRect(const SrcPanoImage &src, const PanoramaOptions &dest, TRANSFORM &transf, vigra::Rect2D &imgRect)
calculate the outline of the image
void enforceMonotonicity(LUT &lut)
enforce monotonicity of an array (mostly used for lookup tables)
declaration of classes to work with mask
vigra::pair< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImage(const ROIImage< Image, Mask > &img)
RemapImage::value_type image_value_type
void transformImageGPU(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress)
Transform an image into the panorama.
vigra_ext::ValueTypeTraits< image_value_type >::value_type component_type
void calcSrcCoordImgs(DistImgType &imgX, DistImgType &imgY)
calculate distance map.
vigra::FRGBImage ImageType
vigra_ext::Interpolator interpolator
float pow(float a, double b)
int getWidth() const
Get the width of the image in pixels.
void remapImage(vigra::triple< ImgIter, ImgIter, ImgAccessor > srcImg, vigra_ext::Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
remap a image without alpha channel
RemapImage m_image
remapped image
Helper class for storing different options.
vigra::ImageImportInfo::ICCProfile m_ICCProfile
void applyExposureClipMask(vigra::triple< ImgIter, ImgIter, ImgAccessor > image, vigra::triple< AlphaIter, AlphaIter, AlphaAccessor > mask, double lowerLimit, double upperLimit)
void setMessage(const std::string &message, const std::string &filename="")
sets the message to given string
vigra::pair< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImage(ROIImage< Image, Alpha > &img)
AlphaImage::ConstAccessor ConstMaskAccessor
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
vigra_ext::ROIImage< RemapImage, AlphaImage > Base
void createEMoRLUT(const std::vector< float > ¶ms, VECTOR &lut)
std::map< std::string, Variable > VariableMap
RemapImage::const_traverser const_image_traverser
AlphaImage::Accessor MaskAccessor
unsigned int getWidth() const
void transformImageAlpha(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, std::pair< SrcAlphaIterator, SrcAlphaAccessor > srcAlpha, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
Transform image, and respect a possible alpha channel.
AlphaImage::traverser mask_traverser
AlphaImage::value_type mask_value_type
ImageType CopyImageNewSize(const ImageType &image, const vigra::Size2D &newSize)
copies image into new image with changed size
void estimateImageAlpha(const SrcPanoImage &src, const PanoramaOptions &dest, TRANSFORM &transf, vigra::Rect2D &imgRect, vigra::BImage &alpha, double &scale)
std::map< std::string, std::string > AdvancedOptions
RemapImage::ConstAccessor ConstImageAccessor
void resize(double x_dest, double y_dest, double *x_src, double *y_src, const _FuncParams ¶ms)
vigra::triple< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImageRange(ROIImage< Image, Alpha > &img)
void copyImage(SrcImageIterator src_upperleft, SrcImageIterator src_lowerright, SrcAccessor src_acc, DestImageIterator dest_upperleft, DestAccessor dest_acc)
#define NONA_DEFAULT_EXPOSURE_LOWER_CUTOFF
void calcAlpha()
calculate only the alpha channel.
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
void setAdvancedOptions(const AdvancedOptions &advancedOptions)
T1::value_type value_type
ProjectionFormat
Projection of final panorama.
RemapImage::Accessor ImageAccessor
Interpolator
enum with all interpolation methods
All variables of a source image.
struct to hold a image state for stitching
void transformImageAlphaGPU(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, std::pair< SrcAlphaIterator, SrcAlphaAccessor > srcAlpha, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress)
Transform image, and respect a possible alpha channel.
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames)
#define NONA_DEFAULT_EXPOSURE_UPPER_CUTOFF
RemapImage::traverser image_traverser
void circularCrop(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > img, hugin_utils::FDiff2D middle, double radius)
Apply a circular crop to img.