static void exportSignature(const Shape & aShape,const Set &aSet, const Z2i::Domain &aDomain) { SetPredicate<Set> aSetPredicate( aSet ); trace.beginBlock("Extracting the boundary"); Z2i::KSpace ks; bool space_ok = ks.init( aDomain.lowerBound(),aDomain.upperBound(), true ); SurfelAdjacency<2> sAdj( true ); ASSERT(space_ok); trace.info() << aSet << std::endl; trace.info() << ks << ( space_ok ? " Successfully instantiated" : " Error" ) << std::endl; std::vector< std::vector< Z2i::Point > > vectContoursBdryPointels; Surfaces<Z2i::KSpace>::extractAllPointContours4C( vectContoursBdryPointels, ks, aSetPredicate, sAdj ); trace.endBlock(); ///Export std::cout<<"## shapeGenerator signature export"<<std::endl; std::cout<<"## shape: "<<aShape<<std::endl; std::cout<<"## x\ty\tdx\tdy\tddx\tddy"<<std::endl; for(unsigned int i=0; i<vectContoursBdryPointels.size(); i++) for(unsigned int j=0 ; j< vectContoursBdryPointels.at(i).size() - 1; j++) { Z2i::Space::Point point = (vectContoursBdryPointels.at(i).at(j) + vectContoursBdryPointels.at(i).at(j+1)); Z2i::Space::RealPoint midpoint (point[0]/2.0,point[1]/2.0); Z2i::Space::RealPoint xp,xpp; double t = aShape.parameter(midpoint); xp = aShape.xp( t ); xpp = aShape.xpp( t ); std::cout<< midpoint[0]<<"\t"<<midpoint[1]<<"\t" << xp[0]<<"\t"<<xp[1]<<"\t" << xpp[0]<<"\t"<<xpp[1]<<std::endl; } }
int main( int argc, char** argv ) { // parse command line ---------------------------------------------- po::options_description general_opt("Allowed options are: "); general_opt.add_options() ("help,h", "display this message") ("image,i", po::value<std::string>(), "image file name") ("min,m", po::value<int>(), "min image threshold value (default 128)") ("max,M", po::value<int>(), "max image threshold value (default 255)") ("minSize,s", po::value<int>(), "minSize of the extracted freeman chain (default 0)") ("contourSelect,s", po::value<vector <int> >()->multitoken(), "Select contour according reference point and maximal distance: ex. --contourSelect X Y distanceMax") ("thresholdRangeMin,r", po::value<vector <int> >()->multitoken(), "use a range interval as threshold (from min) : --thresholdRangeMin min increment max : for each possible i, it define a digital sets [min, min+((i+1)*increment)] such that min+((i+1)*increment)< max and extract their boundary. ") ("thresholdRangeMax,R", po::value<vector <int> >()->multitoken(), "use a range interval as threshold (from max) : --thresholdRangeMax min increment max : for each possible i, it define a digital sets [ max-((i)*increment), max] such that max-((i)*increment)>min and extract their boundary. "); po::variables_map vm; po::store(po::parse_command_line(argc, argv, general_opt), vm); po::notify(vm); if(vm.count("help")||argc<=1) { trace.info()<< "Extract FreemanChains from thresholded image" <<std::endl << "Basic usage: "<<std::endl << "\t image2freeman [options] --image <imageName> -min 128 -max 255 > contours.fc"<<std::endl << general_opt << "\n"; return 0; } double minThreshold = 128; double maxThreshold = 255; unsigned int minSize =0; bool select=false; bool thresholdRange=vm.count("thresholdRangeMin")||vm.count("thresholdRangeMax"); Z2i::Point selectCenter; unsigned int selectDistanceMax = 0; //Parse options if (!(vm.count("image"))){ trace.info() << "Image file name needed"<< endl; return 0; } if(vm.count("min")){ minThreshold= vm["min"].as<int>(); } if(vm.count("max")){ maxThreshold= vm["max"].as<int>(); } if(vm.count("minSize")){ minSize = vm["minSize"].as<int>(); } if(vm.count("contourSelect")){ select=true; vector<int> cntConstraints= vm["contourSelect"].as<vector <int> >(); if(cntConstraints.size()!=3){ trace.info() << "Incomplete option \"--contourSelect\""<< endl; return 0; } selectCenter[0]= cntConstraints.at(0); selectCenter[1]= cntConstraints.at(1); selectDistanceMax= (unsigned int) cntConstraints.at(2); } int min, max, increment; if(! thresholdRange){ min=(int)minThreshold; max= (int)maxThreshold; increment = (int)(maxThreshold- minThreshold); }else{ vector<int> vectRange; if ( vm.count("thresholdRangeMax")){ vectRange= vm["thresholdRangeMax"].as<vector <int> >(); }else{ vectRange= vm["thresholdRangeMin"].as<vector <int> >(); } if(vectRange.size()!=3){ trace.info() << "Incomplete option \"--thresholdRange\""<< endl; return 0; } min=vectRange.at(0); increment=vectRange.at(1); max = vectRange.at(2); minThreshold=min; maxThreshold=max; } typedef ImageSelector < Z2i::Domain, unsigned char>::Type Image; typedef IntervalThresholder<Image::Value> Binarizer; string imageFileName = vm["image"].as<std::string>(); Image image = PNMReader<Image>::importPGM( imageFileName ); Z2i::KSpace ks; if(! ks.init( image.domain().lowerBound(), image.domain().upperBound(), true )){ trace.error() << "Problem in KSpace initialisation"<< endl; } if (!thresholdRange){ Binarizer b(min, max); PointFunctorPredicate<Image,Binarizer> predicate(image, b); trace.info() << "DGtal contour extraction from thresholds ["<< min << "," << max << "]" ; SurfelAdjacency<2> sAdj( true ); std::vector< std::vector< Z2i::Point > > vectContoursBdryPointels; Surfaces<Z2i::KSpace>::extractAllPointContours4C( vectContoursBdryPointels, ks, predicate, sAdj ); if(select){ saveSelContoursAsFC(vectContoursBdryPointels, minSize, selectCenter, selectDistanceMax); }else{ saveAllContoursAsFc(vectContoursBdryPointels, minSize); } }else{ for(int i=0; minThreshold+i*increment< maxThreshold; i++){ if(vm.count("thresholdRangeMin")){ min = (int)(minThreshold+(i)*increment); } if(vm.count("thresholdRangeMax")){ max = (int)(maxThreshold-(i)*increment); } Binarizer b(min, max); PointFunctorPredicate<Image,Binarizer> predicate(image, b); trace.info() << "DGtal contour extraction from thresholds ["<< min << "," << max << "]" ; SurfelAdjacency<2> sAdj( true ); std::vector< std::vector< Z2i::Point > > vectContoursBdryPointels; Surfaces<Z2i::KSpace>::extractAllPointContours4C( vectContoursBdryPointels, ks, predicate, sAdj ); if(select){ saveSelContoursAsFC(vectContoursBdryPointels, minSize, selectCenter, selectDistanceMax); }else{ saveAllContoursAsFc(vectContoursBdryPointels, minSize); } trace.info() << " [done]" << endl; } } }
/** * Algorithms that computes the alpha-shape * of a point set */ void alphaShape() { //Digitization of a disk of radius 8 Ball2D<Z2i::Space> ball(Z2i::Point(0,0), 8); Z2i::Domain domain(ball.getLowerBound(), ball.getUpperBound()); Z2i::DigitalSet digitalSet(domain); Shapes<Z2i::Domain>::euclideanShaper(digitalSet, ball); //Contour of the digital set Z2i::KSpace kspace; kspace.init(domain.lowerBound()-Z2i::Point(1,1), domain.upperBound()+Z2i::Point(1,1), true); typedef DigitalSetBoundary<Z2i::KSpace, Z2i::DigitalSet> DigitalSurfaceContainer; typedef DigitalSurface<DigitalSurfaceContainer> CustomDigitalSurface; DigitalSurfaceContainer digitalSurfaceContainer( kspace, digitalSet ); CustomDigitalSurface digitalSurface( digitalSurfaceContainer ); //Grid curve Z2i::Curve gridCurve; typedef DepthFirstVisitor<DigitalSurface<DigitalSurfaceContainer> > CustomVisitor; CustomVisitor visitor( digitalSurface, *digitalSurface.begin() ); while ( ! visitor.finished() ) { gridCurve.pushBack( visitor.current().first ); visitor.expand(); } //Point set defined as the set of (not duplicated) inner points typedef Z2i::Curve::InnerPointsRange PointRange; PointRange pointsRange = gridCurve.getInnerPointsRange(); vector<Z2i::Point> border; unique_copy( pointsRange.begin(), pointsRange.end(), back_inserter( border ) ); //namespace for hull functions using namespace functions::Hull2D; { //alpha = 0 trace.info() << " alpha == 0 " << endl; vector<Z2i::Point> res; //! [Hull2D-RadiusPredicateInf] typedef AvnaimEtAl2x2DetSignComputer<DGtal::int64_t> DetComputer; typedef InGeneralizedDiskOfGivenRadius<Z2i::Point, DetComputer> Functor; Functor functor(true, 1, 0); //alpha = 0; 1/alpha -> +inf typedef PredicateFromOrientationFunctor2<Functor> Predicate; Predicate predicate( functor ); //! [Hull2D-RadiusPredicateInf] //! [Hull2D-ClosedGrahamScan] closedGrahamScanFromAnyPoint( border.begin(), border.end(), back_inserter( res ), predicate ); //! [Hull2D-ClosedGrahamScan] //display Board2D board; drawPolygon( res.begin(), res.end(), board ); board.saveSVG( "AlphaShape0.svg" ); #ifdef WITH_CAIRO board.saveCairo("AlphaShape0.png", Board2D::CairoPNG); #endif } { //alpha = 0 trace.info() << " alpha == 0 " << endl; vector<Z2i::Point> res; //comparator and functor typedef InHalfPlaneBySimple3x3Matrix<Z2i::Point, DGtal::int64_t> Functor; Functor functor; typedef PredicateFromOrientationFunctor2<Functor> Predicate; Predicate predicate( functor ); closedGrahamScanFromAnyPoint( border.begin(), border.end(), back_inserter( res ), predicate ); //display Board2D board; drawPolygon( res.begin(), res.end(), board ); board.saveSVG( "AlphaShape0bis.svg" ); #ifdef WITH_CAIRO board.saveCairo("AlphaShape0bis.png", Board2D::CairoPNG); #endif } //negative alpha shape { //alpha = -1 trace.info() << " alpha == -1 " << endl; vector<Z2i::Point> res; typedef AvnaimEtAl2x2DetSignComputer<DGtal::int64_t> DetComputer; typedef InGeneralizedDiskOfGivenRadius<Z2i::Point, DetComputer> Functor; //! [Hull2D-RadiusPredicateM1] Functor functor(false, 1, 1); //1/alpha = -sqrt(1/1) = -1 //! [Hull2D-RadiusPredicateM1] typedef PredicateFromOrientationFunctor2<Functor> Predicate; Predicate predicate( functor ); closedGrahamScanFromAnyPoint( border.begin(), border.end(), back_inserter( res ), predicate ); //display Board2D board; drawPolygon( res.begin(), res.end(), board ); board.saveSVG( "AlphaShapeM1.svg" ); #ifdef WITH_CAIRO board.saveCairo("AlphaShapeM1.png", Board2D::CairoPNG); #endif } { //alpha = -sqrt(5) trace.info() << " alpha == -sqrt(5) " << endl; vector<Z2i::Point> res; typedef AvnaimEtAl2x2DetSignComputer<DGtal::int64_t> DetComputer; typedef InGeneralizedDiskOfGivenRadius<Z2i::Point, DetComputer> Functor; //! [Hull2D-RadiusPredicateMsqrt5] Functor functor(false, 5, 1); //1/alpha = -sqrt(5) //! [Hull2D-RadiusPredicateMsqrt5] typedef PredicateFromOrientationFunctor2<Functor> Predicate; Predicate predicate( functor ); closedGrahamScanFromAnyPoint( border.begin(), border.end(), back_inserter( res ), predicate ); //display Board2D board; drawPolygon( res.begin(), res.end(), board ); board.saveSVG( "AlphaShapeMSqrt5.svg" ); #ifdef WITH_CAIRO board.saveCairo("AlphaShapeMSqrt5.png", Board2D::CairoPNG); #endif } { //alpha = -5 trace.info() << " alpha == -5 " << endl; vector<Z2i::Point> res; typedef AvnaimEtAl2x2DetSignComputer<DGtal::int64_t> DetComputer; typedef InGeneralizedDiskOfGivenRadius<Z2i::Point, DetComputer> Functor; //! [Hull2D-RadiusPredicateM5] Functor functor(false, 25, 1); //1/alpha = -sqrt(25/1) = -5 //! [Hull2D-RadiusPredicateM5] typedef PredicateFromOrientationFunctor2<Functor> Predicate; Predicate predicate( functor ); closedGrahamScanFromAnyPoint( border.begin(), border.end(), back_inserter( res ), predicate ); //display Board2D board; drawPolygon( res.begin(), res.end(), board ); board.saveSVG( "AlphaShapeM5.svg" ); #ifdef WITH_CAIRO board.saveCairo("AlphaShapeM5.png", Board2D::CairoPNG); #endif } //positive alpha shape { trace.info() << " alpha == 8 " << endl; vector<Z2i::Point> res; //! [Hull2D-RadiusPredicateP8] typedef AvnaimEtAl2x2DetSignComputer<DGtal::int64_t> DetComputer; typedef InGeneralizedDiskOfGivenRadius<Z2i::Point, DetComputer> Functor; Functor functor(true, 64, 1); //1/alpha = sqrt(64/1) = 8 typedef PredicateFromOrientationFunctor2<Functor, false, true> Predicate; Predicate predicate( functor ); //! [Hull2D-RadiusPredicateP8] closedGrahamScanFromAnyPoint( border.begin(), border.end(), back_inserter( res ), predicate ); //display Board2D board; drawPolygon( res.begin(), res.end(), board ); board.saveSVG( "AlphaShapeP8.svg" ); #ifdef WITH_CAIRO board.saveCairo("AlphaShapeP8.png", Board2D::CairoPNG); #endif } //positive alpha shape { trace.info() << " alpha == 9 " << endl; vector<Z2i::Point> res; typedef AvnaimEtAl2x2DetSignComputer<DGtal::int64_t> DetComputer; typedef InGeneralizedDiskOfGivenRadius<Z2i::Point, DetComputer> Functor; //! [Hull2D-RadiusPredicateP9] Functor functor(true, 81, 1); //1/alpha = sqrt(81/1) = 9 //! [Hull2D-RadiusPredicateP9] typedef PredicateFromOrientationFunctor2<Functor> Predicate; Predicate predicate( functor ); closedGrahamScanFromAnyPoint( border.begin(), border.end(), back_inserter( res ), predicate ); //display Board2D board; drawPolygon( res.begin(), res.end(), board ); board.saveSVG( "AlphaShapeP9.svg" ); #ifdef WITH_CAIRO board.saveCairo("AlphaShapeP9.png", Board2D::CairoPNG); #endif } }
int main() { //! [freemanChainFromImage-imageImport] typedef DGtal::ImageContainerBySTLVector< DGtal::Z2i::Domain, unsigned char> Image; std::string filename = examplesPath + "samples/circleR10modif.pgm"; Image image = DGtal::PGMReader<Image>::importPGM(filename); //! [freemanChainFromImage-imageImport] //![freemanChainFromImage-ksspace] Z2i::KSpace ks; ks.init( image.domain().lowerBound(), image.domain().upperBound(), true ); //![freemanChainFromImage-ksspace] //! [freemanChainFromImage-setAppend] Z2i::DigitalSet set2d (image.domain()); SetFromImage<Z2i::DigitalSet>::append<Image>(set2d, image, 1, 255); //! [freemanChainFromImage-setAppend] //! [freemanChainFromImage-displaySet] Board2D aBoard; aBoard << set2d; aBoard << image.domain(); //! [freemanChainFromImage-displaySet] //! [freemanChainFromImage-adj] SurfelAdjacency<2> sAdj( true ); //! [freemanChainFromImage-adj] //! [freemanChainFromImage-extraction] std::vector< std::vector< Z2i::Point > > vectContoursBdryPointels; Surfaces<Z2i::KSpace>::extractAllPointContours4C( vectContoursBdryPointels, ks, set2d, sAdj ); //! [freemanChainFromImage-extraction] GradientColorMap<int> cmap_grad( 0, (const int)vectContoursBdryPointels.size() ); cmap_grad.addColor( Color( 50, 50, 255 ) ); cmap_grad.addColor( Color( 255, 0, 0 ) ); cmap_grad.addColor( Color( 255, 255, 10 ) ); cmap_grad.addColor( Color( 25, 255, 255 ) ); cmap_grad.addColor( Color( 255, 25, 255 ) ); cmap_grad.addColor( Color( 25, 25, 25 ) ); //! [freemanChainFromImage-fcConstruction] for(unsigned int i=0; i<vectContoursBdryPointels.size(); i++) { // Constructing and displaying FreemanChains from contours. FreemanChain<Z2i::Integer> fc (vectContoursBdryPointels.at(i)); //! [freemanChainFromImage-fcConstruction] //! [freemanChainFromImage-fcdysplay] aBoard << SetMode( fc.className(), "InterGrid" ); aBoard<< CustomStyle( fc.className(), new CustomColors( cmap_grad(i), Color::None ) ); aBoard << fc; //! [freemanChainFromImage-fcdysplay] } aBoard.saveEPS("freemanChainFromImage.eps"); return 0; }
int main(int argc, char** argv) { Point ptL(-1, -1); Point ptU(3, 3); Domain d (ptL, ptU); Point pt0(0,0); Point pt1(1,0); Point pt2(0,1); Point pt3(2,1); Point pt4(1,2); Point pt5(2,2); DigitalSet aSet( d ); aSet.insert(pt0); aSet.insert(pt1); aSet.insert(pt2); aSet.insert(pt3); aSet.insert(pt4); Board2D boardAdj; boardAdj << d; std::set<SCell> bdry; Z2i::KSpace ks; ks.init( ptL, ptU, true ); boardAdj << aSet; // Extracting the surface boundary of the shape Surfaces<Z2i::KSpace>::sMakeBoundary( bdry, ks, aSet, ks.lowerBound(), ks.upperBound() ); SurfelAdjacency<Z2i::KSpace::dimension> sAdjInt( true ); SurfelAdjacency<Z2i::KSpace::dimension> sAdjExt( false ); //Displaying the boundary bels std::set<SCell>::iterator itBoundary; int i=0; Board2D boardDisplayAll; boardDisplayAll<< d; boardAdj.saveFIG("illustrationAdjSRC.fig"); for(itBoundary= bdry.begin(); itBoundary!= bdry.end(); itBoundary++){ boardDisplayAll << *itBoundary; } boardDisplayAll.saveFIG("illustrationAdjBdr.fig"); itBoundary = bdry.begin(); for (int i =0; i<10; i++) itBoundary++; SCell surfel = *itBoundary; // Defining surfel Neighborhood given an surfel Adjacency SurfelNeighborhood<KSpace> sNeighInt; sNeighInt.init( &ks, &sAdjInt, surfel ); SurfelNeighborhood<KSpace> sNeighExt; sNeighExt.init( &ks, &sAdjExt, surfel ); SCell surfelFollowerInt; SCell surfelFollowerExt; sNeighInt.getAdjacentOnDigitalSet ( surfelFollowerInt, aSet, *(ks.sDirs(surfel)), true); sNeighExt.getAdjacentOnDigitalSet ( surfelFollowerExt, aSet, *(ks.sDirs(surfel)), true); boardAdj << CustomStyle( surfel.className() , new CustomColors( Color::Blue, Color::Gray )); boardAdj << surfel; boardAdj << CustomStyle( surfel.className() , new CustomColors( Color::Red, Color::Black )); boardAdj << surfelFollowerInt; boardAdj << CustomStyle( surfel.className() , new CustomColors( Color::Green, Color::White )); boardAdj << surfelFollowerExt; boardAdj.saveFIG("illustrationAdjIntExt.fig"); // Extraction of contour std::set<SCell> aContour1; Surfaces<Z2i::KSpace>::trackBoundary( aContour1, ks, sAdjExt, aSet, surfel ); Board2D boardContour1; boardContour1 << d; std::set<SCell>::iterator iterOnContour; for( iterOnContour= aContour1.begin(); iterOnContour != aContour1.end(); iterOnContour++){ if(*iterOnContour != surfel){ boardContour1 << CustomStyle( surfel.className() , new CustomColors( Color::Green, Color::White )); boardContour1<< *iterOnContour; }else{ boardContour1 << CustomStyle( surfel.className() , new CustomColors( Color::Blue, Color::Gray )); boardContour1<< *iterOnContour; } } boardContour1.saveFIG("illustrationAdjContour.fig"); // Extraction of contour std::set<SCell> aContour2; Surfaces<Z2i::KSpace>::trackBoundary( aContour2, ks, sAdjInt, aSet, surfel ); Board2D boardContour2; boardContour2 << d; std::set<SCell>::iterator iterOnContour2; for( iterOnContour2= aContour2.begin(); iterOnContour2 != aContour2.end(); iterOnContour2++){ if(*iterOnContour2 != surfel){ boardContour2 << CustomStyle( surfel.className() , new CustomColors( Color::Red, Color::White )); boardContour2<< *iterOnContour2; }else{ boardContour2 << CustomStyle( surfel.className() , new CustomColors( Color::Blue, Color::Gray )); boardContour2<< *iterOnContour2; } } boardContour2.saveFIG("illustrationAdjContour2.fig"); return 0; }
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; }
int main( int argc, char** argv ) { // parse command line ---------------------------------------------- po::options_description general_opt("Allowed options are: "); general_opt.add_options() ("help,h", "display this message") ("image,i", po::value<std::string>(), "image file name") ("min,m", po::value<int>(), "min image threshold value (default 128)") ("max,M", po::value<int>(), "max image threshold value (default 255)") ("minSize,s", po::value<int>(), "minSize of the extracted freeman chain (default 0)") ("contourSelect,s", po::value<vector <int> >()->multitoken(), "Select contour according reference point and maximal distance: ex. --contourSelect X Y distanceMax") ("thresholdRange,R", po::value<vector <int> >()->multitoken(), "use a range interval as threshold : --thresholdRange min increment max : for each possible i, it define a digital sets [min+(i*increment),min+((i+1)*increment)] and extract their boundary. "); po::variables_map vm; po::store(po::parse_command_line(argc, argv, general_opt), vm); po::notify(vm); if(vm.count("help")||argc<=1) { trace.info()<< "Extract FreemanChains from thresholded image" <<std::endl << "Basic usage: "<<std::endl << "\t image2freeman [options] --image <imageName> -min 128 -max 255 > contours.fc"<<std::endl << general_opt << "\n"; return 0; } double minThreshold = 128; double maxThreshold = 255; unsigned int minSize =0; bool select=false; bool thresholdRange=vm.count("thresholdRange"); Z2i::Point selectCenter; unsigned int selectDistanceMax = 0; //Parse options if (!(vm.count("image"))){ trace.info() << "Image file name needed"<< endl; return 0; } if(vm.count("min")){ minThreshold= vm["min"].as<int>(); } if(vm.count("max")){ maxThreshold= vm["max"].as<int>(); } if(vm.count("minSize")){ minSize = vm["minSize"].as<int>(); } if(vm.count("contourSelect")){ select=true; vector<int> cntConstraints= vm["contourSelect"].as<vector <int> >(); if(cntConstraints.size()!=3){ trace.info() << "Incomplete option \"--contourSelect\""<< endl; return 0; } selectCenter[0]= cntConstraints.at(0); selectCenter[1]= cntConstraints.at(1); selectDistanceMax= (unsigned int) cntConstraints.at(2); } int min, max, increment; if(! thresholdRange){ min=(int)minThreshold; max= (int)maxThreshold; increment = (int)(maxThreshold- minThreshold); }else{ vector<int> vectRange= vm["thresholdRange"].as<vector <int> >(); if(vectRange.size()!=3){ trace.info() << "Incomplete option \"--thresholdRange\""<< endl; return 0; } min=vectRange.at(0); increment=vectRange.at(1); max = vectRange.at(2); } typedef ImageSelector < Z2i::Domain, unsigned char>::Type Image; string imageFileName = vm["image"].as<std::string>(); Image image = PNMReader<Image>::importPGM( imageFileName ); Z2i::DigitalSet set2d (image.domain()); SetPredicate<Z2i::DigitalSet> set2dPredicate( set2d ); for(int i=0; minThreshold+i*increment< maxThreshold; i++){ min = (int)(minThreshold+i*increment); max = (int)(minThreshold+(i+1)*increment); SetFromImage<Z2i::DigitalSet>::append<Image>(set2d, image, min, max); trace.info() << "DGtal set imported from thresholds ["<< min << "," << max << "]" << endl; Z2i::KSpace ks; if(! ks.init( image.domain().lowerBound(), image.domain().upperBound(), true )){ trace.error() << "Problem in KSpace initialisation"<< endl; } SurfelAdjacency<2> sAdj( true ); std::vector< std::vector< Z2i::Point > > vectContoursBdryPointels; Surfaces<Z2i::KSpace>::extractAllPointContours4C( vectContoursBdryPointels, ks, set2dPredicate, sAdj ); for(unsigned int k=0; k<vectContoursBdryPointels.size(); k++){ if(vectContoursBdryPointels.at(k).size()>minSize){ if(select){ Z2i::Point ptMean = ContourHelper::getMeanPoint(vectContoursBdryPointels.at(k)); unsigned int distance = (unsigned int)ceil(sqrt((double)(ptMean[0]-selectCenter[0])*(ptMean[0]-selectCenter[0])+ (ptMean[1]-selectCenter[1])*(ptMean[1]-selectCenter[1]))); if(distance<=selectDistanceMax){ FreemanChain<Z2i::Integer> fc (vectContoursBdryPointels.at(k)); cout << fc.x0 << " " << fc.y0 << " " << fc.chain << endl; } }else{ FreemanChain<Z2i::Integer> fc (vectContoursBdryPointels.at(k)); cout << fc.x0 << " " << fc.y0 << " " << fc.chain << endl; } } } } }