[ 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         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)