DGtal  1.5.beta
testSurfaceHelper.cpp
Go to the documentation of this file.
1 
31 #include <iostream>
32 #include <fstream>
33 #include "DGtal/base/Common.h"
34 #include "ConfigTest.h"
35 #include "DGtal/helpers/StdDefs.h"
36 #include "DGtal/geometry/curves/FreemanChain.h"
37 #include "DGtal/topology/KhalimskySpaceND.h"
38 #include "DGtal/topology/helpers/Surfaces.h"
39 #include "DGtal/topology/SurfelSetPredicate.h"
40 #include "DGtal/shapes/Shapes.h"
41 #include "DGtal/io/boards/Board2D.h"
42 #include "DGtal/io/readers/VolReader.h"
43 #include "DGtal/base/ConstAlias.h"
44 #include "DGtal/images/ImageContainerBySTLMap.h"
46 
47 using namespace std;
48 using namespace DGtal;
49 using namespace DGtal::functors;
50 
52 // Functions for testing class SurfaceHelper.
54 
62 {
63  unsigned int nbok = 0;
64  unsigned int nb = 0;
65  typedef SpaceND<2, int> Space;
68  typedef KSpace::SCell SCell;
69  typedef KSpace::Point Point;
70  typedef ImageContainerBySTLMap< Domain, bool> BoolImage2D;
71 
72 
73  trace.beginBlock ( "Testing computation of interior from a freeman chain ..." );
74  std::string freemanChainFilename = testPath + "samples/contourS.fc";
75  std::string freemanChainFilename2 = testPath + "samples/SmallBall.fc";
76  fstream fst;
77  fst.open (freemanChainFilename.c_str(), ios::in);
79  fst.close();
80  fst.open (freemanChainFilename2.c_str(), ios::in);
82  fst.close();
83  std::set<SCell> boundaryCell;
84  std::set<SCell> boundaryCell2;
85  KSpace K, Ko;
86 
87  int minx, miny, maxx, maxy;
88  fc.computeBoundingBox(minx, miny, maxx, maxy);
89 
90  BoolImage2D::Domain dom(Point(minx-5,miny-5), Point(maxx+5, maxy+5));
91  trace.info() << "Domain defined by :" << dom.lowerBound() << " " << dom.upperBound() << std::endl;
92  K.init(dom.lowerBound(), dom.upperBound(), true);
93  Ko.init(dom.lowerBound(), dom.upperBound(), false);
95 
96  BoolImage2D interiorImage(dom);
97  unsigned int nbInt = Surfaces<KSpace>::uFillInterior(K, SurfelSetPredicate<std::set<SCell>, SCell>(boundaryCell),
98  interiorImage, 1, false);
99  trace.info() << "Interior size: " << nbInt << " (awaited: 3082)" << std::endl;
100 
101  BoolImage2D exteriorImage(dom);
102  unsigned int nbExt = Surfaces< KSpace >::uFillExterior(K ,SurfelSetPredicate<std::set<SCell>, SCell>(boundaryCell),
103  exteriorImage, 1, true);
104  unsigned int nbExto = Surfaces< KSpace >::uFillExterior(Ko ,SurfelSetPredicate<std::set<SCell>, SCell>(boundaryCell),
105  exteriorImage, 1, true);
106  trace.info() << "Exterior size: (KhalimskySpaceND open) " << nbExto << " (awaited: 9182)" << std::endl;
107  trace.info() << "Exterior size: (KhalimskySpaceND close)" << nbExt << " (awaited: 9182)" << std::endl;
108 
109 
110  KSpace K2, K2c;
111  int minx2, miny2, maxx2, maxy2;
112  fc2.computeBoundingBox(minx2, miny2, maxx2, maxy2);
113  BoolImage2D::Domain dom2(Point(minx2-5,miny2-5), Point(maxx2+5, maxy2+5));
114  K2.init(dom2.lowerBound(), dom2.upperBound(), false);
115  K2c.init(dom2.lowerBound(), dom2.upperBound(), true);
116  FreemanChain<Space::Integer>::getInterPixelLinels(K2, fc2, boundaryCell2 );
117 
118  BoolImage2D interiorImage2(dom2);
119  unsigned int nbInt2 = Surfaces< KSpace >::uFillInterior(K2, SurfelSetPredicate<std::set<SCell>,SCell>(boundaryCell2),
120  interiorImage2, 1, false);
121  trace.info() << "Interior size2: (KhalimskySpaceND open) " << nbInt2 << " (awaited: 196316)" << std::endl;
122  unsigned int nbInt2c = Surfaces< KSpace >::uFillInterior(K2c, SurfelSetPredicate<std::set<SCell>,SCell>(boundaryCell2),
123  interiorImage2, 1, false);
124  trace.info() << "Interior size2: (KhalimskySpaceND closed) " << nbInt2c << " (awaited: 196316)" << std::endl;
125 
126  // Displaying interiorCell
127  Board2D aBoard, aBoard2, aBoard3;
128 
129  for( BoolImage2D::Domain::ConstIterator it = interiorImage.domain().begin(); it!= interiorImage.domain().end(); ++it){
130  if(interiorImage(*it)){
131  aBoard << *it;
132  }
133  }
134 
135  for( BoolImage2D::Domain::ConstIterator it = exteriorImage.domain().begin(); it!= exteriorImage.domain().end(); it++){
136  if(exteriorImage(*it)){
137  aBoard3 << *it;
138  }
139  }
140 
141  for( BoolImage2D::Domain::ConstIterator it = interiorImage2.domain().begin(); it!= interiorImage2.domain().end(); it++){
142  if(interiorImage2(*it)){
143  aBoard2 << *it;
144  }
145  }
146 
147  aBoard<< CustomStyle( (*(boundaryCell.begin())).className(),
148  new CustomColors( Color::Red, Color::None ) );
149  aBoard3<< CustomStyle( (*(boundaryCell.begin())).className(),
150  new CustomColors( Color::Red, Color::None ) );
151  aBoard2<< CustomStyle( (*(boundaryCell.begin())).className(),
152  new CustomColors( Color::Red, Color::None ) );
153  for( std::set<SCell>::const_iterator it= boundaryCell.begin(); it!= boundaryCell.end(); it++){
154  aBoard << *it;
155  aBoard3 << *it;
156  }
157 
158  for( std::set<SCell>::const_iterator it= boundaryCell2.begin(); it!= boundaryCell2.end(); it++){
159  aBoard2 << *it;
160  }
161 
162  aBoard << CustomStyle( fc.className(),
163  new CustomColors( Color::Red, Color::None ) );
164  aBoard3 << CustomStyle( fc.className(),
165  new CustomColors( Color::Red, Color::None ) );
166  aBoard2 << CustomStyle( fc.className(),
167  new CustomColors( Color::Red, Color::None ) );
168  aBoard << SetMode( fc.className(), "InterGrid" );
169  aBoard3 << SetMode( fc.className(), "InterGrid" );
170  aBoard2 << SetMode( fc.className(), "InterGrid" );
171  aBoard << fc;
172  aBoard3 << fc;
173  aBoard2 << fc2;
174 
175  aBoard.saveEPS("testSurfaceHelperComputeInterior.eps");
176  aBoard3.saveEPS("testSurfaceHelperComputeExterior.eps");
177  aBoard2.saveEPS("testSurfaceHelperComputeInterior2.eps");
178  nbok += (nbInt == 3082 && nbInt2 == 196316 && nbInt2c == 196316 && nbExt== 9182 && nbExto== 9182)? 1 : 0;
179  nb++;
180  trace.info() << "(" << nbok << "/" << nb << ") "
181  << nbInt << " (interiorCell.size()) == 3014 and "
182  << nbInt2 << " (interiorCell2.size()) == 60196 "
183  << std::endl;
184  trace.endBlock();
185 
186  return nbok == nb;
187 }
188 
189 
190 bool
192 {
194  unsigned int nbok = 0;
195  unsigned int nb = 0;
196 
197  trace.beginBlock ( "Testing extraction of 3D connected component ..." );
198  // import point from a vol file
200  Image3dChar image = VolReader<Image3dChar>::importVol( testPath + "samples/cat10.vol");
201  Set aSet(image.domain());
202  for(auto const &p: image.domain())
203  {
204  if(image(p)>0)
205  {
206  aSet.insert(p);
207  }
208  }
209  Z3i::KSpace Kc;
210  Kc.init(image.domain().lowerBound(),
211  image.domain().upperBound(), true);
212  SurfelAdjacency<3> SAdj( false );
213  std::vector<std::vector<DGtal::Z3i::SCell> > vectConnectedSCell;
214  Surfaces<DGtal::Z3i::KSpace>::extractAllConnectedSCell(vectConnectedSCell,Kc, SAdj, aSet, false);
215  nb++;
216  nbok += vectConnectedSCell.size()==1;
217  trace.info() << "Connected component :" << vectConnectedSCell.size() << " (should be 1) " << std::endl;
218  trace.endBlock();
219 
220  trace.beginBlock("Test 3D filling interior of surface (in an closed KhalimskySpaceND ) ...");
221  Image3dChar imageFilled(image.domain());
222  std::set<Z3i::SCell> setSCell; for (auto const &s: vectConnectedSCell[0]) setSCell.insert(s);
224 
225  unsigned int nbFilled = DGtal::Surfaces<DGtal::Z3i::KSpace>::uFillInterior(Kc, surfacePred, imageFilled, 1);
226  trace.info() << "Nb voxel filled:" << nbFilled << " (should be " << aSet.size() << " )" << std::endl;
227  nb++;
228  nbok += nbFilled == aSet.size();
229  trace.endBlock();
230 
231 
232  trace.beginBlock("Test 3D filling interior of surface (in an open KhalimskySpaceND ) ...");
233  Z3i::KSpace ko;
234  ko.init(image.domain().lowerBound(),
235  image.domain().upperBound(), false);
236  unsigned int nbFilled2 = DGtal::Surfaces<DGtal::Z3i::KSpace>::uFillInterior(ko, surfacePred, imageFilled, 1);
237  trace.info() << "Nb voxel filled:" << nbFilled2 << " (should be " << aSet.size() << " )" << std::endl;
238  nb++;
239  nbok += nbFilled2 == aSet.size();
240  trace.endBlock();
241 
242 
243  trace.beginBlock("Test 3D filling exterior of surface (in an closed KhalimskySpaceND ) ...");
244  unsigned int nbFilled3 = DGtal::Surfaces<DGtal::Z3i::KSpace>::uFillExterior(Kc, surfacePred, imageFilled, 1);
245  trace.info() << "Nb voxel filled:" << nbFilled3 << " (should be " << aSet.size() << " )" << std::endl;
246  nb++;
247  nbok += nbFilled3 == imageFilled.size()-aSet.size();
248  trace.endBlock();
249 
250 
251 
252  trace.beginBlock("Test 3D filling exterior of surface (in an open KhalimskySpaceND ) ...");
253  unsigned int nbFilled4 = DGtal::Surfaces<DGtal::Z3i::KSpace>::uFillExterior(ko, surfacePred, imageFilled, 1);
254  trace.info() << "Nb voxel filled:" << nbFilled4 << " (should be " << aSet.size() << " )" << std::endl;
255  nb++;
256  nbok += nbFilled4 == imageFilled.size()-aSet.size();
257  trace.endBlock();
258 
259 
260 
261 
262  return nb == nbok;
263 }
264 
265 
271 template <typename KSpace3D>
273 {
274  typedef KSpace3D KSpace;
275  typedef typename KSpace::Space Space;
276  typedef typename KSpace::Point Point;
277  typedef typename KSpace::SCell SCell;
280  unsigned int nbok = 0;
281  unsigned int nb = 0;
282  trace.beginBlock ( "Testing Surfaces::findABel." );
283  Point pts[ 8 ];
284  Point p1( -5, -5, -5 );
285  Point p2( 5, 5, 5 );
286  pts[ 0 ] = p1;
287  pts[ 1 ] = p2;
288  pts[ 2 ] = Point( 5, -5, -5 );
289  pts[ 3 ] = Point( -5, 5, -5 );
290  pts[ 4 ] = Point( 5, 5, -5 );
291  pts[ 5 ] = Point( -5, -5, 5 );
292  pts[ 6 ] = Point( 5, -5, 5 );
293  pts[ 7 ] = Point( -5, 5, 5 );
294  KSpace K; K.init( p1, p2, true );
295  Domain domain( p1, p2 );
296  DigitalSet aSet( domain );
297  Shapes<Domain>::addNorm2Ball( aSet, Point::zero, 2 );
298  for ( unsigned int i = 0; i < 8; ++i )
299  {
300  SCell bel = Surfaces<KSpace>::findABel( K, aSet, pts[ i ], Point::zero );
301  trace.info() << "- Exterior point is " << pts[ i ] << std::endl;
302  trace.info() << " - Found bel = " << bel << std::endl;
303  ++nb; nbok += K.sDim( bel ) == 2;
304  trace.info() << "(" << nbok << "/" << nb << ") "
305  << " K.sDim( bel ) == " << K.sDim( bel ) << " (should be 2)" << std::endl;
306  SCell vox_in = K.sDirectIncident( bel, K.sOrthDir( bel ) );
307  SCell vox_out = K.sIndirectIncident( bel, K.sOrthDir( bel ) );
308  ++nb; nbok += aSet( K.sCoords( vox_in ) ) ? 1 : 0;
309  trace.info() << "(" << nbok << "/" << nb << ") "
310  << " vox_in should be inside the shape." << std::endl;
311  ++nb; nbok += aSet( K.sCoords( vox_out ) ) ? 0 : 1;
312  trace.info() << "(" << nbok << "/" << nb << ") "
313  << " vox_out should be outside the shape." << std::endl;
314  }
315  return nbok == nb;
316 }
317 
318 
320 // Standard services - public :
321 
322 int main( int argc, char** argv )
323 {
324  trace.beginBlock ( "Testing class SurfaceHelper" );
325  trace.info() << "Args:";
326  for ( int i = 0; i < argc; ++i )
327  trace.info() << " " << argv[ i ];
328  trace.info() << endl;
329 
330  bool res = testComputeInterior()
331  && testFindABel< KhalimskySpaceND<3,int> >() && test3dSurfaceHelper();
332  trace.emphase() << ( res ? "Passed." : "Error." ) << endl;
333  trace.endBlock();
334  return res ? 0 : 1;
335 }
336 // //
Aim: This class specializes a 'Board' class so as to display DGtal objects more naturally (with <<)....
Definition: Board2D.h:71
Aim: A wrapper class around a STL associative container for storing sets of digital points within som...
Aim: A container class for storing sets of digital points within some given domain.
void computeBoundingBox(TInteger &min_x, TInteger &min_y, TInteger &max_x, TInteger &max_y) const
std::string className() const
Aim: This class is a model of CCellularGridSpaceND. It represents the cubical grid as a cell complex,...
bool init(const Point &lower, const Point &upper, bool isClosed)
Specifies the upper and lower bounds for the maximal cells in this space.
SCell sIndirectIncident(const SCell &p, Dimension k) const
Return the indirect incident cell of [p] along [k] (the incident cell along [k] whose sign is negativ...
Dimension sOrthDir(const SCell &s) const
Given a signed surfel [s], returns its orthogonal direction (ie, the coordinate where the surfel is c...
Point sCoords(const SCell &c) const
Return its digital coordinates.
SCell sDirectIncident(const SCell &p, Dimension k) const
Return the direct incident cell of [p] along [k] (the incident cell along [k])
Dimension sDim(const SCell &p) const
Return the dimension of the cell [p].
Aim: A utility class for constructing different shapes (balls, diamonds, and others).
Aim: A utility class for constructing surfaces (i.e. set of (n-1)-cells).
Definition: Surfaces.h:79
unsigned static int uFillInterior(const KSpace &aKSpace, const TSurfelPredicate &aSurfPred, TImageContainer &anImage, const typename TImageContainer::Value &aValue, bool empty_is_inside=false, bool incrementMode=true)
unsigned static int uFillExterior(const KSpace &aKSpace, const SurfelPredicate &aSurfPred, TImageContainer &anImage, const typename TImageContainer::Value &aValue, bool empty_is_outside=true, bool incrementMode=true)
Aim: Represent adjacencies between surfel elements, telling if it follows an interior to exterior ord...
void beginBlock(const std::string &keyword="")
std::ostream & emphase()
std::ostream & info()
double endBlock()
void saveEPS(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Definition: Board.cpp:804
Z3i::SCell SCell
MyDigitalSurface::ConstIterator ConstIterator
functors namespace gathers all DGtal functors.
DGtal is the top-level namespace which contains all DGtal functions and types.
Trace trace
Definition: Common.h:153
Custom style class redefining the pen color and the fill color. You may use Board2D::Color::None for ...
Definition: Board2D.h:279
Modifier class in a Board2D stream. Useful to choose your own mode for a given class....
Definition: Board2D.h:247
Represents a signed cell in a cellular grid space by its Khalimsky coordinates and a boolean value.
Aim: implements methods to read a "Vol" file format.
Definition: VolReader.h:90
Aim: The predicate returning true iff the point is in the domain given at construction.
MyPointD Point
Definition: testClone2.cpp:383
KSpace K
Domain domain
Image image(domain)
HyperRectDomain< Space > Domain
bool testFindABel()
int main(int argc, char **argv)
bool test3dSurfaceHelper()
bool testComputeInterior()
Z2i::DigitalSet DigitalSet