Esempio n. 1
0
bool
compareShapeEstimators( const string & name,
      Shape & aShape, 
      double h )
{
  // Types
  typedef typename Space::Point Point;
  typedef typename Space::Vector Vector;
  typedef typename Space::RealPoint RealPoint;
  typedef typename Space::Integer Integer;
  typedef HyperRectDomain<Space> Domain;
  typedef KhalimskySpaceND<Space::dimension,Integer> KSpace;
  typedef typename KSpace::SCell SCell;
  typedef typename GridCurve<KSpace>::PointsRange PointsRange;
  typedef typename GridCurve<KSpace>::ArrowsRange ArrowsRange;
  typedef typename PointsRange::ConstIterator ConstIteratorOnPoints;


  // Digitizer
  GaussDigitizer<Space,Shape> dig;  
  dig.attach( aShape ); // attaches the shape.
  Vector vlow(-1,-1); Vector vup(1,1);
  dig.init( aShape.getLowerBound()+vlow, aShape.getUpperBound()+vup, h ); 
  Domain domain = dig.getDomain();

  // Create cellular space
  KSpace K;
  bool ok = K.init( dig.getLowerBound(), dig.getUpperBound(), true );
  if ( ! ok )
    {
      std::cerr << "[compareShapeEstimators]"
    << " error in creating KSpace." << std::endl;
      return false;
    }
  try {
    // Extracts shape boundary
    SurfelAdjacency<KSpace::dimension> SAdj( true );
    SCell bel = Surfaces<KSpace>::findABel( K, dig, 10000 );
    // Getting the consecutive surfels of the 2D boundary
    std::vector<Point> points;
    Surfaces<KSpace>::track2DBoundaryPoints( points, K, SAdj, dig, bel );
    // Create GridCurve
    GridCurve<KSpace> gridcurve;
    gridcurve.initFromVector( points );
    // Ranges
    PointsRange r = gridcurve.getPointsRange(); 
    std::cout << "# range size = " << r.size() << std::endl;  

    // Estimations
    // True values
    std::cout << "# True values computation" << std::endl;  
    typedef ParametricShapeTangentFunctor< Shape > TangentFunctor;
    typedef ParametricShapeCurvatureFunctor< Shape > CurvatureFunctor;
  
    TrueLocalEstimatorOnPoints< ConstIteratorOnPoints, Shape, TangentFunctor >  
      trueTangentEstimator;
    TrueLocalEstimatorOnPoints< ConstIteratorOnPoints, Shape, CurvatureFunctor >  
      trueCurvatureEstimator;
  
    trueTangentEstimator.init( h, r.begin(), r.end(), &aShape, gridcurve.isClosed());
    std::vector<RealPoint> trueTangents = 
      estimateQuantity( trueTangentEstimator, r.begin(), r.end() );
    trueCurvatureEstimator.init( h, r.begin(), r.end(), &aShape, gridcurve.isClosed());
    std::vector<double> trueCurvatures = 
      estimateQuantity( trueCurvatureEstimator, r.begin(), r.end() );
  
    // Maximal Segments
    std::cout << "# Maximal DSS tangent estimation" << std::endl;  
    typedef ArithmeticalDSS<ConstIteratorOnPoints,Integer,4> SegmentComputer;
    typedef TangentFromDSSFunctor<SegmentComputer> SCFunctor;
    SegmentComputer sc;
    SCFunctor f; 
    MostCenteredMaximalSegmentEstimator<SegmentComputer,SCFunctor> MSTangentEstimator(sc, f); 
   
    Clock c;
    
    c.startClock();
    MSTangentEstimator.init( h, r.begin(), r.end(), gridcurve.isClosed() );
    std::vector<typename SCFunctor::Value> MSTangents = 
      estimateQuantity( MSTangentEstimator, r.begin(), r.end() );
    double TMST = c.stopClock();


    // Binomial
    std::cout << "# Tangent and curvature estimation from binomial convolution" << std::endl;
    typedef BinomialConvolver<ConstIteratorOnPoints, double> MyBinomialConvolver;
    std::cout << "# mask size = " << 
      MyBinomialConvolver::suggestedSize( h, r.begin(), r.end() ) << std::endl;
    typedef TangentFromBinomialConvolverFunctor< MyBinomialConvolver, RealPoint >
      TangentBCFct;
    typedef CurvatureFromBinomialConvolverFunctor< MyBinomialConvolver, double >
      CurvatureBCFct;
    BinomialConvolverEstimator< MyBinomialConvolver, TangentBCFct> BCTangentEstimator;
    BinomialConvolverEstimator< MyBinomialConvolver, CurvatureBCFct> BCCurvatureEstimator;
    
    c.startClock();
    BCTangentEstimator.init( h, r.begin(), r.end(), gridcurve.isClosed() );
    std::vector<RealPoint> BCTangents = 
      estimateQuantity( BCTangentEstimator, r.begin(), r.end() );
    double TBCTan = c.stopClock();

    c.startClock();
    BCCurvatureEstimator.init( h, r.begin(), r.end(), gridcurve.isClosed() );
    std::vector<double> BCCurvatures =
      estimateQuantity( BCCurvatureEstimator, r.begin(), r.end() );
    double TBCCurv = c.stopClock();

    // Output
    std::cout << "# Shape = "<< name <<std::endl
        << "# Time-BCtangent = "<<TBCTan <<std::endl
        << "# Time-BCcurvature = "<<TBCCurv<<std::endl
        << "# Time-MStangent = "<<TMST<<std::endl
        << "# id x y tangentx tangenty curvature"
        << " BCtangentx BCtangenty BCcurvature"
        << " MStangentx MStangenty"
        << std::endl;  
    unsigned int i = 0;
    for ( ConstIteratorOnPoints it = r.begin(), it_end = r.end();
    it != it_end; ++it, ++i )
      {
  Point p = *it;
  std::cout << i << setprecision( 15 )
      << " " << p[ 0 ] << " " << p[ 1 ] 
      << " " << trueTangents[ i ][ 0 ]
      << " " << trueTangents[ i ][ 1 ]
      << " " << trueCurvatures[ i ]
      << " " << BCTangents[ i ][ 0 ]
      << " " << BCTangents[ i ][ 1 ]
      << " " << BCCurvatures[ i ]
      << " " << MSTangents[ i ][ 0 ]
      << " " << MSTangents[ i ][ 1 ]
      << std::endl;
      }
    return true;
  }    
  catch ( InputException e )
    {
      std::cerr << "[compareShapeEstimators]"
    << " error in finding a bel." << std::endl;
      return false;
    }
}
bool
lengthEstimators( const std::string & /*name*/,
      Shape & aShape, 
      double h )
{
  // Types
  typedef typename Space::Point Point;
  typedef typename Space::Vector Vector;
  typedef typename Space::RealPoint RealPoint;
  typedef typename Space::Integer Integer;
  typedef HyperRectDomain<Space> Domain;
  typedef KhalimskySpaceND<Space::dimension,Integer> KSpace;
  typedef typename KSpace::SCell SCell;
  typedef typename GridCurve<KSpace>::PointsRange PointsRange;
  typedef typename GridCurve<KSpace>::ArrowsRange ArrowsRange;

  // Digitizer
  GaussDigitizer<Space,Shape> dig;  
  dig.attach( aShape ); // attaches the shape.
  Vector vlow(-1,-1); Vector vup(1,1);
  dig.init( aShape.getLowerBound()+vlow, aShape.getUpperBound()+vup, h ); 
  Domain domain = dig.getDomain();

  // Create cellular space
  KSpace K;
  bool ok = K.init( dig.getLowerBound(), dig.getUpperBound(), true );
  if ( ! ok )
    {
      std::cerr << "[lengthEstimators]"
    << " error in creating KSpace." << std::endl;
      return false;
    }
  try {
    // Extracts shape boundary
    SurfelAdjacency<KSpace::dimension> SAdj( true );
    SCell bel = Surfaces<KSpace>::findABel( K, dig, 10000 );
    // Getting the consecutive surfels of the 2D boundary
    std::vector<Point> points;
    Surfaces<KSpace>::track2DBoundaryPoints( points, K, SAdj, dig, bel );
    // Create GridCurve
    GridCurve<KSpace> gridcurve;
    gridcurve.initFromVector( points );
    // Ranges
    ArrowsRange ra = gridcurve.getArrowsRange(); 
    PointsRange rp = gridcurve.getPointsRange(); 


    // Estimations
    typedef typename PointsRange::ConstIterator ConstIteratorOnPoints; 
    typedef ParametricShapeArcLengthFunctor< Shape > Length;
    TrueGlobalEstimatorOnPoints< ConstIteratorOnPoints, Shape, Length  >  trueLengthEstimator;
    trueLengthEstimator.init( h, rp.begin(), rp.end(), &aShape, gridcurve.isClosed());

    L1LengthEstimator< typename ArrowsRange::ConstCirculator > l1length;
    DSSLengthEstimator< typename PointsRange::ConstCirculator > DSSlength;
    MLPLengthEstimator< typename PointsRange::ConstIterator > MLPlength;
    FPLengthEstimator< typename PointsRange::ConstIterator > FPlength;
    BLUELocalLengthEstimator< typename ArrowsRange::ConstIterator > BLUElength;
    RosenProffittLocalLengthEstimator< typename ArrowsRange::ConstIterator > RosenProffittlength;
  
    // Output
    double trueValue = trueLengthEstimator.eval();
    double l1, blue, rosen,dss,mlp,fp;
    double Tl1, Tblue, Trosen,Tdss,Tmlp,Tfp;
    
    Clock c;

    //Length evaluation & timing
    c.startClock();
    l1length.init(h, ra.c(), ra.c());
    l1 = l1length.eval();
    Tl1 = c.stopClock();
    
    c.startClock();
    BLUElength.init(h, ra.begin(), ra.end(), gridcurve.isClosed());
    blue = BLUElength.eval();
    Tblue = c.stopClock();
    
    c.startClock();
    RosenProffittlength.init(h, ra.begin(), ra.end(), gridcurve.isClosed());
    rosen = RosenProffittlength.eval();
    Trosen = c.stopClock();
    
    c.startClock();
    DSSlength.init(h, rp.c(), rp.c());
    dss = DSSlength.eval();
    Tdss = c.stopClock();
    
    c.startClock();
    MLPlength.init(h, rp.begin(), rp.end(), gridcurve.isClosed());
    mlp = MLPlength.eval();
    Tmlp = c.stopClock();

    c.startClock();
    FPlength.init(h, rp.begin(), rp.end(), gridcurve.isClosed());
    fp = FPlength.eval();
    Tfp = c.stopClock();

    std::cout << std::setprecision( 15 ) << h << " " << rp.size() << " " << trueValue 
   << " " << l1
   << " " << blue
   << " " << rosen
   << " " << dss
   << " " << mlp   
   << " " << fp
         << " " << Tl1
   << " " << Tblue
   << " " << Trosen
   << " " << Tdss
   << " " << Tmlp
   << " " << Tfp     
   << std::endl;
    return true;
  }    
  catch ( InputException e )
    {
      std::cerr << "[lengthEstimators]"
    << " error in finding a bel." << std::endl;
      return false;
    }
}
GridCurve<TKSpace>
ballGenerator(double aCx, double aCy, double aR, bool aFlagIsCW)
{

  // Types
  typedef TKSpace KSpace;  
  typedef typename KSpace::SCell SCell;
  typedef GridCurve<KSpace> GridCurve; 
  typedef typename KSpace::Space Space;  
  typedef Ball2D<Space> Shape;
  typedef typename Space::Point Point;
  typedef typename Space::RealPoint RealPoint;
  typedef HyperRectDomain<Space> Domain;

  //Forme
  Shape aShape(Point(aCx,aCy), aR);

  // Window for the estimation
  RealPoint xLow ( -aR-1, -aR-1 );
  RealPoint xUp( aR+1, aR+1 );
  GaussDigitizer<Space,Shape> dig;  
  dig.attach( aShape ); // attaches the shape.
  dig.init( xLow, xUp, 1 ); 
  Domain domain = dig.getDomain();
  // Create cellular space
  KSpace K;
  bool ok = K.init( dig.getLowerBound(), dig.getUpperBound(), true );
  if ( ! ok )
  {
      std::cerr << " "
    << " error in creating KSpace." << std::endl;
      return GridCurve();
  }
  try 
  {

    // Extracts shape boundary
    SurfelAdjacency<KSpace::dimension> SAdj( true );
    SCell bel = Surfaces<KSpace>::findABel( K, dig, 10000 );
    // Getting the consecutive surfels of the 2D boundary
    std::vector<Point> points, points2;
    Surfaces<KSpace>::track2DBoundaryPoints( points, K, SAdj, dig, bel );
    //counter-clockwise oriented by default
    GridCurve c; 
    if (aFlagIsCW)
    {
      points2.assign( points.rbegin(), points.rend() );
      c.initFromVector(points2); 
    } 
    else 
    {
      c.initFromVector(points); 
    }
    return c;
  }
  catch ( InputException& e )
  {
      std::cerr << " "
    << " error in finding a bel." << std::endl;
      return GridCurve();
  }
}
Esempio n. 4
0
bool
generateContour(
                Shape & aShape,
                double h,
                const std::string & outputFormat,
                bool withGeom,
                const std::string & outputFileName  )
{
  // Types
  typedef typename Space::Point Point;
  typedef typename Space::Vector Vector;
  typedef typename Space::RealPoint RealPoint;
  typedef typename Space::Integer Integer;
  typedef HyperRectDomain<Space> Domain;
  typedef KhalimskySpaceND<Space::dimension,Integer> KSpace;
  typedef typename KSpace::SCell SCell;
  typedef typename GridCurve<KSpace>::PointsRange Range;
  typedef typename Range::ConstIterator ConstIteratorOnPoints;
  typedef typename GridCurve<KSpace>::MidPointsRange MidPointsRange;
  
  // Digitizer
  GaussDigitizer<Space,Shape> dig;
  dig.attach( aShape ); // attaches the shape.
  Vector vlow(-1,-1); Vector vup(1,1);
  dig.init( aShape.getLowerBound()+vlow, aShape.getUpperBound()+vup, h );
  Domain domain = dig.getDomain();
  // Create cellular space
  KSpace K;
  bool ok = K.init( dig.getLowerBound(), dig.getUpperBound(), true );
  if ( ! ok )
  {
    std::cerr << "[generateContour]"
    << " error in creating KSpace." << std::endl;
    return false;
  }
  try {
    // Extracts shape boundary
    SurfelAdjacency<KSpace::dimension> SAdj( true );
    SCell bel = Surfaces<KSpace>::findABel( K, dig, 10000 );
    // Getting the consecutive surfels of the 2D boundary
    std::vector<Point> points;
    Surfaces<KSpace>::track2DBoundaryPoints( points, K, SAdj, dig, bel );
    // Create GridCurve
    GridCurve<KSpace> gridcurve;
    gridcurve.initFromVector( points );
    // gridcurve contains the digital boundary to analyze.
    Range r = gridcurve.getPointsRange(); //building range
    
    if ( outputFormat == "pts" )
    {
      
      for ( ConstIteratorOnPoints it = r.begin(), it_end = r.end();
           it != it_end; ++it )
      {
        Point p = *it;
        std::cout << p[ 0 ] << " " << p[ 1 ] << std::endl;
      }
    }
    else if ( outputFormat == "fc" )
    {
      ConstIteratorOnPoints it = r.begin();
      Point p = *it++;
      std::cout << p[ 0 ] << " " << p[ 1 ] << " ";
      for ( ConstIteratorOnPoints it_end = r.end(); it != it_end; ++it )
      {
        Point p2 = *it;
        Vector v = p2 - p;
        if ( v[0 ]== 1 ) std::cout << '0';
        if ( v[ 1 ] == 1 ) std::cout << '1';
        if ( v[ 0 ] == -1 ) std::cout << '2';
        if ( v[ 1 ] == -1 ) std::cout << '3';
        p = p2;
      }
      // close freemanchain if necessary.
      Point p2= *(r.begin());
      Vector v = p2 - p;
      if ( v.norm1() == 1 )
      {
        if ( v[ 0 ] == 1 ) std::cout << '0';
        if ( v[ 1 ] == 1 ) std::cout << '1';
        if ( v[ 0 ] == -1 ) std::cout << '2';
        if ( v[ 1 ] == -1 ) std::cout << '3';
      }
      std::cout << std::endl;
    }
    
    if (withGeom)
    {
      // write geometry of the shape
      std::stringstream s;
      s << outputFileName << ".geom";
      std::ofstream outstream(s.str().c_str()); //output stream
      if (!outstream.is_open()) return false;
      else {
        outstream << "# " << outputFileName << std::endl;
        outstream << "# Pointel (x,y), Midpoint of the following linel (x',y')" << std::endl;
        outstream << "# id x y tangentx tangenty curvaturexy"
        << " x' y' tangentx' tangenty' curvaturex'y'" << std::endl;
        
        std::vector<RealPoint> truePoints, truePoints2;
        std::vector<RealPoint> trueTangents, trueTangents2;
        std::vector<double> trueCurvatures, trueCurvatures2;
        
        estimateGeometry<Shape, Range, RealPoint, double>
        (aShape, h, r, truePoints, trueTangents, trueCurvatures);
        
        estimateGeometry<Shape, MidPointsRange, RealPoint, double>
        (aShape, h, gridcurve.getMidPointsRange(), truePoints2, trueTangents2, trueCurvatures2);
        
        
        unsigned int n = (unsigned int)r.size();
        for (unsigned int i = 0; i < n; ++i ) {
          outstream << std::setprecision( 15 ) << i
          << " " << truePoints[ i ][ 0 ]
          << " " << truePoints[ i ][ 1 ]
          << " " << trueTangents[ i ][ 0 ]
          << " " << trueTangents[ i ][ 1 ]
          << " " << trueCurvatures[ i ]
          << " " << truePoints2[ i ][ 0 ]
          << " " << truePoints2[ i ][ 1 ]
          << " " << trueTangents2[ i ][ 0 ]
          << " " << trueTangents2[ i ][ 1 ]
          << " " << trueCurvatures2[ i ]
          << std::endl;
        }
        
      }
      outstream.close();
    }
    
    /////////////////
    
  }
  catch ( InputException e )
  {
    std::cerr << "[generateContour]"
    << " error in finding a bel." << std::endl;
    return false;
  }
  return true;
}
Esempio n. 5
0
bool testCompareEstimator(const std::string &name, Shape & aShape, double h)
{
  using namespace Z2i;

  trace.beginBlock ( ( "Testing CompareEstimator on digitization of "
           + name ). c_str() );
  
  // Creates a digitizer on the window (xLow, xUp).
  typedef Space::RealPoint RealPoint;
  RealPoint xLow( -10.0, -10.0 );
  RealPoint xUp( 10.0, 10.0 );
  GaussDigitizer<Space,Shape> dig;  
  dig.attach( aShape ); // attaches the shape.
  dig.init( xLow, xUp, h ); 
  
  // The domain size is given by the digitizer according to the window
  // and the step.
  Domain domain = dig.getDomain();

  // Create cellular space
  KSpace K;
  bool ok = K.init( dig.getLowerBound(), dig.getUpperBound(), true );
  if ( ! ok )
    {
      std::cerr << "[testCompareEstimators]"
    << " error in creating KSpace." << std::endl;
    }
  else
    try {
      // Extracts shape boundary
      SurfelAdjacency<KSpace::dimension> SAdj( true );
      SCell bel = Surfaces<KSpace>::findABel( K, dig, 10000 );
      // Getting the consecutive surfels of the 2D boundary
      std::vector<Point> points;
      Surfaces<KSpace>::track2DBoundaryPoints( points, K, SAdj, dig, bel );
      // Create GridCurve
      GridCurve<KSpace> gridcurve;
      gridcurve.initFromVector( points );
      typedef GridCurve<KhalimskySpaceND<2> >::PointsRange Range;
      typedef Range::ConstIterator ConstIteratorOnPoints;
      Range r = gridcurve.getPointsRange();//building range

      unsigned int nb = 0; 
      unsigned int nbok = 0; 
      //curvature
      typedef ParametricShapeCurvatureFunctor< Shape > Curvature;
      typedef TrueLocalEstimatorOnPoints< ConstIteratorOnPoints, Shape, Curvature  >  TrueCurvature;
      TrueCurvature curvatureEstimator;
      TrueCurvature curvatureEstimatorBis;
      curvatureEstimator.init( h, r.begin(), r.end() );
      curvatureEstimator.attach( &aShape ); 
      curvatureEstimatorBis.init( h, r.begin(), r.end() );
      curvatureEstimatorBis.attach( &aShape ); 

      typedef CompareLocalEstimators< TrueCurvature, TrueCurvature> Comparator;

      trace.info()<< "True curvature comparison at "<< *r.begin() << " = "
		  << Comparator::compare(curvatureEstimator,curvatureEstimatorBis, r.begin())
		  << std::endl;
      
      typename Comparator::OutputStatistic error
	=Comparator::compare(curvatureEstimator, curvatureEstimatorBis, 
			     r.begin(),
			     r.end());
      
      trace.info() << "Nb samples= "<< error.samples()<<std::endl;
      trace.info() << "Error mean= "<< error.mean()<<std::endl;
      trace.info() << "Error max= "<< error.max()<<std::endl;
      nbok += ( (error.samples() == r.size())&&(error.max() == 0) )?1:0; 
      nb++;
      trace.info() << nbok << "/" << nb << std::endl; 

      //tangents
      typedef ParametricShapeTangentFunctor< Shape > Tangent;
      typedef TrueLocalEstimatorOnPoints< ConstIteratorOnPoints, Shape, Tangent  >  TrueTangent;

      typedef ArithmeticalDSS<ConstIteratorOnPoints,KSpace::Integer,4> 
  SegmentComputer;
      typedef TangentFromDSSEstimator<SegmentComputer> Functor;
      typedef MostCenteredMaximalSegmentEstimator<SegmentComputer,Functor> 
  MSTangentEstimator;

      SegmentComputer sc;
      Functor f; 
      
      TrueTangent tang1;
      MSTangentEstimator tang2(sc, f); 
    
      tang1.init( h, r.begin(), r.end() );
      tang1.attach( &aShape ); 
      tang2.init( h, r.begin(), r.end() );
      
      typedef CompareLocalEstimators< TrueTangent, MSTangentEstimator> ComparatorTan;

      trace.info()<< "Tangent comparison at "<< *r.begin() << " = " 
		  << ComparatorTan::compareVectors( tang1, tang2, r.begin())
		  << std::endl; 
      
      typename ComparatorTan::OutputVectorStatistic error2
	=ComparatorTan::compareVectors(tang1, tang2, 
				       r.begin(),
				       r.end());
      
      trace.info()<< "Nb samples= "<< error2.samples()<<std::endl;
      trace.info()<< "Error mean= "<< error2.mean()<<std::endl;
      trace.info()<< "Error max= "<< error2.max()<<std::endl;
      nbok += (error.samples() == r.size())?1:0; 
      nb++;
      trace.info() << nbok << "/" << nb << std::endl; 
      ok += (nb == nbok); 

     }    
    catch ( InputException e )
      {
  std::cerr << "[testCompareEstimator]"
      << " error in finding a bel." << std::endl;
  ok = false;
      }
  trace.emphase() << ( ok ? "Passed." : "Error." ) << endl;
  trace.endBlock();
  return ok;
  
}
bool
estimatorOnShapeDigitization( const string& name,
			      Shape & aShape,
			      const RealPoint& low, const RealPoint& up,
			      double h )
{
  using namespace Z2i;

  trace.beginBlock ( ( "Curvature estimation on digitization of "
		       + name ). c_str() );

  // Creates a digitizer on the window (low, up).
  GaussDigitizer<Space,Shape> dig;
  dig.attach( aShape ); // attaches the shape.
  dig.init( low, up, h );

  // The domain size is given by the digitizer
  // according to the window and the step.
  Domain domain = dig.getDomain();

  // Create cellular space
  KSpace K;
  bool ok = K.init( dig.getLowerBound(), dig.getUpperBound(), true );
  if ( ! ok )
    {
      std::cerr << "[estimatorOnShapeDigitization]"
		<< " error in creating KSpace." << std::endl;
    }
  else
    try {
      // Extracts shape boundary
      SurfelAdjacency<KSpace::dimension> SAdj( true );
      SCell bel = Surfaces<KSpace>::findABel( K, dig, 10000 );
      // Getting the consecutive surfels of the 2D boundary
      std::vector<Point> points;
      Surfaces<KSpace>::track2DBoundaryPoints( points, K, SAdj, dig, bel );
      // Create GridCurve
      GridCurve<KSpace> gridcurve( K );
      gridcurve.initFromVector( points );
      // Create range of incident points
      typedef GridCurve<KSpace>::IncidentPointsRange Range;
      typedef Range::ConstIterator ClassicIterator;
      typedef Range::ConstCirculator CircularIterator;
      Range r = gridcurve.getIncidentPointsRange();//building range
      // Estimation
      std::vector<double> estimations;
      if (gridcurve.isOpen())
        {
	  typedef StabbingCircleComputer<ClassicIterator> SegmentComputer;
	  typedef CurvatureFromDCAEstimator<SegmentComputer> SCEstimator;
	  typedef MostCenteredMaximalSegmentEstimator<SegmentComputer,SCEstimator> CurvatureEstimator;
	  SegmentComputer sc;
	  SCEstimator sce;
	  CurvatureEstimator estimator(sc, sce);
	  std::cout << "# open grid curve" << endl;
          estimator.init( h, r.begin(), r.end() );
          estimator.eval( r.begin(), r.end(), std::back_inserter(estimations) );
        }
      else
        {
	  typedef StabbingCircleComputer<CircularIterator> SegmentComputer;
	  typedef CurvatureFromDCAEstimator<SegmentComputer> SCEstimator;
	  typedef MostCenteredMaximalSegmentEstimator<SegmentComputer,SCEstimator> CurvatureEstimator;
	  SegmentComputer sc;
	  SCEstimator sce;
	  CurvatureEstimator estimator(sc, sce);
	  std::cout << "# closed grid curve" << endl;
          estimator.init( h, r.c(), r.c() );
          estimator.eval( r.c(), r.c(), std::back_inserter(estimations) );
        }
      // Print (standard output)
      std::cout << "# idx kappa" << endl;
      unsigned int i = 0;
      for ( ClassicIterator it = r.begin(), ite = r.end();
	    it != ite; ++it, ++i )
	{
	  std::cout << i << " " << estimations.at(i) << std::endl;
	}
    }
    catch ( InputException e )
      {
	std::cerr << "[estimatorOnShapeDigitization]"
		  << " error in finding a bel." << std::endl;
	ok = false;
      }
  trace.emphase() << ( ok ? "Passed." : "Error." ) << endl;
  trace.endBlock();
  return ok;
}
int main ()
{
  
  Delaunay t;
  
  trace.beginBlock("Construction the shape");
  typedef Ellipse2D<Z2i::Space> Ellipse; 
  int a = 5, b = 3;
  Ellipse2D<Z2i::Space> ellipse(Z2i::Point(0,0), a, b, 0.3 );
  // Ellipse2D<Z2i::Space> ellipse(Z2i::Point(0,0), 5.5, 5.5, 0 );
  double h = 0.25; 
  GaussDigitizer<Z2i::Space,Ellipse> dig;  
  dig.attach( ellipse );
  dig.init( ellipse.getLowerBound()+Z2i::Vector(-1,-1),
            ellipse.getUpperBound()+Z2i::Vector(1,1), h ); 
  // typedef Flower2D<Z2i::Space> Flower; 
  // Flower2D<Z2i::Space> flower(Z2i::Point(0,0), 15, 2, 5, 0);
  // double h = 0.25; 
  // GaussDigitizer<Z2i::Space,Flower> dig;  
  // dig.attach( flower );
  // dig.init( flower.getLowerBound()+Z2i::Vector(-1,-1),
  //           flower.getUpperBound()+Z2i::Vector(1,1), h ); 
  Z2i::KSpace ks;
  ks.init( dig.getLowerBound(), dig.getUpperBound(), true );
  SurfelAdjacency<2> sAdj( true );
  Z2i::SCell bel = Surfaces<Z2i::KSpace>::findABel( ks, dig, 1000 );
  std::vector<Z2i::Point> boundaryPoints;
  Surfaces<Z2i::KSpace>
    ::track2DBoundaryPoints( boundaryPoints, ks, sAdj, dig, bel );
  Z2i::Curve c;
  c.initFromVector( boundaryPoints );  
  typedef Z2i::Curve::PointsRange Range; 
  Range r = c.getPointsRange(); 
  trace.endBlock();


  trace.beginBlock("Delaunay");
  for(Range::ConstIterator it=r.begin(), itend=r.end(); it != itend;
      ++it)
    { 
      t.insert( Point( (*it)[0], (*it)[1]));
      t.insert( Point( (*it)[0] + 3 + (int) ceil( ((double)b)/h ),
		       (*it)[1] - 3 - (int) ceil( ((double)a)/h ) ));
    }
  trace.endBlock();

  std::cout << "number of vertices :  " ;
  std::cout << t.number_of_vertices() << std::endl;
  std::cout << "number of faces :  " ;
  std::cout << t.number_of_faces() << std::endl;
  
  trace.beginBlock("Area minimizing triangulation");
  Edge_iterator itnext;
  bool flip = true;
  bool inverse = false;
  unsigned int pass = 0;
  while ( flip ) {
    std::cout << "----------- pass " << pass << " -------------------" << std::endl;
    inverse = false;
    flip = false;
    int nb_flip = 0;
    int nb_random_flip = 0;
    for( Edge_iterator it = t.edges_begin(), itend=t.edges_end();
	 it != itend; it = itnext )
      {
	// vertex(cw(i)) and vertex(ccw(i)) of f.
	itnext = it; ++itnext;
	Edge e1 = *it;
	if ( isEdgeElementary( t,
			       e1.first->vertex( t.ccw( e1.second ) ),
			       e1.first->vertex( t.cw( e1.second ) ) ) )
	  continue;
	Edge e2 = t.mirror_edge( e1 );
	if ( ! isQuadrilateral( t, 
				e1.first->vertex( e1.second ),
				e1.first->vertex( t.ccw( e1.second ) ),
				e2.first->vertex( e2.second ),
				e1.first->vertex( t.cw( e1.second ) ) ) )
	  continue;
	int nb_f1 = twiceNbLatticePointsInTriangle( t, e1.first );
	int nb_f2 = twiceNbLatticePointsInTriangle( t, e2.first );
	int nb_flip_f1 = twiceNbLatticePointsInTriangle( t,
							 e1.first->vertex( e1.second ), 
							 e1.first->vertex( t.ccw( e1.second ) ),
							 e2.first->vertex( e2.second ) );
	int nb_flip_f2 = twiceNbLatticePointsInTriangle( t,
							 e1.first->vertex( e1.second ), 
							 e1.first->vertex( t.cw( e1.second ) ),
							 e2.first->vertex( e2.second ) );
	int nb_min = nb_f1 <= nb_f2 ? nb_f1 : nb_f2;
	int nb_flip_min = nb_flip_f1 <= nb_flip_f2 ? nb_flip_f1 : nb_flip_f2;
	if ( nb_flip_min < nb_min )
	  {
	    std::cout << "flipped " << e1.first->vertex( e1.second )->point()
		      << "->" << e1.first->vertex( e1.second )->point()
		      << std::endl;
	    t.flip( e1.first, e1.second );
	    nb_flip++;
	    flip = true;
	  }
	if ( nb_flip_min == nb_min )
	  {
	    inverse = true;
	    if ( random() % 2 == 1 )
	      {
		std::cout << "Random flipped " << e1.first->vertex( e1.second )->point()
			  << "->" << e1.first->vertex( e1.second )->point()
			  << std::endl;
		t.flip( e1.first, e1.second );
		nb_random_flip++;
	      }
	  }
	// if ( ( empty_f1 == false )
	//      && ( empty_f2 == false ) )
	//   { // try if flip is better.
	//     bool empty_flip_f1 
	//       = twiceNbLatticePointsInTriangle( t,
	// 					e1.first->vertex( e1.second ), 
	// 					e1.first->vertex( t.ccw( e1.second ) ),
	// 					e2.first->vertex( e2.second ) ) == 0;
	//     bool empty_flip_f2 
	//       = twiceNbLatticePointsInTriangle( t,
	// 					e2.first->vertex( e2.second ), 
	// 					e2.first->vertex( t.ccw( e2.second ) ),
	// 					e1.first->vertex( e1.second ) ) == 0;
	//     if ( empty_flip_f1 || empty_flip_f2 )
	//       {
	// 	if ( isEdgeElementary( t,
	// 			       e1.first->vertex( t.ccw( e1.second ) ),
	// 			       e1.first->vertex( t.cw( e1.second ) ) ) )
	// 	  {
	// 	    std::cout << "Flip forbidden:  " << e1.first->vertex( e1.second )->point()
	// 		  << "->" << e1.first->vertex( e1.second )->point()
	// 		  << std::endl;
	// 	  }
	// 	else
	// 	  {
	// 	    std::cout << "flipped " << e1.first->vertex( e1.second )->point()
	// 		      << "->" << e1.first->vertex( e1.second )->point()
	// 		      << std::endl;
	// 	    t.flip( e1.first, e1.second );
	// 	    flip = true;
	// 	  }
	//       }
	//   }
      }
    std::cout << "----------- nb_flip " << nb_flip 
	      << ", nb_random " << nb_random_flip << " -------------" << std::endl;
    ++pass;
    if ( inverse && ( (nb_random_flip+4) > log(pass) ) ) 
      flip = true;
  }  
  trace.endBlock();


  // GridCurve
  Z2i::Curve gc;
  gc.initFromPointsRange( r.begin(), r.end() );
  typedef Z2i::Curve::PointsRange::ConstIterator ConstIterator;
  typedef ArithmeticalDSS<ConstIterator,int,4> DSS4;
  typedef SaturatedSegmentation<DSS4> Segmentation;
  //Segmentation
  Z2i::Curve::PointsRange range = gc.getPointsRange();
  DSS4 dss4RecognitionAlgorithm;
  Segmentation theSegmentation( range.begin(), range.end(), dss4RecognitionAlgorithm );
         

  DGtal::Board2D board;

  Z2i::Point dP;
  board << CustomStyle( dP.className(), 
                        new CustomPen( Color(0,0,0), Color(230,230,230), 1, 
                                       Board2D::Shape::SolidStyle,
                                       Board2D::Shape::RoundCap,
                                       Board2D::Shape::RoundJoin ));
  for(Range::ConstIterator it=r.begin(), itend=r.end(); it != itend;
      ++it)
    board << *it;
  
  for(Faces_iterator it = t.finite_faces_begin(), itend=t.finite_faces_end();
      it != itend; ++it)
    {
      Z2i::Point a( toDGtal(it->vertex(0)->point())),
	b(toDGtal(it->vertex(1)->point())),
	c(toDGtal(it->vertex(2)->point()));

      // Z2i::Vector ab( b - a ), ac( c - a );
      // int d = ab[ 0 ] * ac[ 1 ] - ab[ 1 ] * ac[ 0 ];
      if ( emptyLatticeTriangle( t, it ) ) //( ( d == 1 ) || (d == -1 ) )
        {
          board.setPenColor(DGtal::Color::Blue);
          board.setFillColor( DGtal::Color::None );
          board.setLineWidth( 3.0 );
          board.drawTriangle(a[0],a[1],b[0],b[1],c[0],c[1]);
        }
      else
        {
          board.setPenColor(DGtal::Color::Red);
          board.setFillColor( DGtal::Color::None );
          //          board.setFillColorRGBi(200,200,200,128);
          board.setLineWidth( 2.0 );
          board.drawTriangle(a[0],a[1],b[0],b[1],c[0],c[1]);
        }
    }

  Segmentation::SegmentComputerIterator i = theSegmentation.begin();
  Segmentation::SegmentComputerIterator end = theSegmentation.end();
  board.setPenColor(DGtal::Color::Green);
  board.setFillColor( DGtal::Color::None );
  board << SetMode( "ArithmeticalDSS", "BoundingBox" );
  std::string aStyleName = "ArithmeticalDSS/BoundingBox";
  for ( ; i != end; ++i) {
    DSS4 current(*i);
    board << CustomStyle( aStyleName, 
                          new CustomPenColor( DGtal::Color::Green ) )
          << current;
  } 

  // Display Voronoi.
  // for(Edge_iterator it = t.edges_begin(), itend=t.edges_end();
  //     it != itend; ++it)
  //   {
  //     // vertex(cw(i)) and vertex(ccw(i)) of f.
  //     Face_handle itf = it->first;
  //     int i = it->second;
  //     Z2i::Point a( toDGtal(itf->vertex( t.cw( i ) )->point()));
  //     Z2i::Point b( toDGtal(itf->vertex( t.ccw( i ) )->point()));

  //     CGAL::Object o = t.dual( it );
  //     if (CGAL::object_cast<K::Segment_2>(&o)) 
  //       {
  //         const K::Segment_2* ptrSegment = CGAL::object_cast<K::Segment_2>(&o);
  //         board.setPenColor(DGtal::Color::Black);
  //         board.setFillColor( DGtal::Color::None );
  //         board.setLineWidth( 2.0 );
  //         board.drawLine( ptrSegment->source().x(),
  //                         ptrSegment->source().y(),
  //                         ptrSegment->target().x(),
  //                         ptrSegment->target().y() );
  //       }
  //     else if (CGAL::object_cast<K::Ray_2>(&o)) 
  //       {
  //         const K::Ray_2* ptrRay = CGAL::object_cast<K::Ray_2>(&o);
  //         board.setPenColor(DGtal::Color::Black);
  //         board.setFillColor( DGtal::Color::None );
  //         board.setLineWidth( 2.0 );
  //         double dx = ptrRay->to_vector().x();
  //         double dy = ptrRay->to_vector().y();
  //         double norm = sqrt( dx*dx+dy*dy );
  //         dx = 5.0 * dx / norm;
  //         dy = 5.0 * dy / norm;
  //         board.drawArrow( ptrRay->source().x(),
  //                          ptrRay->source().y(),
  //                          ptrRay->source().x() + dx, //1*ptrRay->to_vector().x(),
  //                          ptrRay->source().y() + dy ); //1*ptrRay->to_vector().y() );
  //       }
  //   }

  
  board.saveSVG("delaunay.svg");
  board.saveEPS("delaunay.eps");
  
  return 0;
}
int main()
{
  //shape
  typedef Flower2D<Z2i::Space> Flower; 
  Flower2D<Z2i::Space> flower(Z2i::Point(0,0), 20, 5, 5, 0);
  
  //! [shapeGridCurveEstimator-dig]
  //implicit digitization of a shape of type Flower 
  //into a digital space of type Space
  double h = 1; 
  GaussDigitizer<Z2i::Space,Flower> dig;  
  dig.attach( flower );
  dig.init( flower.getLowerBound()+Z2i::Vector(-1,-1),
            flower.getUpperBound()+Z2i::Vector(1,1), h ); 
  //! [shapeGridCurveEstimator-dig]
  
  //! [shapeGridCurveEstimator-prepareTracking]
  //Khalimsky space
  Z2i::KSpace ks;
  ks.init( dig.getLowerBound(), dig.getUpperBound(), true );
  //adjacency (4-connectivity)
  SurfelAdjacency<2> sAdj( true );
  //! [shapeGridCurveEstimator-prepareTracking]

  //! [shapeGridCurveEstimator-tracking]
  //searching for one boundary element
  Z2i::SCell bel = Surfaces<Z2i::KSpace>::findABel( ks, dig, 1000 );
  //tracking
  vector<Z2i::Point> boundaryPoints;
  Surfaces<Z2i::KSpace>
    ::track2DBoundaryPoints( boundaryPoints, ks, sAdj, dig, bel );
  //! [shapeGridCurveEstimator-tracking]

  //! [shapeGridCurveEstimator-instantiation]
  Z2i::Curve c;
  c.initFromVector( boundaryPoints );  
  //! [shapeGridCurveEstimator-instantiation]
  
  DGtal::Board2D aBoard;
  aBoard << c; 
  aBoard.saveEPS("DisplayGridCurve1.eps");  
  
  //! [shapeGridCurveEstimator-getRange]
  //range of points
  typedef Z2i::Curve::PointsRange Range; 
  Range r = c.getPointsRange(); 
  //! [shapeGridCurveEstimator-getRange]
  
  //! [shapeGridCurveEstimator-lengthEstimation]
  //length estimation
  DSSLengthEstimator< Range::ConstIterator > DSSlength;
  DSSlength.init( h, r.begin(), r.end(), c.isClosed() );
  double length1 = DSSlength.eval();
  trace.info() << "Length (h=" << h << "): " << length1 << endl; 
  //! [shapeGridCurveEstimator-lengthEstimation]

//@TODO correct init method of trueLengthEstimator (remove &flower)
  //! [shapeGridCurveEstimator-trueLengthEstimation]
  typedef ParametricShapeArcLengthFunctor< Flower > Length;
  TrueGlobalEstimatorOnPoints< 
    Range::ConstIterator, 
    Flower, 
    Length  >  trueLengthEstimator;
  trueLengthEstimator.init( h, r.begin(), r.end(), &flower, c.isClosed());
  double trueLength = trueLengthEstimator.eval(); 
  trace.info() << "ground truth: " << trueLength << endl; 
  //! [shapeGridCurveEstimator-trueLengthEstimation]

  //! [shapeGridCurveEstimator-higher]
  //implicit digitization at higher resolution
  h = 0.1; 
  dig.init( flower.getLowerBound()+Z2i::Vector(-1,-1),
            flower.getUpperBound()+Z2i::Vector(1,1), h ); 
  //a greater domain is needed in the Khalimsky space
  ks.init( dig.getLowerBound(), dig.getUpperBound(), true );
  //searching for one boundary element
  bel = Surfaces<Z2i::KSpace>::findABel( ks, dig, 10000 );
  //tracking
  Surfaces<Z2i::KSpace>
    ::track2DBoundaryPoints( boundaryPoints, ks, sAdj, dig, bel );
  //reset grid curve and its points range
  c.initFromVector( boundaryPoints );
  Range r2 = c.getPointsRange(); 
  //estimate length
  DSSlength.init( h, r2.begin(), r2.end(), c.isClosed() );
  double length2 = DSSlength.eval();
  trace.info() << "Length (h=" << h << "): " << length2 << endl;  
  //! [shapeGridCurveEstimator-higher]
  
  aBoard.clear(); 
  aBoard << c; 
  aBoard.saveEPS("DisplayGridCurve01.eps");  
  
  return 0;

}
bool 
testTrueLocalEstimatorOnShapeDigitization( const string & name,
             Shape & aShape, double h )
{
  using namespace Z2i;

  trace.beginBlock ( ( "Testing TrueLocalEstimator on digitization of "
           + name ). c_str() );
  
  // Creates a digitizer on the window (xLow, xUp).
  typedef Space::RealPoint RealPoint;
  RealPoint xLow( -10.0, -10.0 );
  RealPoint xUp( 10.0, 10.0 );
  GaussDigitizer<Space,Shape> dig;  
  dig.attach( aShape ); // attaches the shape.
  dig.init( xLow, xUp, h ); 
  
  // The domain size is given by the digitizer according to the window
  // and the step.
  Domain domain = dig.getDomain();

  // Create cellular space
  KSpace K;
  bool ok = K.init( dig.getLowerBound(), dig.getUpperBound(), true );
  if ( ! ok )
    {
      std::cerr << "[testTrueLocalEstimatorOnShapeDigitization]"
    << " error in creating KSpace." << std::endl;
    }
  else
    try {
      // Extracts shape boundary
      SurfelAdjacency<KSpace::dimension> SAdj( true );
      SCell bel = Surfaces<KSpace>::findABel( K, dig, 10000 );
      // Getting the consecutive surfels of the 2D boundary
      std::vector<Point> points;
      Surfaces<KSpace>::track2DBoundaryPoints( points, K, SAdj, dig, bel );
      // Create GridCurve
      GridCurve<KSpace> gridcurve;
      gridcurve.initFromVector( points );
      typedef GridCurve<KhalimskySpaceND<2> >::PointsRange Range;
      typedef Range::ConstIterator ConstIteratorOnPoints;
      typedef ParametricShapeCurvatureFunctor< Shape > Curvature;
      TrueLocalEstimatorOnPoints< ConstIteratorOnPoints, Shape, Curvature  >  curvatureEstimator;
      Range r = gridcurve.getPointsRange();//building range
      curvatureEstimator.init( h, r.begin(), r.end(), &aShape, true);
      std::cout << "# idx x y kappa" << endl;
      unsigned int i = 0;
      for ( ConstIteratorOnPoints it = r.begin(), ite = r.end();
      it != ite; ++it, ++i )
  {
    RealPoint x = *it;
    double kappa = curvatureEstimator.eval( it );
    std::cout << i << " " << x.at( 0 ) << " " << x.at( 1 ) 
        << " " << kappa << std::endl;
  }
    }    
    catch ( InputException e )
      {
  std::cerr << "[testTrueLocalEstimatorOnShapeDigitization]"
      << " error in finding a bel." << std::endl;
  ok = false;
      }
  trace.emphase() << ( ok ? "Passed." : "Error." ) << endl;
  trace.endBlock();
  return ok;
}
Esempio n. 10
0
bool
testDigitization( const Shape & aShape, double h,
      const string & fileName )
{
  typedef typename Space::Point Point;
  typedef typename Space::RealPoint RealPoint;
  typedef HyperRectDomain<Space> Domain;
  typedef typename DigitalSetSelector
    < Domain, BIG_DS + HIGH_ITER_DS + HIGH_BEL_DS >::Type MySet;

  // Creates a digitizer on the window (xLow, xUp).
  RealPoint xLow( -5.3, -4.3 );
  RealPoint xUp( 7.4, 4.7 );
  GaussDigitizer<Space,Shape> dig;  
  dig.attach( aShape ); // attaches the shape.
  dig.init( xLow, xUp, h ); 
  
  // The domain size is given by the digitizer according to the window
  // and the step.
  Domain domain = dig.getDomain(); // ( dig.getLowerBound(), dig.getUpperBound() );
  MySet aSet( domain );
  // Creates a set from the digitizer.
  Shapes<Domain>::shaper( aSet, dig );
  
  // Create cellular space
  typedef Z2i::KSpace KSpace;
  typedef Z2i::SCell SCell;
  KSpace K;
  bool ok = K.init( dig.getLowerBound(), dig.getUpperBound(), true );
 
  ASSERT( ok );

  SurfelAdjacency<KSpace::dimension> SAdj( true );

 

  // Extracts shape boundary
  SCell bel = Surfaces<KSpace>::findABel( K, dig, 10000 );
  // Getting the consecutive surfels of the 2D boundary
  std::vector<Point> points;
  Surfaces<KSpace>::track2DBoundaryPoints( points, K, SAdj, dig, bel );
  GridCurve<KSpace> gridcurve;
  gridcurve.initFromVector( points );

  // Display all
  Board2D board;
  board.setUnit( LibBoard::Board::UCentimeter );
  board << SetMode( domain.styleName(), "Paving" )
    << domain << aSet;

  board << SetMode( gridcurve.styleName(), "Edges" )
  << CustomStyle( bel.styleName(), 
      new CustomColors( DGtal::Color( 0, 0, 0 ),
            DGtal::Color( 0, 192, 0 ) ) )
  << gridcurve;
  board << SetMode( gridcurve.styleName(), "Points" )
  << CustomStyle( bel.styleName(), 
      new CustomColors( DGtal::Color( 255, 0, 0 ),
            DGtal::Color( 200, 0, 0 ) ) )
  << gridcurve;

  board.saveEPS( ( fileName + ".eps" ).c_str() );
  board.saveSVG( ( fileName + ".svg" ).c_str() );
  
  return true;
}