#line 1 "/user/cvsspst/ees1cg/RAVL/RAVL-0.7/Image/Processing/Segmentation/Segmentation.hh" // This file is part of RAVL, Recognition And Vision Library // Copyright (C) 2001, University of Surrey // This code may be redistributed under the terms of the GNU Lesser // General Public License (LGPL). See the lgpl.licence file for details or // see http://www.gnu.org/copyleft/lesser.html // file-header-ends-here #ifndef RAVLIMAGE_SEGMENTATION_HEADER #define RAVLIMAGE_SEGMENTATION_HEADER 1 ///////////////////////////////////////////////////////////////// //! rcsid="$Id: Segmentation.hh,v 1.7 2002/08/08 16:03:14 craftit Exp $" //! docentry="Ravl.Images.Segmentation" //! lib=RavlImageProc //! file="Ravl/Image/Processing/Segmentation/Segmentation.hh" #include "Ravl/Array2dSqr2Iter2.hh" #include "Ravl/Image/Image.hh" #include "Ravl/SArray1d.hh" #include "Ravl/RefCounter.hh" #include "Ravl/HSet.hh" #include "Ravl/IntC.hh" #include "Ravl/Tuple2.hh" #include "Ravl/Moments2d2.hh" namespace RavlImageN { //! userlevel=Develop //: Segmentation map. class SegmentationBodyC : public RCBodyVC { public: SegmentationBodyC(ImageC nsegmap,UIntT nlabels) : segmap(nsegmap), labels(nlabels) {} //: Constructor. SArray1dC > Adjacency(bool biDir = false); //: Generate a table of region adjacencies. // For each region, a set of adjacent regions is // generated. If biDir is false, only adjacenies from // regions with a smaller id to those with a larger ID are // generated, otherwise both direction are registered. SArray1dC > BoundryLength(); //: Generate a table of region adjacencies boundry lengths. // only adjacenies from regions with a smaller id to those // with a larger ID are generated UIntT RemoveSmallComponents(IntT thrSize); //: Remove small components from map, label them as 0. UIntT CompressAndRelabel(SArray1dC newLabs); //: Compress newlabs and re-label segmentation. // this correctly resolves multilevel mappings. // Note: newLabs will be changed to contain a mapping // from the original labels to there new values. SArray1dC Areas(); //: Compute the areas of all the segmented regions. SArray1dC RedoArea(SArray1dC area,SArray1dC map); //: recompute the areas from the original areas and a mapping. SArray1dC IdentityLabel(); //: Make an array of labels mapping to themselves. // This is useful for making merge tables which can // the be passed to CompressAndRelabel. template UIntT MergeComponents(ImageC &dat,UIntT thrSize,RealT maxDist,CmpT &cmp,IntT iter = 1); //: Merge simlar components smaller than 'thrSize'. // This just looks for the difference between adjacent pixels from different regions. // FIXME :- It maybe better to look at the average different. ImageC &SegMap() { return segmap; } //: Access segmentation map. UIntT Labels() { return labels; } //: Access number of labels. SArray1dC ComputeMoments(bool ignoreZero = false); //: Compute moments for each of the segmented regions. // if ignoreZero is true, region labeled 0 is ignored. protected: UIntT RelabelTable(SArray1dC &labelTable, UIntT currentMaxLabel); //: Compress labels. ImageC segmap; // Segmentation map. UIntT labels; // Number of labels in map. }; //! userlevel=Normal //: Segmentation map. class SegmentationC : public RCHandleC { public: SegmentationC() {} //: Default constructor. // Creates an invalid handle. SegmentationC(ImageC nsegmap,UIntT nlabels) : RCHandleC(*new SegmentationBodyC(nsegmap,nlabels)) {} //: Constructor. SegmentationC(const Tuple2C,UIntT> &tup) : RCHandleC(*new SegmentationBodyC(tup.Data1(),tup.Data2())) {} //: Constructor. protected: SegmentationBodyC &Body() { return RCHandleC::Body(); } //: Access body. const SegmentationBodyC &Body() const { return RCHandleC::Body(); } //: Access body. public: SArray1dC > Adjacency(bool biDir = true) { return Body().Adjacency(biDir); } //: Generate a table of region adjacencies. // For each region, a set of adjacent regions is // generated. If biDir is false, only adjacenies in // one direction are generated, otherwise both directions // are registered. SArray1dC > BoundryLength() { return Body().BoundryLength(); } //: Generate a table of region adjacencies boundry lengths. // only adjacenies from regions with a smaller id to those // with a larger ID are generated UIntT RemoveSmallComponents(IntT thrSize) { return Body().RemoveSmallComponents(thrSize); } //: Remove small components from map, label them as 0. SArray1dC Areas() { return Body().Areas(); } //: Compute the areas of all the segmented regions. template UIntT MergeComponents(ImageC &dat,UIntT thrSize,RealT maxDist,CmpT &cmp,IntT iter = 1) { return Body().MergeComponents(dat,thrSize,maxDist,cmp,iter); } //: Merge simlar components smaller than 'thrSize'. ImageC &SegMap() { return Body().SegMap(); } //: Access segmentation map. UIntT Labels() { return Body().Labels(); } //: Access number of labels. SArray1dC ComputeMoments(bool ignoreZero = false) { return Body().ComputeMoments(ignoreZero); } //: Compute moments for each of the segmented regions. // if ignoreZero is true, region labeled 0 is ignored. }; //: Merge simlar components smaller than 'thrSize'. template UIntT SegmentationBodyC::MergeComponents(ImageC &dat, UIntT thrSize, RealT maxDist, CmpT &cmp, IntT iter) { if(labels <= 1) return labels; SArray1dC minDist(labels); SArray1dC area = Areas(); for(;iter > 0;iter--) { minDist.Fill(maxDist); // Fill with maximum merge threshold./ SArray1dC minLab = IdentityLabel(); // Find closest neigbour of small regions. for(Array2dSqr2Iter2C it(segmap,dat);it;) { // Do up. if(it.DataBR1() != it.DataTR1()) { // Are labels different ? if(area[it.DataBR1()] < thrSize) { RealT d = cmp(it.DataBR2(),it.DataTR2()); if(minDist[it.DataBR1()] > d) { minDist[it.DataBR1()] = d; minLab[it.DataBR1()] = it.DataTR1(); } } if(area[it.DataTR1()] < thrSize) { RealT d = cmp(it.DataBR2(),it.DataTR2()); if(minDist[it.DataTR1()] > d) { minDist[it.DataTR1()] = d; minLab[it.DataTR1()] = it.DataBR1(); } } } for(;it.Next();) { // The rest of the image row. // Do up. if(it.DataBR1() != it.DataTR1()) { // Are labels different ? if(area[it.DataBR1()] < thrSize) { if(it.DataBR1() != it.DataTR1()) { RealT d = cmp(it.DataBR2(),it.DataTR2()); if(minDist[it.DataBR1()] > d) { minDist[it.DataBR1()] = d; minLab[it.DataBR1()] = it.DataTR1(); } } } if(area[it.DataTR1()] < thrSize) { RealT d = cmp(it.DataBR2(),it.DataTR2()); if(minDist[it.DataTR1()] > d) { minDist[it.DataTR1()] = d; minLab[it.DataTR1()] = it.DataBR1(); } } } // Do back. if(it.DataBR1() != it.DataBL1()) { // Are labels different ? if(area[it.DataBR1()] < thrSize) { RealT d = cmp(it.DataBR2(),it.DataBL2()); if(minDist[it.DataBR1()] > d) { minDist[it.DataBR1()] = d; minLab[it.DataBR1()] = it.DataBL1(); } } if(area[it.DataBL1()] < thrSize) { RealT d = cmp(it.DataBR2(),it.DataBL2()); if(minDist[it.DataBL1()] > d) { minDist[it.DataBL1()] = d; minLab[it.DataBL1()] = it.DataBR1(); } } } } } CompressAndRelabel(minLab); if(iter > 1) area = RedoArea(area,minLab); } return labels; } } #endif