void dssLength() { typedef DGtal::ImageContainerBySTLVector< DGtal::Z2i::Domain, unsigned char> Image; std::string filename = examplesPath + "contourS.pgm"; Image image = DGtal::PGMReader<Image>::importPGM(filename); typedef DGtal::functors::IntervalThresholder<Image::Value> Binarizer; Binarizer b(1, 135); DGtal::functors::PointFunctorPredicate<Image, Binarizer> predicate(image, b); DGtal::Z2i::KSpace ks; ks.init( image.domain().lowerBound(), image.domain().upperBound(), true ); DGtal::SurfelAdjacency<2> sAdj(true); std::vector< std::vector< DGtal::Z2i::SCell > > contours; DGtal::Surfaces<DGtal::Z2i::KSpace>::extractAll2DSCellContours(contours, ks, sAdj, predicate); DGtal::Z2i::Curve c; c.initFromSCellsVector( contours.at(1) ); typedef DGtal::Z2i::Curve::PointsRange Range; Range r = c.getPointsRange(); DGtal::DSSLengthEstimator< Range::ConstCirculator > DSSlength; DSSlength.init(1, r.c(), r.c()); DGtal::trace.info() << "Length: " << DSSlength.eval() << std::endl; }
void estimateGeometry(Shape& s, const double& h, const Range& r, std::vector<Point>& points, std::vector<Point>& tangents, std::vector<Quantity>& curvatures) { typedef typename Range::ConstIterator ConstIterator; for (ConstIterator i = r.begin(); i != r.end(); ++i) { Point p( *i ); p *= h; points.push_back(p); } typedef typename Range::ConstCirculator ConstCirculator; typedef ParametricShapeTangentFunctor< Shape > TangentFunctor; TrueLocalEstimatorOnPoints< ConstCirculator, Shape, TangentFunctor > trueTangentEstimator; trueTangentEstimator.attach(&s); trueTangentEstimator.init( h, r.c(), r.c()); trueTangentEstimator.eval(r.c(), r.c(), std::back_inserter(tangents) ); typedef ParametricShapeCurvatureFunctor< Shape > CurvatureFunctor; TrueLocalEstimatorOnPoints< ConstCirculator, Shape, CurvatureFunctor > trueCurvatureEstimator; trueCurvatureEstimator.attach(&s); trueCurvatureEstimator.init( h, r.c(), r.c()); trueCurvatureEstimator.eval(r.c(), r.c(), std::back_inserter(curvatures) ); }
/** * Test * */ bool testFP(string filename) { trace.info() << endl; trace.info() << "Reading GridCurve from " << filename << endl; ifstream instream; // input stream instream.open (filename.c_str(), ifstream::in); //range of points typedef int Coordinate; typedef KhalimskySpaceND<2,Coordinate> Kspace; //space GridCurve<Kspace> c; //building grid curve c.initFromVectorStream(instream); typedef GridCurve<Kspace >::PointsRange Range;//range Range r = c.getPointsRange();//building range typedef Range::ConstIterator ConstIterator;//constIterator //faithful polyon trace.info() << "Building FP (process digital curve as"; trace.info() << ( (c.isClosed())?"closed":"open" ) << ")" << endl; bool res = true; if (c.isClosed()) { typedef FP<Range::ConstCirculator,Coordinate,4> FP; FP theFP( r.c(), r.c() ); res = theFP.isValid(); } else { typedef FP<Range::ConstIterator,Coordinate,4> FP; FP theFP( r.begin(), r.end() ); res = theFP.isValid(); } return res; }
/** * Applying test on a given data file * */ bool testEval(string filename) { trace.info() << endl; trace.info() << "Reading GridCurve from " << filename << endl; ifstream instream; // input stream instream.open (filename.c_str(), ifstream::in); typedef KhalimskySpaceND<2> Kspace; //space GridCurve<Kspace> c; //building grid curve c.initFromVectorStream(instream); typedef GridCurve<Kspace >::PointsRange Range;//range Range r = c.getPointsRange();//building range trace.info() << "Building Estimator (process range as"; trace.info() << ( (c.isClosed())?"closed":"open" ) << ")" << endl; if (c.isClosed()) return test(r.c(), r.c()); else return test(r.begin(), r.end()); }
bool testRange(const Range &aRange) { trace.info() << endl; trace.info() << "Testing Range (" << aRange.size() << " elts)" << endl; typedef typename IteratorCirculatorTraits<typename Range::ConstIterator>::Value Value; std::vector<Value> v1,v2,v3,v4; { trace.info() << "Forward" << endl; typename Range::ConstIterator i = aRange.begin(); typename Range::ConstIterator end = aRange.end(); for ( ; i != end; ++i) { //cout << *i << endl; v1.push_back(*i); } } { trace.info() << "Backward" << endl; typename Range::ConstReverseIterator i = aRange.rbegin(); typename Range::ConstReverseIterator end = aRange.rend(); for ( ; i != end; ++i) { //cout << *i << endl; v2.push_back(*i); } } { trace.info() << "Circulator" << endl; typename Range::ConstCirculator c = aRange.c(); typename Range::ConstCirculator cend = aRange.c(); if (isNotEmpty(c,cend)) { do { //cout << *c << endl; v3.push_back(*c); c++; } while (c!=cend); } } { trace.info() << "Reverse Circulator" << endl; typename Range::ConstReverseCirculator c = aRange.rc(); typename Range::ConstReverseCirculator cend = aRange.rc(); if (isNotEmpty(c,cend)) { do { //cout << *c << endl; v4.push_back(*c); c++; } while (c!=cend); } } return ( std::equal(v1.begin(),v1.end(),v3.begin()) && std::equal(v2.begin(),v2.end(),v4.begin()) && std::equal(v1.begin(),v1.end(),v2.rbegin()) && std::equal(v3.begin(),v3.end(),v4.rbegin()) ); }
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") ("input,i", po::value<std::string>(), "input FreemanChain file name") ("SDP", po::value<std::string>(), "Import a contour as a Sequence of Discrete Points (SDP format)") ("SFP", po::value<std::string>(), "Import a contour as a Sequence of Floating Points (SFP format)") ("drawContourPoint", po::value<double>(), "<size> display contour points as disk of radius <size>") ("fillContour", "fill the contours with default color (gray)") ("lineWidth", po::value<double>()->default_value(1.0), "Define the linewidth of the contour (SDP format)") ("drawPointOfIndex", po::value<int>(), "<index> Draw the contour point of index <index> (default 0) ") ("pointSize", po::value<double>()->default_value(2.0), "<size> Set the display point size of the point displayed by drawPointofIndex option (default 2.0) ") ("noXFIGHeader", " to exclude xfig header in the resulting output stream (no effect with option -outputFile).") ("withProcessing", po::value<std::string>(), "Processing (used only when the input is a Freeman chain (--input)):\n\t DSS segmentation {DSS}\n\t Maximal segments {MS}\n\t Faithful Polygon {FP}\n\t Minimum Length Polygon {MLP}") ("outputFile,o", po::value<std::string>(), " <filename> save output file automatically according the file format extension.") ("outputStreamEPS", " specify eps for output stream format.") ("outputStreamSVG", " specify svg for output stream format.") ("outputStreamFIG", " specify fig for output stream format.") ("invertYaxis", " invertYaxis invert the Y axis for display contours (used only with --SDP)") ("backgroundImage", po::value<std::string>(), "backgroundImage <filename> : display image as background ") ("alphaBG", po::value<double>(), "alphaBG <value> 0-1.0 to display the background image in transparency (default 1.0), (transparency works only if cairo is available)") ("scale", po::value<double>(), "scale <value> 1: normal; >1 : larger ; <1 lower resolutions )"); bool parseOK=true; po::variables_map vm; try { po::store(po::parse_command_line(argc, argv, general_opt), vm); } catch(const std::exception& ex) { parseOK=false; trace.info()<< "Error checking program options: "<< ex.what()<< std::endl; } po::notify(vm); if(!parseOK||vm.count("help")||argc<=1 || (!(vm.count("input")) && !(vm.count("SDP")) && !(vm.count("SFP"))&& !(vm.count("backgroundImage")) ) ) { trace.info()<< "Display discrete contours. " <<std::endl << "Basic usage: "<<std::endl << "\t displayContours [options] --input <fileName> "<<std::endl << general_opt << "\n"; return 0; } double lineWidth= vm["lineWidth"].as<double>(); bool filled = vm.count("fillContour"); double scale=1.0; if(vm.count("scale")) { scale = vm["scale"].as<double>(); } Board2D aBoard; aBoard.setUnit (0.05*scale, LibBoard::Board::UCentimeter); double alpha=1.0; if(vm.count("alphaBG")) { alpha = vm["alphaBG"].as<double>(); } if(vm.count("backgroundImage")) { std::string imageName = vm["backgroundImage"].as<std::string>(); typedef ImageSelector<Z2i::Domain, unsigned char>::Type Image; Image img = DGtal::GenericReader<Image>::import( imageName ); Z2i::Point ptInf = img.domain().lowerBound(); Z2i::Point ptSup = img.domain().upperBound(); unsigned int width = abs(ptSup[0]-ptInf[0]+1); unsigned int height = abs(ptSup[1]-ptInf[1]+1); aBoard.drawImage(imageName, 0-0.5,height-0.5, width, height, -1, alpha ); } if(vm.count("input")) { std::string fileName = vm["input"].as<std::string>(); std::vector< FreemanChain<int> > vectFc = PointListReader< Z2i::Point>:: getFreemanChainsFromFile<int> (fileName); aBoard << CustomStyle( vectFc.at(0).className(), new CustomColors( Color::Red , filled? Color::Gray: Color::None ) ); aBoard.setLineWidth (lineWidth); for(unsigned int i=0; i<vectFc.size(); i++) { aBoard << vectFc.at(i) ; if(vm.count("drawPointOfIndex")) { int index = vm["drawPointOfIndex"].as<int>(); double size = vm["pointSize"].as<double>(); aBoard.setPenColor(Color::Blue); aBoard.fillCircle((double)(vectFc.at(i).getPoint(index)[0]), (double)(vectFc.at(i).getPoint(index)[1]), size); } if(vm.count("withProcessing")) { std::string processingName = vm["withProcessing"].as<std::string>(); std::vector<Z2i::Point> vPts(vectFc.at(i).size()+1); copy ( vectFc.at(i).begin(), vectFc.at(i).end(), vPts.begin() ); bool isClosed; if ( vPts.at(0) == vPts.at(vPts.size()-1) ) { isClosed = true; vPts.pop_back(); } else isClosed = false; if (processingName == "DSS") { typedef ArithmeticalDSSComputer<std::vector<Z2i::Point>::iterator,int,4> DSS4; typedef GreedySegmentation<DSS4> Decomposition4; DSS4 computer; Decomposition4 theDecomposition( vPts.begin(),vPts.end(),computer ); //for each segment std::string className; for ( Decomposition4::SegmentComputerIterator it = theDecomposition.begin(); it != theDecomposition.end(); ++it ) { DSS4::Primitive segment(it->primitive()); aBoard << SetMode( segment.className(), "BoundingBox" ); className = segment.className() + "/BoundingBox"; aBoard << CustomStyle( className, new CustomPenColor( DGtal::Color::Gray ) ); aBoard << segment; // draw each segment } } else if (processingName == "MS") { typedef ArithmeticalDSSComputer<std::vector<Z2i::Point>::iterator,int,4> DSS4; typedef SaturatedSegmentation<DSS4> Decomposition4; //Segmentation DSS4 computer; Decomposition4 theDecomposition( vPts.begin(),vPts.end(),computer ); //for each segment std::string className; for ( Decomposition4::SegmentComputerIterator it = theDecomposition.begin(); it != theDecomposition.end(); ++it ) { DSS4::Primitive segment(it->primitive()); aBoard << SetMode( segment.className(), "BoundingBox" ); className = segment.className() + "/BoundingBox"; aBoard << CustomStyle( className, new CustomPenColor( DGtal::Color::Gray ) ); aBoard << segment; // draw each segment } } else if (processingName == "FP") { typedef FP<std::vector<Z2i::Point>::iterator,int,4> FP; FP theFP( vPts.begin(),vPts.end() ); aBoard << CustomStyle( theFP.className(), new CustomPenColor( DGtal::Color::Black ) ); aBoard << theFP; } else if (processingName == "MLP") { typedef FP<std::vector<Z2i::Point>::iterator,int,4> FP; FP theFP( vPts.begin(),vPts.end() ); std::vector<FP::RealPoint> v( theFP.size() ); theFP.copyMLP( v.begin() ); //polyline to draw std::vector<LibBoard::Point> polyline; std::vector<FP::RealPoint>::const_iterator it = v.begin(); for ( ; it != v.end(); ++it) { FP::RealPoint p = (*it); polyline.push_back(LibBoard::Point(p[0],p[1])); } if (isClosed) { FP::RealPoint p = (*v.begin()); polyline.push_back(LibBoard::Point(p[0],p[1])); } aBoard.setPenColor(DGtal::Color::Black); aBoard.drawPolyline(polyline); } else if (processingName == "MDCA") { typedef KhalimskySpaceND<2,int> KSpace; typedef GridCurve<KSpace> Curve; Curve curve; //grid curve curve.initFromPointsVector( vPts ); typedef Curve::IncidentPointsRange Range; //range Range r = curve.getIncidentPointsRange(); //range typedef Range::ConstCirculator ConstCirculator; //iterator typedef StabbingCircleComputer<ConstCirculator> SegmentComputer; //segment computer //typedef GeometricalDCA<ConstIterator> SegmentComputer; //segment computer typedef SaturatedSegmentation<SegmentComputer> Segmentation; //Segmentation theSegmentation( r.begin(), r.end(), SegmentComputer() ); Segmentation theSegmentation( r.c(), r.c(), SegmentComputer() ); theSegmentation.setMode("Last"); // board << curve; Segmentation::SegmentComputerIterator it = theSegmentation.begin(); Segmentation::SegmentComputerIterator itEnd = theSegmentation.end(); Board2D otherBoard; otherBoard.setPenColor(DGtal::Color::Black); otherBoard << curve; for ( ; it != itEnd; ++it ) { aBoard << SetMode(SegmentComputer().className(), "") << (*it); otherBoard << SetMode(SegmentComputer().className(), "") << (*it); } otherBoard.saveSVG("mdca.svg", Board2D::BoundingBox, 5000 ); } } } } if(vm.count("SDP") || vm.count("SFP")) { bool drawPoints= vm.count("drawContourPoint"); bool invertYaxis = vm.count("invertYaxis"); double pointSize=1.0; if(drawPoints) { pointSize = vm["drawContourPoint"].as<double>(); } std::vector<LibBoard::Point> contourPt; if(vm.count("SDP")) { std::string fileName = vm["SDP"].as<std::string>(); std::vector< Z2i::Point > contour = PointListReader< Z2i::Point >::getPointsFromFile(fileName); for(unsigned int j=0; j<contour.size(); j++) { LibBoard::Point pt((double)(contour.at(j)[0]), (invertYaxis? (double)(-contour.at(j)[1]+contour.at(0)[1]):(double)(contour.at(j)[1]))); contourPt.push_back(pt); if(drawPoints) { aBoard.fillCircle(pt.x, pt.y, pointSize); } } } if(vm.count("SFP")) { std::string fileName = vm["SFP"].as<std::string>(); std::vector< PointVector<2,double> > contour = PointListReader< PointVector<2,double> >::getPointsFromFile(fileName); for(unsigned int j=0; j<contour.size(); j++) { LibBoard::Point pt((double)(contour.at(j)[0]), (invertYaxis? (double)(-contour.at(j)[1]+contour.at(0)[1]):(double)(contour.at(j)[1]))); contourPt.push_back(pt); if(drawPoints) { aBoard.fillCircle(pt.x, pt.y, pointSize); } } } aBoard.setPenColor(Color::Red); aBoard.setFillColor(Color::Gray); aBoard.setLineStyle (LibBoard::Shape::SolidStyle ); aBoard.setLineWidth (lineWidth); if(!filled) { aBoard.drawPolyline(contourPt); } else { aBoard.fillPolyline(contourPt); } if(vm.count("drawPointOfIndex")) { int index = vm["drawPointOfIndex"].as<int>(); double size = vm["pointSize"].as<double>(); aBoard.fillCircle((double)(contourPt.at(index).x), (double)(contourPt.at(index).y), size); } } if(vm.count("outputFile")) { std::string outputFileName= vm["outputFile"].as<std::string>(); std::string extension = outputFileName.substr(outputFileName.find_last_of(".") + 1); if(extension=="svg") { aBoard.saveSVG(outputFileName.c_str()); } #ifdef WITH_CAIRO else if (extension=="eps") { aBoard.saveCairo(outputFileName.c_str(),Board2D::CairoEPS ); } else if (extension=="pdf") { aBoard.saveCairo(outputFileName.c_str(),Board2D::CairoPDF ); } else if (extension=="png") { aBoard.saveCairo(outputFileName.c_str(),Board2D::CairoPNG ); } #endif else if(extension=="eps") { aBoard.saveEPS(outputFileName.c_str()); } else if(extension=="fig") { aBoard.saveFIG(outputFileName.c_str(),LibBoard::Board::BoundingBox, 10.0, !vm.count("noXFIGHeader") ); } } if (vm.count("outputStreamSVG")) { aBoard.saveSVG(std::cout); } else if (vm.count("outputStreamFIG")) { aBoard.saveFIG(std::cout, LibBoard::Board::BoundingBox, 10.0, !vm.count("noXFIGHeader")); } else if (vm.count("outputStreamEPS")) { aBoard.saveEPS(std::cout); } }
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; }