cmtkDataGridConnectedComponents.cxx

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2010 Torsten Rohlfing
00004 //
00005 //  This file is part of the Computational Morphometry Toolkit.
00006 //
00007 //  http://www.nitrc.org/projects/cmtk/
00008 //
00009 //  The Computational Morphometry Toolkit is free software: you can
00010 //  redistribute it and/or modify it under the terms of the GNU General Public
00011 //  License as published by the Free Software Foundation, either version 3 of
00012 //  the License, or (at your option) any later version.
00013 //
00014 //  The Computational Morphometry Toolkit is distributed in the hope that it
00015 //  will be useful, but WITHOUT ANY WARRANTY; without even the implied
00016 //  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 //  GNU General Public License for more details.
00018 //
00019 //  You should have received a copy of the GNU General Public License along
00020 //  with the Computational Morphometry Toolkit.  If not, see
00021 //  <http://www.gnu.org/licenses/>.
00022 //
00023 //  $Revision: 2398 $
00024 //
00025 //  $LastChangedDate: 2010-10-05 14:54:37 -0700 (Tue, 05 Oct 2010) $
00026 //
00027 //  $LastChangedBy: torstenrohlfing $
00028 //
00029 */
00030 
00031 #include "cmtkDataGridMorphologicalOperators.h"
00032 
00033 #include <Base/cmtkUnionFind.h>
00034 
00035 #include <map>
00036 #include <vector>
00037 #include <list>
00038 
00039 cmtk::TypedArray::SmartPtr
00040 cmtk::DataGridMorphologicalOperators::GetBinaryConnectedComponents() const
00041 {
00042   const size_t numberOfPixels = this->m_DataGrid->GetNumberOfPixels();
00043 
00044   // this vector will hold the component index per pixel; since we move strictly forward and only look back in the algorithm below,
00045   // there is no need to initialize the vector elements.
00046   std::vector<int> result( numberOfPixels);
00047 
00048   const DataGrid::IndexType& dims = this->m_DataGrid->GetDims();
00049 
00050   DataGrid::IndexType relative;
00051   relative[0] = this->m_DataGrid->GetNextI();
00052   relative[1] = this->m_DataGrid->GetNextJ();
00053   relative[2] = this->m_DataGrid->GetNextK();
00054 
00055   UnionFind<int> connected;
00056   int nextComponent = 1;
00057 
00058   DataGrid::IndexType index;
00059   size_t offset = 0;
00060   for ( index[2] = 0; index[2] < dims[2]; ++index[2] )
00061     {
00062     for ( index[1] = 0; index[1] < dims[1]; ++index[1] )
00063       {
00064       for ( index[0] = 0; index[0] < dims[0]; ++index[0], ++offset )
00065         {
00066         // initialize as "background"
00067         int component = 0;
00068           
00069         // foreground pixel?
00070         if ( this->m_DataGrid->GetDataAt( offset ) != 0 )
00071           {
00072           // loop over x,y,z neighbor
00073           for ( int dim = 2; dim >= 0; --dim )
00074             {
00075             // is there a preceding neighbor in this direction?
00076             if ( index[dim] )
00077               {
00078               // get component ID for that neighbor
00079               const int existing = result[offset - relative[dim]];
00080               // is there something there?
00081               if ( existing )
00082                 {
00083                 // did we already get a different component ID from another neighbor?
00084                 if ( component && (component != existing) ) // note: this implies "component != 0" because "existing" is at least 1 in this branch.
00085                   {
00086                   // link old and new component via this pixel
00087                   connected.Union( connected.Find( component ), connected.Find( existing ) );
00088                   }
00089                 // mark current pixel as belonging to the same component
00090                 component = existing;
00091                 }
00092               }
00093             }
00094           
00095           // none of the neighbors is foreground, so use next available component ID.
00096           if ( !component )
00097             {
00098             component = nextComponent++;
00099             connected.Insert( component );
00100             }
00101           }
00102         
00103         // set component result for this pixel
00104         result[offset] = component;
00105         }
00106       }
00107     }
00108   
00109   // now collapse all component indexes into their unique representative
00110   std::map<int,int> linkMap;
00111   for ( int component = 1; component < nextComponent; ++component )
00112     {
00113     linkMap[component] = connected.FindKey( component );
00114     }
00115   
00116   // re-number components
00117   TypedArray::SmartPtr resultArray( TypedArray::Create( TYPE_INT, numberOfPixels ) );
00118 #pragma omp parallel for
00119   for ( size_t px = 0; px < numberOfPixels; ++px )
00120     {
00121     resultArray->Set( linkMap[result[px]], px );
00122     }
00123   
00124   return resultArray;
00125 }
00126 
00127 cmtk::TypedArray::SmartPtr 
00128 cmtk::DataGridMorphologicalOperators::GetRegionsRenumberedBySize() const
00129 {
00130   const size_t numberOfPixels = this->m_DataGrid->GetNumberOfPixels();
00131   
00132   // first, count pixels in each region
00133   std::map<int,int> regionSizeMap;
00134   for ( size_t px = 0; px < numberOfPixels; ++px )
00135     {
00136     const int value = static_cast<int>( this->m_DataGrid->GetDataAt( px ) );
00137     if ( value )
00138       ++regionSizeMap[value];
00139     }
00140 
00141   // now create list sorted by region size
00142   std::list< std::pair<const int,int> > sortedList;
00143   for ( std::map<int,int>::const_iterator it = regionSizeMap.begin(); it != regionSizeMap.end(); ++it )
00144     {
00145     std::list< std::pair<const int,int> >::iterator ins = sortedList.begin();
00146     while ( (ins != sortedList.end()) && (ins->second >= it->second) )
00147       ++ins;
00148     
00149     sortedList.insert( ins, *it ); // need to explicitly create new pair because some STL implementation have it->first as "const".
00150     }
00151 
00152   // create renumbering lookup map
00153   std::map<int,int> renumberMap;
00154   int component = 1;
00155   for ( std::list< std::pair<const int,int> >::iterator it = sortedList.begin(); it != sortedList.end(); ++it )
00156     {
00157     renumberMap[it->first] = component++;
00158     }
00159   
00160   // re-number components
00161   TypedArray::SmartPtr resultArray( TypedArray::Create( TYPE_INT, numberOfPixels ) );
00162   for ( size_t px = 0; px < numberOfPixels; ++px )
00163     {
00164     resultArray->Set( renumberMap[static_cast<int>( this->m_DataGrid->GetDataAt( px ) )], px );
00165     }
00166   
00167   return resultArray;  
00168 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines