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

details vigra/flatmorphology.hxx VIGRA

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
00005 /*                                                                      */
00006 /*    This file is part of the VIGRA computer vision library.           */
00007 /*    ( Version 1.2.0, Aug 07 2003 )                                    */
00008 /*    You may use, modify, and distribute this software according       */
00009 /*    to the terms stated in the LICENSE file included in               */
00010 /*    the VIGRA distribution.                                           */
00011 /*                                                                      */
00012 /*    The VIGRA Website is                                              */
00013 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00014 /*    Please direct questions, bug reports, and contributions to        */
00015 /*        koethe@informatik.uni-hamburg.de                              */
00016 /*                                                                      */
00017 /*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
00018 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
00019 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
00020 /*                                                                      */
00021 /************************************************************************/
00022  
00023  
00024 #ifndef VIGRA_FLATMORPHOLOGY_HXX
00025 #define VIGRA_FLATMORPHOLOGY_HXX
00026 
00027 #include <cmath>
00028 #include <vector>
00029 #include "vigra/utilities.hxx"
00030 
00031 namespace vigra {
00032 
00033 /** \addtogroup Morphology Basic Morphological Operations
00034     Perform erosion, dilation, and median with disc structuring functions
00035 */
00036 //@{
00037 
00038 /********************************************************/
00039 /*                                                      */
00040 /*                  discRankOrderFilter                 */
00041 /*                                                      */
00042 /********************************************************/
00043 
00044 /** \brief Apply rank order filter with disc structuring function to the image.
00045 
00046     The pixel values of the source image <b> must</b> be in the range
00047     0...255. Radius must be >= 0. Rank must be in the range 0.0 <= rank 
00048     <= 1.0. The filter acts as a minimum filter if rank = 0.0, 
00049     as a median if rank = 0.5, and as a maximum filter if rank = 1.0.
00050     Accessor are used to access the pixel data.
00051     
00052     <b> Declarations:</b>
00053     
00054     pass arguments explicitely:
00055     \code
00056     namespace vigra {
00057         template <class SrcIterator, class SrcAccessor,
00058               class DestIterator, class DestAccessor>
00059         void
00060         discRankOrderFilter(SrcIterator upperleft1, 
00061                 SrcIterator lowerright1, SrcAccessor sa,
00062                 DestIterator upperleft2, DestAccessor da,
00063                 int radius, float rank)
00064     }
00065     \endcode
00066     
00067     
00068     use argument objects in conjuction with \ref ArgumentObjectFactories:
00069     \code
00070     namespace vigra {
00071         template <class SrcIterator, class SrcAccessor,
00072               class DestIterator, class DestAccessor>
00073         void
00074         discRankOrderFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00075                 pair<DestIterator, DestAccessor> dest,
00076                 int radius, float rank)
00077     }
00078     \endcode
00079     
00080     <b> Usage:</b>
00081     
00082         <b>\#include</b> "<a href="flatmorphology_8hxx-source.html">vigra/flatmorphology.hxx</a>"<br>
00083     Namespace: vigra
00084     
00085     \code
00086     vigra::CImage src, dest;
00087     
00088     // do median filtering
00089     vigra::discRankOrderFilter(srcImageRange(src), destImage(dest), 10, 0.5);
00090     \endcode
00091 
00092     <b> Required Interface:</b>
00093     
00094     \code
00095     SrcIterator src_upperleft;
00096     DestIterator dest_upperleft;
00097     int x, y;
00098     unsigned char value;
00099     
00100     SrcAccessor src_accessor;
00101     DestAccessor dest_accessor;
00102     
00103     // value_type of accessor must be convertible to unsigned char
00104     value = src_accessor(src_upperleft, x, y); 
00105     
00106     dest_accessor.set(value, dest_upperleft, x, y);
00107     \endcode
00108     
00109     <b> Preconditions:</b>
00110     
00111     \code
00112     for all source pixels: 0 <= value <= 255
00113     
00114     (rank >= 0.0) && (rank <= 1.0)
00115     radius >= 0
00116     \endcode
00117     
00118 */
00119 template <class SrcIterator, class SrcAccessor,
00120           class DestIterator, class DestAccessor>
00121 void
00122 discRankOrderFilter(SrcIterator upperleft1, 
00123                     SrcIterator lowerright1, SrcAccessor sa,
00124                     DestIterator upperleft2, DestAccessor da,
00125             int radius, float rank)
00126 {
00127     vigra_precondition((rank >= 0.0) && (rank <= 1.0),
00128             "discRankOrderFilter(): Rank must be between 0 and 1"
00129         " (inclusive).");
00130     
00131     vigra_precondition(radius >= 0,
00132             "discRankOrderFilter(): Radius must be >= 0.");
00133     
00134     int i, x, y, xmax, ymax, xx, yy;
00135     int rankpos, winsize, leftsum;
00136     
00137     long hist[256];
00138     
00139     // prepare structuring function
00140     std::vector<int> struct_function(radius+1);
00141     struct_function[0] = radius;
00142     
00143     double r2 = (double)radius*radius;
00144     for(i=1; i<=radius; ++i)
00145     {
00146     double r = (double) i - 0.5;
00147     struct_function[i] = (int)(VIGRA_CSTD::sqrt(r2 - r*r) + 0.5);
00148     }
00149 
00150     int w = lowerright1.x - upperleft1.x;
00151     int h = lowerright1.y - upperleft1.y;
00152     
00153     SrcIterator ys(upperleft1);
00154     DestIterator yd(upperleft2);
00155 
00156     for(y=0; y<h; ++y, ++ys.y, ++yd.y)
00157     {
00158     SrcIterator xs(ys);
00159     DestIterator xd(yd);
00160         
00161     // first column
00162     int x0 = 0;
00163     int y0 = y;
00164     int x1 = w - 1;
00165     int y1 = h - y - 1;
00166 
00167     // clear histogram
00168     for(i=0; i<256; ++i) hist[i] = 0;
00169     winsize = 0;
00170     
00171     // init histogram
00172     ymax = (y1 < radius) ? y1 : radius;
00173     for(yy=0; yy<=ymax; ++yy)
00174     {
00175         xmax = (x1 < struct_function[yy]) ? x1 : struct_function[yy];
00176         for(xx=0; xx<=xmax; ++xx)
00177         {
00178         hist[sa(xs, Diff2D(xx, yy))]++;
00179         winsize++;
00180         }
00181     }
00182     
00183     ymax = (y0 < radius) ? y0 : radius;
00184     for(yy=1; yy<=ymax; ++yy)
00185     {
00186         xmax = (x1 < struct_function[yy]) ? x1 : struct_function[yy];
00187         for(xx=0; xx<=xmax; ++xx)
00188         {
00189         hist[sa(xs, Diff2D(xx, -yy))]++;
00190         winsize++;
00191         }
00192     }
00193     
00194     // find the desired histogramm bin 
00195     leftsum = 0;
00196     if(rank == 0.0)
00197     {
00198         for(i=0; i<256; i++)
00199         {
00200         if(hist[i]) break;
00201         }
00202         rankpos = i;
00203     }
00204     else
00205     {
00206         for(i=0; i<256; i++)
00207         {
00208         if((float)(hist[i]+leftsum) / winsize >= rank) break;
00209         leftsum += hist[i];
00210         }
00211         rankpos = i;
00212     }
00213     
00214     da.set(rankpos, xd);
00215     
00216     ++xs.x;
00217     ++xd.x;
00218     
00219     // inner columns
00220     for(x=1; x<w; ++x, ++xs.x, ++xd.x)
00221     {
00222         x0 = x;
00223         y0 = y;
00224         x1 = w - x - 1;
00225         y1 = h - y - 1;
00226         
00227         // update histogramm 
00228         // remove pixels at left border 
00229         yy = (y1 < radius) ? y1 : radius;
00230         for(; yy>=0; yy--)
00231         {
00232         unsigned char cur;
00233         xx = struct_function[yy]+1;
00234         if(xx > x0) break;
00235         
00236         cur = sa(xs, Diff2D(-xx, yy));
00237         
00238         hist[cur]--;
00239         if(cur < rankpos) leftsum--;
00240         winsize--;
00241         }
00242         yy = (y0 < radius) ? y0 : radius;
00243         for(; yy>=1; yy--)
00244         {
00245         unsigned char cur;
00246         xx = struct_function[yy]+1;
00247         if(xx > x0) break;
00248         
00249         cur = sa(xs, Diff2D(-xx, -yy));
00250         
00251         hist[cur]--;
00252         if(cur < rankpos) leftsum--;
00253         winsize--;
00254         }
00255         
00256         // add pixels at right border 
00257         yy = (y1 < radius) ? y1 : radius;
00258         for(; yy>=0; yy--)
00259         {
00260         unsigned char cur;
00261         xx = struct_function[yy];
00262         if(xx > x1) break;
00263         
00264         cur = sa(xs, Diff2D(xx, yy));
00265         
00266         hist[cur]++;
00267         if(cur < rankpos) leftsum++;
00268         winsize++;
00269         }
00270         yy = (y0 < radius) ? y0 : radius;
00271         for(; yy>=1; yy--)
00272         {
00273         unsigned char cur;
00274         xx = struct_function[yy];
00275         if(xx > x1) break;
00276         
00277         cur = sa(xs, Diff2D(xx, -yy));
00278         
00279         hist[cur]++;
00280         if(cur < rankpos) leftsum++;
00281         winsize++;
00282         }
00283     
00284         // find the desired histogramm bin 
00285         if(rank == 0.0)
00286         {
00287         if(leftsum == 0)
00288         {
00289             // search to the right 
00290             for(i=rankpos; i<256; i++)
00291             {
00292             if(hist[i]) break;
00293             }
00294             rankpos = i;
00295         }
00296         else
00297         {
00298             // search to the left 
00299             for(i=rankpos-1; i>=0; i--)
00300             {
00301             leftsum -= hist[i];
00302             if(leftsum == 0) break;
00303             }
00304             rankpos = i;
00305         }
00306         }
00307         else  // rank > 0.0 
00308         {
00309         if((float)leftsum / winsize < rank)
00310         {
00311             // search to the right 
00312             for(i=rankpos; i<256; i++)
00313             {
00314             if((float)(hist[i]+leftsum) / winsize >= rank) break;
00315             leftsum+=hist[i];
00316             }
00317             rankpos = i;
00318         }
00319         else
00320         {
00321             /// search to the left 
00322             for(i=rankpos-1; i>=0; i--)
00323             {
00324             leftsum-=hist[i];
00325             if((float)leftsum / winsize < rank) break;
00326             }
00327             rankpos = i;
00328         }
00329         }
00330             
00331         da.set(rankpos, xd);
00332     }
00333     }
00334 }
00335 
00336 template <class SrcIterator, class SrcAccessor,
00337           class DestIterator, class DestAccessor>
00338 void
00339 discRankOrderFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00340                     pair<DestIterator, DestAccessor> dest,
00341             int radius, float rank)
00342 {
00343     discRankOrderFilter(src.first, src.second, src.third,
00344                         dest.first, dest.second,
00345             radius, rank);
00346 }
00347 
00348 /********************************************************/
00349 /*                                                      */
00350 /*                      discErosion                     */
00351 /*                                                      */
00352 /********************************************************/
00353 
00354 /** \brief Apply erosion (minimum) filter with disc of given radius to image.
00355 
00356     This is an abbreviation vor the rank order filter with rank = 0.0.
00357     See \ref discRankOrderFilter() for more information.
00358     
00359     <b> Declarations:</b>
00360     
00361     pass arguments explicitely:
00362     \code
00363     namespace vigra {
00364         template <class SrcIterator, class SrcAccessor,
00365               class DestIterator, class DestAccessor>
00366         inline void 
00367         discErosion(SrcIterator upperleft1, 
00368             SrcIterator lowerright1, SrcAccessor sa,
00369             DestIterator upperleft2, DestAccessor da,
00370             int radius)
00371     }
00372     \endcode
00373     
00374     
00375     use argument objects in conjuction with \ref ArgumentObjectFactories:
00376     \code
00377     namespace vigra {
00378         template <class SrcIterator, class SrcAccessor,
00379               class DestIterator, class DestAccessor>
00380         void
00381         discErosion(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00382             pair<DestIterator, DestAccessor> dest,
00383             int radius)
00384     }
00385     \endcode
00386 
00387 */
00388 template <class SrcIterator, class SrcAccessor,
00389           class DestIterator, class DestAccessor>
00390 inline void 
00391 discErosion(SrcIterator upperleft1, 
00392             SrcIterator lowerright1, SrcAccessor sa,
00393             DestIterator upperleft2, DestAccessor da,
00394         int radius)
00395 {
00396     vigra_precondition(radius >= 0, "discErosion(): Radius must be >= 0.");
00397     
00398     discRankOrderFilter(upperleft1, lowerright1, sa, 
00399                         upperleft2, da, radius, 0.0);
00400 }
00401 
00402 template <class SrcIterator, class SrcAccessor,
00403           class DestIterator, class DestAccessor>
00404 void
00405 discErosion(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00406             pair<DestIterator, DestAccessor> dest,
00407             int radius)
00408 {
00409     vigra_precondition(radius >= 0, "discErosion(): Radius must be >= 0.");
00410     
00411     discRankOrderFilter(src.first, src.second, src.third,
00412                         dest.first, dest.second,
00413             radius, 0.0);
00414 }
00415 
00416 /********************************************************/
00417 /*                                                      */
00418 /*                     discDilation                     */
00419 /*                                                      */
00420 /********************************************************/
00421 
00422 /** \brief Apply dilation (maximum) filter with disc of given radius to image.
00423 
00424     This is an abbreviation vor the rank order filter with rank = 1.0.
00425     See \ref discRankOrderFilter() for more information.
00426     
00427     <b> Declarations:</b>
00428     
00429     pass arguments explicitely:
00430     \code
00431     namespace vigra {
00432         template <class SrcIterator, class SrcAccessor,
00433               class DestIterator, class DestAccessor>
00434         inline void 
00435         discDilation(SrcIterator upperleft1, 
00436             SrcIterator lowerright1, SrcAccessor sa,
00437             DestIterator upperleft2, DestAccessor da,
00438             int radius)
00439     }
00440     \endcode
00441     
00442     
00443     use argument objects in conjuction with \ref ArgumentObjectFactories:
00444     \code
00445     namespace vigra {
00446         template <class SrcIterator, class SrcAccessor,
00447               class DestIterator, class DestAccessor>
00448         void
00449         discDilation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00450             pair<DestIterator, DestAccessor> dest,
00451             int radius)
00452     }
00453     \endcode
00454 
00455 */
00456 template <class SrcIterator, class SrcAccessor,
00457           class DestIterator, class DestAccessor>
00458 inline void 
00459 discDilation(SrcIterator upperleft1, 
00460             SrcIterator lowerright1, SrcAccessor sa,
00461             DestIterator upperleft2, DestAccessor da,
00462         int radius)
00463 {
00464     vigra_precondition(radius >= 0, "discDilation(): Radius must be >= 0.");
00465     
00466     discRankOrderFilter(upperleft1, lowerright1, sa, 
00467                         upperleft2, da, radius, 1.0);
00468 }
00469 
00470 template <class SrcIterator, class SrcAccessor,
00471           class DestIterator, class DestAccessor>
00472 void
00473 discDilation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00474             pair<DestIterator, DestAccessor> dest,
00475             int radius)
00476 {
00477     vigra_precondition(radius >= 0, "discDilation(): Radius must be >= 0.");
00478     
00479     discRankOrderFilter(src.first, src.second, src.third,
00480                         dest.first, dest.second,
00481             radius, 1.0);
00482 }
00483 
00484 /********************************************************/
00485 /*                                                      */
00486 /*                      discMedian                      */
00487 /*                                                      */
00488 /********************************************************/
00489 
00490 /** \brief Apply median filter with disc of given radius to image.
00491 
00492     This is an abbreviation vor the rank order filter with rank = 0.5.
00493     See \ref discRankOrderFilter() for more information.
00494     
00495     <b> Declarations:</b>
00496     
00497     pass arguments explicitely:
00498     \code
00499     namespace vigra {
00500         template <class SrcIterator, class SrcAccessor,
00501               class DestIterator, class DestAccessor>
00502         inline void 
00503         discMedian(SrcIterator upperleft1, 
00504             SrcIterator lowerright1, SrcAccessor sa,
00505             DestIterator upperleft2, DestAccessor da,
00506             int radius)
00507     }
00508     \endcode
00509     
00510     
00511     use argument objects in conjuction with \ref ArgumentObjectFactories:
00512     \code
00513     namespace vigra {
00514         template <class SrcIterator, class SrcAccessor,
00515               class DestIterator, class DestAccessor>
00516         void
00517         discMedian(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00518             pair<DestIterator, DestAccessor> dest,
00519             int radius)
00520     }
00521     \endcode
00522 
00523 */
00524 template <class SrcIterator, class SrcAccessor,
00525           class DestIterator, class DestAccessor>
00526 inline void 
00527 discMedian(SrcIterator upperleft1, 
00528             SrcIterator lowerright1, SrcAccessor sa,
00529             DestIterator upperleft2, DestAccessor da,
00530         int radius)
00531 {
00532     vigra_precondition(radius >= 0, "discMedian(): Radius must be >= 0.");
00533     
00534     discRankOrderFilter(upperleft1, lowerright1, sa, 
00535                         upperleft2, da, radius, 0.5);
00536 }
00537 
00538 template <class SrcIterator, class SrcAccessor,
00539           class DestIterator, class DestAccessor>
00540 void
00541 discMedian(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00542             pair<DestIterator, DestAccessor> dest,
00543             int radius)
00544 {
00545     vigra_precondition(radius >= 0, "discMedian(): Radius must be >= 0.");
00546     
00547     discRankOrderFilter(src.first, src.second, src.third,
00548                         dest.first, dest.second,
00549             radius, 0.5);
00550 }
00551 
00552 /********************************************************/
00553 /*                                                      */
00554 /*            discRankOrderFilterWithMask               */
00555 /*                                                      */
00556 /********************************************************/
00557 
00558 /** \brief Apply rank order filter with disc structuring function to the image
00559     using a mask.
00560     
00561     The pixel values of the source image <b> must</b> be in the range
00562     0...255. Radius must be >= 0. Rank must be in the range 0.0 <= rank 
00563     <= 1.0. The filter acts as a minimum filter if rank = 0.0, 
00564     as a median if rank = 0.5, and as a maximum filter if rank = 1.0.
00565     Accessor are used to access the pixel data.
00566     
00567     The mask is only applied to th input image, i.e. the function
00568     generates an output wherever the current disc contains at least 
00569     one pixel with mask value 'true'. Source pixels with mask value
00570     'false' are ignored during the calculation of the rank order.
00571     
00572     <b> Declarations:</b>
00573     
00574     pass arguments explicitely:
00575     \code
00576     namespace vigra {
00577         template <class SrcIterator, class SrcAccessor,
00578               class MaskIterator, class MaskAccessor,
00579               class DestIterator, class DestAccessor>
00580         void
00581         discRankOrderFilterWithMask(SrcIterator upperleft1, 
00582                     SrcIterator lowerright1, SrcAccessor sa,
00583                     MaskIterator upperleftm, MaskAccessor mask,
00584                     DestIterator upperleft2, DestAccessor da,
00585                     int radius, float rank)
00586     }
00587     \endcode
00588     
00589     
00590     group arguments (use in conjuction with \ref ArgumentObjectFactories):
00591     \code
00592     namespace vigra {
00593         template <class SrcIterator, class SrcAccessor,
00594               class MaskIterator, class MaskAccessor,
00595               class DestIterator, class DestAccessor>
00596         void
00597         discRankOrderFilterWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00598                     pair<MaskIterator, MaskAccessor> mask,
00599                     pair<DestIterator, DestAccessor> dest,
00600                     int radius, float rank)
00601     }
00602     \endcode
00603     
00604     <b> Usage:</b>
00605     
00606         <b>\#include</b> "<a href="flatmorphology_8hxx-source.html">vigra/flatmorphology.hxx</a>"<br>
00607     Namespace: vigra
00608     
00609     \code
00610     vigra::CImage src, dest, mask;
00611     
00612     // do median filtering
00613     vigra::discRankOrderFilterWithMask(srcImageRange(src), 
00614                                 maskImage(mask), destImage(dest), 10, 0.5);
00615     \endcode
00616 
00617     <b> Required Interface:</b>
00618     
00619     \code
00620     SrcIterator src_upperleft;
00621     DestIterator dest_upperleft;
00622     MaskIterator mask_upperleft;
00623     int x, y;
00624     unsigned char value;
00625     
00626     SrcAccessor src_accessor;
00627     DestAccessor dest_accessor;
00628     MaskAccessor mask_accessor;
00629              
00630     mask_accessor(mask_upperleft, x, y) // convertible to bool
00631     
00632     // value_type of accessor must be convertible to unsigned char
00633     value = src_accessor(src_upperleft, x, y); 
00634     
00635     dest_accessor.set(value, dest_upperleft, x, y);
00636     \endcode
00637     
00638     <b> Preconditions:</b>
00639     
00640     \code
00641     for all source pixels: 0 <= value <= 255
00642     
00643     (rank >= 0.0) && (rank <= 1.0)
00644     radius >= 0
00645     \endcode
00646     
00647 */
00648 template <class SrcIterator, class SrcAccessor,
00649           class MaskIterator, class MaskAccessor,
00650       class DestIterator, class DestAccessor>
00651 void
00652 discRankOrderFilterWithMask(SrcIterator upperleft1, 
00653                             SrcIterator lowerright1, SrcAccessor sa,
00654                             MaskIterator upperleftm, MaskAccessor mask,
00655                 DestIterator upperleft2, DestAccessor da,
00656                 int radius, float rank)
00657 {
00658     vigra_precondition((rank >= 0.0) && (rank <= 1.0),
00659                  "discRankOrderFilter(): Rank must be between 0 and 1"
00660          " (inclusive).");
00661     
00662     vigra_precondition(radius >= 0, "discRankOrderFilter(): Radius must be >= 0.");
00663     
00664     int i, x, y, xmax, ymax, xx, yy;
00665     int rankpos, winsize, leftsum;
00666     
00667     long hist[256];
00668     
00669     // prepare structuring function
00670     std::vector<int> struct_function(radius+1);
00671     struct_function[0] = radius;
00672     
00673     double r2 = (double)radius*radius;
00674     for(i=1; i<=radius; ++i)
00675     {
00676     double r = (double) i - 0.5;
00677     struct_function[i] = (int)(VIGRA_CSTD::sqrt(r2 - r*r) + 0.5);
00678     }
00679 
00680     int w = lowerright1.x - upperleft1.x;
00681     int h = lowerright1.y - upperleft1.y;
00682         
00683     SrcIterator ys(upperleft1);
00684     MaskIterator ym(upperleftm);
00685     DestIterator yd(upperleft2);
00686 
00687     for(y=0; y<h; ++y, ++ys.y, ++yd.y, ++ym.y)
00688     {
00689     SrcIterator xs(ys);
00690     MaskIterator xm(ym);
00691     DestIterator xd(yd);
00692         
00693     // first column
00694     int x0 = 0;
00695     int y0 = y;
00696     int x1 = w - 1;
00697     int y1 = h - y - 1;
00698 
00699     // clear histogram
00700     for(i=0; i<256; ++i) hist[i] = 0;
00701     winsize = 0;
00702     leftsum = 0;
00703     rankpos = 0;
00704     
00705     // init histogram
00706     ymax = (y1 < radius) ? y1 : radius;
00707     for(yy=0; yy<=ymax; ++yy)
00708     {
00709         xmax = (x1 < struct_function[yy]) ? x1 : struct_function[yy];
00710         for(xx=0; xx<=xmax; ++xx)
00711         {
00712             Diff2D pos(xx, yy);
00713                 if(mask(xm, pos))
00714         {
00715             hist[sa(xs, pos)]++;
00716             winsize++;
00717         }
00718         }
00719     }
00720     
00721     ymax = (y0 < radius) ? y0 : radius;
00722     for(yy=1; yy<=ymax; ++yy)
00723     {
00724         xmax = (x1 < struct_function[yy]) ? x1 : struct_function[yy];
00725         for(xx=0; xx<=xmax; ++xx)
00726         {
00727             Diff2D pos(xx, -yy);
00728             if(mask(xm, pos))
00729         {
00730             hist[sa(xs, pos)]++;
00731             winsize++;
00732         }
00733         }
00734     }
00735     
00736     // find the desired histogramm bin 
00737     if(winsize) 
00738     {
00739         if(rank == 0.0)
00740         {
00741         for(i=0; i<256; i++)
00742         {
00743             if(hist[i]) break;
00744         }
00745         rankpos = i;
00746         }
00747         else
00748         {
00749         for(i=0; i<256; i++)
00750         {
00751             if((float)(hist[i]+leftsum) / winsize >= rank) break;
00752             leftsum += hist[i];
00753         }
00754         rankpos = i;
00755         }
00756         
00757         da.set(rankpos, xd);
00758     }
00759         
00760     ++xs.x;
00761     ++xd.x;
00762     ++xm.x;
00763     
00764     // inner columns
00765     for(x=1; x<w; ++x, ++xs.x, ++xd.x, ++xm.x)
00766     {
00767         x0 = x;
00768         y0 = y;
00769         x1 = w - x - 1;
00770         y1 = h - y - 1;
00771         
00772         // update histogramm 
00773         // remove pixels at left border 
00774         yy = (y1 < radius) ? y1 : radius;
00775         for(; yy>=0; yy--)
00776         {
00777         unsigned char cur;
00778         xx = struct_function[yy]+1;
00779         if(xx > x0) break;
00780         
00781             Diff2D pos(-xx, yy);
00782             if(mask(xm, pos))
00783         {
00784             cur = sa(xs, pos);
00785             
00786             hist[cur]--;
00787             if(cur < rankpos) leftsum--;
00788             winsize--;
00789         }
00790         }
00791         yy = (y0 < radius) ? y0 : radius;
00792         for(; yy>=1; yy--)
00793         {
00794         unsigned char cur;
00795         xx = struct_function[yy]+1;
00796         if(xx > x0) break;
00797         
00798             Diff2D pos(-xx, -yy);
00799             if(mask(xm, pos))
00800         {
00801             cur = sa(xs, pos);
00802             
00803             hist[cur]--;
00804             if(cur < rankpos) leftsum--;
00805             winsize--;
00806         }
00807         }
00808         
00809         // add pixels at right border 
00810         yy = (y1 < radius) ? y1 : radius;
00811         for(; yy>=0; yy--)
00812         {
00813         unsigned char cur;
00814         xx = struct_function[yy];
00815         if(xx > x1) break;
00816         
00817             Diff2D pos(xx, yy);
00818             if(mask(xm, pos))
00819         {
00820             cur = sa(xs, pos);
00821             
00822             hist[cur]++;
00823             if(cur < rankpos) leftsum++;
00824             winsize++;
00825         }
00826         }
00827         yy = (y0 < radius) ? y0 : radius;
00828         for(; yy>=1; yy--)
00829         {
00830         unsigned char cur;
00831         xx = struct_function[yy];
00832         if(xx > x1) break;
00833         
00834             Diff2D pos(xx, -yy);
00835             if(mask(xm, pos))
00836         {
00837             cur = sa(xs, pos);
00838             
00839             hist[cur]++;
00840             if(cur < rankpos) leftsum++;
00841             winsize++;
00842         }
00843         }
00844     
00845         // find the desired histogramm bin 
00846         if(winsize) 
00847         {
00848         if(rank == 0.0)
00849         {
00850             if(leftsum == 0)
00851             {
00852             // search to the right 
00853             for(i=rankpos; i<256; i++)
00854             {
00855                 if(hist[i]) break;
00856             }
00857             rankpos = i;
00858             }
00859             else
00860             {
00861             // search to the left 
00862             for(i=rankpos-1; i>=0; i--)
00863             {
00864                 leftsum -= hist[i];
00865                 if(leftsum == 0) break;
00866             }
00867             rankpos = i;
00868             }
00869         }
00870         else  // rank > 0.0 
00871         {
00872             if((float)leftsum / winsize < rank)
00873             {
00874             // search to the right 
00875             for(i=rankpos; i<256; i++)
00876             {
00877                 if((float)(hist[i]+leftsum) / winsize >= rank) break;
00878                 leftsum+=hist[i];
00879             }
00880             rankpos = i;
00881             }
00882             else
00883             {
00884             /// search to the left 
00885             for(i=rankpos-1; i>=0; i--)
00886             {
00887                 leftsum-=hist[i];
00888                 if((float)leftsum / winsize < rank) break;
00889             }
00890             rankpos = i;
00891             }
00892         }
00893             
00894         da.set(rankpos, xd);
00895         }
00896         else
00897         {
00898             leftsum = 0;
00899         rankpos = 0;
00900         }
00901     }
00902     }
00903 }
00904 
00905 template <class SrcIterator, class SrcAccessor,
00906           class MaskIterator, class MaskAccessor,
00907       class DestIterator, class DestAccessor>
00908 void
00909 discRankOrderFilterWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00910                             pair<MaskIterator, MaskAccessor> mask,
00911                 pair<DestIterator, DestAccessor> dest,
00912                 int radius, float rank)
00913 {
00914     discRankOrderFilterWithMask(src.first, src.second, src.third,
00915                         mask.first, mask.second,
00916                         dest.first, dest.second,
00917             radius, rank);
00918 }
00919 
00920 /********************************************************/
00921 /*                                                      */
00922 /*                 discErosionWithMask                  */
00923 /*                                                      */
00924 /********************************************************/
00925 
00926 /** \brief Apply erosion (minimum) filter with disc of given radius to image
00927     using a mask.
00928     
00929     This is an abbreviation vor the masked rank order filter with 
00930     rank = 0.0. See \ref discRankOrderFilterWithMask() for more information.
00931     
00932     <b> Declarations:</b>
00933     
00934     pass arguments explicitely:
00935     \code
00936     namespace vigra {
00937         template <class SrcIterator, class SrcAccessor,
00938               class MaskIterator, class MaskAccessor,
00939               class DestIterator, class DestAccessor>
00940         inline void 
00941         discErosionWithMask(SrcIterator upperleft1, 
00942                 SrcIterator lowerright1, SrcAccessor sa,
00943                 MaskIterator upperleftm, MaskAccessor mask,
00944                 DestIterator upperleft2, DestAccessor da,
00945                 int radius)
00946     }
00947     \endcode
00948     
00949     
00950     group arguments (use in conjuction with \ref ArgumentObjectFactories):
00951     \code
00952     namespace vigra {
00953         template <class SrcIterator, class SrcAccessor,
00954               class MaskIterator, class MaskAccessor,
00955               class DestIterator, class DestAccessor>
00956         inline void 
00957         discErosionWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00958                 pair<MaskIterator, MaskAccessor> mask,
00959                 pair<DestIterator, DestAccessor> dest,
00960                 int radius)
00961     }
00962     \endcode
00963 
00964 */
00965 template <class SrcIterator, class SrcAccessor,
00966           class MaskIterator, class MaskAccessor,
00967       class DestIterator, class DestAccessor>
00968 inline void 
00969 discErosionWithMask(SrcIterator upperleft1, 
00970             SrcIterator lowerright1, SrcAccessor sa,
00971             MaskIterator upperleftm, MaskAccessor mask,
00972             DestIterator upperleft2, DestAccessor da,
00973             int radius)
00974 {
00975     vigra_precondition(radius >= 0, "discErosionWithMask(): Radius must be >= 0.");
00976     
00977     discRankOrderFilterWithMask(upperleft1, lowerright1, sa, 
00978                                 upperleftm, mask,
00979                                 upperleft2, da,
00980                 radius, 0.0);
00981 }
00982 
00983 template <class SrcIterator, class SrcAccessor,
00984           class MaskIterator, class MaskAccessor,
00985       class DestIterator, class DestAccessor>
00986 inline void 
00987 discErosionWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src,
00988             pair<MaskIterator, MaskAccessor> mask,
00989             pair<DestIterator, DestAccessor> dest,
00990             int radius)
00991 {
00992     vigra_precondition(radius >= 0, "discErosionWithMask(): Radius must be >= 0.");
00993     
00994     discRankOrderFilterWithMask(src.first, src.second, src.third,
00995                         mask.first, mask.second,
00996                         dest.first, dest.second,
00997             radius, 0.0);
00998 }
00999 
01000 /********************************************************/
01001 /*                                                      */
01002 /*                discDilationWithMask                  */
01003 /*                                                      */
01004 /********************************************************/
01005 
01006 /** \brief Apply dilation (maximum) filter with disc of given radius to image
01007     using a mask.
01008     
01009     This is an abbreviation vor the masked rank order filter with 
01010     rank = 1.0. See \ref discRankOrderFilterWithMask() for more information.
01011     
01012     <b> Declarations:</b>
01013     
01014     pass arguments explicitely:
01015     \code
01016     namespace vigra {
01017         template <class SrcIterator, class SrcAccessor,
01018               class MaskIterator, class MaskAccessor,
01019               class DestIterator, class DestAccessor>
01020         inline void 
01021         discDilationWithMask(SrcIterator upperleft1, 
01022                 SrcIterator lowerright1, SrcAccessor sa,
01023                 MaskIterator upperleftm, MaskAccessor mask,
01024                 DestIterator upperleft2, DestAccessor da,
01025                 int radius)
01026     }
01027     \endcode
01028     
01029     
01030     group arguments (use in conjuction with \ref ArgumentObjectFactories):
01031     \code
01032     namespace vigra {
01033         template <class SrcIterator, class SrcAccessor,
01034               class MaskIterator, class MaskAccessor,
01035               class DestIterator, class DestAccessor>
01036         inline void 
01037         discDilationWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src,
01038                 pair<MaskIterator, MaskAccessor> mask,
01039                 pair<DestIterator, DestAccessor> dest,
01040                 int radius)
01041     }
01042     \endcode
01043 
01044 */
01045 template <class SrcIterator, class SrcAccessor,
01046           class MaskIterator, class MaskAccessor,
01047       class DestIterator, class DestAccessor>
01048 inline void 
01049 discDilationWithMask(SrcIterator upperleft1, 
01050             SrcIterator lowerright1, SrcAccessor sa,
01051             MaskIterator upperleftm, MaskAccessor mask,
01052             DestIterator upperleft2, DestAccessor da,
01053             int radius)
01054 {
01055     vigra_precondition(radius >= 0, "discDilationWithMask(): Radius must be >= 0.");
01056     
01057     discRankOrderFilterWithMask(upperleft1, lowerright1, sa, 
01058                                 upperleftm, mask,
01059                                 upperleft2, da,
01060                 radius, 1.0);
01061 }
01062 
01063 template <class SrcIterator, class SrcAccessor,
01064           class MaskIterator, class MaskAccessor,
01065       class DestIterator, class DestAccessor>
01066 inline void 
01067 discDilationWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src,
01068             pair<MaskIterator, MaskAccessor> mask,
01069             pair<DestIterator, DestAccessor> dest,
01070             int radius)
01071 {
01072     vigra_precondition(radius >= 0, "discDilationWithMask(): Radius must be >= 0.");
01073     
01074     discRankOrderFilterWithMask(src.first, src.second, src.third,
01075                         mask.first, mask.second,
01076                         dest.first, dest.second,
01077             radius, 1.0);
01078 }
01079 
01080 /********************************************************/
01081 /*                                                      */
01082 /*                 discMedianWithMask                   */
01083 /*                                                      */
01084 /********************************************************/
01085 
01086 /** \brief Apply median filter with disc of given radius to image
01087     using a mask.
01088     
01089     This is an abbreviation vor the masked rank order filter with 
01090     rank = 0.5. See \ref discRankOrderFilterWithMask() for more information.
01091     
01092     <b> Declarations:</b>
01093     
01094     pass arguments explicitely:
01095     \code
01096     namespace vigra {
01097         template <class SrcIterator, class SrcAccessor,
01098               class MaskIterator, class MaskAccessor,
01099               class DestIterator, class DestAccessor>
01100         inline void 
01101         discMedianWithMask(SrcIterator upperleft1, 
01102                 SrcIterator lowerright1, SrcAccessor sa,
01103                 MaskIterator upperleftm, MaskAccessor mask,
01104                 DestIterator upperleft2, DestAccessor da,
01105                 int radius)
01106     }
01107     \endcode
01108     
01109     
01110     group arguments (use in conjuction with \ref ArgumentObjectFactories):
01111     \code
01112     namespace vigra {
01113         template <class SrcIterator, class SrcAccessor,
01114               class MaskIterator, class MaskAccessor,
01115               class DestIterator, class DestAccessor>
01116         inline void 
01117         discMedianWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src,
01118                 pair<MaskIterator, MaskAccessor> mask,
01119                 pair<DestIterator, DestAccessor> dest,
01120                 int radius)
01121     }
01122     \endcode
01123 
01124 */
01125 template <class SrcIterator, class SrcAccessor,
01126           class MaskIterator, class MaskAccessor,
01127       class DestIterator, class DestAccessor>
01128 inline void 
01129 discMedianWithMask(SrcIterator upperleft1, 
01130             SrcIterator lowerright1, SrcAccessor sa,
01131             MaskIterator upperleftm, MaskAccessor mask,
01132             DestIterator upperleft2, DestAccessor da,
01133             int radius)
01134 {
01135     vigra_precondition(radius >= 0, "discMedianWithMask(): Radius must be >= 0.");
01136     
01137     discRankOrderFilterWithMask(upperleft1, lowerright1, sa, 
01138                                 upperleftm, mask,
01139                                 upperleft2, da,
01140                 radius, 0.5);
01141 }
01142 
01143 template <class SrcIterator, class SrcAccessor,
01144           class MaskIterator, class MaskAccessor,
01145       class DestIterator, class DestAccessor>
01146 inline void 
01147 discMedianWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src,
01148             pair<MaskIterator, MaskAccessor> mask,
01149             pair<DestIterator, DestAccessor> dest,
01150             int radius)
01151 {
01152     vigra_precondition(radius >= 0, "discMedianWithMask(): Radius must be >= 0.");
01153     
01154     discRankOrderFilterWithMask(src.first, src.second, src.third,
01155                         mask.first, mask.second,
01156                         dest.first, dest.second,
01157             radius, 0.5);
01158 }
01159 
01160 //@}
01161 
01162 } // namespace vigra
01163 
01164 #endif // VIGRA_FLATMORPHOLOGY_HXX

© Ullrich Köthe (koethe@informatik.uni-hamburg.de)
Cognitive Systems Group, University of Hamburg, Germany

html generated using doxygen and Python
VIGRA 1.2.0 (7 Aug 2003)