00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00211
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
00232
00233
00234
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