blend.h

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00024 #ifndef _VIGRA_EXT_BLEND_H
00025 #define _VIGRA_EXT_BLEND_H
00026 
00027 #include <vigra/impex.hxx>
00028 #include <hugin_utils/utils.h>
00029 #include <appbase/ProgressDisplayOld.h>
00030 
00031 #include <vigra_ext/utils.h>
00032 #include <vigra_ext/NearestFeatureTransform.h>
00033 #include <vigra_ext/ROIImage.h>
00034 
00035 
00036 //#define DEBUG_MASKIMG
00037 
00038 
00039 namespace vigra_ext
00040 {
00041 
00042 
00046 template <typename ImgIter, typename ImgAccessor,
00047           typename ImgMaskIter, typename ImgMaskAccessor,
00048           typename PanoIter, typename PanoAccessor,
00049           typename MaskIter, typename MaskAccessor>
00050 void blendOverlap(vigra::triple<ImgIter, ImgIter, ImgAccessor> image,
00051                   std::pair<ImgMaskIter, ImgMaskAccessor> imageMask,
00052                   std::pair<PanoIter, PanoAccessor> pano,
00053                   std::pair<MaskIter, MaskAccessor> panoMask,
00054                   AppBase::MultiProgressDisplay & progress)
00055 {
00056     vigra::Diff2D size = image.second - image.first;
00057 
00058 #ifdef DEBUG_MASKIMG
00059     // save the masks
00060     vigra::exportImage(srcIterRange(imageMask.first, imageMask.first + size),
00061                 vigra::ImageExportInfo("blendImageMask_before.tif"));
00062     vigra::exportImage(srcIterRange(panoMask.first, panoMask.first + size),
00063                 vigra::ImageExportInfo("blendPanoMask_before.tif"));
00064         
00065 #endif
00066 
00067     // create new blending masks
00068     vigra::BasicImage<typename MaskIter::value_type> blendPanoMask(size);
00069     vigra::BasicImage<typename MaskIter::value_type> blendImageMask(size);
00070 
00071     // calculate the stitching masks.
00072     vigra_ext::nearestFeatureTransform(srcIterRange(panoMask.first, panoMask.first + size),
00073                                        imageMask,
00074                                        destImage(blendPanoMask),
00075                                        destImage(blendImageMask),
00076                                        progress);
00077 
00078 #ifdef DEBUG_MASKIMG
00079      // save the masks
00080      vigra::exportImage(srcImageRange(blendImageMask), vigra::ImageExportInfo("blendImageMask.tif"));
00081      vigra::exportImage(srcImageRange(blendPanoMask), vigra::ImageExportInfo("blendPanoMask.tif"));
00082         
00083 #endif
00084      // copy the image into the panorama
00085      vigra::copyImageIf(image, vigra::maskImage(blendImageMask), pano);
00086      // copy mask
00087      vigra::copyImageIf(vigra::srcImageRange(blendImageMask), vigra::maskImage(blendImageMask), panoMask);
00088 }
00089 
00102 template <typename ImageType, typename AlphaImageType,
00103           typename PanoIter, typename PanoAccessor,
00104           typename AlphaIter, typename AlphaAccessor>
00105 void blend(vigra_ext::ROIImage<ImageType, AlphaImageType> & img,
00106            vigra::triple<PanoIter, PanoIter, PanoAccessor> pano,
00107            std::pair<AlphaIter, AlphaAccessor> alpha,
00108            vigra::Rect2D & panoROI,
00109            AppBase::MultiProgressDisplay & progress)
00110 {
00111     typedef typename AlphaIter::value_type AlphaValue;
00112     // calculate the overlap by intersecting the two image
00113     // rectangles.
00114     DEBUG_DEBUG("image bounding Box: " << img.boundingBox());
00115     DEBUG_DEBUG("pano size: " << pano.second - pano.first);
00116     DEBUG_DEBUG("pano roi: " << panoROI);
00117     vigra::Rect2D overlap = img.boundingBox() & panoROI;
00118     DEBUG_DEBUG("overlap: " << overlap);
00119 
00120     if (!overlap.isEmpty()) {
00121         // image ROI's overlap.. calculate real overlapping area.
00122 
00123         // corner points of overlapping area.
00124         vigra::Point2D overlapUL(INT_MAX, INT_MAX);
00125         vigra::Point2D overlapLR(0,0);
00126         AlphaIter alphaIter = alpha.first + overlap.upperLeft();
00127 //      typename AlphaImageType::traverser imgAlphaIter = img.maskUpperLeft()
00128 //                                                      + overlap.upperLeft();
00129 // DGSW FIXME - Unreferenced
00130 //      typename AlphaImageType::Accessor imgAlphaAcc = img.maskAccessor();
00131         // find real, overlapping ROI, by iterating over ROI
00132         for (int y=overlap.top(); y < overlap.bottom(); y++, ++(alphaIter.y))
00133         {
00134             for (int x=overlap.left(); x < overlap.right(); x++,
00135                   ++(alphaIter.x)) {
00136                 // check if images overlap
00137                 if (img.getMask(x,y) > 0 && alpha.second(alpha.first,vigra::Diff2D(x,y)) > 0) {
00138                     // overlap, use it to calculate bounding box
00139                     if (overlapUL.x > x) overlapUL.x = x;
00140                     if (overlapUL.y > y) overlapUL.y = y;
00141                     if (overlapLR.x < x) overlapLR.x = x;
00142                     if (overlapLR.y < y) overlapLR.y = y;
00143                 }
00144             }
00145         }
00146         if (overlapUL.x != INT_MAX) {
00147             // the real overlap. we could have copied the image here, but
00148             // we leave that to the real blending routine.
00149             vigra::Rect2D realOverlap(overlapUL, overlapLR + vigra::Point2D(1,1));
00150 
00151             // images overlap, call real blending routine
00152             blendOverlap(applyRect(realOverlap, vigra_ext::srcImageRange(img)),
00153                          applyRect(realOverlap, vigra_ext::srcMask(img)),
00154                          applyRect(realOverlap, std::make_pair(pano.first, pano.third)),
00155                          applyRect(realOverlap, alpha),
00156                          progress);
00157 
00158             // now, copy the non-overlapping parts
00159 
00160             // upper stripe
00161             vigra::Rect2D border(img.boundingBox().left(),
00162                                  img.boundingBox().top(),
00163                                  img.boundingBox().right(),
00164                                  realOverlap.top());
00165             // copy image
00166             vigra::copyImageIf(applyRect(border, vigra_ext::srcImageRange(img)),
00167                                applyRect(border, vigra_ext::srcMask(img)),
00168                                applyRect(border, std::make_pair(pano.first,pano.third)));
00169             // copy mask
00170             vigra::copyImageIf(applyRect(border, vigra_ext::srcMaskRange(img)),
00171                                applyRect(border, vigra_ext::srcMask(img)),
00172                                applyRect(border, alpha));
00173 
00174             // left stripe
00175             border.setUpperLeft(vigra::Point2D(img.boundingBox().left(),
00176                                                realOverlap.top()));
00177             border.setLowerRight(vigra::Point2D(realOverlap.left(),
00178                                                 realOverlap.bottom()));
00179             // copy image
00180             vigra::copyImageIf(applyRect(border, vigra_ext::srcImageRange(img)),
00181                                applyRect(border, vigra_ext::srcMask(img)),
00182                                applyRect(border, std::make_pair(pano.first,pano.third)));
00183             // copy mask
00184             vigra::copyImageIf(applyRect(border, vigra_ext::srcMaskRange(img)),
00185                                applyRect(border, vigra_ext::srcMask(img)),
00186                                applyRect(border, alpha));
00187 
00188             // right stripe
00189             border.setUpperLeft(vigra::Point2D(realOverlap.right(),
00190                                 realOverlap.top()));
00191             border.setLowerRight(vigra::Point2D(img.boundingBox().right(),
00192                                  realOverlap.bottom()));
00193             // copy image
00194             vigra::copyImageIf(applyRect(border, vigra_ext::srcImageRange(img)),
00195                                applyRect(border, vigra_ext::srcMask(img)),
00196                                applyRect(border, std::make_pair(pano.first,pano.third)));
00197             // copy mask
00198             vigra::copyImageIf(applyRect(border, vigra_ext::srcMaskRange(img)),
00199                                applyRect(border, vigra_ext::srcMask(img)),
00200                                applyRect(border, alpha));
00201 
00202             // lower stripe
00203             border.setUpperLeft(vigra::Point2D(img.boundingBox().left(),
00204                                                realOverlap.bottom()));
00205             border.setLowerRight(vigra::Point2D(img.boundingBox().right(),
00206                                                 img.boundingBox().bottom()));
00207             // copy image
00208             vigra::copyImageIf(applyRect(border, vigra_ext::srcImageRange(img)),
00209                                applyRect(border, vigra_ext::srcMask(img)),
00210                                applyRect(border, std::make_pair(pano.first,pano.third)));
00211             // copy mask
00212             vigra::copyImageIf(applyRect(border, vigra_ext::srcMaskRange(img)),
00213                                applyRect(border, vigra_ext::srcMask(img)),
00214                                applyRect(border, alpha));
00215         } else {
00216             DEBUG_DEBUG("ROI's overlap, but no overlapping pixels found");
00217             // copy image
00218             vigra::copyImageIf(applyRect(img.boundingBox(), vigra_ext::srcImageRange(img)),
00219                                applyRect(img.boundingBox(), vigra_ext::srcMask(img)),
00220                                applyRect(img.boundingBox(), std::make_pair(pano.first,pano.third)));
00221             // copy mask
00222             vigra::copyImageIf(applyRect(img.boundingBox(), vigra_ext::srcMaskRange(img)),
00223                                applyRect(img.boundingBox(), vigra_ext::srcMask(img)),
00224                                applyRect(img.boundingBox(), alpha));
00225         }
00226     } else {
00227         // image ROI's do not overlap, no blending, just copy
00228         // alpha channel is not considered, because the whole target
00229         // is free.
00230         // copy image
00231         DEBUG_DEBUG("image rect: " <<img.boundingBox());
00232         DEBUG_DEBUG("panorama size: " << pano.second - pano.first); 
00233         vigra::copyImage(applyRect(img.boundingBox(), vigra_ext::srcImageRange(img)),
00234                          applyRect(img.boundingBox(), std::make_pair(pano.first,pano.third)));
00235         // copy mask
00236         vigra::copyImage(applyRect(img.boundingBox(), vigra_ext::srcMaskRange(img)),
00237                          applyRect(img.boundingBox(), alpha));
00238 
00239     }
00240 }
00241 
00242 
00243 } // namespace
00244 
00245 
00246 #endif // _H

Generated on 5 Dec 2014 for Hugintrunk by  doxygen 1.4.7