00001
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
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
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
00068 vigra::BasicImage<typename MaskIter::value_type> blendPanoMask(size);
00069 vigra::BasicImage<typename MaskIter::value_type> blendImageMask(size);
00070
00071
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
00080 vigra::exportImage(srcImageRange(blendImageMask), vigra::ImageExportInfo("blendImageMask.tif"));
00081 vigra::exportImage(srcImageRange(blendPanoMask), vigra::ImageExportInfo("blendPanoMask.tif"));
00082
00083 #endif
00084
00085 vigra::copyImageIf(image, vigra::maskImage(blendImageMask), pano);
00086
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
00113
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
00122
00123
00124 vigra::Point2D overlapUL(INT_MAX, INT_MAX);
00125 vigra::Point2D overlapLR(0,0);
00126 AlphaIter alphaIter = alpha.first + overlap.upperLeft();
00127
00128
00129
00130
00131
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
00137 if (img.getMask(x,y) > 0 && alpha.second(alpha.first,vigra::Diff2D(x,y)) > 0) {
00138
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
00148
00149 vigra::Rect2D realOverlap(overlapUL, overlapLR + vigra::Point2D(1,1));
00150
00151
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
00159
00160
00161 vigra::Rect2D border(img.boundingBox().left(),
00162 img.boundingBox().top(),
00163 img.boundingBox().right(),
00164 realOverlap.top());
00165
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
00170 vigra::copyImageIf(applyRect(border, vigra_ext::srcMaskRange(img)),
00171 applyRect(border, vigra_ext::srcMask(img)),
00172 applyRect(border, alpha));
00173
00174
00175 border.setUpperLeft(vigra::Point2D(img.boundingBox().left(),
00176 realOverlap.top()));
00177 border.setLowerRight(vigra::Point2D(realOverlap.left(),
00178 realOverlap.bottom()));
00179
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
00184 vigra::copyImageIf(applyRect(border, vigra_ext::srcMaskRange(img)),
00185 applyRect(border, vigra_ext::srcMask(img)),
00186 applyRect(border, alpha));
00187
00188
00189 border.setUpperLeft(vigra::Point2D(realOverlap.right(),
00190 realOverlap.top()));
00191 border.setLowerRight(vigra::Point2D(img.boundingBox().right(),
00192 realOverlap.bottom()));
00193
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
00198 vigra::copyImageIf(applyRect(border, vigra_ext::srcMaskRange(img)),
00199 applyRect(border, vigra_ext::srcMask(img)),
00200 applyRect(border, alpha));
00201
00202
00203 border.setUpperLeft(vigra::Point2D(img.boundingBox().left(),
00204 realOverlap.bottom()));
00205 border.setLowerRight(vigra::Point2D(img.boundingBox().right(),
00206 img.boundingBox().bottom()));
00207
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
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
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
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
00228
00229
00230
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
00236 vigra::copyImage(applyRect(img.boundingBox(), vigra_ext::srcMaskRange(img)),
00237 applyRect(img.boundingBox(), alpha));
00238
00239 }
00240 }
00241
00242
00243 }
00244
00245
00246 #endif // _H