connected.hh

00001 // Copyright (C) 2001, 2002, 2003, 2004  EPITA Research and Development Laboratory
00002 //
00003 // This file is part of the Olena Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the terms
00005 // of the GNU General Public License version 2 as published by the
00006 // Free Software Foundation.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this library; see the file COPYING.  If not, write to
00015 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
00016 // MA 02111-1307, USA.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software library without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License.  This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
00027 
00028 #ifndef OLENA_LEVEL_CONNECTED_HH
00029 # define OLENA_LEVEL_CONNECTED_HH
00030 
00031 # include <ntg/basics.hh>
00032 # include <oln/level/lut.hh>
00033 # include <oln/level/fill.hh>
00034 # include <oln/morpho/splitse.hh>
00035 # include <oln/convert/conversion_ng_se.hh>
00036 
00037 namespace oln {
00038 
00039   namespace level {
00040 
00041     /* \brief Processing connected_component extract the connected components.
00042     **
00043     ** \arg: input a 2d image of binary.
00044     ** \arg: Ng neighborhood
00045     **
00046     ** \return Returns a labeled image
00047     **
00048     ** It removes the small (in area) connected components of the upper
00049     ** level sets of \var{input} using \var{se} as structural element.
00050     **
00051     ** REF: The implementation comes from Cocquerez et Philipp, Analyse
00052     ** d'images, filtrages et segmentations p.62.
00053     **
00054     ** \see level::frontp_connected_component
00055     */
00056     // Number the connected components i.e label true. background(i.e
00057     // label false) has the label 0; This algorithm works only for 2D images.
00058     template <class DestType, class I, class N>
00059     typename mute<I, DestType>::ret
00060     connected_component(const abstract::binary_image_with_dim<2, I>& input,
00061                         const abstract::neighborhood<N>& Ng)
00062     {
00063       mlc::eq<I::dim, N::dim>::ensure();
00064       typename mute<I, DestType>::ret output(input.size());
00065       level::hlut< DestType, DestType > T;
00066       DestType k = 1;
00067 
00068       fill(output, 0);
00069       oln_iter_type(I) p(input);
00070       for_all(p)
00071         {
00072           if (input[p] == true)
00073             {
00074               typedef typename abstract::neighborhood<N>::win_type E;
00075               E se_plus = morpho::get_plus_se_only(convert::ng_to_se(Ng));
00076               oln_neighb_type(E) p_prime(se_plus, p);
00077               bool all_zero = true;
00078               for_all(p_prime)
00079                 if (input.hold(p_prime) && input[p_prime])
00080                   {
00081                     all_zero = false;
00082                     break;
00083                   }
00084               if (all_zero)
00085                 {
00086                   output[p] = k++;
00087                 }
00088               else
00089                 {
00090                   // Check if all neighbors have the same label.
00091                   bool same_label = true;
00092                   DestType cl = 0;
00093                   // Find the first label.
00094                   for_all (p_prime)
00095                     if (output.hold(p_prime))
00096                       {
00097                         cl = output[p_prime];
00098                         break;
00099                       }
00100                   // Check whether all remaining neighbors are equal.
00101                   for_all_remaining (p_prime)
00102                     if (output.hold(p_prime) && cl != output[p_prime])
00103                       {
00104                         same_label = false;
00105                         break;
00106                       }
00107 
00108                   if (same_label)
00109                     output[p] = cl;
00110                   else
00111                     {
00112                       DestType min = ntg_max_val(DestType);
00113                       for_all(p_prime)
00114                         if (output.hold(p_prime))
00115                           if (output[p_prime] && T(output[p_prime]) < min)
00116                             min = T(output[p_prime]);
00117                       output[p] = min;
00118 
00119                       for_all(p_prime)
00120                         if (input.hold(p_prime) && output[p_prime])
00121                           {
00122                             DestType m;
00123                             DestType beta = T(output[p_prime]);
00124                             while (T(beta) != min)
00125                               {
00126                                 m = T(beta);
00127                                 T.set(beta, min);
00128                                 beta = m;
00129                               }
00130                           }
00131                     }
00132                 }
00133             }
00134         }
00135 
00136       for (DestType i = 1; i <= k; ++i)
00137         {
00138           DestType m = i;
00139           while (T(m) != m)
00140             m = T(m);
00141           T.set(i,m);
00142         }
00143       for_all (p)
00144         output[p] = T(output[p]);
00145       return output;
00146     }
00147 
00148   } // end of namespace level
00149 
00150 } // end of namespace oln
00151 
00152 #endif // ! OLENA_LEVEL_CONNECTED_HH

Generated on Thu Apr 15 20:13:07 2004 for Olena by doxygen 1.3.6-20040222