[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

vigra/seededregiongrowing.hxx
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&ouml;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)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.7.0 (Thu Aug 25 2011)