00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00021 #ifndef _MorphologicalOperators_hpp
00022 #define _MorphologicalOperators_hpp
00023
00024 #include<ImLib3D/ImageProcessor.hpp>
00025 #include<map>
00026
00028
00030 enum StructureElementType
00031 {
00032 MORPHO_CUSTOM,
00033 MORPHO_FORWARD,
00034 MORPHO_BACKWARD,
00035 MORPHO_ALLDIRECTIONS,
00036 MORPHO_Cubic27,
00037 MORPHO_Cross7,
00038 MORPHO_Planar19,
00039 MORPHO_Corner9 ,
00040 MORPHO_Pts81,
00041 MORPHO_Pts14,
00042 MORPHO_Pts4,
00043 MORPHO_Pts10,
00044 MORPHO_Pts5,
00045 MORPHO_Pts41,
00046 MORPHO_XYCross5,
00047 MORPHO_XZCross5,
00048 MORPHO_YZCross5,
00049 MORPHO_SphereR3,
00050 MORPHO_SphereR4
00051 };
00052
00054
00057 class StructureElement
00058 {
00059 protected:
00061 StructureElementType maskType;
00063 void CreateMask();
00064 public:
00066 void ComputeMaskPointsSize(Vect3Di &minv,Vect3Di &maxv) const;
00067 protected:
00069 void CreateMaskPoints(StructureElementType maskType);
00071 void CreateMaskPoints();
00072
00074 vector<Vect3Di> maskPoints;
00076 vector<float> coeffs;
00078
00080 Mask3D *mask;
00081 public:
00082 static void CreateSpherePointList(int radius,vector<Vect3Di>& pl);
00083 void ComputeCoeffs();
00085 void Show(const string &name) const;
00087 inline const Vect3Di &GetPoint(int i) const {return maskPoints[i];}
00088 inline const Vect3Di &operator[](uint i) const {return maskPoints[i];}
00089 inline float GetCoeff(int i) const {return coeffs[i];}
00091 RectZone3Di SafeZone(const Size3D &imageSize) const
00092 {
00093 Vect3Di vmin,vmax;
00094 ComputeMaskPointsSize(vmin,vmax);
00095 return RectZone3Di(Vect3Di(0,0,0),imageSize).Intersection(
00096 RectZone3Di(-vmin,imageSize.GetV()-vmax-Vect3Di(1,1,1)));
00097 }
00099 int FindPoint(const Vect3Di &P) const
00100 {
00101 for(uint i=0;i<maskPoints.size();i++)
00102 {if(P==maskPoints[i]){return i;}}
00103 return -1;
00104 }
00106 float GetCoeff(const Vect3Di &P) const
00107 {
00108 int i=FindPoint(P);
00109 if(i<0)ThrowError("GetCoeff(P=%d %d %d) point not found",P.x,P.y,P.z);
00110 return coeffs[i];
00111 }
00112 const Mask3D &Mask() const {return *mask;}
00113 inline int GetNbPoints() const {return maskPoints.size();}
00114 inline uint size() const {return maskPoints.size();}
00116
00118
00120 void RemoveCenter();
00121
00123 ~StructureElement()
00124 {
00125 if(mask){delete mask;}
00126 }
00128 StructureElement(const string &s);
00129
00131 StructureElement(const StructureElement &other,StructureElementType direction);
00132
00134 StructureElement(StructureElementType _maskType):
00135 maskType(_maskType),
00136 mask(NULL)
00137 {
00138 CreateMaskPoints(maskType);
00139 CreateMask();
00140 }
00142 StructureElement(const vector<Vect3Di> &_maskPoints):
00143 maskType(MORPHO_CUSTOM),
00144 mask(NULL)
00145 {
00146 maskPoints=_maskPoints;
00147 CreateMask();
00148 }
00149 };
00150
00152
00154 template<class ImageType,class Inst=typename HasPointerIterators<ImageType>::value >
00155 class ImageNeighbors
00156 {
00157 typedef typename ImageType::value_type Im3DValue;
00158 typedef typename ImageType::iteratorFast Iterator;
00159 ImageType ℑ
00160 const StructureElement &sel;
00163 Im3DValue ** iterators;
00164 typename ImageType::iteratorXYZ p;
00165 uint npts;
00166 RectZone3Di safezone;
00167 int lastY;
00168 int lastX;
00169 public:
00170 inline bool IsSafe(const Vect3Di &pos){return safezone.IsInside(pos);}
00171 inline void MoveTo(const Vect3Di &pos)
00172 {
00173 if(lastY!=pos.y || lastX!=pos.x-1)
00174 {
00175 for(uint i=0;i<npts;i++)
00176 {
00177 iterators[i]=(Im3DValue *)&image(pos+sel[i]);
00178
00179 }
00180 lastY=pos.y;
00181 lastX=pos.x;
00182 }
00183 else
00184 {
00185 for(uint i=0;i<npts;i++){iterators[i]++;}
00186 lastX++;
00187 }
00188 }
00189 inline void MoveBackwardsTo(const Vect3Di &pos)
00190 {
00191 if(lastY!=pos.y || lastX!=pos.x+1)
00192 {
00193 for(uint i=0;i<npts;i++)
00194 {
00195 iterators[i]=(Im3DValue *)&image(pos+sel[i]);
00196
00197 }
00198 lastY=pos.y;
00199 lastX=pos.x;
00200 }
00201 else
00202 {
00203 for(uint i=0;i<npts;i++){iterators[i]--;}
00204 lastX--;
00205 }
00206 }
00207 inline Im3DValue &operator[](int i){return *(iterators[i]);}
00208 ~ImageNeighbors(){delete [] iterators;}
00209 ImageNeighbors(ImageType &_image,const StructureElement &_sel):
00210 image(_image),sel(_sel),
00211 iterators(new Im3DValue*[sel.size()]),
00212 npts(sel.size()),
00213 safezone(sel.SafeZone(image.Size())),lastY(-1),lastX(-2)
00214 {
00215
00216 }
00217 };
00218
00219 template<class ImageType>
00220 struct IteratorType
00221 {
00222 typedef typename ImageType::iterator type;
00223 };
00224 template<class ImageType>
00225 struct IteratorType<const ImageType>
00226 {
00227 typedef typename ImageType::const_iterator type;
00228 };
00229
00230 template<class ImageType>
00231 class ImageNeighbors<ImageType,__false_type>
00232 {
00233 typedef typename ImageType::value_type Im3DValue;
00234 typedef typename IteratorType<ImageType>::type Iterator;
00235 ImageType ℑ
00236 const StructureElement &sel;
00239 vector<Iterator> iterators;
00240 typename ImageType::iteratorXYZ p;
00241 uint npts;
00242 RectZone3Di safezone;
00243 int lastY;
00244 int lastX;
00245 public:
00246 inline bool IsSafe(const Vect3Di &pos){return safezone.IsInside(pos);}
00247 inline void MoveTo(const Vect3Di &pos)
00248 {
00249 if(lastY!=pos.y || lastX!=pos.x-1)
00250 {
00251 for(uint i=0;i<npts;i++)
00252 {
00253 iterators[i]=pos+sel[i];
00254 }
00255 lastY=pos.y;
00256 lastX=pos.x;
00257 }
00258 else
00259 {
00260 for(uint i=0;i<npts;i++){iterators[i]++;}
00261 lastX++;
00262 }
00263 }
00264 inline void MoveBackwardsTo(const Vect3Di &pos)
00265 {
00266 if(lastY!=pos.y || lastX!=pos.x+1)
00267 {
00268 for(uint i=0;i<npts;i++)
00269 {
00270
00271 iterators[i]=pos+sel[i];
00272 }
00273 lastY=pos.y;
00274 lastX=pos.x;
00275 }
00276 else
00277 {
00278 for(uint i=0;i<npts;i++){iterators[i]--;}
00279 lastX--;
00280 }
00281 }
00282 inline Im3DValue operator[](int i){return *(iterators[i]);}
00283 ~ImageNeighbors(){}
00284 ImageNeighbors(ImageType &_image,const StructureElement &_sel):
00285 image(_image),sel(_sel),
00286
00287 iterators(sel.size()),
00288 npts(sel.size()),
00289 safezone(sel.SafeZone(image.Size())),lastY(-1),lastX(-2)
00290 {
00291 for(uint i=0;i<npts;i++){iterators[i]=image.begin();}
00292 }
00293 };
00294
00295
00296
00297 namespace IP3D
00298 {
00308 template <class ImageType>
00309 void MedianFilter(const ImageType& src, const StructureElement &mask, ImageType& res);
00310 };
00311
00312 namespace IP3D
00313 {
00324 template <class ImageType>
00325 void SharpeningFilter(const ImageType& src, const StructureElement &mask, ImageType& res);
00326 };
00327
00328
00329 namespace IP3D
00330 {
00340 template <class ImageType>
00341 void Erosion(const ImageType& src, const StructureElement &mask, ImageType& res);
00342 };
00343
00344 namespace IP3D
00345 {
00355 template <class ImageType>
00356 void Dilation(const ImageType& src, const StructureElement &mask, ImageType& res);
00357 };
00358
00359 namespace IP3D
00360 {
00369 template <class ImageType>
00370 void Opening(const ImageType& src, const StructureElement &mask, ImageType& res)
00371 {
00372 IP3D::Erosion(src,mask,res);
00373 IP3D::Dilation(res,mask,res);
00374 }
00375 };
00376
00377 namespace IP3D
00378 {
00387 template <class ImageType>
00388 void Closing(const ImageType& src, const StructureElement &mask, ImageType& res)
00389 {
00390 IP3D::Dilation(src,mask,res);
00391 IP3D::Erosion(res,mask,res);
00392 }
00393 };
00394
00395 namespace IP3D
00396 {
00411 void DistanceTransform(const Mask3D& src, const StructureElement &mask, Image3Df& res,bool borderExtend=false);
00412 };
00413
00414 namespace IP3D
00415 {
00427 template <class ImageType>
00428 void ConnectedComponentLabelling(const ImageType& src, const StructureElement &mask0, LabelImage3D& res,typename ImageType::value_type *background0=NULL);
00429 };
00430 template <class ImageType> inline pair<bool,typename ImageType::value_type> DefaultBackground(){return pair<bool,typename ImageType::value_type>(false,typename ImageType::value_type());}
00431 template <> inline pair<bool,byte> DefaultBackground<Mask3D>(){return pair<bool,byte>(true,0);}
00432
00433 namespace IP3D
00434 {
00444 void FillHoles(const Mask3D& src, const StructureElement &mask, Mask3D& res);
00445 };
00446
00447 class CMakeValueList;
00448
00449
00451 template<class Im3DValue>
00452 class ImageValues
00453 {
00454 friend class CMakeValueList;
00455 public:
00456 class ImageValue
00457 {
00458 public:
00459 int size;
00460 Vect3Di point;
00461 ImageValue(){size=0;point.x=-1;point.y=-1;}
00462 };
00463 typedef map<Im3DValue,ImageValue> MapType;
00464 map<Im3DValue,ImageValue> values;
00465 ImageValue operator[](const Im3DValue &v)
00466 {
00467 return values[v];
00468 }
00469
00470 };
00471 namespace IP3D
00472 {
00480 template <class ImageType>
00481 void MakeValueList(const ImageType& src, ImageValues<typename ImageType::value_type>& res);
00482 };
00483
00484 namespace IP3D
00485 {
00493 void LargestConnectedComponent(const Mask3D &src,Mask3D &res);
00494 };
00495
00496
00497 #include<ImLib3D/MorphologicalOperators.hxx>
00498
00499 #endif // _MorphologicalOperators_hpp