[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 1998-2010 by Ullrich Koethe, Hans Meine */ 00004 /* */ 00005 /* This file is part of the VIGRA computer vision library. */ 00006 /* The VIGRA Website is */ 00007 /* http://hci.iwr.uni-heidelberg.de/vigra/ */ 00008 /* Please direct questions, bug reports, and contributions to */ 00009 /* ullrich.koethe@iwr.uni-heidelberg.de or */ 00010 /* vigra@informatik.uni-hamburg.de */ 00011 /* */ 00012 /* Permission is hereby granted, free of charge, to any person */ 00013 /* obtaining a copy of this software and associated documentation */ 00014 /* files (the "Software"), to deal in the Software without */ 00015 /* restriction, including without limitation the rights to use, */ 00016 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00017 /* sell copies of the Software, and to permit persons to whom the */ 00018 /* Software is furnished to do so, subject to the following */ 00019 /* conditions: */ 00020 /* */ 00021 /* The above copyright notice and this permission notice shall be */ 00022 /* included in all copies or substantial portions of the */ 00023 /* Software. */ 00024 /* */ 00025 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00026 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00027 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00028 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00029 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00030 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00031 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00032 /* OTHER DEALINGS IN THE SOFTWARE. */ 00033 /* */ 00034 /************************************************************************/ 00035 00036 #ifndef VIGRA_SEEDEDREGIONGROWING_HXX 00037 #define VIGRA_SEEDEDREGIONGROWING_HXX 00038 00039 #include <vector> 00040 #include <stack> 00041 #include <queue> 00042 #include "utilities.hxx" 00043 #include "stdimage.hxx" 00044 #include "stdimagefunctions.hxx" 00045 #include "pixelneighborhood.hxx" 00046 00047 namespace vigra { 00048 00049 namespace detail { 00050 00051 template <class COST> 00052 class SeedRgPixel 00053 { 00054 public: 00055 Point2D location_, nearest_; 00056 COST cost_; 00057 int count_; 00058 int label_; 00059 int dist_; 00060 00061 SeedRgPixel() 00062 : location_(0,0), nearest_(0,0), cost_(0), count_(0), label_(0) 00063 {} 00064 00065 SeedRgPixel(Point2D const & location, Point2D const & nearest, 00066 COST const & cost, int const & count, int const & label) 00067 : location_(location), nearest_(nearest), 00068 cost_(cost), count_(count), label_(label) 00069 { 00070 int dx = location_.x - nearest_.x; 00071 int dy = location_.y - nearest_.y; 00072 dist_ = dx * dx + dy * dy; 00073 } 00074 00075 void set(Point2D const & location, Point2D const & nearest, 00076 COST const & cost, int const & count, int const & label) 00077 { 00078 location_ = location; 00079 nearest_ = nearest; 00080 cost_ = cost; 00081 count_ = count; 00082 label_ = label; 00083 00084 int dx = location_.x - nearest_.x; 00085 int dy = location_.y - nearest_.y; 00086 dist_ = dx * dx + dy * dy; 00087 } 00088 00089 struct Compare 00090 { 00091 // must implement > since priority_queue looks for largest element 00092 bool operator()(SeedRgPixel const & l, 00093 SeedRgPixel const & r) const 00094 { 00095 if(r.cost_ == l.cost_) 00096 { 00097 if(r.dist_ == l.dist_) return r.count_ < l.count_; 00098 00099 return r.dist_ < l.dist_; 00100 } 00101 00102 return r.cost_ < l.cost_; 00103 } 00104 bool operator()(SeedRgPixel const * l, 00105 SeedRgPixel const * r) const 00106 { 00107 if(r->cost_ == l->cost_) 00108 { 00109 if(r->dist_ == l->dist_) return r->count_ < l->count_; 00110 00111 return r->dist_ < l->dist_; 00112 } 00113 00114 return r->cost_ < l->cost_; 00115 } 00116 }; 00117 00118 struct Allocator 00119 { 00120 ~Allocator() 00121 { 00122 while(!freelist_.empty()) 00123 { 00124 delete freelist_.top(); 00125 freelist_.pop(); 00126 } 00127 } 00128 00129 SeedRgPixel * 00130 create(Point2D const & location, Point2D const & nearest, 00131 COST const & cost, int const & count, int const & label) 00132 { 00133 if(!freelist_.empty()) 00134 { 00135 SeedRgPixel * res = freelist_.top(); 00136 freelist_.pop(); 00137 res->set(location, nearest, cost, count, label); 00138 return res; 00139 } 00140 00141 return new SeedRgPixel(location, nearest, cost, count, label); 00142 } 00143 00144 void dismiss(SeedRgPixel * p) 00145 { 00146 freelist_.push(p); 00147 } 00148 00149 std::stack<SeedRgPixel<COST> *> freelist_; 00150 }; 00151 }; 00152 00153 struct UnlabelWatersheds 00154 { 00155 int operator()(int label) const 00156 { 00157 return label < 0 ? 0 : label; 00158 } 00159 }; 00160 00161 } // namespace detail 00162 00163 enum SRGType { CompleteGrow = 0, KeepContours = 1, StopAtThreshold = 2, SRGWatershedLabel = -1 }; 00164 00165 /** \addtogroup SeededRegionGrowing Region Segmentation Algorithms 00166 Region growing, watersheds, and voronoi tesselation 00167 */ 00168 //@{ 00169 00170 /********************************************************/ 00171 /* */ 00172 /* seededRegionGrowing */ 00173 /* */ 00174 /********************************************************/ 00175 00176 /** \brief Region Segmentation by means of Seeded Region Growing. 00177 00178 This algorithm implements seeded region growing as described in 00179 00180 R. Adams, L. Bischof: "<em> Seeded Region Growing</em>", IEEE Trans. on Pattern 00181 Analysis and Maschine Intelligence, vol 16, no 6, 1994, and 00182 00183 Ullrich Köthe: 00184 <em><a href="http://hci.iwr.uni-heidelberg.de/people/ukoethe/papers/index.php#cite_primary_segmentation">Primary Image Segmentation</a></em>, 00185 in: G. Sagerer, S. 00186 Posch, F. Kummert (eds.): Mustererkennung 1995, Proc. 17. DAGM-Symposium, 00187 Springer 1995 00188 00189 The seed image is a partly segmented image which contains uniquely 00190 labeled regions (the seeds) and unlabeled pixels (the candidates, label 0). 00191 Seed regions can be as large as you wish and as small as one pixel. If 00192 there are no candidates, the algorithm will simply copy the seed image 00193 into the output image. Otherwise it will aggregate the candidates into 00194 the existing regions so that a cost function is minimized. 00195 Candidates are taken from the neighborhood of the already assigned pixels, 00196 where the type of neighborhood is determined by parameter <tt>neighborhood</tt> 00197 which can take the values <tt>FourNeighborCode()</tt> (the default) 00198 or <tt>EightNeighborCode()</tt>. The algorithm basically works as follows 00199 (illustrated for 4-neighborhood, but 8-neighborhood works in the same way): 00200 00201 <ol> 00202 00203 <li> Find all candidate pixels that are 4-adjacent to a seed region. 00204 Calculate the cost for aggregating each candidate into its adajacent region 00205 and put the candidates into a priority queue. 00206 00207 <li> While( priority queue is not empty and termination criterion is not fulfilled) 00208 00209 <ol> 00210 00211 <li> Take the candidate with least cost from the queue. If it has not 00212 already been merged, merge it with it's adjacent region. 00213 00214 <li> Put all candidates that are 4-adjacent to the pixel just processed 00215 into the priority queue. 00216 00217 </ol> 00218 00219 </ol> 00220 00221 <tt>SRGType</tt> can take the following values: 00222 00223 <DL> 00224 <DT><tt>CompleteGrow</tt> <DD> produce a complete tesselation of the volume (default). 00225 <DT><tt>KeepContours</tt> <DD> keep a 1-voxel wide unlabeled contour between all regions. 00226 <DT><tt>StopAtThreshold</tt> <DD> stop when the boundary indicator values exceed the 00227 threshold given by parameter <tt>max_cost</tt>. 00228 <DT><tt>KeepContours | StopAtThreshold</tt> <DD> keep 1-voxel wide contour and stop at given <tt>max_cost</tt>. 00229 </DL> 00230 00231 The cost is determined jointly by the source image and the 00232 region statistics functor. The source image contains feature values for each 00233 pixel which will be used by the region statistics functor to calculate and 00234 update statistics for each region and to calculate the cost for each 00235 candidate. The <TT>RegionStatisticsArray</TT> must be compatible to the 00236 \ref ArrayOfRegionStatistics functor and contains an <em> array</em> of 00237 statistics objects for each region. The indices must correspond to the 00238 labels of the seed regions. The statistics for the initial regions must have 00239 been calculated prior to calling <TT>seededRegionGrowing()</TT> (for example by 00240 means of \ref inspectTwoImagesIf()). 00241 00242 For each candidate 00243 <TT>x</TT> that is adjacent to region <TT>i</TT>, the algorithm will call 00244 <TT>stats[i].cost(as(x))</TT> to get the cost (where <TT>x</TT> is a <TT>SrcImageIterator</TT> 00245 and <TT>as</TT> is 00246 the SrcAccessor). When a candidate has been merged with a region, the 00247 statistics are updated by calling <TT>stats[i].operator()(as(x))</TT>. Since 00248 the <TT>RegionStatisticsArray</TT> is passed by reference, this will overwrite 00249 the original statistics. 00250 00251 If a candidate could be merged into more than one regions with identical 00252 cost, the algorithm will favour the nearest region. If <tt>StopAtThreshold</tt> is active, 00253 and the cost of the current candidate at any point in the algorithm exceeds the optional 00254 <tt>max_cost</tt> value (which defaults to <tt>NumericTraits<double>::max()</tt>), 00255 region growing is aborted, and all voxels not yet assigned to a region remain unlabeled. 00256 00257 In some cases, the cost only depends on the feature value of the current 00258 pixel. Then the update operation will simply be a no-op, and the <TT>cost()</TT> 00259 function returns its argument. This behavior is implemented by the 00260 \ref SeedRgDirectValueFunctor. With <tt>SRGType == KeepContours</tt>, 00261 this is equivalent to the watershed algorithm. 00262 00263 <b> Declarations:</b> 00264 00265 pass arguments explicitly: 00266 \code 00267 namespace vigra { 00268 template <class SrcImageIterator, class SrcAccessor, 00269 class SeedImageIterator, class SeedAccessor, 00270 class DestImageIterator, class DestAccessor, 00271 class RegionStatisticsArray, class Neighborhood> 00272 void 00273 seededRegionGrowing(SrcImageIterator srcul, SrcImageIterator srclr, SrcAccessor as, 00274 SeedImageIterator seedsul, SeedAccessor aseeds, 00275 DestImageIterator destul, DestAccessor ad, 00276 RegionStatisticsArray & stats, 00277 SRGType srgType = CompleteGrow, 00278 Neighborhood neighborhood = FourNeighborCode(), 00279 double max_cost = NumericTraits<double>::max()); 00280 } 00281 \endcode 00282 00283 use argument objects in conjunction with \ref ArgumentObjectFactories : 00284 \code 00285 namespace vigra { 00286 template <class SrcImageIterator, class SrcAccessor, 00287 class SeedImageIterator, class SeedAccessor, 00288 class DestImageIterator, class DestAccessor, 00289 class RegionStatisticsArray, class Neighborhood> 00290 void 00291 seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, 00292 pair<SeedImageIterator, SeedAccessor> seeds, 00293 pair<DestImageIterator, DestAccessor> dest, 00294 RegionStatisticsArray & stats, 00295 SRGType srgType = CompleteGrow, 00296 Neighborhood neighborhood = FourNeighborCode(), 00297 double max_cost = NumericTraits<double>::max()); 00298 } 00299 \endcode 00300 00301 <b> Usage:</b> 00302 00303 <b>\#include</b> <<a href="seededregiongrowing_8hxx-source.html">vigra/seededregiongrowing.hxx</a>><br> 00304 Namespace: vigra 00305 00306 Example: implementation of the voronoi tesselation 00307 00308 \code 00309 vigra::BImage points(w,h); 00310 vigra::FImage dist(x,y); 00311 00312 // empty edge image 00313 points = 0; 00314 dist = 0; 00315 00316 int max_region_label = 100; 00317 00318 // throw in some random points: 00319 for(int i = 1; i <= max_region_label; ++i) 00320 points(w * rand() / RAND_MAX , h * rand() / RAND_MAX) = i; 00321 00322 // calculate Euclidean distance transform 00323 vigra::distanceTransform(srcImageRange(points), destImage(dist), 2); 00324 00325 // init statistics functor 00326 vigra::ArrayOfRegionStatistics<vigra::SeedRgDirectValueFunctor<float> > 00327 stats(max_region_label); 00328 00329 // find voronoi region of each point 00330 vigra:: seededRegionGrowing(srcImageRange(dist), srcImage(points), 00331 destImage(points), stats); 00332 \endcode 00333 00334 <b> Required Interface:</b> 00335 00336 \code 00337 SrcImageIterator src_upperleft, src_lowerright; 00338 SeedImageIterator seed_upperleft; 00339 DestImageIterator dest_upperleft; 00340 00341 SrcAccessor src_accessor; 00342 SeedAccessor seed_accessor; 00343 DestAccessor dest_accessor; 00344 00345 RegionStatisticsArray stats; 00346 00347 // calculate costs 00348 RegionStatisticsArray::value_type::cost_type cost = 00349 stats[seed_accessor(seed_upperleft)].cost(src_accessor(src_upperleft)); 00350 00351 // compare costs 00352 cost < cost; 00353 00354 // update statistics 00355 stats[seed_accessor(seed_upperleft)](src_accessor(src_upperleft)); 00356 00357 // set result 00358 dest_accessor.set(seed_accessor(seed_upperleft), dest_upperleft); 00359 \endcode 00360 00361 Further requirements are determined by the <TT>RegionStatisticsArray</TT>. 00362 */ 00363 doxygen_overloaded_function(template <...> void seededRegionGrowing) 00364 00365 template <class SrcImageIterator, class SrcAccessor, 00366 class SeedImageIterator, class SeedAccessor, 00367 class DestImageIterator, class DestAccessor, 00368 class RegionStatisticsArray, class Neighborhood> 00369 void seededRegionGrowing(SrcImageIterator srcul, 00370 SrcImageIterator srclr, SrcAccessor as, 00371 SeedImageIterator seedsul, SeedAccessor aseeds, 00372 DestImageIterator destul, DestAccessor ad, 00373 RegionStatisticsArray & stats, 00374 SRGType srgType, 00375 Neighborhood, 00376 double max_cost) 00377 { 00378 int w = srclr.x - srcul.x; 00379 int h = srclr.y - srcul.y; 00380 int count = 0; 00381 00382 SrcImageIterator isy = srcul, isx = srcul; // iterators for the src image 00383 00384 typedef typename RegionStatisticsArray::value_type RegionStatistics; 00385 typedef typename RegionStatistics::cost_type CostType; 00386 typedef detail::SeedRgPixel<CostType> Pixel; 00387 00388 typename Pixel::Allocator allocator; 00389 00390 typedef std::priority_queue<Pixel *, std::vector<Pixel *>, 00391 typename Pixel::Compare> SeedRgPixelHeap; 00392 00393 // copy seed image in an image with border 00394 IImage regions(w+2, h+2); 00395 IImage::Iterator ir = regions.upperLeft() + Diff2D(1,1); 00396 IImage::Iterator iry, irx; 00397 00398 initImageBorder(destImageRange(regions), 1, SRGWatershedLabel); 00399 copyImage(seedsul, seedsul+Diff2D(w,h), aseeds, ir, regions.accessor()); 00400 00401 // allocate and init memory for the results 00402 00403 SeedRgPixelHeap pheap; 00404 int cneighbor; 00405 00406 typedef typename Neighborhood::Direction Direction; 00407 int directionCount = Neighborhood::DirectionCount; 00408 00409 Point2D pos(0,0); 00410 for(isy=srcul, iry=ir, pos.y=0; pos.y<h; 00411 ++pos.y, ++isy.y, ++iry.y) 00412 { 00413 for(isx=isy, irx=iry, pos.x=0; pos.x<w; 00414 ++pos.x, ++isx.x, ++irx.x) 00415 { 00416 if(*irx == 0) 00417 { 00418 // find candidate pixels for growing and fill heap 00419 for(int i=0; i<directionCount; i++) 00420 { 00421 // cneighbor = irx[dist[i]]; 00422 cneighbor = irx[Neighborhood::diff((Direction)i)]; 00423 if(cneighbor > 0) 00424 { 00425 CostType cost = stats[cneighbor].cost(as(isx)); 00426 00427 Pixel * pixel = 00428 allocator.create(pos, pos+Neighborhood::diff((Direction)i), cost, count++, cneighbor); 00429 pheap.push(pixel); 00430 } 00431 } 00432 } 00433 } 00434 } 00435 00436 // perform region growing 00437 while(pheap.size() != 0) 00438 { 00439 Pixel * pixel = pheap.top(); 00440 pheap.pop(); 00441 00442 if((srgType & StopAtThreshold) != 0 && pixel->cost_ > max_cost) 00443 break; 00444 00445 Point2D pos = pixel->location_; 00446 Point2D nearest = pixel->nearest_; 00447 int lab = pixel->label_; 00448 00449 allocator.dismiss(pixel); 00450 00451 irx = ir + pos; 00452 isx = srcul + pos; 00453 00454 if(*irx) // already labelled region / watershed? 00455 continue; 00456 00457 if((srgType & KeepContours) != 0) 00458 { 00459 for(int i=0; i<directionCount; i++) 00460 { 00461 cneighbor = irx[Neighborhood::diff((Direction)i)]; 00462 if((cneighbor>0) && (cneighbor != lab)) 00463 { 00464 lab = SRGWatershedLabel; 00465 break; 00466 } 00467 } 00468 } 00469 00470 *irx = lab; 00471 00472 if((srgType & KeepContours) == 0 || lab > 0) 00473 { 00474 // update statistics 00475 stats[*irx](as(isx)); 00476 00477 // search neighborhood 00478 // second pass: find new candidate pixels 00479 for(int i=0; i<directionCount; i++) 00480 { 00481 if(irx[Neighborhood::diff((Direction)i)] == 0) 00482 { 00483 CostType cost = stats[lab].cost(as(isx, Neighborhood::diff((Direction)i))); 00484 00485 Pixel * new_pixel = 00486 allocator.create(pos+Neighborhood::diff((Direction)i), nearest, cost, count++, lab); 00487 pheap.push(new_pixel); 00488 } 00489 } 00490 } 00491 } 00492 00493 // write result 00494 transformImage(ir, ir+Point2D(w,h), regions.accessor(), destul, ad, 00495 detail::UnlabelWatersheds()); 00496 } 00497 00498 template <class SrcImageIterator, class SrcAccessor, 00499 class SeedImageIterator, class SeedAccessor, 00500 class DestImageIterator, class DestAccessor, 00501 class RegionStatisticsArray, class Neighborhood> 00502 inline void 00503 seededRegionGrowing(SrcImageIterator srcul, 00504 SrcImageIterator srclr, SrcAccessor as, 00505 SeedImageIterator seedsul, SeedAccessor aseeds, 00506 DestImageIterator destul, DestAccessor ad, 00507 RegionStatisticsArray & stats, 00508 SRGType srgType, 00509 Neighborhood n) 00510 { 00511 seededRegionGrowing(srcul, srclr, as, 00512 seedsul, aseeds, 00513 destul, ad, 00514 stats, srgType, n, NumericTraits<double>::max()); 00515 } 00516 00517 00518 00519 template <class SrcImageIterator, class SrcAccessor, 00520 class SeedImageIterator, class SeedAccessor, 00521 class DestImageIterator, class DestAccessor, 00522 class RegionStatisticsArray> 00523 inline void 00524 seededRegionGrowing(SrcImageIterator srcul, 00525 SrcImageIterator srclr, SrcAccessor as, 00526 SeedImageIterator seedsul, SeedAccessor aseeds, 00527 DestImageIterator destul, DestAccessor ad, 00528 RegionStatisticsArray & stats, 00529 SRGType srgType) 00530 { 00531 seededRegionGrowing(srcul, srclr, as, 00532 seedsul, aseeds, 00533 destul, ad, 00534 stats, srgType, FourNeighborCode()); 00535 } 00536 00537 template <class SrcImageIterator, class SrcAccessor, 00538 class SeedImageIterator, class SeedAccessor, 00539 class DestImageIterator, class DestAccessor, 00540 class RegionStatisticsArray> 00541 inline void 00542 seededRegionGrowing(SrcImageIterator srcul, 00543 SrcImageIterator srclr, SrcAccessor as, 00544 SeedImageIterator seedsul, SeedAccessor aseeds, 00545 DestImageIterator destul, DestAccessor ad, 00546 RegionStatisticsArray & stats) 00547 { 00548 seededRegionGrowing(srcul, srclr, as, 00549 seedsul, aseeds, 00550 destul, ad, 00551 stats, CompleteGrow); 00552 } 00553 00554 template <class SrcImageIterator, class SrcAccessor, 00555 class SeedImageIterator, class SeedAccessor, 00556 class DestImageIterator, class DestAccessor, 00557 class RegionStatisticsArray, class Neighborhood> 00558 inline void 00559 seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> img1, 00560 pair<SeedImageIterator, SeedAccessor> img3, 00561 pair<DestImageIterator, DestAccessor> img4, 00562 RegionStatisticsArray & stats, 00563 SRGType srgType, 00564 Neighborhood n, 00565 double max_cost) 00566 { 00567 seededRegionGrowing(img1.first, img1.second, img1.third, 00568 img3.first, img3.second, 00569 img4.first, img4.second, 00570 stats, srgType, n, max_cost); 00571 } 00572 00573 template <class SrcImageIterator, class SrcAccessor, 00574 class SeedImageIterator, class SeedAccessor, 00575 class DestImageIterator, class DestAccessor, 00576 class RegionStatisticsArray, class Neighborhood> 00577 inline void 00578 seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> img1, 00579 pair<SeedImageIterator, SeedAccessor> img3, 00580 pair<DestImageIterator, DestAccessor> img4, 00581 RegionStatisticsArray & stats, 00582 SRGType srgType, 00583 Neighborhood n) 00584 { 00585 seededRegionGrowing(img1.first, img1.second, img1.third, 00586 img3.first, img3.second, 00587 img4.first, img4.second, 00588 stats, srgType, n, NumericTraits<double>::max()); 00589 } 00590 00591 template <class SrcImageIterator, class SrcAccessor, 00592 class SeedImageIterator, class SeedAccessor, 00593 class DestImageIterator, class DestAccessor, 00594 class RegionStatisticsArray> 00595 inline void 00596 seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> img1, 00597 pair<SeedImageIterator, SeedAccessor> img3, 00598 pair<DestImageIterator, DestAccessor> img4, 00599 RegionStatisticsArray & stats, 00600 SRGType srgType) 00601 { 00602 seededRegionGrowing(img1.first, img1.second, img1.third, 00603 img3.first, img3.second, 00604 img4.first, img4.second, 00605 stats, srgType, FourNeighborCode()); 00606 } 00607 00608 template <class SrcImageIterator, class SrcAccessor, 00609 class SeedImageIterator, class SeedAccessor, 00610 class DestImageIterator, class DestAccessor, 00611 class RegionStatisticsArray> 00612 inline void 00613 seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> img1, 00614 pair<SeedImageIterator, SeedAccessor> img3, 00615 pair<DestImageIterator, DestAccessor> img4, 00616 RegionStatisticsArray & stats) 00617 { 00618 seededRegionGrowing(img1.first, img1.second, img1.third, 00619 img3.first, img3.second, 00620 img4.first, img4.second, 00621 stats, CompleteGrow); 00622 } 00623 00624 /********************************************************/ 00625 /* */ 00626 /* SeedRgDirectValueFunctor */ 00627 /* */ 00628 /********************************************************/ 00629 00630 /** \brief Statistics functor to be used for seeded region growing. 00631 00632 This functor can be used if the cost of a candidate during 00633 \ref seededRegionGrowing() is equal to the feature value of that 00634 candidate and does not depend on properties of the region it is going to 00635 be merged with. 00636 00637 <b>\#include</b> <<a href="seededregiongrowing_8hxx-source.html">vigra/seededregiongrowing.hxx</a>><br> 00638 Namespace: vigra 00639 00640 00641 <b> Required Interface:</b> 00642 00643 no requirements 00644 */ 00645 template <class Value> 00646 class SeedRgDirectValueFunctor 00647 { 00648 public: 00649 /** the functor's argument type 00650 */ 00651 typedef Value argument_type; 00652 00653 /** the functor's result type (unused, only necessary for 00654 use of SeedRgDirectValueFunctor in \ref vigra::ArrayOfRegionStatistics 00655 */ 00656 typedef Value result_type; 00657 00658 /** \deprecated use argument_type 00659 */ 00660 typedef Value value_type; 00661 00662 /** the return type of the cost() function 00663 */ 00664 typedef Value cost_type; 00665 00666 /** Do nothing (since we need not update region statistics). 00667 */ 00668 void operator()(argument_type const &) const {} 00669 00670 /** Return argument (since cost is identical to feature value) 00671 */ 00672 cost_type const & cost(argument_type const & v) const 00673 { 00674 return v; 00675 } 00676 }; 00677 00678 //@} 00679 00680 } // namespace vigra 00681 00682 #endif // VIGRA_SEEDEDREGIONGROWING_HXX 00683
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|