Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

VoxelCoding.hpp

Go to the documentation of this file.
00001 /* ImLib3D
00002  * Copyright (c) 2001, ULP-IPB Strasbourg.
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or (at
00007  * your option) any later version.
00008  * 
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  * 
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00020 #ifndef _VoxelCoding_hpp
00021 #define _VoxelCoding_hpp
00022 #include<ImLib3D/MorphologicalOperators.hpp>
00023 #include<ImLib3D/Threshold.hpp>
00024 
00025 
00026 namespace IP3D
00027 {
00043         void VoxelCode(const Mask3D &shape,const Mask3D &seeds,int m0,int m1,int m2,LabelImage3D& res,
00044                       const Vect3Di *stopPoint=NULL);
00045 };
00046 
00047 namespace IP3D
00048 {
00061     inline void SSCode(const Mask3D &shape,const Vect3Di &sourcePoint,int m0,int m1,int m2,LabelImage3D& res,
00062                       const Vect3Di *stopPoint=NULL)
00063     {
00064         Mask3D seeds(shape.Size());
00065         seeds.Fill(0);
00066         seeds(sourcePoint)=1;
00067         VoxelCode(shape,seeds,m0,m1,m2,res,stopPoint);
00068     }
00069 };
00070 namespace IP3D
00071 {
00082     inline void BSCode(const Mask3D &shape,int m0,int m1,int m2,LabelImage3D& res)
00083     {
00084         Mask3D seeds=shape;
00085         Mask3D t;
00086         Erosion(shape,MORPHO_Cross7,t);
00087         seeds-=t;
00088         VoxelCode(shape,seeds,m0,m1,m2,res);
00089     }
00090 };
00091 class CodeCluster;
00092 
00093 namespace IP3D
00094 {
00095 namespace ShortestPathExtractionHelpers
00096 {
00098     typedef bool (*StopFctType)(void *dat,const Vect3Di &p);
00100     typedef pair<StopFctType,void*> StopCBType;
00101 }
00102 
00114     void ShortestPathExtraction(const Mask3D &shape,const Vect3Di &start,const Vect3Di &end,vector<Vect3Di> &path,
00115                                 Mask3D *pres=NULL,StructureElement *psel=NULL,
00116                                 const LabelImage3D *pssCode0=NULL,
00117                                 ShortestPathExtractionHelpers::StopCBType stopCB=
00118                                 ShortestPathExtractionHelpers::StopCBType(NULL,NULL));
00119 
00120 
00121 };
00122 
00123 
00125 class CodeCluster
00126 {
00127     friend class SkeletonExtraction;
00128 public:
00130     int value;
00132     Vect3Df center;
00134     vector<CodeCluster *> neighbors;
00136     vector<Vect3Di> points;
00138     bool isLM;
00139     bool isMerging;
00140     bool isDividing;
00141     bool isBranching;
00143 
00144     int stop;
00145 private:
00146     CodeCluster(int _value):
00147         value(_value),stop(0)
00148     {
00149     }
00150     void Init()
00151     {
00152         center=points[0];
00153         for(uint i=1;i<points.size();i++){center+=points[i];}
00154         center/=points.size();
00155     }
00156     void FindType()
00157     {
00158         isLM=true;
00159         for(uint i=0;i<neighbors.size();i++)
00160         {
00161             if(neighbors[i]->value>value){isLM=false;break;}
00162         }
00163         int ct=0;
00164         for(uint i=0;i<neighbors.size();i++)
00165         {
00166             if(neighbors[i]->value==value-1){ct++;}
00167         }
00168         if(ct>=2){isMerging=true;}else{isMerging=false;}
00169         ct=0;
00170         for(uint i=0;i<neighbors.size();i++)
00171         {
00172             if(neighbors[i]->value==value+1){ct++;}
00173         }
00174         if(ct>=2){isDividing=true;}else{isDividing=false;}
00175         if(isDividing || isMerging){isBranching=true;}else{isBranching=false;}
00176     }
00177 public:
00179     void GetSuccessors(vector<CodeCluster *> &successors)
00180     {
00181         for(uint i=0;i<neighbors.size();i++)
00182         {
00183             if(neighbors[i]->value<value){successors.push_back(neighbors[i]);}
00184         }
00185     } 
00187     vector<Vect3Di> medialPoints;
00189     void FindMedialPoints(const LabelImage3D &bsCode)
00190     {
00191         int mx=bsCode(points[0]);
00192         for(uint i=1;i<points.size();i++){mx=max(mx,bsCode(points[i]));}
00193         for(uint i=0;i<points.size();i++){if(bsCode(points[i])==mx){medialPoints.push_back(points[i]);}}
00194     }
00196     Vect3Di MedialPoint(const Vect3Df &ref=Vect3Di(0,0,0))
00197     {
00198         int imin=0;
00199         float d2=ref.Dist2(medialPoints[0]);
00200         for(uint i=1;i<medialPoints.size();i++)
00201         {
00202             float d=ref.Dist2(medialPoints[i]);
00203             if(d<d2){d2=d;imin=i;}
00204         }
00205         return medialPoints[imin];
00206     }
00208     void FindNeighbors(Container3D<CodeCluster *> &clustersIma)
00209     {
00210         // for each point in this cluster, check all if each of its neighbors is in another cluster
00211         // and add it if it's not there
00212         StructureElement sel(MORPHO_Cubic27);
00213         sel.RemoveCenter();
00214         for(uint pt=0;pt<points.size();pt++)
00215         {
00216             for(uint i=0;i<sel.size();i++)
00217             {
00218                 Vect3Di npos=points[pt]+sel[i];
00219                 if(!clustersIma.IsInside(npos)){continue;}
00220                 CodeCluster *neighbor=clustersIma(npos);
00221                 if(neighbor && neighbor->value!=value && abs(neighbor->value-value)<2)
00222                 {
00223                     if(find(neighbors.begin(),neighbors.end(),neighbor)==neighbors.end())
00224                     {
00225                         neighbors.push_back(neighbor);
00226                     }
00227                 }
00228             }
00229                 
00230         }
00231 //          printf("neighbors for cluster %x %03d\n",this,value);
00232 //          for(uint i=0;i<neighbors.size();i++)
00233 //          {
00234 //              printf("cluster %x %03d:neighbor %2d: %x %03d\n",this,value,i,neighbors[i],neighbors[i]->value);
00235 //          }
00236     }
00237     
00238 };
00240 class PathGraph
00241 {
00242 public:
00243     class Node;
00244     class Path
00245     {
00246         friend class PathGraph;
00247     public:
00248         Node *first,*last;
00249         vector<Vect3Di> points;
00250     private:
00251         Path(Node *_first,Node *_last,const vector<Vect3Di> &_points);
00252     };
00253     class Node
00254     {
00255         friend class PathGraph;
00256     public:
00257         Vect3Di point;
00258         vector<Path *> paths;
00259     private:
00260         Node(){;}
00261     };
00262     vector<Node *> nodes;
00263     vector<Path *> paths;
00264     Node *AddNode(){Node *node=new Node();nodes.push_back(node);return node;}
00265     RectZone3Di BoundingBox() const;
00266     Path *AddPath(Node *_first,Node *_last,const vector<Vect3Di> &_points)
00267     {
00268         Path *path=new Path(_first,_last,_points);paths.push_back(path);return path;
00269     }
00270 };
00271 
00273 class SkeletonExtraction
00274 {
00275     static bool SpeStopCB(void *dat,const Vect3Di &p)
00276     {
00277         return ((SkeletonExtraction *)dat)->clustersIma(p)->stop!=-1;
00278     }
00279     class MedPathFind
00280     {
00281     public:
00282         CodeCluster *parentCluster;
00283         int id;
00284         int id1,id2;
00285         vector<Vect3Di> path;
00286         vector<CodeCluster *> cpath;
00287         vector<vector<int> > branches;
00288         vector<PathGraph::Node *> branchNodes;
00289         void ExtractPath(SkeletonExtraction *se);
00290         int FindCluster(CodeCluster *cluster)
00291         {
00292             int res=-1;
00293             for(uint i=0;i<cpath.size();i++){if(cpath[i]==cluster){res=i;break;}}
00294             return res;
00295         }
00296         int operator<(const MedPathFind &other) const {return cpath[0]->value<other.cpath[0]->value;}
00297         MedPathFind(CodeCluster *startCluster):
00298             id1(-1),id2(-1)
00299         {
00300             cpath.push_back(startCluster);
00301         }
00302     };
00303     friend class SkeletonExtraction::MedPathFind;
00305     const Mask3D &shape;
00307     LabelImage3D ssCode;
00309     LabelImage3D bsCode;
00311     vector<CodeCluster *> clusters;
00313     Container3D<CodeCluster *> clustersIma;
00315     void CreateClusters();
00317     void InitClusters();
00318 
00319     void PathGraphFromMedPaths(vector<MedPathFind> &medPaths,PathGraph &pathGraph);
00320     void ExtractAllMedPaths(vector<MedPathFind> &medPaths);
00321     void ExtractPaths(PathGraph &pathGraph);
00322 
00323     SkeletonExtraction(const Mask3D &_shape,const Vect3Di *psourcePoint=NULL);
00324     void MedPathFromPath(const vector<Vect3Di> &path,vector<Vect3Di> &medPath)
00325     {
00326         medPath.push_back(path[0]);
00327         for(uint i=1;i<path.size();i++)
00328         {
00329             medPath.push_back(clustersIma(path[i])->MedialPoint(medPath[i-1]));
00330         }
00331     }
00332 public:
00333     static void ExtractAll(const Mask3D &shape,PathGraph &pathGraph);
00334     static void ExtractLinkingMedPath(const Mask3D &shape,const Vect3Di &start,const Vect3Di &end,vector<Vect3Di> &res);
00335     static void DrawPathGraph(const PathGraph &pathGraph,Mask3D &res);
00336 };
00337 
00338 namespace IP3D
00339 {
00349     inline void Skeleton(const Mask3D &shape,Mask3D& res)
00350     {
00351         PathGraph pathGraph;
00352         SkeletonExtraction::ExtractAll(shape,pathGraph);
00353         res.Resize(shape.Size());
00354         res.Fill(0);
00355         SkeletonExtraction::DrawPathGraph(pathGraph,res);
00356     }
00357 };
00358 
00359 #endif// _VoxelCoding_hpp

Generated on Fri Jun 17 13:36:09 2005 for ImLib3D by  doxygen 1.4.2