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

vigra/seededregiongrowing.hxx VIGRA

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         Point2D pos = pixel->location_;
00443         Point2D nearest = pixel->nearest_;
00444         int lab = pixel->label_;
00445         CostType cost = pixel->cost_;
00446 
00447         allocator.dismiss(pixel);
00448 
00449         if((srgType & StopAtThreshold) != 0 && cost > max_cost)
00450             break;
00451 
00452         irx = ir + pos;
00453         isx = srcul + pos;
00454 
00455         if(*irx) // already labelled region / watershed?
00456             continue;
00457 
00458         if((srgType & KeepContours) != 0)
00459         {
00460             for(int i=0; i<directionCount; i++)
00461             {
00462                 cneighbor = irx[Neighborhood::diff((Direction)i)];
00463                 if((cneighbor>0) && (cneighbor != lab))
00464                 {
00465                     lab = SRGWatershedLabel;
00466                     break;
00467                 }
00468             }
00469         }
00470 
00471         *irx = lab;
00472 
00473         if((srgType & KeepContours) == 0 || lab > 0)
00474         {
00475             // update statistics
00476             stats[*irx](as(isx));
00477 
00478             // search neighborhood
00479             // second pass: find new candidate pixels
00480             for(int i=0; i<directionCount; i++)
00481             {
00482                 if(irx[Neighborhood::diff((Direction)i)] == 0)
00483                 {
00484                     CostType cost = stats[lab].cost(as(isx, Neighborhood::diff((Direction)i)));
00485 
00486                     Pixel * new_pixel =
00487                         allocator.create(pos+Neighborhood::diff((Direction)i), nearest, cost, count++, lab);
00488                     pheap.push(new_pixel);
00489                 }
00490             }
00491         }
00492     }
00493     
00494     // free temporary memory
00495     while(pheap.size() != 0)
00496     {
00497         allocator.dismiss(pheap.top());
00498         pheap.pop();
00499     }
00500 
00501     // write result
00502     transformImage(ir, ir+Point2D(w,h), regions.accessor(), destul, ad,
00503                    detail::UnlabelWatersheds());
00504 }
00505 
00506 template <class SrcImageIterator, class SrcAccessor,
00507           class SeedImageIterator, class SeedAccessor,
00508           class DestImageIterator, class DestAccessor,
00509           class RegionStatisticsArray, class Neighborhood>
00510 inline void
00511 seededRegionGrowing(SrcImageIterator srcul,
00512                     SrcImageIterator srclr, SrcAccessor as,
00513                     SeedImageIterator seedsul, SeedAccessor aseeds,
00514                     DestImageIterator destul, DestAccessor ad,
00515                     RegionStatisticsArray & stats,
00516                     SRGType srgType,
00517                     Neighborhood n)
00518 {
00519     seededRegionGrowing(srcul, srclr, as,
00520                         seedsul, aseeds,
00521                         destul, ad,
00522                         stats, srgType, n, NumericTraits<double>::max());
00523 }
00524 
00525 
00526 
00527 template <class SrcImageIterator, class SrcAccessor,
00528           class SeedImageIterator, class SeedAccessor,
00529           class DestImageIterator, class DestAccessor,
00530           class RegionStatisticsArray>
00531 inline void
00532 seededRegionGrowing(SrcImageIterator srcul,
00533                     SrcImageIterator srclr, SrcAccessor as,
00534                     SeedImageIterator seedsul, SeedAccessor aseeds,
00535                     DestImageIterator destul, DestAccessor ad,
00536                     RegionStatisticsArray & stats,
00537                     SRGType srgType)
00538 {
00539     seededRegionGrowing(srcul, srclr, as,
00540                         seedsul, aseeds,
00541                         destul, ad,
00542                         stats, srgType, FourNeighborCode());
00543 }
00544 
00545 template <class SrcImageIterator, class SrcAccessor,
00546           class SeedImageIterator, class SeedAccessor,
00547           class DestImageIterator, class DestAccessor,
00548           class RegionStatisticsArray>
00549 inline void
00550 seededRegionGrowing(SrcImageIterator srcul,
00551                     SrcImageIterator srclr, SrcAccessor as,
00552                     SeedImageIterator seedsul, SeedAccessor aseeds,
00553                     DestImageIterator destul, DestAccessor ad,
00554                     RegionStatisticsArray & stats)
00555 {
00556     seededRegionGrowing(srcul, srclr, as,
00557                         seedsul, aseeds,
00558                         destul, ad,
00559                         stats, CompleteGrow);
00560 }
00561 
00562 template <class SrcImageIterator, class SrcAccessor,
00563           class SeedImageIterator, class SeedAccessor,
00564           class DestImageIterator, class DestAccessor,
00565           class RegionStatisticsArray, class Neighborhood>
00566 inline void
00567 seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> img1,
00568                     pair<SeedImageIterator, SeedAccessor> img3,
00569                     pair<DestImageIterator, DestAccessor> img4,
00570                     RegionStatisticsArray & stats,
00571                     SRGType srgType, 
00572                     Neighborhood n,
00573                     double max_cost)
00574 {
00575     seededRegionGrowing(img1.first, img1.second, img1.third,
00576                         img3.first, img3.second,
00577                         img4.first, img4.second,
00578                         stats, srgType, n, max_cost);
00579 }
00580 
00581 template <class SrcImageIterator, class SrcAccessor,
00582           class SeedImageIterator, class SeedAccessor,
00583           class DestImageIterator, class DestAccessor,
00584           class RegionStatisticsArray, class Neighborhood>
00585 inline void
00586 seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> img1,
00587                     pair<SeedImageIterator, SeedAccessor> img3,
00588                     pair<DestImageIterator, DestAccessor> img4,
00589                     RegionStatisticsArray & stats,
00590                     SRGType srgType, 
00591                     Neighborhood n)
00592 {
00593     seededRegionGrowing(img1.first, img1.second, img1.third,
00594                         img3.first, img3.second,
00595                         img4.first, img4.second,
00596                         stats, srgType, n, NumericTraits<double>::max());
00597 }
00598 
00599 template <class SrcImageIterator, class SrcAccessor,
00600           class SeedImageIterator, class SeedAccessor,
00601           class DestImageIterator, class DestAccessor,
00602           class RegionStatisticsArray>
00603 inline void
00604 seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> img1,
00605                     pair<SeedImageIterator, SeedAccessor> img3,
00606                     pair<DestImageIterator, DestAccessor> img4,
00607                     RegionStatisticsArray & stats,
00608                     SRGType srgType)
00609 {
00610     seededRegionGrowing(img1.first, img1.second, img1.third,
00611                         img3.first, img3.second,
00612                         img4.first, img4.second,
00613                         stats, srgType, FourNeighborCode());
00614 }
00615 
00616 template <class SrcImageIterator, class SrcAccessor,
00617           class SeedImageIterator, class SeedAccessor,
00618           class DestImageIterator, class DestAccessor,
00619           class RegionStatisticsArray>
00620 inline void
00621 seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> img1,
00622                     pair<SeedImageIterator, SeedAccessor> img3,
00623                     pair<DestImageIterator, DestAccessor> img4,
00624                     RegionStatisticsArray & stats)
00625 {
00626     seededRegionGrowing(img1.first, img1.second, img1.third,
00627                         img3.first, img3.second,
00628                         img4.first, img4.second,
00629                         stats, CompleteGrow);
00630 }
00631 
00632 /********************************************************/
00633 /*                                                      */
00634 /*               SeedRgDirectValueFunctor               */
00635 /*                                                      */
00636 /********************************************************/
00637 
00638 /** \brief Statistics functor to be used for seeded region growing.
00639 
00640     This functor can be used if the cost of a candidate during
00641     \ref seededRegionGrowing() is equal to the feature value of that
00642     candidate and does not depend on properties of the region it is going to
00643     be merged with.
00644 
00645     <b>\#include</b> <<a href="seededregiongrowing_8hxx-source.html">vigra/seededregiongrowing.hxx</a>><br>
00646     Namespace: vigra
00647 
00648 
00649      <b> Required Interface:</b>
00650 
00651      no requirements
00652 */
00653 template <class Value>
00654 class SeedRgDirectValueFunctor
00655 {
00656   public:
00657         /** the functor's argument type
00658         */
00659     typedef Value argument_type;
00660 
00661         /** the functor's result type (unused, only necessary for
00662             use of SeedRgDirectValueFunctor in \ref vigra::ArrayOfRegionStatistics
00663         */
00664     typedef Value result_type;
00665 
00666         /** \deprecated use argument_type
00667         */
00668     typedef Value value_type;
00669 
00670         /** the return type of the cost() function
00671         */
00672     typedef Value cost_type;
00673 
00674         /** Do nothing (since we need not update region statistics).
00675         */
00676     void operator()(argument_type const &) const {}
00677 
00678         /** Return argument (since cost is identical to feature value)
00679         */
00680     cost_type const & cost(argument_type const & v) const
00681     {
00682         return v;
00683     }
00684 };
00685 
00686 //@}
00687 
00688 } // namespace vigra
00689 
00690 #endif // VIGRA_SEEDEDREGIONGROWING_HXX
00691 

© 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.1 (3 Dec 2010)