Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages
hugin_base/vigra_ext/ROIImage.h
Go to the documentation of this file.00001 // -*- c-basic-offset: 4 -*- 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 // typedefs for own types 00089 00090 00091 public: 00092 // typedefs for the children types 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 // get maximum roi 00416 vigra::Rect2D maxRoi= rois[0]; 00417 for (unsigned i=1; i < nImg; i++) { 00418 maxRoi |= rois[i]; 00419 } 00420 // skip empty area on the top and right 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 // iterate over the whole image... 00485 // calculate something on the pixels in the overlapping images. 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
1.3.9.1