TuttleOFX  1
localMaxima.hpp
Go to the documentation of this file.
00001 #ifndef _TERRY_FILTER_LOCALMAXIMA_HPP_
00002 #define _TERRY_FILTER_LOCALMAXIMA_HPP_
00003 
00004 #include <terry/channel.hpp>
00005 #include <terry/math/Rect.hpp>
00006 #include <terry/algorithm/transform_pixels.hpp>
00007 #include <terry/numeric/operations.hpp>
00008 #include <terry/numeric/init.hpp>
00009 #include <terry/numeric/assign_minmax.hpp>
00010 
00011 #include <boost/assert.hpp>
00012 
00013 
00014 namespace terry {
00015 namespace filter {
00016 
00017 
00018 /**
00019  * Computation of gradient norm local maxima in regard of gradient direction
00020  *
00021  *     there are 4 cases:
00022  *
00023  *                          The X marks the pixel in question, and each
00024  *          C     B         of the quadrants for the gradient vector
00025  *        O----0----0       fall into two cases, divided by the 45
00026  *      D |         | A     degree line.  In one case the gradient
00027  *        |         |       vector is more horizontal, and in the other
00028  *        O    X    O       it is more vertical.  There are eight
00029  *        |         |       divisions, but for the non-maximum suppression
00030  *     (A)|         |(D)    we are only worried about 4 of them since we
00031  *        O----O----O       use symmetric points about the center pixel.
00032  *         (B)   (C)
00033  */
00034 template<class SView, class DView=SView>
00035 struct pixel_locator_gradientLocalMaxima_t
00036 {
00037         typedef typename SView::locator SLocator;
00038         typedef typename SView::value_type SPixel;
00039         typedef typename boost::gil::channel_type<SPixel>::type SChannel;
00040         typedef typename terry::channel_base_type<SChannel>::type SType;
00041         typedef typename SLocator::cached_location_t SCachedLocation;
00042 
00043         typedef typename DView::locator DLocator;
00044         typedef typename DView::value_type DPixel;
00045 
00046         DPixel _black;
00047         const SLocator _loc_ref;
00048         // LT CT RT
00049         // LC    RC
00050         // LB CB RB
00051         const SCachedLocation LT;
00052         const SCachedLocation CT;
00053         const SCachedLocation RT;
00054         const SCachedLocation LC;
00055         const SCachedLocation RC;
00056         const SCachedLocation LB;
00057         const SCachedLocation CB;
00058         const SCachedLocation RB;
00059 
00060         static const unsigned int vecX = 0;
00061         static const unsigned int vecY = 1;
00062         static const unsigned int norm = 2;
00063 
00064         pixel_locator_gradientLocalMaxima_t( const SView& src )
00065         : _loc_ref(src.xy_at(0,0))
00066         , LT(_loc_ref.cache_location(-1,-1))
00067         , CT(_loc_ref.cache_location( 0,-1))
00068         , RT(_loc_ref.cache_location( 1,-1))
00069 
00070         , LC(_loc_ref.cache_location(-1, 0))
00071         , RC(_loc_ref.cache_location( 1, 0))
00072 
00073         , LB(_loc_ref.cache_location(-1, 1))
00074         , CB(_loc_ref.cache_location( 0, 1))
00075         , RB(_loc_ref.cache_location( 1, 1))
00076         {
00077                 using namespace terry::numeric;
00078                 pixel_assigns_min( _black );
00079         }
00080 
00081         DPixel operator()( const SLocator& src ) const
00082         {
00083                 using namespace terry;
00084                 
00085                 SType g1;
00086                 SType g2;
00087 
00088                 if( (*src)[vecX] == 0 && (*src)[vecY] == 0 )
00089                 {
00090                         return _black;
00091                 }
00092                 // A
00093                 if( ((*src)[vecY] <= 0 && (*src)[vecX] > -(*src)[vecY]) ||
00094                         ((*src)[vecY] >= 0 && (*src)[vecX] < -(*src)[vecY]) )
00095                 {
00096                         SType d = 0.0;
00097                         if( (*src)[vecX] )
00098                         {
00099                                 d = std::abs( (*src)[vecY] / (*src)[vecX] );
00100                         }
00101                         SType invd = 1.0 - d;
00102                         // __________
00103                         // |__|__|RT|
00104                         // |LC|__|RC|
00105                         // |LB|__|__|
00106                         g1 = src[RC][norm] * invd + src[RT][norm] * d;
00107                         g2 = src[LC][norm] * invd + src[LB][norm] * d;
00108                 }
00109                 // B
00110                 else if ( ((*src)[vecX] > 0 && -(*src)[vecY] >= (*src)[vecX]) ||
00111                                   ((*src)[vecX] < 0 && -(*src)[vecY] <= (*src)[vecX]) )
00112                 {
00113                         SType d = 0.0;
00114                         if( (*src)[vecY] )
00115                         {
00116                                 d = std::abs( (*src)[vecX] / (*src)[vecY] );
00117                         }
00118                         SType invd = 1.0 - d;
00119                         // __________
00120                         // |__|CT|RT|
00121                         // |__|__|__|
00122                         // |LB|CB|__|
00123                         g1 = src[CT][norm] * invd + src[RT][norm] * d;
00124                         g2 = src[CB][norm] * invd + src[LB][norm] * d;
00125                 }
00126                 // C
00127                 else if( ((*src)[vecX] <= 0 && (*src)[vecX] > (*src)[vecY]) ||
00128                                  ((*src)[vecX] >= 0 && (*src)[vecX] < (*src)[vecY]) )
00129                 {
00130                         SType d = 0.0;
00131                         if( (*src)[vecY] )
00132                         {
00133                                 d = std::abs( (*src)[vecX] / (*src)[vecY] );
00134                         }
00135                         SType invd = 1.0 - d;
00136                         // __________
00137                         // |LT|CT|__|
00138                         // |__|__|__|
00139                         // |__|CB|RB|
00140                         g1 = src[CT][norm] * invd + src[LT][norm] * d;
00141                         g2 = src[CB][norm] * invd + src[RB][norm] * d;
00142                 }
00143                 // D
00144 //              else if( ((*src)[vecY] < 0 && (*src)[vecX] <= (*src)[vecY]) ||
00145 //                       ((*src)[vecY] > 0 && (*src)[vecX] >= (*src)[vecY]) )
00146                 else
00147                 {
00148                         BOOST_ASSERT(
00149                                 ( (*src)[vecY] < 0 && (*src)[vecX] <= (*src)[vecY] ) ||
00150                                 ( (*src)[vecY] > 0 && (*src)[vecX] >= (*src)[vecY] ) );
00151                         SType d = 0.0;
00152                         if( (*src)[vecX] )
00153                         {
00154                                 d = std::abs( (*src)[vecY] / (*src)[vecX] );
00155                         }
00156                         SType invd = 1.0 - d;
00157                         // __________
00158                         // |LT|__|__|
00159                         // |LC|__|RC|
00160                         // |__|__|RB|
00161                         g1 = src[LC][norm] * invd + src[LT][norm] * d;
00162                         g2 = src[RC][norm] * invd + src[RB][norm] * d;
00163                 }
00164                 
00165                 if( (*src)[norm] >= g1 && (*src)[norm] >= g2 )
00166                 {
00167                         // wins !
00168                         DPixel dst;
00169                         static_fill( dst, (*src)[norm] );
00170                         return dst;
00171                 }
00172                 return _black;
00173         }
00174 };
00175 
00176 
00177 template<class SView, class DView>
00178 void applyLocalMaxima( const SView& srcView, DView& dstView )
00179 {
00180         using namespace terry::numeric;
00181         
00182         typedef typename DView::value_type DPixel;
00183         DPixel pixelZero; pixel_zeros_t<DPixel>()( pixelZero );
00184         
00185         // todo: only fill borders !!
00186         fill_pixels( dstView, pixelZero );
00187 
00188         terry::algorithm::transform_pixels_locator(
00189                 srcView, getBounds<std::ptrdiff_t>(srcView),
00190                 dstView, getBounds<std::ptrdiff_t>(dstView),
00191                 getBounds<std::ptrdiff_t>(dstView),
00192                 terry::filter::pixel_locator_gradientLocalMaxima_t<SView,DView>(srcView)
00193                 );
00194 }
00195 
00196 
00197 
00198 
00199 }
00200 }
00201 
00202 #endif