DGtalTools  0.9.4
2dLocalEstimators.cpp
1 
38 #include <iostream>
40 #include <iomanip>
41 #include <vector>
42 #include <string>
43 #include <fstream>
44 
45 #include <boost/program_options/options_description.hpp>
46 #include <boost/program_options/parsers.hpp>
47 #include <boost/program_options/variables_map.hpp>
48 
49 #include "DGtal/base/Common.h"
50 #include "DGtal/base/Clock.h"
51 
52 //shapes
53 #include "DGtal/shapes/ShapeFactory.h"
54 #include "DGtal/shapes/Shapes.h"
55 #include "DGtal/helpers/StdDefs.h"
56 #include "DGtal/topology/helpers/Surfaces.h"
57 #include "DGtal/topology/DigitalSurface.h"
58 
59 //Digitizer
60 #include "DGtal/shapes/GaussDigitizer.h"
61 #include "DGtal/geometry/curves/GridCurve.h"
62 #include "DGtal/topology/LightImplicitDigitalSurface.h"
63 #include "DGtal/graph/DepthFirstVisitor.h"
64 #include "DGtal/graph/GraphVisitorRange.h"
65 #include "DGtal/geometry/volumes/KanungoNoise.h"
66 
67 
68 //Estimators
69 #include "DGtal/geometry/curves/estimation/TrueLocalEstimatorOnPoints.h"
70 #include "DGtal/geometry/curves/estimation/TrueGlobalEstimatorOnPoints.h"
71 #include "DGtal/geometry/curves/estimation/ParametricShapeCurvatureFunctor.h"
72 #include "DGtal/geometry/curves/estimation/ParametricShapeTangentFunctor.h"
73 #include "DGtal/geometry/curves/estimation/ParametricShapeArcLengthFunctor.h"
74 
75 #include "DGtal/geometry/curves/BinomialConvolver.h"
76 #include "DGtal/geometry/curves/estimation/MostCenteredMaximalSegmentEstimator.h"
77 #include "DGtal/geometry/curves/estimation/SegmentComputerEstimators.h"
78 #include "DGtal/geometry/curves/ArithmeticalDSSComputer.h"
79 #include "DGtal/geometry/curves/StabbingCircleComputer.h"
80 
81 #include "DGtal/images/ImageHelper.h"
82 #include "DGtal/geometry/surfaces/estimation/IIGeometricFunctors.h"
83 #include "DGtal/geometry/surfaces/estimation/IntegralInvariantVolumeEstimator.h"
84 
85 #include "DGtal/kernel/BasicPointFunctors.h"
86 
87 using namespace DGtal;
88 
89 
90 
175 std::vector<std::string> shapes2D;
176 std::vector<std::string> shapesDesc;
177 std::vector<std::string> shapesParam1;
178 std::vector<std::string> shapesParam2;
179 std::vector<std::string> shapesParam3;
180 std::vector<std::string> shapesParam4;
181 
182 template< typename RealPoint >
183 struct OptionsIntegralInvariant
184 {
185  double alpha; // <! Alpha parameter for the convolution kernel. 1/3 by default
186  double radius; // <! Radius of the convolution kernel.
187  RealPoint center; // <! Center of the shape.
188  bool lambda_optimized;
189 };
190 
191 
196 void createList()
197 {
198  shapes2D.push_back("ball");
199  shapesDesc.push_back("Ball for the Euclidean metric.");
200  shapesParam1.push_back("--radius [-R]");
201  shapesParam2.push_back("");
202  shapesParam3.push_back("");
203  shapesParam4.push_back("");
204 
205  shapes2D.push_back("square");
206  shapesDesc.push_back("square (no signature).");
207  shapesParam1.push_back("--width [-w]");
208  shapesParam2.push_back("");
209  shapesParam3.push_back("");
210  shapesParam4.push_back("");
211 
212  shapes2D.push_back("lpball");
213  shapesDesc.push_back("Ball for the l_power metric (no signature).");
214  shapesParam1.push_back("--radius [-R],");
215  shapesParam2.push_back("--power [-p]");
216  shapesParam3.push_back("");
217  shapesParam4.push_back("");
218 
219  shapes2D.push_back("flower");
220  shapesDesc.push_back("Flower with k petals with radius ranging from R+/-v.");
221  shapesParam1.push_back("--radius [-R],");
222  shapesParam2.push_back("--varsmallradius [-v],");
223  shapesParam3.push_back("--k [-k],");
224  shapesParam4.push_back("--phi");
225 
226  shapes2D.push_back("ngon");
227  shapesDesc.push_back("Regular k-gon.");
228  shapesParam1.push_back("--radius [-R],");
229  shapesParam2.push_back("--k [-k],");
230  shapesParam3.push_back("--phi");
231  shapesParam4.push_back("");
232 
233  shapes2D.push_back("accflower");
234  shapesDesc.push_back("Accelerated Flower with k petals.");
235  shapesParam1.push_back("--radius [-R],");
236  shapesParam2.push_back("--varsmallradius [-v],");
237  shapesParam3.push_back("--k [-k],");
238  shapesParam4.push_back("--phi");
239 
240  shapes2D.push_back("ellipse");
241  shapesDesc.push_back("Ellipse.");
242  shapesParam1.push_back("--axis1 [-A],");
243  shapesParam2.push_back("--axis2 [-a],");
244  shapesParam3.push_back("--phi");
245  shapesParam4.push_back("");
246 
247 
248 }
249 
254 void displayList()
255 {
256  trace.emphase()<<"2D Shapes:"<<std::endl;
257  for(unsigned int i=0; i<shapes2D.size(); ++i)
258  trace.info()<<"\t"<<shapes2D[i]<<"\t"
259  <<shapesDesc[i]<<std::endl
260  <<"\t\tRequired parameter(s): "
261  << shapesParam1[i]<<" "
262  << shapesParam2[i]<<" "
263  << shapesParam3[i]<<" "
264  << shapesParam4[i]<<std::endl;
265 
266 }
267 
268 
277 unsigned int checkAndReturnIndex(const std::string &shapeName)
278 {
279  unsigned int pos=0;
280 
281  while ((pos < shapes2D.size()) && (shapes2D[pos] != shapeName))
282  pos++;
283 
284  if (pos == shapes2D.size())
285  {
286  trace.error() << "The specified shape has not found.";
287  trace.info() << std::endl;
288  exit(1);
289  }
290 
291  return pos;
292 }
293 
299 void missingParam(std::string param)
300 {
301  trace.error() <<" Parameter: "<<param<<" is required.";
302  trace.info()<<std::endl;
303  exit(1);
304 }
305 
312 void estimationError(int currentSize, int expectedSize)
313 {
314  if (currentSize != expectedSize)
315  {
316  trace.error() << " error in the estimation"
317  << " (got " << currentSize << " values"
318  << " instead of " << expectedSize << ")";
319  trace.info() << std::endl;
320  exit(1);
321  }
322 
323 }
324 
335 template <typename Estimator, typename ConstIterator, typename OutputIterator>
336 void
337 estimation( Estimator & estimator, double h,
338  const ConstIterator& itb, const ConstIterator& ite, const OutputIterator& ito )
339 {
340  Clock c;
341  c.startClock();
342  estimator.init( h, itb, ite );
343  estimator.eval( itb, ite, ito );
344  double time = c.stopClock();
345  std::cout << "# Time: " << time << std::endl;
346 }
347 
348 
353 template< typename ConstIteratorOnPoints, typename Point >
354 unsigned int suggestedSizeIntegralInvariant( const double h,
355  const Point& center,
356  const ConstIteratorOnPoints& itb,
357  const ConstIteratorOnPoints& ite )
358 {
359  typedef typename Point::Component TValue;
360 
361  ConstIteratorOnPoints it = itb;
362  Point p( *it );
363  Point distance = p - center;
364  TValue minRadius = distance.norm();
365  ++it;
366 
367  for ( ; it != ite; ++it )
368  {
369  p = *it;
370  distance = p - center;
371  if ( distance.norm() < minRadius )
372  {
373  minRadius = distance.norm();
374  }
375  }
376 
377  return minRadius * h;
378 }
379 
380 
393 template <typename Space, typename Shape>
394 bool
395 computeLocalEstimations( const std::string & filename,
396  Shape * aShape,
397  const double & h,
398  struct OptionsIntegralInvariant< Z2i::RealPoint > optionsII,
399  const std::string & options,
400  const std::string & properties,
401  const std::string & outShape,
402  double noiseLevel = 0.0 )
403 {
404  // Types
405  typedef typename Space::Vector Vector;
406  typedef typename Space::RealPoint RealPoint;
407  typedef typename Space::Integer Integer;
410  typedef typename KSpace::SCell SCell;
411  typedef GaussDigitizer<Space,Shape> Digitizer;
412  typedef KanungoNoise< Digitizer, Z2i::Domain > KanungoPredicate;
413 
414  bool withNoise = ( noiseLevel <= 0.0 ) ? false : true;
415  /*if( withNoise )
416  noiseLevel = std::pow(noiseLevel, h);*/
417 
418  ASSERT (( noiseLevel < 1.0 ));
419 
420  bool tangent = ( properties.at( 0 ) != '0' ) ? true : false;
421  bool curvature = ( properties.at( 1 ) != '0' ) ? true : false;
422 
423  // Digitizer
424  Digitizer* dig = new Digitizer();
425  dig->attach( *aShape ); // attaches the shape.
426  Vector vlow(-1,-1); Vector vup(1,1);
427  dig->init( aShape->getLowerBound()+vlow, aShape->getUpperBound()+vup, h );
428  Domain domain = dig->getDomain();
429 
430  //Noise
431 
432  Clock c;
433 
434  // Create cellular space
435  KSpace K;
436  bool ok = K.init( dig->getLowerBound(), dig->getUpperBound(), true );
437  if ( ! ok )
438  {
439  std::cerr << "[2dLocalEstimators]"
440  << " error in creating KSpace." << std::endl;
441  return false;
442  }
443  try {
444 
445  // Extracts shape boundary
447  SCell bel;
448  std::vector< SCell > points;
449 
450  KanungoPredicate *noisifiedObject;
451  if ( withNoise )
452  {
453  noisifiedObject = new KanungoPredicate( *dig, domain, noiseLevel );
454  bel = Surfaces< KSpace >::findABel( K, *noisifiedObject, 10000 );
455  Surfaces< KSpace >::track2DBoundary( points, K, SAdj, *noisifiedObject, bel );
456 
457  double minsize = dig->getUpperBound()[0] - dig->getLowerBound()[0];
458  while( points.size() < 2 * minsize )
459  {
460  points.clear();
461  bel = Surfaces< KSpace >::findABel( K, *noisifiedObject, 10000 );
462  Surfaces< KSpace >::track2DBoundary( points, K, SAdj, *noisifiedObject, bel );
463  }
464  }
465  else
466  {
467  bel = Surfaces< KSpace >::findABel( K, *dig, 10000 );
468  Surfaces< KSpace >::track2DBoundary( points, K, SAdj, *dig, bel );
469  }
470 
471  // Create GridCurve
472  GridCurve< KSpace > gridcurve;
473  gridcurve.initFromSCellsVector( points );
474  if(outShape != "")
475  {
476  std::ofstream outS;
477  outS.open(outShape.c_str());
478  for(const auto &p : points)
479  {
480 
481  Dimension track = *( K.sDirs( p ) );
482  SCell pointel = K.sIndirectIncident( p, track );
483  outS << K.sCoords( pointel )[0] << " " << K.sCoords( pointel )[1] << std::endl;
484  }
485  outS.close();
486  }
487  // Ranges
488  typedef typename GridCurve< KSpace >::MidPointsRange PointsRange;
489  PointsRange pointsRange = gridcurve.getMidPointsRange();
490 
491  // Estimations
492  if (gridcurve.isClosed())
493  {
494  if (options.at(0) != '0')
495  {
496  if( tangent )
497  {
498  char full_filename[360];
499  sprintf( full_filename, "%s%s", filename.c_str(), "_True_tangeant.dat" );
500  std::ofstream file( full_filename );
501 
502  file << "# h = " << h << std::endl;
503  file << "# True tangents computation" << std::endl;
504  file << "# range size = " << pointsRange.size() << std::endl;
505  if ( withNoise )
506  {
507  file << "# noise level (init) = " << noiseLevel/h << std::endl;
508  file << "# noise level (current) = " << noiseLevel << std::endl;
509  }
510 
511  std::ostream_iterator< RealPoint > out_it( file, "\n" );
512 
513  typedef ParametricShapeTangentFunctor< Shape > TangentFunctor;
514  typedef typename PointsRange::ConstCirculator C;
516  trueTangentEstimator;
517  trueTangentEstimator.attach( aShape );
518  estimation( trueTangentEstimator, h,
519  pointsRange.c(), pointsRange.c(),
520  out_it );
521 
522  file.close();
523 
524  }
525 
526  if( curvature )
527  {
528  char full_filename[360];
529  sprintf( full_filename, "%s%s", filename.c_str(), "_True_curvature.dat" );
530  std::ofstream file( full_filename );
531 
532  file << "# h = " << h << std::endl;
533  file << "# True curvature computation" << std::endl;
534  file << "# range size = " << pointsRange.size() << std::endl;
535  if ( withNoise )
536  {
537  file << "# noise level (init) = " << noiseLevel/h << std::endl;
538  file << "# noise level (current) = " << noiseLevel << std::endl;
539  }
540 
541  std::ostream_iterator< double > out_it( file, "\n" );
542 
543  typedef ParametricShapeCurvatureFunctor< Shape > CurvatureFunctor;
544  typedef typename PointsRange::ConstCirculator C;
546  trueCurvatureEstimator;
547  trueCurvatureEstimator.attach( aShape );
548  estimation( trueCurvatureEstimator, h,
549  pointsRange.c(), pointsRange.c(),
550  out_it );
551 
552  file.close();
553  }
554  }
555 
556  // Maximal Segments
557  if (options.at(1) != '0')
558  {
559  if( tangent )
560  {
561  char full_filename[360];
562  sprintf( full_filename, "%s%s", filename.c_str(), "_MDSS_tangeant.dat" );
563  std::ofstream file( full_filename );
564 
565  file << "# h = " << h << std::endl;
566  file << "# Most centered maximal DSS tangent estimation" << std::endl;
567  file << "# range size = " << pointsRange.size() << std::endl;
568  if ( withNoise )
569  {
570  file << "# noise level (init) = " << noiseLevel/h << std::endl;
571  file << "# noise level (current) = " << noiseLevel << std::endl;
572  }
573 
574  std::ostream_iterator< RealPoint > out_it( file, "\n" );
575 
576  typedef typename GridCurve< KSpace >::PointsRange PointsRange2;
577  PointsRange2 pointsRange2 = gridcurve.getPointsRange();
578 
579  typedef typename PointsRange2::ConstCirculator C;
580  typedef ArithmeticalDSSComputer< C, int, 4 > SegmentComputer;
582  SegmentComputer sc;
583  SCFunctor f;
584 
585 
587  estimation( MDSSTangentEstimator, h,
588  pointsRange2.c(), pointsRange2.c(),
589  out_it );
590 
591  file.close();
592  }
593  if( curvature )
594  {
595  c.startClock();
596 
597  char full_filename[360];
598  sprintf( full_filename, "%s%s", filename.c_str(), "_MDSSl_curvature.dat" );
599  std::ofstream file( full_filename );
600 
601  file << "# h = " << h << std::endl;
602  file << "# Most centered maximal DSS (length) curvature estimation" << std::endl;
603  file << "# range size = " << pointsRange.size() << std::endl;
604  if ( withNoise )
605  {
606  file << "# noise level (init) = " << noiseLevel/h << std::endl;
607  file << "# noise level (current) = " << noiseLevel << std::endl;
608  }
609 
610  std::ostream_iterator< double > out_it( file, "\n" );
611 
612  typedef typename GridCurve< KSpace >::PointsRange PointsRange2;
613  PointsRange2 pointsRange2 = gridcurve.getPointsRange();
614 
615  typedef typename PointsRange2::ConstCirculator C;
616  typedef ArithmeticalDSSComputer< C, int, 4 > SegmentComputer;
618  SegmentComputer sc;
619  SCFunctor f;
621 
622  estimation( MDSSCurvatureEstimator, h,
623  pointsRange2.c(), pointsRange2.c(),
624  out_it );
625 
626  file.close();
627 
628 
629  memset(&full_filename[0], 0, sizeof(full_filename));
630  sprintf( full_filename, "%s%s", filename.c_str(), "_MDSSlw_curvature.dat" );
631  file.open( full_filename );
632 
633  file << "# h = " << h << std::endl;
634  file << "# Most centered maximal DSS (length & width) curvature estimation" << std::endl;
635  file << "# range size = " << pointsRange.size() << std::endl;
636  if ( withNoise )
637  {
638  file << "# noise level (init) = " << noiseLevel/h << std::endl;
639  file << "# noise level (current) = " << noiseLevel << std::endl;
640  }
641 
642  std::ostream_iterator< double > out_it2( file, "\n" );
643 
645  SegmentComputer sc2;
646  SCFunctor2 f2;
648  estimation( MDSSCurvatureEstimator2, h,
649  pointsRange2.c(), pointsRange2.c(),
650  out_it2 );
651 
652  double time = c.stopClock();
653  file << "# Time: " << time << std::endl;
654 
655  file.close();
656 
657  }
658  }
659 
660  //Maximal circular arcs
661  if (options.at(2) != '0')
662  {
663  if( tangent )
664  {
665  char full_filename[360];
666  sprintf( full_filename, "%s%s", filename.c_str(), "_MDCA_tangent.dat" );
667  std::ofstream file( full_filename );
668 
669  file << "# h = " << h << std::endl;
670  file << "# Most centered maximal DCA tangents estimation" << std::endl;
671  file << "# range size = " << pointsRange.size() << std::endl;
672  if ( withNoise )
673  {
674  file << "# noise level (init) = " << noiseLevel/h << std::endl;
675  file << "# noise level (current) = " << noiseLevel << std::endl;
676  }
677 
678  std::ostream_iterator< RealPoint > out_it( file, "\n" );
679 
680  typedef typename GridCurve<KSpace>::IncidentPointsRange Range;
681  typedef typename Range::ConstCirculator C;
682  Range r = gridcurve.getIncidentPointsRange();
683  typedef StabbingCircleComputer<C> SegmentComputer;
685  SegmentComputer sc;
686  SCFunctor f;
688  estimation( MDCATangentEstimator, h,
689  r.c(), r.c(),
690  out_it );
691 
692  file.close();
693  }
694 
695  if( curvature )
696  {
697  c.startClock();
698 
699  char full_filename[360];
700  sprintf( full_filename, "%s%s", filename.c_str(), "_MDCA_curvature.dat" );
701  std::ofstream file( full_filename );
702 
703  file << "# h = " << h << std::endl;
704  file << "# Most centered maximal DCA curvature estimation" << std::endl;
705  file << "# range size = " << pointsRange.size() << std::endl;
706  if ( withNoise )
707  {
708  file << "# noise level (init) = " << noiseLevel/h << std::endl;
709  file << "# noise level (current) = " << noiseLevel << std::endl;
710  }
711 
712  std::ostream_iterator< double > out_it( file, "\n" );
713 
714  typedef typename GridCurve<KSpace>::IncidentPointsRange Range;
715  typedef typename Range::ConstCirculator C;
716  Range r = gridcurve.getIncidentPointsRange();
717  typedef StabbingCircleComputer<C> SegmentComputer;
719  SegmentComputer sc;
720  SCFunctor f;
722  estimation( MDCACurvatureEstimator, h,
723  r.c(), r.c(),
724  out_it );
725 
726  double time = c.stopClock();
727  file << "# Time: " << time << std::endl;
728 
729  file.close();
730  }
731  }
732 
733  //Binomial convolver
734  if (options.at(3) != '0')
735  {
736  if( tangent )
737  {
738  c.startClock();
739 
740  char full_filename[360];
741  sprintf( full_filename, "%s%s", filename.c_str(), "_BC_tangeant.dat" );
742  std::ofstream file( full_filename );
743 
744  file << "# h = " << h << std::endl;
745  file << "# Tangents estimation from binomial convolution" << std::endl;
746  file << "# range size = " << pointsRange.size() << std::endl;
747  if ( withNoise )
748  {
749  file << "# noise level (init) = " << noiseLevel/h << std::endl;
750  file << "# noise level (current) = " << noiseLevel << std::endl;
751  }
752 
753  typedef typename PointsRange::ConstIterator I;
754  typedef BinomialConvolver<I, double> MyBinomialConvolver;
755  file << "# mask size = " <<
756  MyBinomialConvolver::suggestedSize( h, pointsRange.begin(), pointsRange.end() ) << std::endl;
757 
759  TangentBCFct;
761 
762  std::ostream_iterator< RealPoint > out_it( file, "\n" );
763 
764  BCTangentEstimator.init( h, pointsRange.begin(), pointsRange.end(), true );
765  BCTangentEstimator.eval( pointsRange.begin(), pointsRange.end(), out_it );
766 
767  double time = c.stopClock();
768  file << "# Time: " << time << std::endl;
769 
770  file.close();
771  }
772 
773  if( curvature )
774  {
775  c.startClock();
776 
777  char full_filename[360];
778  sprintf( full_filename, "%s%s", filename.c_str(), "_BC_curvature.dat" );
779  std::ofstream file( full_filename );
780 
781  file << "# h = " << h << std::endl;
782  file << "# Curvature estimation from binomial convolution" << std::endl;
783  file << "# range size = " << pointsRange.size() << std::endl;
784  if ( withNoise )
785  {
786  file << "# noise level (init) = " << noiseLevel/h << std::endl;
787  file << "# noise level (current) = " << noiseLevel << std::endl;
788  }
789 
790  typedef typename PointsRange::ConstIterator I;
791  typedef BinomialConvolver<I, double> MyBinomialConvolver;
792  file << "# mask size = " <<
793  MyBinomialConvolver::suggestedSize( h, pointsRange.begin(), pointsRange.end() ) << std::endl;
794 
795  std::ostream_iterator< double > out_it( file, "\n" );
796 
798  CurvatureBCFct;
800 
801  BCCurvatureEstimator.init( h, pointsRange.begin(), pointsRange.end(), true );
802  BCCurvatureEstimator.eval( pointsRange.begin(), pointsRange.end(), out_it );
803 
804  double time = c.stopClock();
805  file << "# Time: " << time << std::endl;
806 
807  file.close();
808  }
809  }
810 
812  //Integral Invariants
813  if (options.at(4) != '0')
814  {
815  if( curvature )
816  {
817  c.startClock();
818 
819  char full_filename[360];
820  sprintf( full_filename, "%s%s", filename.c_str(), "_II_curvature.dat" );
821  std::ofstream file( full_filename );
822 
823  file << "# h = " << h << std::endl;
824  file << "# Integral Invariant curvature estimation" << std::endl;
825  file << "# range size = " << pointsRange.size() << std::endl;
826  if ( withNoise )
827  {
828  file << "# noise level (init) = " << noiseLevel/h << std::endl;
829  file << "# noise level (current) = " << noiseLevel << std::endl;
830  }
831 
832  if( optionsII.radius <= 0.0 )
833  {
834  optionsII.radius = suggestedSizeIntegralInvariant( h, dig->round( optionsII.center ), pointsRange.begin(), pointsRange.end() );
835  file << "# Estimated radius: " << optionsII.radius << std::endl;
836  }
837  double re = optionsII.radius * std::pow( h, optionsII.alpha );
838  file << "# full kernel (digital) size (with alpha = " << optionsII.alpha << ") = " <<
839  re / h << std::endl;
840 
841  std::ostream_iterator< double > out_it( file, "\n" );
842 
843  if ( withNoise )
844  {
845  typedef LightImplicitDigitalSurface< KSpace, KanungoPredicate > LightImplicitDigSurface;
847 
848  LightImplicitDigSurface LightImplDigSurf( K, *noisifiedObject, SAdj, bel );
849  DigSurface surf( LightImplDigSurf );
850 
851  typedef DepthFirstVisitor< DigSurface > Visitor;
852  typedef GraphVisitorRange< Visitor > VisitorRange;
853  typedef typename VisitorRange::ConstIterator VisitorConstIterator;
854 
855  VisitorRange range( new Visitor( surf, *surf.begin() ));
856  VisitorConstIterator ibegin = range.begin();
857  VisitorConstIterator iend = range.end();
858 
859  typedef functors::IICurvatureFunctor<Z2i::Space> MyIICurvatureFunctor;
861 
862  MyIICurvatureFunctor curvatureFunctor;
863  curvatureFunctor.init( h, re );
864 
865  MyIICurvatureEstimator curvatureEstimator( curvatureFunctor );
866  curvatureEstimator.attach( K, *noisifiedObject );
867  curvatureEstimator.setParams( re/h );
868  curvatureEstimator.init( h, ibegin, iend );
869 
870  curvatureEstimator.eval( ibegin, iend, out_it );
871  }
872  else
873  {
874  typedef LightImplicitDigitalSurface< KSpace, Digitizer > LightImplicitDigSurface;
876 
877  LightImplicitDigSurface LightImplDigSurf( K, *dig, SAdj, bel );
878  DigSurface surf( LightImplDigSurf );
879 
880  typedef DepthFirstVisitor< DigSurface > Visitor;
881  typedef GraphVisitorRange< Visitor > VisitorRange;
882  typedef typename VisitorRange::ConstIterator VisitorConstIterator;
883 
884  VisitorRange range( new Visitor( surf, *surf.begin() ));
885  VisitorConstIterator ibegin = range.begin();
886  VisitorConstIterator iend = range.end();
887 
888  typedef functors::IICurvatureFunctor<Z2i::Space> MyIICurvatureFunctor;
890 
891  MyIICurvatureFunctor curvatureFunctor;
892  curvatureFunctor.init( h, re );
893 
894  MyIICurvatureEstimator curvatureEstimator( curvatureFunctor );
895  curvatureEstimator.attach( K, *dig );
896  curvatureEstimator.setParams( re/h );
897  curvatureEstimator.init( h, ibegin, iend );
898 
899  curvatureEstimator.eval( ibegin, iend, out_it );
900  }
901 
902  double time = c.stopClock();
903  file << "# Time: " << time << std::endl;
904 
905  file.close();
906  }
907  }
908 
909  //delete noisifiedObject;
910  delete dig;
911  }
912  else
913  {
914  //delete noisifiedObject;
915  delete dig;
916  std::cerr << "[computeLocalEstimations]"
917  << " error: open digital curve found." << std::endl;
918  return false;
919  }
920  }
921  catch ( InputException e )
922  {
923  std::cerr << "[computeLocalEstimations]"
924  << " error in finding a bel." << std::endl;
925  return false;
926  }
927  return true;
928 }
929 
930 
932 namespace po = boost::program_options;
933 
934 int main( int argc, char** argv )
935 {
936  // parse command line ----------------------------------------------
937  po::options_description general_opt("Allowed options are");
938  general_opt.add_options()
939  ("help,h", "display this message")
940  ("list,l", "List all available shapes")
941  ("output,o", po::value<std::string>(), "Output")
942  ("shape,s", po::value<std::string>(), "Shape name")
943  ("radius,R", po::value<double>(), "Radius of the shape" )
944  ("kernelradius,K", po::value<double>()->default_value(0.0), "Radius of the convolution kernel (Integral invariants estimators)" )
945  ("alpha", po::value<double>()->default_value(1.0/3.0), "Alpha parameter for Integral Invariant computation" )
946  ("axis1,A", po::value<double>(), "Half big axis of the shape (ellipse)" )
947  ("axis2,a", po::value<double>(), "Half small axis of the shape (ellipse)" )
948  ("smallradius,r", po::value<double>()->default_value(5), "Small radius of the shape" )
949  ("varsmallradius,v", po::value<double>()->default_value(5), "Variable small radius of the shape" )
950  ("k,k", po::value<unsigned int>()->default_value(3), "Number of branches or corners the shape" )
951  ("phi", po::value<double>()->default_value(0.0), "Phase of the shape (in radian)" )
952  ("width,w", po::value<double>()->default_value(10.0), "Width of the shape" )
953  ("power,p", po::value<double>()->default_value(2.0), "Power of the metric (double)" )
954  ("center_x,x", po::value<double>()->default_value(0.0), "x-coordinate of the shape center (double)" )
955  ("center_y,y", po::value<double>()->default_value(0.0), "y-coordinate of the shape center (double)" )
956  ("gridstep,g", po::value<double>()->default_value(1.0), "Grid step for the digitization" )
957  ("noise,n", po::value<double>()->default_value(0.0), "Level of noise to perturb the shape" )
958  ("properties", po::value<std::string>()->default_value("11"), "the i-th property is disabled iff there is a 0 at position i" )
959  ("estimators,e", po::value<std::string>()->default_value("10000"), "the i-th estimator is disabled iff there is a 0 at position i" )
960  ("exportShape,E", po::value<std::string>(), "Exports the contour of the source shape as a sequence of discrete points (.sdp)" )
961  ("lambda,l", po::value< bool >()->default_value( false ), "Use the shape to get a better approximation of the surface (optional)" );
962 
963 
964  bool parseOK=true;
965  po::variables_map vm;
966  try{
967  po::store(po::parse_command_line(argc, argv, general_opt), vm);
968  }catch(const std::exception& ex){
969  parseOK=false;
970  trace.info()<< "Error checking program options: "<< ex.what()<< std::endl;
971  }
972  po::notify(vm);
973  if(!parseOK || vm.count("help")||argc<=1)
974  {
975  trace.info()<< "Compare local estimators on implicit shapes using DGtal library" <<std::endl
976  << "Basic usage: "<<std::endl
977  << "\t2dlocalEstimators --output <output> --shape <shapeName> [required parameters] --estimators <binaryWord> --properties <binaryWord>"<<std::endl
978  << std::endl
979  << "Below are the different available families of estimators: " << std::endl
980  << "\t - True estimators" << std::endl
981  << "\t - Maximal DSS based estimators" << std::endl
982  << "\t - Maximal DCA based estimators" << std::endl
983  << "\t - Binomial convolver based estimators" << std::endl
984  << "\t - Integral Invariants based estimators" << std::endl
985  << std::endl
986  << "The i-th family of estimators is enabled if the i-th character of the binary word is not 0. "
987  << "The default binary word is '10000'. This means that the first family of estimators, "
988  << "ie. true estimators, is enabled, whereas the next ones are disabled. "
989  << std::endl
990  << "Below are the different available properties: " << std::endl
991  << "\t - Tangent" << std::endl
992  << "\t - Curvature" << std::endl
993  << std::endl
994  << "Example: "<<std::endl
995  << "\t2dlocalEstimators --output curvature --shape ellipse --axis1 20 --axis2 7 --gridstep 0.1 --kernelradius 5 --estimators 10001 --properties 01"<<std::endl
996  << std::endl
997  << general_opt << std::endl;
998  return 0;
999  }
1000 
1001  //List creation
1002  createList();
1003 
1004  if (vm.count("list"))
1005  {
1006  displayList();
1007  return 0;
1008  }
1009 
1010  //Parse options
1011  if (!(vm.count("shape"))) missingParam("--shape");
1012  if (!(vm.count("output"))) missingParam("--output");
1013 
1014  std::string shapeName = vm["shape"].as<std::string>();
1015  std::string filename = vm["output"].as<std::string>();
1016 
1017  unsigned int nb = 4; //number of available methods
1018  std::string options = vm["estimators"].as< std::string >();
1019  if (options.size() < nb)
1020  {
1021  trace.error() << " At least " << nb
1022  << " characters are required "
1023  << " with option --estimators.";
1024  trace.info() << std::endl;
1025  exit(1);
1026  }
1027 
1028  nb = 2; //number of available properties
1029  std::string properties = vm["properties"].as<std::string>();
1030  if (properties.size() < nb)
1031  {
1032  trace.error() << " At least " << nb
1033  << " characters are required "
1034  << " with option --properties.";
1035  trace.info() << std::endl;
1036  exit(1);
1037  }
1038 
1039  //We check that the shape is known
1040  unsigned int id = checkAndReturnIndex(shapeName);
1041 
1042  // standard types
1043  typedef Z2i::Space Space;
1044  typedef Space::RealPoint RealPoint;
1045 
1046  RealPoint center( vm["center_x"].as<double>(),
1047  vm["center_y"].as<double>() );
1048  double h = vm["gridstep"].as<double>();
1049 
1050  struct OptionsIntegralInvariant< RealPoint > optII;
1051  optII.radius = vm["kernelradius"].as<double>();
1052  optII.alpha = vm["alpha"].as<double>();
1053  optII.lambda_optimized = vm["lambda"].as< bool >();
1054  optII.center = center;
1055 
1056  std::string outShape = vm.count("exportShape")? vm["exportShape"].as<std::string>(): "";
1057  double noiseLevel = vm["noise"].as<double>();
1058 
1059  if (id ==0)
1060  {
1061  if (!(vm.count("radius"))) missingParam("--radius");
1062  //if (!(vm.count("kernelradius"))) missingParam("--kernelradius");
1063  double radius = vm["radius"].as<double>();
1064 
1065  Ball2D<Space> * ball = new Ball2D<Space>( center, radius);
1066  computeLocalEstimations<Space>( filename, ball, h, optII, options, properties, outShape, noiseLevel );
1067  delete ball;
1068  }
1069  else if (id ==1)
1070  {
1071  if (!(vm.count("width"))) missingParam("--width");
1072  double width = vm["width"].as<double>();
1073 
1074  ImplicitHyperCube<Space> object(Z2i::Point(0,0), width/2);
1075  trace.error()<< "Not available.";
1076  trace.info()<<std::endl;
1077  }
1078  else if (id ==2)
1079  {
1080  if (!(vm.count("power"))) missingParam("--power");
1081  if (!(vm.count("radius"))) missingParam("--radius");
1082  double radius = vm["radius"].as<double>();
1083  double power = vm["power"].as<double>();
1084 
1085  ImplicitRoundedHyperCube<Space> ball( Z2i::Point(0,0), radius, power );
1086  trace.error()<< "Not available.";
1087  trace.info()<<std::endl;
1088  }
1089  else if (id ==3)
1090  {
1091  if (!(vm.count("varsmallradius"))) missingParam("--varsmallradius");
1092  if (!(vm.count("radius"))) missingParam("--radius");
1093  if (!(vm.count("k"))) missingParam("--k");
1094  if (!(vm.count("phi"))) missingParam("--phi");
1095  //if (!(vm.count("kernelradius"))) missingParam("--kernelradius");
1096  double radius = vm["radius"].as<double>();
1097  double varsmallradius = vm["varsmallradius"].as<double>();
1098  unsigned int k = vm["k"].as<unsigned int>();
1099  double phi = vm["phi"].as<double>();
1100 
1101  Flower2D<Space> * flower = new Flower2D<Space>( center, radius, varsmallradius, k, phi );
1102  computeLocalEstimations<Space>( filename, flower, h, optII, options, properties, outShape, noiseLevel );
1103  delete flower;
1104  }
1105  else if (id ==4)
1106  {
1107  if (!(vm.count("radius"))) missingParam("--radius");
1108  if (!(vm.count("k"))) missingParam("--k");
1109  if (!(vm.count("phi"))) missingParam("--phi");
1110  //if (!(vm.count("kernelradius"))) missingParam("--kernelradius");
1111  double radius = vm["radius"].as<double>();
1112  unsigned int k = vm["k"].as<unsigned int>();
1113  double phi = vm["phi"].as<double>();
1114 
1115  NGon2D<Space> * object = new NGon2D<Space>( center, radius, k, phi );
1116  computeLocalEstimations<Space>( filename, object, h, optII, options, properties, outShape, noiseLevel );
1117  delete object;
1118  }
1119  else if (id ==5)
1120  {
1121  if (!(vm.count("varsmallradius"))) missingParam("--varsmallradius");
1122  if (!(vm.count("radius"))) missingParam("--radius");
1123  if (!(vm.count("k"))) missingParam("--k");
1124  if (!(vm.count("phi"))) missingParam("--phi");
1125  //if (!(vm.count("kernelradius"))) missingParam("--kernelradius");
1126  double radius = vm["radius"].as<double>();
1127  double varsmallradius = vm["varsmallradius"].as<double>();
1128  unsigned int k = vm["k"].as<unsigned int>();
1129  double phi = vm["phi"].as<double>();
1130 
1131  AccFlower2D<Space> * accflower = new AccFlower2D<Space>( center, radius, varsmallradius, k, phi );
1132  computeLocalEstimations<Space>( filename, accflower, h, optII, options, properties, outShape, noiseLevel );
1133  delete accflower;
1134  }
1135  else if (id ==6)
1136  {
1137  if (!(vm.count("axis1"))) missingParam("--axis1");
1138  if (!(vm.count("axis2"))) missingParam("--axis2");
1139  if (!(vm.count("phi"))) missingParam("--phi");
1140  //if (!(vm.count("kernelradius"))) missingParam("--kernelradius");
1141  double a1 = vm["axis1"].as<double>();
1142  double a2 = vm["axis2"].as<double>();
1143  double phi = vm["phi"].as<double>();
1144 
1145  Ellipse2D<Space> * ellipse = new Ellipse2D<Space>( center, a1, a2, phi );
1146  computeLocalEstimations<Space>( filename, ellipse, h, optII, options, properties, outShape, noiseLevel );
1147  delete ellipse;
1148  }
1149 }
DGtal::int32_t Integer
PointsRange getPointsRange() const
MidPointsRange getMidPointsRange() const
void init(const double h, const ConstIterator &itb, const ConstIterator &ite, const bool isClosed=true)
SpaceND< 2, Integer > Space
double stopClock() const
DGtal::uint32_t Dimension
void attach(ParametricShape *aShapePtr)
T power(const T &aVal, const unsigned int exponent)
bool isClosed() const
static SCell findABel(const KSpace &K, const PointPredicate &pp, unsigned int nbtries=1000)
static void track2DBoundary(std::vector< SCell > &aSCellContour2D, const KSpace &K, const SurfelAdjacency< KSpace::dimension > &surfel_adj, const PointPredicate &pp, const SCell &start_surfel)
DirIterator sDirs(const SCell &p) const
IncidentPointsRange getIncidentPointsRange() const
std::ostream & emphase()
bool init(const Point &lower, const Point &upper, bool isClosed)
void startClock()
Point sCoords(const SCell &c) const
Trace trace(traceWriterTerm)
std::ostream & info()
SCell sIndirectIncident(const SCell &p, Dimension k) const
typename Self::Point Point
void init(const double _h, SurfelConstIterator itb, SurfelConstIterator ite)
Quantity eval(const ConstIterator &it)
std::ostream & error()
Space::Vector Vector
bool initFromSCellsVector(const std::vector< SCell > &aVectorOfSCells)
typename Self::Domain Domain