00001
00024 #ifndef _ROIIMAGE_H
00025 #define _ROIIMAGE_H
00026
00027 #include <hugin_utils/utils.h>
00028 #include <vigra/imageinfo.hxx>
00029
00030 #include "lut.h"
00031
00032 namespace vigra_ext
00033 {
00034
00035
00044 template <class ImgIter, class ImgAcc>
00045 vigra::triple<ImgIter, ImgIter, ImgAcc>
00046 applyRect(vigra::Rect2D & r, vigra::triple<ImgIter, ImgIter, ImgAcc> img)
00047 {
00048 #ifdef DEBUG
00049 vigra::Diff2D t = img.second - (img.first + r.lowerRight());
00050 DEBUG_ASSERT(t.x >= 0);
00051 DEBUG_ASSERT(t.y >= 0);
00052 #endif
00053 return vigra::triple<ImgIter, ImgIter, ImgAcc>
00054 (img.first + r.upperLeft(),
00055 img.first + r.lowerRight(),
00056 img.third);
00057 }
00058
00064 template <class ImgIter, class ImgAcc>
00065 vigra::pair<ImgIter, ImgAcc>
00066 applyRect(vigra::Rect2D & r, vigra::pair<ImgIter, ImgAcc> img)
00067 {
00068 return vigra::pair<ImgIter, ImgAcc>
00069 (img.first + r.upperLeft(),
00070 img.second);
00071 }
00072
00073
00074
00084 template <class Image, class Mask>
00085 class ROIImage
00086 {
00087
00088
00089
00090
00091 public:
00092
00093 typedef typename Image::value_type image_value_type;
00094 typedef typename Image::traverser image_traverser;
00095 typedef typename Image::const_traverser image_const_traverser;
00096 typedef typename Image::Accessor ImageAccessor;
00097 typedef typename Image::ConstAccessor ImageConstAccessor;
00098
00099 typedef typename Mask::value_type mask_value_type;
00100 typedef typename Mask::traverser mask_traverser;
00101 typedef typename Mask::const_traverser mask_const_traverser;
00102 typedef typename Mask::Accessor MaskAccessor;
00103 typedef typename Mask::ConstAccessor MaskConstAccessor;
00104
00107 ROIImage()
00108 {}
00109
00112 virtual ~ROIImage()
00113 {}
00114
00119 void resize(const vigra::Rect2D & rect)
00120 {
00121 m_region = rect;
00122 if (!m_region.isEmpty()) {
00123 m_image.resize(m_region.size());
00124 m_mask.resize(m_region.size());
00125 } else {
00126 m_image.resize(vigra::Size2D(1,1));
00127 m_mask.resize(vigra::Size2D(1,1));
00128 }
00129 }
00130
00137 image_traverser
00138 upperLeft()
00139 {
00140 DEBUG_DEBUG(m_region);
00141 DEBUG_ASSERT(m_image.size().x > 0);
00142 DEBUG_ASSERT(m_image.size().y > 0);
00143 return m_image.upperLeft() - m_region.upperLeft();
00144 }
00145
00146 image_const_traverser
00147 upperLeft() const
00148 {
00149 DEBUG_DEBUG(m_region);
00150 DEBUG_ASSERT(m_image.size().x > 0);
00151 DEBUG_ASSERT(m_image.size().y > 0);
00152 return m_image.upperLeft() - m_region.upperLeft();
00153 }
00154
00155 image_traverser
00156 lowerRight()
00157 {
00158 DEBUG_DEBUG(m_region);
00159 DEBUG_ASSERT(m_image.size().x > 0);
00160 DEBUG_ASSERT(m_image.size().y > 0);
00161 return m_image.upperLeft() + m_region.size();
00162 }
00163
00164 image_const_traverser
00165 lowerRight() const
00166 {
00167 DEBUG_DEBUG(m_region);
00168 DEBUG_ASSERT(m_image.size().x > 0);
00169 DEBUG_ASSERT(m_image.size().y > 0);
00170 return m_image.upperLeft() + m_region.size();
00171 }
00172
00174 ImageAccessor accessor()
00175 {
00176 return m_image.accessor();
00177 }
00178
00179 ImageConstAccessor accessor() const
00180 {
00181 const ROIImage<Image,Mask> & t = *this;
00182 return t.m_image.accessor();
00183 }
00184
00191 mask_traverser
00192 maskUpperLeft()
00193 {
00194 DEBUG_DEBUG(m_region);
00195 DEBUG_ASSERT(m_mask.size().x > 0);
00196 DEBUG_ASSERT(m_mask.size().y > 0);
00197 return m_mask.upperLeft() - m_region.upperLeft();
00198 }
00199
00200 mask_const_traverser
00201 maskUpperLeft() const
00202 {
00203 DEBUG_DEBUG(m_region);
00204 DEBUG_ASSERT(m_mask.size().x > 0);
00205 DEBUG_ASSERT(m_mask.size().y > 0);
00206 return m_mask.upperLeft() - m_region.upperLeft();
00207 }
00208
00209 mask_traverser
00210 maskLowerRight()
00211 {
00212 DEBUG_DEBUG(m_region);
00213 DEBUG_ASSERT(m_mask.size().x > 0);
00214 DEBUG_ASSERT(m_mask.size().y > 0);
00215 return m_mask.upperLeft() + m_region.size();
00216 }
00217
00218 mask_const_traverser
00219 maskLowerRight() const
00220 {
00221 DEBUG_DEBUG(m_region);
00222 DEBUG_ASSERT(m_mask.size().x > 0);
00223 DEBUG_ASSERT(m_mask.size().y > 0);
00224 return m_mask.upperLeft() + m_region.size();
00225 }
00226
00228 MaskAccessor maskAccessor()
00229 {
00230 return m_mask.accessor();
00231 }
00232
00233 MaskConstAccessor maskAccessor() const
00234 {
00235 return m_mask.accessor();
00236 }
00237
00238 vigra::Rect2D & boundingBox()
00239 {
00240 return m_region;
00241 }
00242
00243 image_value_type operator()(int x, int y)
00244 {
00245 return operator[](vigra::Diff2D(x,y));
00246 }
00247
00248 image_value_type operator[](vigra::Diff2D const & pos)
00249 {
00250 if (m_region.contains(vigra::Point2D(pos))) {
00251 return m_image[pos - m_region.upperLeft()];
00252 } else {
00253 return vigra::NumericTraits<image_value_type>::zero();
00254 }
00255 }
00256
00257
00258 mask_value_type getMask(int x, int y)
00259 {
00260 return getMask(vigra::Diff2D(x,y));
00261 }
00262
00263 mask_value_type getMask(const vigra::Diff2D & pos)
00264 {
00265 if (m_region.contains(vigra::Point2D(pos))) {
00266 return m_mask[pos - m_region.upperLeft()];
00267 } else {
00268 return vigra::NumericTraits<mask_value_type>::zero();
00269 }
00270 }
00271
00272
00273 Image m_image;
00274 Mask m_mask;
00275
00276 protected:
00277 vigra::Rect2D m_region;
00278 };
00279
00280
00283 template<typename Image, typename Mask>
00284 inline vigra::triple<typename ROIImage<Image, Mask>::image_const_traverser,
00285 typename ROIImage<Image, Mask>::image_const_traverser,
00286 typename ROIImage<Image, Mask>::ImageConstAccessor>
00287 srcImageRange(const ROIImage<Image,Mask> & img)
00288 {
00289 return vigra::triple<typename ROIImage<Image,Mask>::image_const_traverser,
00290 typename ROIImage<Image,Mask>::image_const_traverser,
00291 typename ROIImage<Image,Mask>::ImageConstAccessor>(img.upperLeft(),
00292 img.lowerRight(),
00293 img.accessor());
00294 }
00295
00296
00297 template<typename Image, typename Mask>
00298 inline vigra::pair<typename ROIImage<Image, Mask>::image_const_traverser,
00299 typename ROIImage<Image, Mask>::ImageConstAccessor>
00300 srcImage(const ROIImage<Image,Mask> & img)
00301 {
00302 return vigra::pair<typename ROIImage<Image,Mask>::image_const_traverser,
00303 typename ROIImage<Image,Mask>::ImageConstAccessor>(img.upperLeft(),
00304 img.accessor());
00305 }
00306
00307
00308 template <class Image, class Alpha>
00309 inline vigra::triple<typename ROIImage<Image,Alpha>::image_traverser,
00310 typename ROIImage<Image,Alpha>::image_traverser,
00311 typename ROIImage<Image,Alpha>::ImageAccessor>
00312 destImageRange(ROIImage<Image,Alpha> & img)
00313 {
00314 return vigra::triple<typename ROIImage<Image,Alpha>::image_traverser,
00315 typename ROIImage<Image,Alpha>::image_traverser,
00316 typename ROIImage<Image,Alpha>::ImageAccessor>(img.upperLeft(),
00317 img.lowerRight(),
00318 img.accessor());
00319 }
00320
00321 template <class Image, class Alpha>
00322 inline vigra::pair<typename ROIImage<Image,Alpha>::image_traverser,
00323 typename ROIImage<Image,Alpha>::ImageAccessor>
00324 destImage(ROIImage<Image,Alpha> & img)
00325 {
00326 return vigra::pair<typename ROIImage<Image,Alpha>::image_traverser,
00327 typename ROIImage<Image,Alpha>::ImageAccessor>(img.upperLeft(),
00328 img.accessor());
00329 }
00330
00331 template <class Image, class Alpha>
00332 inline vigra::triple<typename ROIImage<Image,Alpha>::mask_const_traverser,
00333 typename ROIImage<Image,Alpha>::mask_const_traverser,
00334 typename ROIImage<Image,Alpha>::MaskConstAccessor>
00335 srcMaskRange(const ROIImage<Image,Alpha> & img)
00336 {
00337 return vigra::triple<typename ROIImage<Image,Alpha>::mask_const_traverser,
00338 typename ROIImage<Image,Alpha>::mask_const_traverser,
00339 typename ROIImage<Image,Alpha>::MaskConstAccessor>(img.maskUpperLeft(),
00340 img.maskLowerRight(),
00341 img.maskAccessor());
00342 }
00343
00344 template <class Image, class Alpha>
00345 inline vigra::pair<typename ROIImage<Image,Alpha>::mask_const_traverser,
00346 typename ROIImage<Image,Alpha>::MaskConstAccessor>
00347 srcMask(const ROIImage<Image,Alpha> & img)
00348 {
00349 return vigra::pair<typename ROIImage<Image,Alpha>::mask_const_traverser,
00350 typename ROIImage<Image,Alpha>::MaskConstAccessor>(img.maskUpperLeft(),
00351 img.maskAccessor());
00352 }
00353
00354 template <class Image, class Alpha>
00355 inline vigra::triple<typename ROIImage<Image,Alpha>::mask_traverser,
00356 typename ROIImage<Image,Alpha>::mask_traverser,
00357 typename ROIImage<Image,Alpha>::MaskAccessor>
00358 destMaskRange(ROIImage<Image,Alpha> & img)
00359 {
00360 return vigra::triple<typename ROIImage<Image,Alpha>::mask_traverser,
00361 typename ROIImage<Image,Alpha>::mask_traverser,
00362 typename ROIImage<Image,Alpha>::MaskAccessor>(img.maskUpperLeft(),
00363 img.maskLowerRight(),
00364 img.maskAccessor());
00365 }
00366
00367 template <class Image, class Alpha>
00368 inline vigra::pair<typename ROIImage<Image,Alpha>::mask_traverser,
00369 typename ROIImage<Image,Alpha>::MaskAccessor>
00370 destMask(ROIImage<Image,Alpha> & img)
00371 {
00372 return vigra::pair<typename ROIImage<Image,Alpha>::mask_traverser,
00373 typename ROIImage<Image,Alpha>::MaskAccessor>(img.maskUpperLeft(),
00374 img.maskAccessor());
00375 }
00376
00377 #if 0
00378 template <class Image, class Mask, class Functor>
00379 void inspectROIImages(std::vector<ROIImage<Image,Mask> *> imgs, Functor & f)
00380 {
00381 int nImg = imgs.size();
00382 std::vector<typename Image::traverser> imgUL(nImg);
00383 std::vector<typename Mask::traverser> maskUL(nImg);
00384 std::vector<vigra::Rect2D> rois(nImg);
00385 for (unsigned i=0; i < nImg; i++) {
00386 imgs[i] = imgs->upperLeft();
00387 masks[i] = imgs->maskUpperLeft();
00388 rois[i] = imgs->boundingBox();
00389 }
00390 }
00391 #endif
00392
00398 template <class ImgIter, class ImgAcc, class MaskIter, class MaskAcc, class Functor>
00399 void inspectImagesIf(std::vector<ImgIter> imgs,
00400 std::vector<MaskIter> masks,
00401 std::vector<vigra::Rect2D> rois,
00402 Functor & f)
00403 {
00404
00405 typedef typename ImgIter::value_type PixelType;
00406 typedef typename MaskIter::value_type MaskType;
00407
00408 typedef typename ImgIter::row_iterator RowImgIter;
00409 typedef typename MaskIter::row_iterator RowMaskIter;
00410
00411 int nImg = imgs.size();
00412
00413 vigra_precondition(nImg > 1, "more than one image needed");
00414
00415
00416 vigra::Rect2D maxRoi= rois[0];
00417 for (unsigned i=1; i < nImg; i++) {
00418 maxRoi |= rois[i];
00419 }
00420
00421 for (int k=0; k < nImg; k++) {
00422 imgs[k].first.x += maxRoi.left();
00423 imgs[k].first.y += maxRoi.top();
00424 masks[k].first.x += maxRoi.left();
00425 masks[k].first.y += maxRoi.top();
00426 }
00427
00428 std::vector<RowImgIter> rowImgIter(nImg);
00429 std::vector<RowMaskIter> rowMaskIter(nImg);
00430
00431 vigra::Point2D p;
00432 std::vector<PixelType> val(nImg);
00433 std::vector<MaskType> mval(nImg);
00434 for(p.y=maxRoi.top(); p.y < maxRoi.bottom(); ++p.y)
00435 {
00436 for (int k=0; k < nImg; k++) {
00437 rowImgIter[k] = imgs[k].first.rowIterator();
00438 rowMaskIter[k] = masks[k].first.rowIterator();
00439 }
00440
00441 for (p.x=maxRoi.left(); p.x < maxRoi.right(); ++p.x) {
00442 for (int k=0; k < nImg; k++) {
00443 if (rois[k].contains(p)) {
00444 val[k] = *(rowImgIter[k]);
00445 mval[k] = *(rowMaskIter[k]);
00446 } else {
00447 mval[k] = 0;
00448 }
00449 rowImgIter[k]++;
00450 rowMaskIter[k]++;
00451 }
00452 f(val,mval);
00453 }
00454 for (int k=0; k < nImg; k++) {
00455 ++(imgs[k].first.y);
00456 ++(masks[k].first.y);
00457 }
00458 }
00459 }
00460
00461
00463 template<class ROIIMG, class DestIter, class DestAccessor,
00464 class MaskIter, class MaskAccessor, class FUNCTOR>
00465 void reduceROIImages(std::vector<ROIIMG *> images,
00466 vigra::triple<DestIter, DestIter, DestAccessor> dest,
00467 vigra::pair<MaskIter, MaskAccessor> destMask,
00468 FUNCTOR & reduce)
00469 {
00470 typedef typename DestAccessor::value_type ImgType;
00471 typedef typename MaskAccessor::value_type MaskType;
00472
00473 typedef typename
00474 vigra::NumericTraits<ImgType> Traits;
00475 typedef typename
00476 Traits::RealPromote RealImgType;
00477
00478 typedef typename vigra_ext::LUTTraits<MaskType> MaskLUTTraits;
00479
00480 unsigned int nImg = images.size();
00481
00482 vigra::Diff2D size = dest.second - dest.first;
00483
00484
00485
00486 for (int y=0; y < size.y; y++) {
00487 for (int x=0; x < size.x; x++) {
00488 reduce.reset();
00489 MaskType maskRes=0;
00490 for (unsigned int i=0; i< nImg; i++) {
00491 MaskType a;
00492 a = images[i]->getMask(x,y);
00493 if (a) {
00494 maskRes = vigra_ext::LUTTraits<MaskType>::max();
00495 reduce(images[i]->operator()(x,y), a);
00496 }
00497 }
00498 dest.third.set(reduce(), dest.first, vigra::Diff2D(x,y));
00499 destMask.second.set(maskRes, destMask.first, vigra::Diff2D(x,y));
00500 }
00501 }
00502 }
00503
00504
00505 }
00506
00507 #endif // _ROIIMAGE_H