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

vigra/localminmax.hxx |

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*               Copyright 1998-2010 by Ullrich Koethe                  */
    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_LOCALMINMAX_HXX
    00037 #define VIGRA_LOCALMINMAX_HXX
    00038
    00039 #include <vector>
    00040 #include <functional>
    00041 #include "utilities.hxx"
    00042 #include "stdimage.hxx"
    00043 #include "initimage.hxx"
    00044 #include "labelimage.hxx"
    00045 #include "labelvolume.hxx"
    00046 #include "pixelneighborhood.hxx"
    00047 #include "voxelneighborhood.hxx"
    00048
    00049 namespace vigra
    00050 {
    00051
    00052 /** \addtogroup LocalMinMax Local Minima and Maxima
    00053
    00054     Detect local minima and maxima in a gray level image,
    00055     including extremal plateaus larger than 1 pixel
    00056 */
    00057 //@{
    00058
    00059 namespace detail {
    00060
    00061 template <class SrcIterator, class SrcAccessor,
    00062           class Neighborhood,
    00063           class Compare>
    00064 inline bool
    00065 isLocalExtremum(SrcIterator is, SrcAccessor sa, Neighborhood,
    00066                 typename SrcAccessor::value_type threshold,
    00067                 Compare compare, AtImageBorder atBorder)
    00068 {
    00069     typename SrcAccessor::value_type v = sa(is);
    00070
    00071     if(!compare(v, threshold))
    00072         return false;
    00073
    00074     int directionCount = Neighborhood::nearBorderDirectionCount(atBorder);
    00075     RestrictedNeighborhoodCirculator<SrcIterator, Neighborhood> sc(is, atBorder);
    00076     for(int i = 0; i < directionCount; ++i, ++sc)
    00077     {
    00078         if(!compare(v, sa(sc)))
    00079             return false;
    00080     }
    00081     return true;
    00082 }
    00083
    00084 template <class SrcIterator, class SrcAccessor,
    00085           class DestIterator, class DestAccessor,
    00086           class DestValue, class Neighborhood,
    00087           class Compare>
    00088 void
    00089 localMinMax(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    00090             DestIterator dul, DestAccessor da,
    00091             DestValue marker, Neighborhood neighborhood,
    00092             typename SrcAccessor::value_type threshold,
    00093             Compare compare,
    00094             bool allowExtremaAtBorder = false)
    00095 {
    00096     int w = slr.x - sul.x;
    00097     int h = slr.y - sul.y;
    00098
    00099     int x, y;
    00100
    00101     if(allowExtremaAtBorder)
    00102     {
    00103         SrcIterator is = sul;
    00104         DestIterator id = dul;
    00105
    00106         for(x=0; x<w; ++x, ++is.x, ++id.x)
    00107         {
    00108             if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
    00109                                 isAtImageBorder(x, 0, w, h)))
    00110                 da.set(marker, id);
    00111         }
    00112
    00113         is = sul + Diff2D(0,1);
    00114         id = dul + Diff2D(0,1);
    00115
    00116         for(y=1; y<h-1; ++y, ++is.y, ++id.y)
    00117         {
    00118             if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
    00119                                 isAtImageBorder(0, y, w, h)))
    00120                 da.set(marker, id);
    00121         }
    00122
    00123         is = sul + Diff2D(w-1,1);
    00124         id = dul + Diff2D(w-1,1);
    00125
    00126         for(y=1; y<h-1; ++y, ++is.y, ++id.y)
    00127         {
    00128             if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
    00129                                 isAtImageBorder(w-1, y, w, h)))
    00130                 da.set(marker, id);
    00131         }
    00132
    00133         is = sul + Diff2D(0,h-1);
    00134         id = dul + Diff2D(0,h-1);
    00135
    00136         for(x=0; x<w; ++x, ++is.x, ++id.x)
    00137         {
    00138             if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
    00139                                 isAtImageBorder(x, h-1, w, h)))
    00140                 da.set(marker, id);
    00141         }
    00142     }
    00143
    00144     w -= 2;
    00145     h -= 2;
    00146     sul += Diff2D(1,1);
    00147     dul += Diff2D(1,1);
    00148
    00149     for(y=0; y<h; ++y, ++sul.y, ++dul.y)
    00150     {
    00151         SrcIterator  sx = sul;
    00152         DestIterator dx = dul;
    00153
    00154         for(x=0; x<w; ++x, ++sx.x, ++dx.x)
    00155         {
    00156             typename SrcAccessor::value_type v = sa(sx);
    00157
    00158             if(!compare(v, threshold))
    00159                 continue;
    00160
    00161             int i;
    00162             NeighborhoodCirculator<SrcIterator, Neighborhood> sc(sx);
    00163             for(i = 0; i < Neighborhood::DirectionCount; ++i, ++sc)
    00164             {
    00165                 if(!compare(v, sa(sc)))
    00166                     break;
    00167             }
    00168
    00169             if(i == Neighborhood::DirectionCount)
    00170                 da.set(marker, dx);
    00171         }
    00172     }
    00173 }
    00174
    00175 template<class SrcIterator, class SrcShape, class SrcAccessor,
    00176         class DestIterator, class DestAccessor, class DestValue,
    00177         class Neighborhood, class Compare>
    00178 void
    00179 localMinMax3D(SrcIterator sul, SrcShape shp, SrcAccessor sa,
    00180               DestIterator dul, DestAccessor da,
    00181               DestValue marker,
    00182               Neighborhood neighborhood,
    00183               typename SrcAccessor::value_type threshold,
    00184               Compare compare,
    00185               bool allowExtremaAtBorder = false)
    00186 {
    00187     int w = shp[0];
    00188     int h = shp[1];
    00189     int d = shp[2];
    00190
    00191     int x, y, z;
    00192
    00193     if (allowExtremaAtBorder)
    00194     {
    00195         throw std::runtime_error("not implemented!");
    00196         /*
    00197         SrcIterator is = sul;
    00198         DestIterator id = dul;
    00199
    00200         for(x=0; x<w; ++x, ++is.x, ++id.x)
    00201         {
    00202             if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
    00203                         isAtImageBorder(x, 0, w, h)))
    00204             da.set(marker, id);
    00205         }
    00206
    00207         is = sul + Diff2D(0,1);
    00208         id = dul + Diff2D(0,1);
    00209
    00210         for(y=1; y<h-1; ++y, ++is.y, ++id.y)
    00211         {
    00212             if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
    00213                         isAtImageBorder(0, y, w, h)))
    00214             da.set(marker, id);
    00215         }
    00216
    00217         is = sul + Diff2D(w-1,1);
    00218         id = dul + Diff2D(w-1,1);
    00219
    00220         for(y=1; y<h-1; ++y, ++is.y, ++id.y)
    00221         {
    00222             if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
    00223                         isAtImageBorder(w-1, y, w, h)))
    00224             da.set(marker, id);
    00225         }
    00226
    00227         is = sul + Diff2D(0,h-1);
    00228         id = dul + Diff2D(0,h-1);
    00229
    00230         for(x=0; x<w; ++x, ++is.x, ++id.x)
    00231         {
    00232             if(isLocalExtremum(is, sa, neighborhood, threshold, compare,
    00233                         isAtImageBorder(x, h-1, w, h)))
    00234             da.set(marker, id);
    00235         }
    00236     */
    00237     }
    00238
    00239     w -= 2;
    00240     h -= 2;
    00241     d -= 2;
    00242     sul.dim0() += 1;
    00243     sul.dim1() += 1;
    00244     sul.dim2() += 1;
    00245     dul += Diff3D(1, 1, 1);
    00246
    00247     SrcIterator zs = sul;
    00248     DestIterator zd = dul;
    00249
    00250     for (z = 0; z != d; ++z, ++zs.dim2(), ++zd.dim2())
    00251     {
    00252         SrcIterator ys(zs);
    00253         DestIterator yd(zd);
    00254
    00255         for (y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1())
    00256         {
    00257             SrcIterator xs(ys);
    00258             DestIterator xd(yd);
    00259
    00260             for (x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0())
    00261             {
    00262
    00263                 typename SrcAccessor::value_type v = sa(xs);
    00264                 if (!compare(v, threshold))
    00265                     continue;
    00266
    00267                 int i;
    00268                 NeighborhoodCirculator<SrcIterator, Neighborhood> sc(xs);
    00269                 for (i = 0; i < Neighborhood::DirectionCount; ++i, ++sc)
    00270                 {
    00271                     if(!compare(v, sa(sc)))
    00272                         break;
    00273                 }
    00274
    00275                 if(i == Neighborhood::DirectionCount)
    00276                     da.set(marker, xd);
    00277             }
    00278         }
    00279     }
    00280 }
    00281
    00282 template <class SrcIterator, class SrcAccessor,
    00283           class DestIterator, class DestAccessor, class DestValue,
    00284           class Neighborhood, class Compare, class Equal>
    00285 void
    00286 extendedLocalMinMax(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    00287                     DestIterator dul, DestAccessor da, DestValue marker,
    00288                     Neighborhood /*neighborhood*/,
    00289                     Compare compare, Equal equal,
    00290                     typename SrcAccessor::value_type threshold,
    00291                     bool allowExtremaAtBorder = false)
    00292 {
    00293     typedef typename SrcAccessor::value_type SrcType;
    00294
    00295     int w = slr.x - sul.x;
    00296     int h = slr.y - sul.y;
    00297
    00298     int i,x,y;
    00299
    00300     BasicImage<int> labels(w,h);
    00301
    00302     int number_of_regions =
    00303         labelImage(sul, slr, sa, labels.upperLeft(), labels.accessor(),
    00304                    (Neighborhood::DirectionCount == 8), equal);
    00305
    00306     // assume that a region is a extremum until the opposite is proved
    00307     std::vector<unsigned char> isExtremum(number_of_regions+1, (unsigned char)1);
    00308
    00309     BasicImage<int>::traverser ly = labels.upperLeft();
    00310
    00311     for(y=0; y<h; ++y, ++sul.y, ++ly.y)
    00312     {
    00313         SrcIterator  sx = sul;
    00314         BasicImage<int>::traverser lx(ly);
    00315
    00316         for(x=0; x<w; ++x, ++sx.x, ++lx.x)
    00317         {
    00318             int lab = *lx;
    00319             SrcType v = sa(sx);
    00320
    00321             if(isExtremum[lab] == 0)
    00322                 continue;
    00323
    00324             if(!compare(v, threshold))
    00325             {
    00326                 // mark all regions that don't exceed the threshold as non-extremum
    00327                 isExtremum[lab] = 0;
    00328                 continue;
    00329             }
    00330
    00331             AtImageBorder atBorder = isAtImageBorder(x, y, w, h);
    00332             if(atBorder == NotAtBorder)
    00333             {
    00334                 NeighborhoodCirculator<SrcIterator, Neighborhood> sc(sx);
    00335                 NeighborhoodCirculator<BasicImage<int>::traverser, Neighborhood> lc(lx);
    00336                 for(i=0; i<Neighborhood::DirectionCount; ++i, ++sc, ++lc)
    00337                 {
    00338                     if(lab != *lc && compare(sa(sc),v))
    00339                     {
    00340                         isExtremum[lab] = 0;
    00341                         break;
    00342                     }
    00343                 }
    00344             }
    00345             else
    00346             {
    00347                 if(allowExtremaAtBorder)
    00348                 {
    00349                     RestrictedNeighborhoodCirculator<SrcIterator, Neighborhood>
    00350                                                                sc(sx, atBorder), scend(sc);
    00351                     do
    00352                     {
    00353                         if(lab != *(lx+sc.diff()) && compare(sa(sc),v))
    00354                         {
    00355                             isExtremum[lab] = 0;
    00356                             break;
    00357                         }
    00358                     }
    00359                     while(++sc != scend);
    00360                 }
    00361                 else
    00362                 {
    00363                     isExtremum[lab] = 0;
    00364                 }
    00365             }
    00366         }
    00367     }
    00368
    00369     ly = labels.upperLeft();
    00370     for(y=0; y<h; ++y, ++dul.y, ++ly.y)
    00371     {
    00372         DestIterator  xd = dul;
    00373         BasicImage<int>::Iterator lx(ly);
    00374
    00375         for(x=0; x<w; ++x, ++xd.x, ++lx.x)
    00376         {
    00377             if(isExtremum[*lx])
    00378                 da.set(marker, xd);
    00379         }
    00380     }
    00381 }
    00382
    00383 template<class SrcIterator, class SrcShape, class SrcAccessor,
    00384         class DestIterator, class DestAccessor, class DestValue,
    00385         class Neighborhood, class Compare, class Equal>
    00386 void
    00387 extendedLocalMinMax3D(SrcIterator sul, SrcShape shp, SrcAccessor sa,
    00388                       DestIterator dul, DestAccessor da,
    00389                       DestValue marker,
    00390                       Neighborhood neighbourhood,
    00391                       Compare compare,
    00392                       Equal equal,
    00393                       typename SrcAccessor::value_type threshold,
    00394                       bool allowExtremaAtBorder = false)
    00395 {
    00396     typedef typename SrcAccessor::value_type SrcType;
    00397
    00398     int w = shp[0];
    00399     int h = shp[1];
    00400     int d = shp[2];
    00401
    00402     int i, x, y, z;
    00403
    00404     MultiArray<3, int> labels(shp);
    00405
    00406     int number_of_regions =
    00407         labelVolume(sul, shp, sa, labels.traverser_begin(),
    00408                     typename AccessorTraits<int>::default_accessor(),
    00409                     neighbourhood);
    00410
    00411     MultiArray<3, int>::traverser zl(labels.traverser_begin());
    00412
    00413     SrcIterator zs = sul;
    00414     DestIterator zd = dul;
    00415
    00416     // assume that a region is a extremum until the opposite is proved
    00417     std::vector<unsigned char> isExtremum(number_of_regions + 1, (unsigned char)1);
    00418
    00419     for (z = 0; z != d; ++z, ++zs.dim2(), ++zd.dim2(), ++zl.dim2())
    00420     {
    00421         SrcIterator ys(zs);
    00422         DestIterator yd(zd);
    00423         MultiArray<3, int>::traverser yl(zl);
    00424
    00425         for (y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1(), ++yl.dim1())
    00426         {
    00427             SrcIterator xs(ys);
    00428             DestIterator xd(yd);
    00429             MultiArray<3, int>::traverser xl(yl);
    00430
    00431             for (x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0(), ++xl.dim0())
    00432             {
    00433
    00434                 int lab = *xl;
    00435                 SrcType v = sa(xs);
    00436
    00437                 if (isExtremum[lab] == 0)
    00438                     continue;
    00439
    00440                 if (!compare(v, threshold))
    00441                 {
    00442                     // mark all regions that don't exceed the threshold as non-extremum
    00443                     isExtremum[lab] = 0;
    00444                     continue;
    00445                 }
    00446
    00447                 AtVolumeBorder atBorder = isAtVolumeBorder(x, y, z, w, h, d);
    00448                 if (atBorder == NotAtBorder)
    00449                 {
    00450                     NeighborhoodCirculator<SrcIterator, Neighborhood> sc(xs);
    00451                     NeighborhoodCirculator<MultiArray<3, int>::traverser, Neighborhood> lc(xl);
    00452                     for (i = 0; i < Neighborhood::DirectionCount; ++i, ++sc, ++lc)
    00453                     {
    00454                         if (lab != *lc && compare(sa(sc), v))
    00455                         {
    00456
    00457                             isExtremum[lab] = 0;
    00458                             break;
    00459                         }
    00460                     }
    00461                 }
    00462                 else
    00463                 {
    00464                     if (allowExtremaAtBorder)
    00465                     {
    00466                         RestrictedNeighborhoodCirculator<SrcIterator, Neighborhood>
    00467                         sc(xs, atBorder), scend(sc);
    00468                         do
    00469                         {
    00470                             if (lab != *(xl + sc.diff()) && compare(sa(sc), v))
    00471                             {
    00472                                 isExtremum[lab] = 0;
    00473                                 break;
    00474                             }
    00475                         }
    00476                         while (++sc != scend);
    00477                     }
    00478                     else
    00479                     {
    00480                         isExtremum[lab] = 0;
    00481                     }
    00482                 }
    00483             }
    00484         }
    00485     }
    00486
    00487     zl = labels.traverser_begin();
    00488     zs = sul;
    00489     zd = dul;
    00490
    00491     for (z = 0; z != d; ++z, ++zs.dim2(), ++zd.dim2(), ++zl.dim2())
    00492     {
    00493         SrcIterator ys(zs);
    00494         DestIterator yd(zd);
    00495         MultiArray<3, int>::traverser yl(zl);
    00496
    00497         for (y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1(), ++yl.dim1())
    00498         {
    00499             SrcIterator xs(ys);
    00500             DestIterator xd(yd);
    00501             MultiArray<3, int>::traverser xl(yl);
    00502
    00503             for (x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0(), ++xl.dim0())
    00504             {
    00505                 if(isExtremum[*xl])
    00506                     da.set(marker, xd);
    00507             }
    00508         }
    00509     }
    00510 }
    00511
    00512 template <class SrcIterator, class SrcAccessor,
    00513           class DestIterator, class DestAccessor, class DestValue,
    00514           class Neighborhood, class Compare, class Equal>
    00515 void
    00516 extendedLocalMinMaxOld(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    00517             DestIterator dul, DestAccessor da, DestValue marker,
    00518             Neighborhood /*neighborhood*/,
    00519             Compare compare, Equal equal,
    00520             typename SrcAccessor::value_type threshold,
    00521             bool allowExtremaAtBorder = false)
    00522 {
    00523     typedef typename SrcAccessor::value_type SrcType;
    00524
    00525     int w = slr.x - sul.x;
    00526     int h = slr.y - sul.y;
    00527
    00528     int i,x,y;
    00529
    00530     BasicImage<int> labels(w,h);
    00531
    00532     int number_of_regions =
    00533         labelImage(sul, slr, sa, labels.upperLeft(), labels.accessor(),
    00534                    (Neighborhood::DirectionCount == 8), equal);
    00535
    00536     // assume that a region is a extremum until the opposite is proved
    00537     std::vector<unsigned char> isExtremum(number_of_regions+1, (unsigned char)1);
    00538
    00539     BasicImage<int>::traverser ly = labels.upperLeft();
    00540
    00541     for(y=0; y<h; ++y, ++sul.y, ++ly.y)
    00542     {
    00543         SrcIterator  sx = sul;
    00544         BasicImage<int>::traverser lx(ly);
    00545
    00546         for(x=0; x<w; ++x, ++sx.x, ++lx.x)
    00547         {
    00548             int lab = *lx;
    00549             SrcType v = sa(sx);
    00550             if(x == 0 || y == 0 || x == w-1 || y == h-1 || !compare(v, threshold))
    00551             {
    00552                 // mark all regions that touch the image border as non-extremum
    00553                 // likewise for all pixels that don't exceed the threshold
    00554                 isExtremum[lab] = 0;
    00555                 continue;
    00556             }
    00557
    00558             NeighborhoodCirculator<SrcIterator, Neighborhood> sc(sx);
    00559             NeighborhoodCirculator<BasicImage<int>::traverser, Neighborhood> lc(lx);
    00560             for(i=0; i<Neighborhood::DirectionCount; ++i, ++sc, ++lc)
    00561             {
    00562                 if(lab != *lc && compare(sa(sc),v))
    00563                     isExtremum[lab] = 0;
    00564             }
    00565
    00566         }
    00567     }
    00568
    00569     ly = labels.upperLeft();
    00570     for(y=0; y<h; ++y, ++dul.y, ++ly.y)
    00571     {
    00572         DestIterator  xd = dul;
    00573         BasicImage<int>::Iterator lx(ly);
    00574
    00575         for(x=0; x<w; ++x, ++xd.x, ++lx.x)
    00576         {
    00577             if(isExtremum[*lx])
    00578                 da.set(marker, xd);
    00579         }
    00580     }
    00581 }
    00582
    00583 } // namespace detail
    00584
    00585
    00586 /** \brief Options object for localMinima() and localMaxima().
    00587
    00588     <b> Usage:</b>
    00589
    00590     <b>\#include</b> <vigra/localminmax.hxx><br>
    00591     Namespace: vigra
    00592
    00593     \code
    00594     vigra::BImage src(w,h), minima(w,h);
    00595     ... // fill src
    00596
    00597     // use 4-neighborhood, allow minima at the image border,
    00598     // and discard those where the gray value is not below 5
    00599     vigra::localMinima(srcImageRange(src), destImage(minima),
    00600                        vigra::LocalMinmaxOptions().neighborhood(4).allowAtBorder().threshold(5));
    00601
    00602     \endcode
    00603 */
    00604 class LocalMinmaxOptions
    00605 {
    00606   public:
    00607     double marker, thresh;
    00608     int neigh;
    00609     bool use_threshold, allow_at_border, allow_plateaus;
    00610
    00611         /**\brief Construct default options object.
    00612          *
    00613             Defaults are: marker value '1', no threshold, indirect neighborhood,
    00614                           don't allow extrema at border and extremal plateaus.
    00615          */
    00616     LocalMinmaxOptions()
    00617     : marker(1.0),
    00618       thresh(0.0),
    00619       neigh(1),
    00620       use_threshold(false),
    00621       allow_at_border(false),
    00622       allow_plateaus(false)
    00623     {}
    00624
    00625         /**\brief Use the given neighborhood.
    00626
    00627             The value '0' indicates direct neighborhood (i.e. 4-neighborhood
    00628             in 2D, 6-neighborhood in 3D, 2*N neighborhood in N-D), the value '1'
    00629             indicates indirect neighborhood (i.e. 8-neighborhood in 2D,
    00630             26-neighborhood in 3D, 3<sup>N</sup>-1 neighborhood in N-D). The specific number
    00631             of neighbors for the desired dimension can also be used.
    00632
    00633             Default: 1 (indirect neighborhood)
    00634          */
    00635     LocalMinmaxOptions & neighborhood(unsigned int n)
    00636     {
    00637         neigh = n;
    00638         return *this;
    00639     }
    00640
    00641         /**\brief Mark extrema in the destination image with the given value.
    00642
    00643             Default: 1
    00644          */
    00645     LocalMinmaxOptions & markWith(double m)
    00646     {
    00647         marker = m;
    00648         return *this;
    00649     }
    00650
    00651         /**\brief Threshold the extrema.
    00652
    00653            Discard minima whose gray value is not below the threshold.
    00654            and maxima whose gray level is not above the threshold.
    00655
    00656             Default: don't threshold (i.e. return all extrema)
    00657          */
    00658     LocalMinmaxOptions & threshold(double t)
    00659     {
    00660         use_threshold = true;
    00661         thresh = t;
    00662         return *this;
    00663     }
    00664
    00665         /**\brief Detect extrema at the image border.
    00666
    00667             Default: false
    00668          */
    00669     LocalMinmaxOptions & allowAtBorder(bool f = true)
    00670     {
    00671         allow_at_border = f;
    00672         return *this;
    00673     }
    00674
    00675         /**\brief Allow extremal plateaus.
    00676
    00677             That is regions of constant gray value whose neighbors are all
    00678             higher (minima) or lower than the value of the region.
    00679
    00680             Default: false
    00681          */
    00682     LocalMinmaxOptions & allowPlateaus(bool f = true)
    00683     {
    00684         allow_plateaus = f;
    00685         return *this;
    00686     }
    00687 };
    00688
    00689
    00690 /********************************************************/
    00691 /*                                                      */
    00692 /*                       localMinima                    */
    00693 /*                                                      */
    00694 /********************************************************/
    00695
    00696 /** \brief Find local minima in an image or multi-dimensional array.
    00697
    00698     Note: the function is not yet implemented for arbitrary dimensional
    00699     arrays, but see \ref localMinima3D() for 3D.
    00700
    00701     By default, minima are defined as points which are not
    00702     at the array border and whose value is lower than the value
    00703     of all indirect neighbors (i.e. 8-neighbors in 2D,
    00704     26-neighbors in 3D, 3<sup>N</sup>-1 neighbors in N-D).
    00705     The detected points will be marked
    00706     with the default value 1 in the destination array.
    00707
    00708     The defaults can be overridden in various ways by providing
    00709     \ref LocalMinmaxOptions : you can switch to the direct neighborhood
    00710     (i.e. 4-neighborhood in 2D, 6-neighborhood in 3D, 2*N neighborhood
    00711     in N-D), allow minima at the border, discard minima where the function
    00712     value is not below a given threshold, allow extended minima
    00713     (i.e. minima that form minimal plateaus rather than isolated pixels --
    00714     note that this option is only supported for 2D images),
    00715     and change the marker in the destination image. See usage examples below
    00716     for details.
    00717
    00718     There are also variants of the localMinima() function where parameters
    00719     are passed explicitly rather than via an option object. These versions
    00720     of the function are deprecated, but will be kept for compatibility.
    00721
    00722     <b> Declarations:</b>
    00723
    00724     use arbitrary-dimensional arrays:
    00725     \code
    00726     namespace vigra {
    00727         template <unsigned int N, class T1, class C1, class T2, class C2>
    00728         void
    00729         localMinima(MultiArrayView<N, T1, C1> src,
    00730                     MultiArrayView<N, T2, C2> dest,
    00731                     LocalMinmaxOptions const & options = LocalMinmaxOptions());
    00732     }
    00733     \endcode
    00734
    00735     pass image iterators explicitly:
    00736     \code
    00737     namespace vigra {
    00738         template <class SrcIterator, class SrcAccessor,
    00739                   class DestIterator, class DestAccessor>
    00740         void
    00741         localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    00742                     DestIterator dul, DestAccessor da,
    00743                     LocalMinmaxOptions const & options = LocalMinmaxOptions());
    00744     }
    00745     \endcode
    00746
    00747     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00748     \code
    00749     namespace vigra {
    00750         template <class SrcIterator, class SrcAccessor,
    00751                   class DestIterator, class DestAccessor>
    00752         void
    00753         localMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00754                     pair<DestIterator, DestAccessor> dest,
    00755                     LocalMinmaxOptions const & options = LocalMinmaxOptions());
    00756     }
    00757     \endcode
    00758
    00759     <b> Usage:</b>
    00760
    00761     <b>\#include</b> <vigra/localminmax.hxx><br>
    00762     <b>\#include</b> <vigra/multi_localminmax.hxx><br>
    00763     Namespace: vigra
    00764
    00765     \code
    00766     // 3D examples using MultiArray
    00767     vigra::MultiArrayShape<3>::type shape(w,h,d);
    00768     vigra::MultiArray<3, unsigned char> src(shape), minima(shape);
    00769     ... // fill src
    00770
    00771     // use default parameterisation
    00772     vigra::localMinima(src, minima);
    00773
    00774     // reset destination image
    00775     minima = 0;
    00776
    00777     // use 6-neighborhood and allow minima at the image border
    00778     vigra::localMinima(src, minima,
    00779                        vigra::LocalMinmaxOptions().neighborhood(6).allowAtBorder());
    00780     \endcode
    00781
    00782     \code
    00783     // 2D examples using BasicImage
    00784     vigra::BImage src(w,h), minima(w,h);
    00785     ... // fill src
    00786
    00787     // use default parameterisation
    00788     vigra::localMinima(srcImageRange(src), destImage(minima));
    00789
    00790     // reset destination image
    00791     minima = 0;
    00792
    00793     // use 4-neighborhood and allow minima at the image border
    00794     vigra::localMinima(srcImageRange(src), destImage(minima),
    00795                        vigra::LocalMinmaxOptions().neighborhood(4).allowAtBorder());
    00796
    00797     // reset destination image
    00798     minima = 0;
    00799
    00800     // allow extended minima (minimal plateaus) and use value '255' as a marker
    00801     vigra::localMinima(srcImageRange(src), destImage(minima),
    00802                        vigra::LocalMinmaxOptions().allowPlateaus().markWith(255));
    00803     \endcode
    00804
    00805     <b> Required Interface:</b>
    00806
    00807     \code
    00808     SrcIterator src_upperleft, src_lowerright;
    00809     DestIterator dest_upperleft;
    00810
    00811     SrcAccessor src_accessor;
    00812     DestAccessor dest_accessor;
    00813
    00814     SrcAccessor::value_type u = src_accessor(src_upperleft);
    00815
    00816     u < u
    00817     \endcode
    00818 */
    00819 doxygen_overloaded_function(template <...> void localMinima)
    00820
    00821 template <class SrcIterator, class SrcAccessor,
    00822           class DestIterator, class DestAccessor>
    00823 inline void
    00824 localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    00825             DestIterator dul, DestAccessor da,
    00826             LocalMinmaxOptions const & options = LocalMinmaxOptions())
    00827 {
    00828     typedef typename SrcAccessor::value_type SrcType;
    00829     typedef typename DestAccessor::value_type DestType;
    00830
    00831     SrcType threshold = options.use_threshold
    00832                            ? std::min(NumericTraits<SrcType>::max(), (SrcType)options.thresh)
    00833                            : NumericTraits<SrcType>::max();
    00834     DestType marker = (DestType)options.marker;
    00835
    00836     if(options.allow_plateaus)
    00837     {
    00838         if(options.neigh == 0 || options.neigh == 4)
    00839         {
    00840             detail::extendedLocalMinMax(sul, slr, sa, dul, da, marker, FourNeighborCode(),
    00841                                         std::less<SrcType>(), std::equal_to<SrcType>(),
    00842                                         threshold, options.allow_at_border);
    00843         }
    00844         else if(options.neigh == 1 || options.neigh == 8)
    00845         {
    00846             detail::extendedLocalMinMax(sul, slr, sa, dul, da, marker, EightNeighborCode(),
    00847                                         std::less<SrcType>(), std::equal_to<SrcType>(),
    00848                                         threshold, options.allow_at_border);
    00849         }
    00850         else
    00851             vigra_precondition(false, "localMinima(): neighborhood must be 4 or 8.");
    00852
    00853     }
    00854     else
    00855     {
    00856         if(options.neigh == 0 || options.neigh == 4)
    00857         {
    00858             detail::localMinMax(sul, slr, sa, dul, da, marker, FourNeighborCode(),
    00859                                 threshold, std::less<SrcType>(), options.allow_at_border);
    00860         }
    00861         else if(options.neigh == 1 || options.neigh == 8)
    00862         {
    00863             detail::localMinMax(sul, slr, sa, dul, da, marker, EightNeighborCode(),
    00864                                 threshold, std::less<SrcType>(), options.allow_at_border);
    00865         }
    00866         else
    00867             vigra_precondition(false, "localMinima(): neighborhood must be 4 or 8.");
    00868     }
    00869 }
    00870
    00871 template <class SrcIterator, class SrcAccessor,
    00872           class DestIterator, class DestAccessor,
    00873           class DestValue>
    00874 inline void
    00875 localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    00876             DestIterator dul, DestAccessor da,
    00877             DestValue marker, FourNeighborCode neighborhood)
    00878 {
    00879     detail::localMinMax(sul, slr, sa, dul, da, marker, neighborhood,
    00880                         NumericTraits<typename SrcAccessor::value_type>::max(),
    00881                         std::less<typename SrcAccessor::value_type>());
    00882 }
    00883
    00884 template <class SrcIterator, class SrcAccessor,
    00885           class DestIterator, class DestAccessor,
    00886           class DestValue>
    00887 inline void
    00888 localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    00889             DestIterator dul, DestAccessor da,
    00890             DestValue marker, EightNeighborCode neighborhood)
    00891 {
    00892     detail::localMinMax(sul, slr, sa, dul, da, marker, neighborhood,
    00893                         NumericTraits<typename SrcAccessor::value_type>::max(),
    00894                         std::less<typename SrcAccessor::value_type>());
    00895 }
    00896
    00897 template <class SrcIterator, class SrcAccessor,
    00898           class DestIterator, class DestAccessor, class DestValue>
    00899 inline void
    00900 localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    00901             DestIterator dul, DestAccessor da,
    00902             DestValue marker)
    00903 {
    00904     localMinima(sul, slr, sa, dul, da, marker, EightNeighborCode());
    00905 }
    00906
    00907 template <class SrcIterator, class SrcAccessor,
    00908           class DestIterator, class DestAccessor,
    00909           class DestValue>
    00910 inline void
    00911 localMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00912             pair<DestIterator, DestAccessor> dest,
    00913             DestValue marker, FourNeighborCode neighborhood)
    00914 {
    00915     localMinima(src.first, src.second, src.third,
    00916                 dest.first, dest.second, marker, neighborhood);
    00917 }
    00918
    00919 template <class SrcIterator, class SrcAccessor,
    00920           class DestIterator, class DestAccessor,
    00921           class DestValue>
    00922 inline void
    00923 localMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00924             pair<DestIterator, DestAccessor> dest,
    00925             DestValue marker, EightNeighborCode neighborhood)
    00926 {
    00927     localMinima(src.first, src.second, src.third,
    00928                 dest.first, dest.second, marker, neighborhood);
    00929 }
    00930
    00931 template <class SrcIterator, class SrcAccessor,
    00932           class DestIterator, class DestAccessor, class DestValue>
    00933 inline void
    00934 localMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00935             pair<DestIterator, DestAccessor> dest,
    00936             DestValue marker)
    00937 {
    00938     localMinima(src.first, src.second, src.third,
    00939                 dest.first, dest.second, marker, EightNeighborCode());
    00940 }
    00941
    00942 template <class SrcIterator, class SrcAccessor,
    00943           class DestIterator, class DestAccessor>
    00944 inline void
    00945 localMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00946             pair<DestIterator, DestAccessor> dest,
    00947             LocalMinmaxOptions const & options = LocalMinmaxOptions())
    00948 {
    00949     localMinima(src.first, src.second, src.third,
    00950                 dest.first, dest.second, options);
    00951 }
    00952
    00953 /**************************************************************************/
    00954
    00955 /********************************************************/
    00956 /*                                                      */
    00957 /*                       localMinima3D                  */
    00958 /*                                                      */
    00959 /********************************************************/
    00960
    00961 /** \brief Find local minima in a 3D multi array.
    00962
    00963  By default, minima are defined as points which are not
    00964  at the array border and whose value is lower than the value
    00965  of all indirect neighbors.
    00966  The detected points will be marked. See localMinima() for more details.
    00967
    00968  */
    00969 doxygen_overloaded_function(template <...> void localMinima3D)
    00970
    00971 template<class SrcIterator, class SrcAccessor, class SrcShape,
    00972          class DestIterator, class DestAccessor, class DestValue>
    00973 inline void
    00974 localMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
    00975               DestIterator dul, DestAccessor da,
    00976               DestValue marker,
    00977               NeighborCode3DTwentySix neighborhood)
    00978 {
    00979     detail::localMinMax3D(sul, slr, sa, dul, da, marker, neighborhood,
    00980                 NumericTraits<typename SrcAccessor::value_type>::max(),
    00981                 std::less<typename SrcAccessor::value_type>());
    00982 }
    00983
    00984 template<class SrcIterator, class SrcAccessor, class SrcShape,
    00985          class DestIterator, class DestAccessor, class DestValue>
    00986 inline void
    00987 localMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
    00988               DestIterator dul, DestAccessor da,
    00989               DestValue marker,
    00990               NeighborCode3DSix neighborhood)
    00991 {
    00992     detail::localMinMax3D(sul, slr, sa, dul, da, marker, neighborhood,
    00993                 NumericTraits<typename SrcAccessor::value_type>::max(),
    00994                 std::less<typename SrcAccessor::value_type>());
    00995 }
    00996
    00997 template<class SrcIterator, class SrcShape, class SrcAccessor,
    00998          class DestIterator, class DestAccessor, class DestValue>
    00999 inline void
    01000 localMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
    01001               DestIterator dul, DestAccessor da,
    01002               DestValue marker)
    01003 {
    01004     localMinima3D(sul, slr, sa, dul, da, marker, NeighborCode3DSix());
    01005 }
    01006
    01007 template<class SrcIterator, class SrcShape, class SrcAccessor,
    01008          class DestIterator, class DestAccessor, class DestValue>
    01009 inline void
    01010 localMinima3D(triple<SrcIterator, SrcShape, SrcAccessor> src,
    01011               pair<DestIterator, DestAccessor> dest,
    01012               DestValue marker,
    01013               NeighborCode3DSix neighborhood)
    01014 {
    01015     localMinima3D(src.first, src.second, src.third, dest.first, dest.second,
    01016                 marker, neighborhood);
    01017 }
    01018
    01019 template<class SrcIterator, class SrcShape, class SrcAccessor,
    01020          class DestIterator, class DestAccessor, class DestValue>
    01021 inline void
    01022 localMinima3D(triple<SrcIterator, SrcShape, SrcAccessor> src,
    01023               pair<DestIterator, DestAccessor> dest,
    01024               DestValue marker,
    01025               NeighborCode3DTwentySix neighborhood)
    01026 {
    01027     localMinima3D(src.first, src.second, src.third, dest.first, dest.second,
    01028                 marker, neighborhood);
    01029 }
    01030
    01031 /**************************************************************************/
    01032
    01033 /********************************************************/
    01034 /*                                                      */
    01035 /*                       localMaxima                    */
    01036 /*                                                      */
    01037 /********************************************************/
    01038
    01039 /** \brief Find local maxima in an image or multi-dimensional array.
    01040
    01041     Note: the function is not yet implemented for arbitrary dimensional
    01042     arrays, but see \ref localMaxima3D() for 3D.
    01043
    01044     By default, maxima are defined as points which are not
    01045     at the array border and whose value is higher than the value
    01046     of all indirect neighbors (i.e. 8-neighbors in 2D,
    01047     26-neighbors in 3D, 3<sup>N</sup>-1 neighbors in N-D).
    01048     The detected points will be marked
    01049     with the default value 1 in the destination array.
    01050
    01051     The defaults can be overridden in various ways by providing
    01052     \ref LocalMinmaxOptions : you can switch to the direct neighborhood
    01053     (i.e. 4-neighborhood in 2D, 6-neighborhood in 3D, 2*N neighborhood
    01054     in N-D), allow maxima at the border, discard maxima where the function
    01055     value is not above a given threshold, allow extended maxima
    01056     (i.e. maxima that form maximal plateaus rather than isolated pixels --
    01057     note that this option is only supported for 2D images),
    01058     and change the marker in the destination image. See usage examples below
    01059     for details.
    01060
    01061     There are also variants of the localMaxima() function where parameters
    01062     are passed explicitly rather than via an option object. These versions
    01063     of the function are deprecated, but will be kept for compatibility.
    01064
    01065     <b> Declarations:</b>
    01066
    01067     use arbitrary-dimensional arrays:
    01068     \code
    01069     namespace vigra {
    01070         template <unsigned int N, class T1, class C1, class T2, class C2>
    01071         void
    01072         localMaxima(MultiArrayView<N, T1, C1> src,
    01073                     MultiArrayView<N, T2, C2> dest,
    01074                     LocalMinmaxOptions const & options = LocalMinmaxOptions());
    01075     }
    01076     \endcode
    01077
    01078     pass image iterators explicitly:
    01079     \code
    01080     namespace vigra {
    01081         template <class SrcIterator, class SrcAccessor,
    01082                   class DestIterator, class DestAccessor>
    01083         void
    01084         localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    01085                     DestIterator dul, DestAccessor da,
    01086                     LocalMinmaxOptions const & options = LocalMinmaxOptions());
    01087     }
    01088     \endcode
    01089
    01090     use argument objects in conjunction with \ref ArgumentObjectFactories :
    01091     \code
    01092     namespace vigra {
    01093         template <class SrcIterator, class SrcAccessor,
    01094                   class DestIterator, class DestAccessor>
    01095         void
    01096         localMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01097                     pair<DestIterator, DestAccessor> dest,
    01098                     LocalMinmaxOptions const & options = LocalMinmaxOptions());
    01099     }
    01100     \endcode
    01101
    01102     <b> Usage:</b>
    01103
    01104         <b>\#include</b> <vigra/localminmax.hxx><br>
    01105         <b>\#include</b> <vigra/multi_localminmax.hxx><br>
    01106     Namespace: vigra
    01107
    01108     \code
    01109     // 3D examples using MultiArray
    01110     vigra::MultiArrayShape<3>::type shape(w,h,d);
    01111     vigra::MultiArray<3, unsigned char> src(shape), maxima(shape);
    01112     ... // fill src
    01113
    01114     // use default parameterisation
    01115     vigra::localMaxima(src, maxima);
    01116
    01117     // reset destination image
    01118     maxima = 0;
    01119
    01120     // use 6-neighborhood and allow maxima at the image border
    01121     vigra::localMaxima(src, maxima,
    01122                        vigra::LocalMinmaxOptions().neighborhood(6).allowAtBorder());
    01123     \endcode
    01124
    01125     \code
    01126     // 2D examples using BasicImage
    01127     vigra::BImage src(w,h), maxima(w,h);
    01128     ... // fill src
    01129
    01130     // use default parameterisation
    01131     vigra::localMaxima(srcImageRange(src), destImage(maxima));
    01132
    01133     // reset destination image
    01134     maxima = 0;
    01135
    01136     // use 4-neighborhood and allow maxima at the image border
    01137     vigra::localMaxima(srcImageRange(src), destImage(maxima),
    01138                        vigra::LocalMinmaxOptions().neighborhood(4).allowAtBorder());
    01139
    01140     // reset destination image
    01141     maxima = 0;
    01142
    01143     // allow extended maxima (maximal plateaus) and use value '255' as a marker
    01144     vigra::localMaxima(srcImageRange(src), destImage(maxima),
    01145                        vigra::LocalMinmaxOptions().allowPlateaus().markWith(255));
    01146     \endcode
    01147
    01148     <b> Required Interface:</b>
    01149
    01150     \code
    01151     SrcIterator src_upperleft, src_lowerright;
    01152     DestIterator dest_upperleft;
    01153
    01154     SrcAccessor src_accessor;
    01155     DestAccessor dest_accessor;
    01156
    01157     SrcAccessor::value_type u = src_accessor(src_upperleft);
    01158
    01159     u < u
    01160     \endcode
    01161 */
    01162 doxygen_overloaded_function(template <...> void localMaxima)
    01163
    01164 template <class SrcIterator, class SrcAccessor,
    01165           class DestIterator, class DestAccessor>
    01166 inline void
    01167 localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    01168             DestIterator dul, DestAccessor da,
    01169             LocalMinmaxOptions const & options = LocalMinmaxOptions())
    01170 {
    01171     typedef typename SrcAccessor::value_type SrcType;
    01172     typedef typename DestAccessor::value_type DestType;
    01173
    01174     SrcType threshold = options.use_threshold
    01175                            ? std::max(NumericTraits<SrcType>::min(), (SrcType)options.thresh)
    01176                            : NumericTraits<SrcType>::min();
    01177     DestType marker = (DestType)options.marker;
    01178
    01179     if(options.allow_plateaus)
    01180     {
    01181         if(options.neigh == 0 || options.neigh == 4)
    01182         {
    01183             detail::extendedLocalMinMax(sul, slr, sa, dul, da, marker, FourNeighborCode(),
    01184                                         std::greater<SrcType>(), std::equal_to<SrcType>(),
    01185                                         threshold, options.allow_at_border);
    01186         }
    01187         else if(options.neigh == 1 || options.neigh == 8)
    01188         {
    01189             detail::extendedLocalMinMax(sul, slr, sa, dul, da, marker, EightNeighborCode(),
    01190                                         std::greater<SrcType>(), std::equal_to<SrcType>(),
    01191                                         threshold, options.allow_at_border);
    01192         }
    01193         else
    01194             vigra_precondition(false, "localMaxima(): neighborhood must be 4 or 8.");
    01195     }
    01196     else
    01197     {
    01198         if(options.neigh == 0 || options.neigh == 4)
    01199         {
    01200             detail::localMinMax(sul, slr, sa, dul, da, marker, FourNeighborCode(),
    01201                                 threshold, std::greater<SrcType>(), options.allow_at_border);
    01202         }
    01203         else if(options.neigh == 1 || options.neigh == 8)
    01204         {
    01205             detail::localMinMax(sul, slr, sa, dul, da, marker, EightNeighborCode(),
    01206                                 threshold, std::greater<SrcType>(), options.allow_at_border);
    01207         }
    01208         else
    01209             vigra_precondition(false, "localMaxima(): neighborhood must be 4 or 8.");
    01210     }
    01211 }
    01212
    01213 template <class SrcIterator, class SrcAccessor,
    01214           class DestIterator, class DestAccessor,
    01215           class DestValue>
    01216 inline void
    01217 localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    01218             DestIterator dul, DestAccessor da,
    01219             DestValue marker, FourNeighborCode neighborhood)
    01220 {
    01221     detail::localMinMax(sul, slr, sa, dul, da, marker, neighborhood,
    01222                         NumericTraits<typename SrcAccessor::value_type>::min(),
    01223                         std::greater<typename SrcAccessor::value_type>());
    01224 }
    01225
    01226 template <class SrcIterator, class SrcAccessor,
    01227           class DestIterator, class DestAccessor,
    01228           class DestValue>
    01229 inline void
    01230 localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    01231             DestIterator dul, DestAccessor da,
    01232             DestValue marker, EightNeighborCode neighborhood)
    01233 {
    01234     detail::localMinMax(sul, slr, sa, dul, da, marker, neighborhood,
    01235                         NumericTraits<typename SrcAccessor::value_type>::min(),
    01236                         std::greater<typename SrcAccessor::value_type>());
    01237 }
    01238
    01239 template <class SrcIterator, class SrcAccessor,
    01240           class DestIterator, class DestAccessor, class DestValue>
    01241 inline void
    01242 localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    01243             DestIterator dul, DestAccessor da,
    01244             DestValue marker)
    01245 {
    01246     localMaxima(sul, slr, sa, dul, da, marker, EightNeighborCode());
    01247 }
    01248
    01249 template <class SrcIterator, class SrcAccessor,
    01250           class DestIterator, class DestAccessor,
    01251           class DestValue>
    01252 inline void
    01253 localMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01254             pair<DestIterator, DestAccessor> dest,
    01255             DestValue marker, FourNeighborCode neighborhood)
    01256 {
    01257     localMaxima(src.first, src.second, src.third,
    01258                 dest.first, dest.second, marker, neighborhood);
    01259 }
    01260
    01261 template <class SrcIterator, class SrcAccessor,
    01262           class DestIterator, class DestAccessor,
    01263           class DestValue>
    01264 inline void
    01265 localMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01266             pair<DestIterator, DestAccessor> dest,
    01267             DestValue marker, EightNeighborCode neighborhood)
    01268 {
    01269     localMaxima(src.first, src.second, src.third,
    01270                 dest.first, dest.second, marker, neighborhood);
    01271 }
    01272
    01273 template <class SrcIterator, class SrcAccessor,
    01274           class DestIterator, class DestAccessor, class DestValue>
    01275 inline void
    01276 localMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01277             pair<DestIterator, DestAccessor> dest,
    01278             DestValue marker)
    01279 {
    01280     localMaxima(src.first, src.second, src.third,
    01281                 dest.first, dest.second, marker, EightNeighborCode());
    01282 }
    01283
    01284 template <class SrcIterator, class SrcAccessor,
    01285           class DestIterator, class DestAccessor>
    01286 inline void
    01287 localMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01288             pair<DestIterator, DestAccessor> dest,
    01289             LocalMinmaxOptions const & options = LocalMinmaxOptions())
    01290 {
    01291     localMaxima(src.first, src.second, src.third,
    01292                 dest.first, dest.second, options);
    01293 }
    01294
    01295 /**************************************************************************/
    01296
    01297 /********************************************************/
    01298 /*                                                      */
    01299 /*                       localMaxima3D                  */
    01300 /*                                                      */
    01301 /********************************************************/
    01302
    01303 /** \brief Find local maxima in a 3D multi array.
    01304
    01305  By default, maxima are defined as points which are not
    01306  at the array border and whose value is higher than the value
    01307  of all indirect neighbors.
    01308  The detected points will be marked as specified. See localMaxima() for mor details.
    01309  */
    01310 doxygen_overloaded_function(template <...> void localMaxima3D)
    01311
    01312 template<class SrcIterator, class SrcShape, class SrcAccessor,
    01313          class DestIterator, class DestAccessor, class DestValue>
    01314 inline void
    01315 localMaxima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
    01316               DestIterator dul, DestAccessor da,
    01317               DestValue marker,
    01318               NeighborCode3DSix neighborhood)
    01319 {
    01320     detail::localMinMax3D(sul, slr, sa, dul, da, marker, neighborhood,
    01321                 NumericTraits<typename SrcAccessor::value_type>::min(),
    01322                 std::greater<typename SrcAccessor::value_type>());
    01323 }
    01324
    01325 template<class SrcIterator, class SrcShape, class SrcAccessor,
    01326          class DestIterator, class DestAccessor, class DestValue>
    01327 inline void
    01328 localMaxima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
    01329               DestIterator dul, DestAccessor da,
    01330               DestValue marker,
    01331               NeighborCode3DTwentySix neighborhood)
    01332 {
    01333     detail::localMinMax3D(sul, slr, sa, dul, da, marker, neighborhood,
    01334                 NumericTraits<typename SrcAccessor::value_type>::min(),
    01335                 std::greater<typename SrcAccessor::value_type>());
    01336 }
    01337
    01338 template<class SrcIterator, class SrcShape, class SrcAccessor,
    01339          class DestIterator, class DestAccessor, class DestValue>
    01340 inline void
    01341 localMaxima3D(triple<SrcIterator, SrcShape, SrcAccessor> src,
    01342               pair<DestIterator, DestAccessor> dest,
    01343               DestValue marker,
    01344               NeighborCode3DTwentySix neighborhood)
    01345 {
    01346     localMaxima3D(src.first, src.second, src.third, dest.first, dest.second,
    01347                 marker, neighborhood);
    01348 }
    01349
    01350 template<class SrcIterator, class SrcShape, class SrcAccessor,
    01351          class DestIterator, class DestAccessor, class DestValue>
    01352 inline void
    01353 localMaxima3D(vigra::triple<SrcIterator, SrcShape, SrcAccessor> src,
    01354               std::pair<DestIterator, DestAccessor> dest,
    01355               DestValue marker)
    01356 {
    01357     localMaxima3D(src.first, src.second, src.third, dest.first, dest.second,
    01358                 marker, NeighborCode3DSix());
    01359 }
    01360
    01361 template<class SrcIterator, class SrcShape, class SrcAccessor,
    01362          class DestIterator, class DestAccessor, class DestValue>
    01363 inline void
    01364 localMaxima3D(triple<SrcIterator, SrcShape, SrcAccessor> src,
    01365               pair<DestIterator, DestAccessor> dest,
    01366               DestValue marker,
    01367               NeighborCode3DSix neighborhood)
    01368 {
    01369     localMaxima3D(src.first, src.second, src.third, dest.first, dest.second,
    01370                 marker, neighborhood);
    01371 }
    01372
    01373 /**************************************************************************/
    01374
    01375 /********************************************************/
    01376 /*                                                      */
    01377 /*                 extendedLocalMinima                  */
    01378 /*                                                      */
    01379 /********************************************************/
    01380
    01381 /** \brief Find local minimal regions in an image or volume.
    01382
    01383     Note: the function is not yet implemented for arbitrary dimensional
    01384     arrays, but see \ref extendedLocalMinima3D() for 3D.
    01385
    01386     This function finds regions of uniform pixel value
    01387     whose neighboring regions are all have smaller values
    01388     (minimal plateaus of arbitrary size). By default, the pixels
    01389     in a plateau have exactly identical values. By passing an <tt>EqualityFunctor</tt>
    01390     with tolerance, one can allow for plateaus that are not quite constant
    01391     (this is often necessary with float pixel values). Pass
    01392     \ref vigra::EightNeighborCode or \ref vigra::FourNeighborCode
    01393     to determine the neighborhood where pixel values are compared.
    01394
    01395     Minimal regions are
    01396     marked in the destination image with the given marker value
    01397     (default is 1), all other destination pixels remain unchanged.
    01398     <TT>SrcAccessor::value_type</TT> must be equality-comparable and
    01399     less-comparable. A pixel or region touching the image border will
    01400     never be marked as minimum or minimal plateau. Use localMinima() with the
    01401     appropriate options if you need that functionality. Likewise if you want to
    01402     apply a threshold onl the fly. In fact, all functionality
    01403     except for 'equality with tolerance' can be accessed via that function in
    01404     a more readable way, so localMinima() should be preferred.
    01405     The function uses accessors.
    01406
    01407     <b> Declarations:</b>
    01408
    01409     use 3-dimensional arrays:
    01410     \code
    01411     namespace vigra {
    01412         template <class T1, class C1, class T2, class C2,
    01413                   class Neighborhood>
    01414         void
    01415         extendedLocalMinima(MultiArrayView<3, T1, C1> src,
    01416                             MultiArrayView<3, T2, C2> dest,
    01417                             LocalMinmaxOptions const & options = LocalMinmaxOptions());
    01418     \endcode
    01419
    01420     pass image iterators explicitly:
    01421     \code
    01422     namespace vigra {
    01423         template <class SrcIterator, class SrcAccessor,
    01424                   class DestIterator, class DestAccessor,
    01425                   class DestValue = DestAccessor::value_type,
    01426                   class Neighborhood = EightNeighborCode,
    01427                   class EqualityFunctor = std::equal_to<typename SrcAssessor::value_type> >
    01428         void
    01429         extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    01430                             DestIterator dul, DestAccessor da,
    01431                             DestValue marker = NumericTraits<DestValue>::one(),
    01432                             Neighborhood neighborhood = EightNeighborCode(),
    01433                             EqualityFunctor equal = EqualityFunctor());
    01434     }
    01435     \endcode
    01436
    01437     use argument objects in conjunction with \ref ArgumentObjectFactories :
    01438     \code
    01439     namespace vigra {
    01440         template <class SrcIterator, class SrcAccessor,
    01441                   class DestIterator, class DestAccessor,
    01442                   class DestValue = DestAccessor::value_type,
    01443                   class Neighborhood = EightNeighborCode,
    01444                   class EqualityFunctor = std::equal_to<typename SrcAssessor::value_type> >
    01445         void
    01446         extendedLocalMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01447                             pair<DestIterator, DestAccessor> dest,
    01448                             DestValue marker = NumericTraits<DestValue>::one(),
    01449                             Neighborhood neighborhood = EightNeighborCode(),
    01450                             EqualityFunctor equal = EqualityFunctor());
    01451     }
    01452     \endcode
    01453
    01454     <b> Usage:</b>
    01455
    01456         <b>\#include</b> <vigra/localminmax.hxx><br>
    01457     Namespace: vigra
    01458
    01459     \code
    01460
    01461     // optional: define an equality functor
    01462     template <class T>
    01463     struct EqualWithToleranceFunctor
    01464     {
    01465         EqualWithToleranceFunctor(T tolerance)
    01466         : t(tolerance)
    01467         {}
    01468
    01469         bool operator()(T l, T r) const
    01470         {
    01471             return vigra::abs(l-r) <= t;
    01472         }
    01473
    01474         T t;
    01475     };
    01476
    01477     vigra::BImage src(w,h), minima(w,h);
    01478
    01479     // init destiniation image
    01480     minima.init(0);
    01481
    01482     vigra::extendedLocalMinima(srcImageRange(src), destImage(minima));
    01483
    01484     // allow plateaus with tolerance
    01485     minima.init(0);
    01486     vigra::extendedLocalMinima(srcImageRange(src), destImage(minima), 1.0,
    01487                                EqualWithToleranceFunctor<unsigned char>(1));
    01488     \endcode
    01489
    01490     <b> Required Interface:</b>
    01491
    01492     \code
    01493     SrcImageIterator src_upperleft, src_lowerright;
    01494     DestImageIterator dest_upperleft;
    01495
    01496     SrcAccessor src_accessor;
    01497     DestAccessor dest_accessor;
    01498
    01499     SrcAccessor::value_type u = src_accessor(src_upperleft);
    01500
    01501     EqualityFunctor equal;
    01502     u == u
    01503     equal(u, u);
    01504     u < u
    01505
    01506     DestValue marker;
    01507     dest_accessor.set(marker, dest_upperleft);
    01508     \endcode
    01509
    01510 */
    01511 doxygen_overloaded_function(template <...> void extendedLocalMinima)
    01512
    01513 template <class SrcIterator, class SrcAccessor,
    01514           class DestIterator, class DestAccessor,
    01515           class Neighborhood, class EqualityFunctor>
    01516 inline void
    01517 extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    01518             DestIterator dul, DestAccessor da,
    01519             typename DestAccessor::value_type marker,
    01520             Neighborhood neighborhood, EqualityFunctor equal)
    01521 {
    01522     typedef typename SrcAccessor::value_type SrcType;
    01523
    01524     detail::extendedLocalMinMax(sul, slr, sa, dul, da,
    01525                                 marker, neighborhood,
    01526                                 std::less<SrcType>(), equal,
    01527                                 NumericTraits<typename SrcAccessor::value_type>::max());
    01528 }
    01529
    01530 template <class SrcIterator, class SrcAccessor,
    01531           class DestIterator, class DestAccessor,
    01532           class Neighborhood>
    01533 inline void
    01534 extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    01535             DestIterator dul, DestAccessor da,
    01536             typename DestAccessor::value_type marker,
    01537             Neighborhood neighborhood)
    01538 {
    01539     typedef typename SrcAccessor::value_type SrcType;
    01540
    01541     extendedLocalMinima(sul, slr, sa, dul, da,
    01542                         marker, neighborhood, std::equal_to<SrcType>());
    01543 }
    01544
    01545 template <class SrcIterator, class SrcAccessor,
    01546           class DestIterator, class DestAccessor>
    01547 inline void
    01548 extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    01549             DestIterator dul, DestAccessor da,
    01550             typename DestAccessor::value_type marker)
    01551 {
    01552     typedef typename SrcAccessor::value_type SrcType;
    01553
    01554     extendedLocalMinima(sul, slr, sa, dul, da,
    01555                         marker, EightNeighborCode());
    01556 }
    01557
    01558 template <class SrcIterator, class SrcAccessor,
    01559           class DestIterator, class DestAccessor>
    01560 inline void
    01561 extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    01562             DestIterator dul, DestAccessor da)
    01563 {
    01564     extendedLocalMinima(sul, slr, sa, dul, da,
    01565                 NumericTraits<typename DestAccessor::value_type>::one());
    01566 }
    01567
    01568 template <class SrcIterator, class SrcAccessor,
    01569           class DestIterator, class DestAccessor,
    01570           class Neighborhood, class EqualityFunctor>
    01571 inline void
    01572 extendedLocalMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01573             pair<DestIterator, DestAccessor> dest,
    01574             typename DestAccessor::value_type marker, Neighborhood neighborhood,
    01575             EqualityFunctor equal)
    01576 {
    01577     extendedLocalMinima(src.first, src.second, src.third,
    01578                 dest.first, dest.second, marker, neighborhood, equal);
    01579 }
    01580
    01581 template <class SrcIterator, class SrcAccessor,
    01582           class DestIterator, class DestAccessor,
    01583           class Neighborhood>
    01584 inline void
    01585 extendedLocalMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01586             pair<DestIterator, DestAccessor> dest,
    01587             typename DestAccessor::value_type marker, Neighborhood neighborhood)
    01588 {
    01589     extendedLocalMinima(src.first, src.second, src.third,
    01590                         dest.first, dest.second, marker, neighborhood);
    01591 }
    01592
    01593 template <class SrcIterator, class SrcAccessor,
    01594           class DestIterator, class DestAccessor>
    01595 inline void
    01596 extendedLocalMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01597             pair<DestIterator, DestAccessor> dest,
    01598             typename DestAccessor::value_type marker)
    01599 {
    01600     extendedLocalMinima(src.first, src.second, src.third,
    01601                         dest.first, dest.second, marker, EightNeighborCode());
    01602 }
    01603
    01604 template <class SrcIterator, class SrcAccessor,
    01605           class DestIterator, class DestAccessor>
    01606 inline void
    01607 extendedLocalMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01608             pair<DestIterator, DestAccessor> dest)
    01609 {
    01610     extendedLocalMinima(src.first, src.second, src.third,
    01611                         dest.first, dest.second);
    01612 }
    01613
    01614 /**************************************************************************/
    01615
    01616 /********************************************************/
    01617 /*                                                      */
    01618 /*                 extendedLocalMinima3D                */
    01619 /*                                                      */
    01620 /********************************************************/
    01621
    01622 /** \brief Find local minimal regions in a volume.
    01623
    01624  This function finds regions of uniform pixel value
    01625  whose neighboring regions are all have smaller values
    01626  (minimal plateaus of arbitrary size). By default, the pixels
    01627  in a plateau have exactly identical values. By passing an <tt>EqualityFunctor</tt>
    01628  with tolerance, one can allow for plateaus that are not quite constant
    01629  (this is often necessary with float pixel values). Pass the neighborhood
    01630  where pixel values are compared. See extendedLocalMinima() for more details.
    01631
    01632 */
    01633 doxygen_overloaded_function(template <...> void extendedLocalMinima3D)
    01634
    01635 template<class SrcIterator, class SrcShape, class SrcAccessor,
    01636          class DestIterator, class DestAccessor, class Neighborhood,
    01637          class EqualityFunctor>
    01638 inline void
    01639 extendedLocalMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
    01640                       DestIterator dul, DestAccessor da,
    01641                       typename DestAccessor::value_type marker,
    01642                       Neighborhood neighborhood,
    01643                       EqualityFunctor equal)
    01644 {
    01645     typedef typename SrcAccessor::value_type SrcType;
    01646
    01647     detail::extendedLocalMinMax3D(sul, slr, sa, dul, da, marker, neighborhood,
    01648                 std::less<SrcType>(), equal,
    01649                 NumericTraits<typename SrcAccessor::value_type>::max());
    01650 }
    01651
    01652 template<class SrcIterator, class SrcShape, class SrcAccessor,
    01653          class DestIterator, class DestAccessor, class Neighborhood>
    01654 inline void
    01655 extendedLocalMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
    01656                       DestIterator dul, DestAccessor da,
    01657                       typename DestAccessor::value_type marker,
    01658                       Neighborhood neighborhood)
    01659 {
    01660     typedef typename SrcAccessor::value_type SrcType;
    01661
    01662     extendedLocalMinima3D(sul, slr, sa, dul, da, marker, neighborhood,
    01663                           std::equal_to<SrcType>());
    01664 }
    01665
    01666 template<class SrcIterator, class SrcShape, class SrcAccessor,
    01667          class DestIterator, class DestAccessor>
    01668 inline void
    01669 extendedLocalMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
    01670                       DestIterator dul, DestAccessor da)
    01671 {
    01672     extendedLocalMinima3D(sul, slr, sa, dul, da,
    01673                           NumericTraits<typename DestAccessor::value_type>::one(),
    01674                           NeighborCode3DSix());
    01675 }
    01676
    01677 template<class SrcIterator, class SrcAccessor, class SrcShape,
    01678          class DestIterator, class DestAccessor, class Neighborhood>
    01679 inline void
    01680 extendedLocalMinima3D(triple<SrcIterator, SrcShape, SrcAccessor> src,
    01681                       pair<DestIterator, DestAccessor> dest,
    01682                       typename DestAccessor::value_type marker,
    01683                       Neighborhood neighborhood)
    01684 {
    01685     extendedLocalMinima3D(src.first, src.second, src.third,
    01686                           dest.first, dest.second,
    01687                           marker, neighborhood);
    01688 }
    01689
    01690 /**************************************************************************/
    01691
    01692 /********************************************************/
    01693 /*                                                      */
    01694 /*                 extendedLocalMaxima                  */
    01695 /*                                                      */
    01696 /********************************************************/
    01697
    01698 /** \brief Find local maximal regions in an image or volume.
    01699
    01700     Note: the function is not yet implemented for arbitrary dimensional
    01701     arrays, but see \ref extendedLocalMaxima3D() for 3D.
    01702
    01703     This function finds regions of uniform pixel value
    01704     whose neighboring regions are all have smaller values
    01705     (maximal plateaus of arbitrary size). By default, the pixels
    01706     in a plateau have exactly identical values. By passing an <tt>EqualityFunctor</tt>
    01707     with tolerance, one can allow for plateaus that are not quite constant
    01708     (this is often necessary with float pixel values). Pass
    01709     \ref vigra::EightNeighborCode or \ref vigra::FourNeighborCode
    01710     to determine the neighborhood where pixel values are compared.
    01711
    01712     Maximal regions are
    01713     marked in the destination image with the given marker value
    01714     (default is 1), all other destination pixels remain unchanged.
    01715     <TT>SrcAccessor::value_type</TT> must be equality-comparable and
    01716     less-comparable. A pixel or region touching the image border will
    01717     never be marked as maximum or maximal plateau. Use localMaxima() with the
    01718     appropriate options if you need that functionality. Likewise if you want to
    01719     apply a threshold onl the fly. In fact, all functionality
    01720     except for 'equality with tolerance' can be accessed via that function in
    01721     a more readable way, so localMaxima() should be preferred.
    01722     The function uses accessors.
    01723
    01724     <b> Declarations:</b>
    01725
    01726     use 3-dimensional arrays:
    01727     \code
    01728     namespace vigra {
    01729         template <class T1, class C1, class T2, class C2,
    01730                   class Neighborhood>
    01731         void
    01732         extendedLocalMaxima(MultiArrayView<3, T1, C1> src,
    01733                             MultiArrayView<3, T2, C2> dest,
    01734                             LocalMinmaxOptions const & options = LocalMinmaxOptions());
    01735     \endcode
    01736
    01737     pass image iterators explicitly:
    01738     \code
    01739     namespace vigra {
    01740         template <class SrcIterator, class SrcAccessor,
    01741                   class DestIterator, class DestAccessor,
    01742                   class DestValue = DestAccessor::value_type,
    01743                   class Neighborhood = EightNeighborCode,
    01744                   class EqualityFunctor = std::equal_to<typename SrcAssessor::value_type> >
    01745         void
    01746         extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    01747                             DestIterator dul, DestAccessor da,
    01748                             DestValue marker = NumericTraits<DestValue>::one(),
    01749                             Neighborhood neighborhood = EightNeighborCode(),
    01750                             EqualityFunctor equal = EqualityFunctor())
    01751     }
    01752     \endcode
    01753
    01754     use argument objects in conjunction with \ref ArgumentObjectFactories :
    01755     \code
    01756     namespace vigra {
    01757         template <class SrcIterator, class SrcAccessor,
    01758                   class DestIterator, class DestAccessor,
    01759                   class DestValue = DestAccessor::value_type,
    01760                   class Neighborhood = EightNeighborCode,
    01761                   class EqualityFunctor = std::equal_to<typename SrcAssessor::value_type> >
    01762         void
    01763         extendedLocalMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01764                             pair<DestIterator, DestAccessor> dest,
    01765                             DestValue marker = NumericTraits<DestValue>::one(),
    01766                             Neighborhood neighborhood = EightNeighborCode(),
    01767                             EqualityFunctor equal = EqualityFunctor())
    01768     }
    01769     \endcode
    01770
    01771     <b> Usage:</b>
    01772
    01773         <b>\#include</b> <vigra/localminmax.hxx><br>
    01774     Namespace: vigra
    01775
    01776     \code
    01777
    01778     // optional: define an equality functor
    01779     template <class T>
    01780     struct EqualWithToleranceFunctor
    01781     {
    01782         EqualWithToleranceFunctor(T tolerance)
    01783         : t(tolerance)
    01784         {}
    01785
    01786         bool operator()(T l, T r) const
    01787         {
    01788             return vigra::abs(l-r) <= t;
    01789         }
    01790
    01791         T t;
    01792     };
    01793
    01794     vigra::BImage src(w,h), maxima(w,h);
    01795
    01796     // init destiniation image
    01797     maxima.init(0);
    01798
    01799     vigra::extendedLocalMaxima(srcImageRange(src), destImage(maxima));
    01800
    01801     // allow plateaus with tolerance
    01802     maxima.init(0);
    01803     vigra::extendedLocalMaxima(srcImageRange(src), destImage(maxima), 1.0,
    01804                                EqualWithToleranceFunctor<unsigned char>(1));
    01805     \endcode
    01806
    01807     <b> Required Interface:</b>
    01808
    01809     \code
    01810     SrcImageIterator src_upperleft, src_lowerright;
    01811     DestImageIterator dest_upperleft;
    01812
    01813     SrcAccessor src_accessor;
    01814     DestAccessor dest_accessor;
    01815
    01816     SrcAccessor::value_type u = src_accessor(src_upperleft);
    01817
    01818     EqualityFunctor equal;
    01819     u == u
    01820     equal(u, u);
    01821     u < u
    01822
    01823     DestValue marker;
    01824     dest_accessor.set(marker, dest_upperleft);
    01825     \endcode
    01826
    01827 */
    01828 doxygen_overloaded_function(template <...> void extendedLocalMaxima)
    01829
    01830 template <class SrcIterator, class SrcAccessor,
    01831           class DestIterator, class DestAccessor,
    01832           class Neighborhood, class EqualityFunctor>
    01833 inline void
    01834 extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    01835             DestIterator dul, DestAccessor da,
    01836             typename DestAccessor::value_type marker,
    01837             Neighborhood neighborhood, EqualityFunctor equal)
    01838 {
    01839     typedef typename SrcAccessor::value_type SrcType;
    01840
    01841     detail::extendedLocalMinMax(sul, slr, sa, dul, da,
    01842                                 marker, neighborhood,
    01843                                 std::greater<SrcType>(), equal,
    01844                                 NumericTraits<typename SrcAccessor::value_type>::min());
    01845 }
    01846
    01847 template <class SrcIterator, class SrcAccessor,
    01848           class DestIterator, class DestAccessor,
    01849           class Neighborhood>
    01850 inline void
    01851 extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    01852             DestIterator dul, DestAccessor da,
    01853             typename DestAccessor::value_type marker,
    01854             Neighborhood neighborhood)
    01855 {
    01856     typedef typename SrcAccessor::value_type SrcType;
    01857
    01858     extendedLocalMaxima(sul, slr, sa, dul, da,
    01859                         marker, neighborhood, std::equal_to<SrcType>());
    01860 }
    01861
    01862 template <class SrcIterator, class SrcAccessor,
    01863           class DestIterator, class DestAccessor>
    01864 inline void
    01865 extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    01866             DestIterator dul, DestAccessor da,
    01867             typename DestAccessor::value_type marker)
    01868 {
    01869     typedef typename SrcAccessor::value_type SrcType;
    01870
    01871     extendedLocalMaxima(sul, slr, sa, dul, da,
    01872                         marker, EightNeighborCode());
    01873 }
    01874
    01875 template <class SrcIterator, class SrcAccessor,
    01876           class DestIterator, class DestAccessor>
    01877 inline void
    01878 extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
    01879             DestIterator dul, DestAccessor da)
    01880 {
    01881     extendedLocalMaxima(sul, slr, sa, dul, da,
    01882                 NumericTraits<typename DestAccessor::value_type>::one());
    01883 }
    01884
    01885 template <class SrcIterator, class SrcAccessor,
    01886           class DestIterator, class DestAccessor,
    01887           class Neighborhood, class EqualityFunctor>
    01888 inline void
    01889 extendedLocalMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01890             pair<DestIterator, DestAccessor> dest,
    01891             typename DestAccessor::value_type marker, Neighborhood neighborhood,
    01892             EqualityFunctor equal)
    01893 {
    01894     extendedLocalMaxima(src.first, src.second, src.third,
    01895                 dest.first, dest.second, marker, neighborhood, equal);
    01896 }
    01897
    01898 template <class SrcIterator, class SrcAccessor,
    01899           class DestIterator, class DestAccessor,
    01900           class Neighborhood>
    01901 inline void
    01902 extendedLocalMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01903             pair<DestIterator, DestAccessor> dest,
    01904             typename DestAccessor::value_type marker, Neighborhood neighborhood)
    01905 {
    01906     extendedLocalMaxima(src.first, src.second, src.third,
    01907                         dest.first, dest.second, marker, neighborhood);
    01908 }
    01909
    01910 template <class SrcIterator, class SrcAccessor,
    01911           class DestIterator, class DestAccessor>
    01912 inline void
    01913 extendedLocalMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01914             pair<DestIterator, DestAccessor> dest,
    01915             typename DestAccessor::value_type marker)
    01916 {
    01917     extendedLocalMaxima(src.first, src.second, src.third,
    01918                         dest.first, dest.second, marker, EightNeighborCode());
    01919 }
    01920
    01921 template <class SrcIterator, class SrcAccessor,
    01922           class DestIterator, class DestAccessor>
    01923 inline void
    01924 extendedLocalMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
    01925             pair<DestIterator, DestAccessor> dest)
    01926 {
    01927     extendedLocalMaxima(src.first, src.second, src.third,
    01928                         dest.first, dest.second);
    01929 }
    01930
    01931 /********************************************************/
    01932 /*                                                      */
    01933 /*                 extendedLocalMaxima3D                */
    01934 /*                                                      */
    01935 /********************************************************/
    01936
    01937 /** \brief Find local maximal regions in 3D multi array.
    01938
    01939  This function finds regions of uniform pixel value
    01940  whose neighboring regions are all have smaller values
    01941  (maximal plateaus of arbitrary size). By default, the pixels
    01942  in a plateau have exactly identical values. By passing an <tt>EqualityFunctor</tt>
    01943  with tolerance, one can allow for plateaus that are not quite constant
    01944  (this is often necessary with float pixel values). Pass
    01945  the neighborhood where pixel values are compared. See extendedLocalMaxima() for more details.
    01946  */
    01947
    01948 doxygen_overloaded_function(template <...> void extendedLocalMaxima3D)
    01949
    01950 template<class SrcIterator, class SrcShape, class SrcAccessor,
    01951          class DestIterator, class DestAccessor, class Neighborhood,
    01952          class EqualityFunctor>
    01953 inline void
    01954 extendedLocalMaxima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
    01955                       DestIterator dul, DestAccessor da,
    01956                       typename DestAccessor::value_type marker,
    01957                       Neighborhood neighborhood,
    01958                       EqualityFunctor equal)
    01959 {
    01960     typedef typename SrcAccessor::value_type SrcType;
    01961
    01962     detail::extendedLocalMinMax3D(sul, slr, sa, dul, da, marker, neighborhood,
    01963                                   std::greater<SrcType>(), equal,
    01964                                   NumericTraits<typename SrcAccessor::value_type>::min());
    01965 }
    01966
    01967 template<class SrcIterator, class SrcShape, class SrcAccessor,
    01968          class DestIterator, class DestAccessor, class Neighborhood>
    01969 inline void
    01970 extendedLocalMaxima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
    01971                       DestIterator dul, DestAccessor da,
    01972                       typename DestAccessor::value_type marker,
    01973                       Neighborhood neighborhood)
    01974 {
    01975     typedef typename SrcAccessor::value_type SrcType;
    01976
    01977     extendedLocalMaxima3D(sul, slr, sa, dul, da,
    01978                           marker, neighborhood,
    01979                           std::equal_to<SrcType>());
    01980 }
    01981
    01982 template<class SrcIterator, class SrcShape, class SrcAccessor,
    01983          class DestIterator, class DestAccessor>
    01984 inline void
    01985 extendedLocalMaxima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa,
    01986                       DestIterator dul, DestAccessor da)
    01987 {
    01988     extendedLocalMaxima3D(sul, slr, sa, dul, da,
    01989                           NumericTraits<typename DestAccessor::value_type>::one(),
    01990                           NeighborCode3DSix());
    01991 }
    01992
    01993 template<class SrcIterator, class SrcShape, class SrcAccessor,
    01994          class DestIterator, class DestAccessor, class Neighborhood>
    01995 inline void
    01996 extendedLocalMaxima3D(triple<SrcIterator, SrcShape, SrcAccessor> src,
    01997                       pair<DestIterator, DestAccessor> dest,
    01998                       typename DestAccessor::value_type marker,
    01999                       Neighborhood neighborhood)
    02000 {
    02001     extendedLocalMaxima3D(src.first, src.second, src.third,
    02002                           dest.first, dest.second,
    02003                           marker, neighborhood);
    02004 }
    02005
    02006 //@}
    02007
    02008 } // namespace vigra
    02009
    02010 #endif // VIGRA_LOCALMINMAX_HXX

© 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.9.0 (Tue Nov 6 2012)