DGtalTools  0.9.4
displayContours.cpp
1 
29 #include <iostream>
31 
32 //boost
33 #include <boost/program_options/options_description.hpp>
34 #include <boost/program_options/parsers.hpp>
35 #include <boost/program_options/variables_map.hpp>
36 
37 //STL
38 #include <vector>
39 #include <string>
40 
41 #include "DGtal/base/Common.h"
42 #include "DGtal/helpers/StdDefs.h"
43 
44 #include "DGtal/shapes/ShapeFactory.h"
45 #include "DGtal/shapes/Shapes.h"
46 #include "DGtal/topology/helpers/Surfaces.h"
47 
48 //image
49 #include "DGtal/images/imagesSetsUtils/ImageFromSet.h"
50 #include "DGtal/images/imagesSetsUtils/SetFromImage.h"
51 #include "DGtal/images/ImageContainerBySTLVector.h"
52 #include "DGtal/images/ImageSelector.h"
53 #include "DGtal/io/readers/PointListReader.h"
54 #include "DGtal/io/readers/TableReader.h"
55 #include "DGtal/io/Color.h"
56 
57  #include "DGtal/io/readers/GenericReader.h"
58 
59 
60 //contour
61 #include "DGtal/geometry/curves/FreemanChain.h"
62 
63 //processing
64 #include "DGtal/geometry/curves/ArithmeticalDSSComputer.h"
65 #include "DGtal/geometry/curves/GreedySegmentation.h"
66 #include "DGtal/geometry/curves/SaturatedSegmentation.h"
67 #include "DGtal/geometry/curves/FP.h"
68 #include "DGtal/geometry/curves/StabbingCircleComputer.h"
69 #include "DGtal/geometry/curves/SaturatedSegmentation.h"
70 #include "DGtal/geometry/curves/SegmentComputerUtils.h"
71 
72 #include "DGtal/io/boards/Board2D.h"
73 #include "DGtal/io/boards/CDrawableWithBoard2D.h"
74 
75 using namespace DGtal;
76 
77 
78 
174 namespace po = boost::program_options;
176 
177 int main( int argc, char** argv )
178 {
179 
180  // parse command line ----------------------------------------------
181  po::options_description general_opt("Allowed options are: ");
182  general_opt.add_options()
183  ("help,h", "display this message")
184  ("input,i", po::value<std::string>(), "input FreemanChain file name")
185  ("SDP", po::value<std::string>(), "Import a contour as a Sequence of Discrete Points (SDP format)")
186  ("SFP", po::value<std::string>(), "Import a contour as a Sequence of Floating Points (SFP format)")
187  ("drawContourPoint", po::value<double>(), "<size> display contour points as disk of radius <size>")
188  ("fillContour", "fill the contours with default color (gray)")
189  ("lineWidth", po::value<double>()->default_value(1.0), "Define the linewidth of the contour (SDP format)")
190  ("drawPointOfIndex", po::value<int>(), "<index> Draw the contour point of index <index> (default 0) ")
191  ("pointSize", po::value<double>()->default_value(2.0), "<size> Set the display point size of the point displayed by drawPointofIndex option (default 2.0) ")
192  ("noXFIGHeader", " to exclude xfig header in the resulting output stream (no effect with option -outputFile).")
193  ("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}")
194  ("outputFile,o", po::value<std::string>(), " <filename> save output file automatically according the file format extension.")
195  ("displayVectorField,v", po::value<std::string>(), "Add the display of a vector field represented by two floating coordinates. Each vector is displayed starting from the corresponding contour point coordinates.")
196  ("scaleVectorField,v", po::value<double>()->default_value(1.0), "set the scale of the vector field (default 1) (used with --displayVectorField).")
197  ("vectorFieldIndex", po::value<std::vector <unsigned int> >()->multitoken(), "specify the vector field index (by default 0,1) (used with --displayVectorField)." )
198  ("vectorFromAngle", po::value<unsigned int>(), "specify that the vectors are defined from an angle value represented at the given index (by default 0) (used with --displayVectorField)." )
199  ("rotateVectorField", "apply a CCW rotation of 90° (used with --displayVectorField). ")
200  ("outputStreamEPS", " specify eps for output stream format.")
201  ("outputStreamSVG", " specify svg for output stream format.")
202  ("outputStreamFIG", " specify fig for output stream format.")
203  ("invertYaxis", " invertYaxis invert the Y axis for display contours (used only with --SDP)")
204 
205  ("backgroundImage", po::value<std::string>(), "backgroundImage <filename> : display image as background ")
206  ("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)")
207 
208  ("scale", po::value<double>(), "scale <value> 1: normal; >1 : larger ; <1 lower resolutions )");
209 
210 
211 
212  bool parseOK=true;
213  po::variables_map vm;
214  try{
215  po::store(po::parse_command_line(argc, argv, general_opt), vm);
216  }catch(const std::exception& ex){
217  parseOK=false;
218  trace.info()<< "Error checking program options: "<< ex.what()<< std::endl;
219  }
220 
221  po::notify(vm);
222  if(!parseOK||vm.count("help")||argc<=1 || (!(vm.count("input")) && !(vm.count("SDP")) && !(vm.count("SFP"))&&
223  !(vm.count("backgroundImage")) ) )
224  {
225  trace.info()<< "Display discrete contours. " <<std::endl << "Basic usage: "<<std::endl
226  << "\t displayContours [options] --input <fileName> "<<std::endl
227  << general_opt << "\n";
228  return 0;
229  }
230 
231 
232 
233  double lineWidth= vm["lineWidth"].as<double>();
234  bool filled = vm.count("fillContour");
235  double scale=1.0;
236  if(vm.count("scale")){
237  scale = vm["scale"].as<double>();
238  }
239 
240  Board2D aBoard;
241  aBoard.setUnit (0.05*scale, LibBoard::Board::UCentimeter);
242 
243 
244 
245 
246 
247  double alpha=1.0;
248  if(vm.count("alphaBG")){
249  alpha = vm["alphaBG"].as<double>();
250  }
251 
252  if(vm.count("backgroundImage")){
253  std::string imageName = vm["backgroundImage"].as<std::string>();
255  Image img = DGtal::GenericReader<Image>::import( imageName );
256  Z2i::Point ptInf = img.domain().lowerBound();
257  Z2i::Point ptSup = img.domain().upperBound();
258  unsigned int width = abs(ptSup[0]-ptInf[0]+1);
259  unsigned int height = abs(ptSup[1]-ptInf[1]+1);
260 
261  aBoard.drawImage(imageName, 0-0.5,height-0.5, width, height, -1, alpha );
262  }
263 
264 
265 
266 
267  if(vm.count("input")){
268  std::string fileName = vm["input"].as<std::string>();
269  std::vector< FreemanChain<int> > vectFc = PointListReader< Z2i::Point>:: getFreemanChainsFromFile<int> (fileName);
270  aBoard << CustomStyle( vectFc.at(0).className(),
271  new CustomColors( Color::Red , filled? Color::Gray: Color::None ) );
272  aBoard.setLineWidth (lineWidth);
273  for(unsigned int i=0; i<vectFc.size(); i++){
274  aBoard << vectFc.at(i) ;
275  if(vm.count("drawPointOfIndex")){
276  int index = vm["drawPointOfIndex"].as<int>();
277  double size = vm["pointSize"].as<double>();
278  aBoard.setPenColor(Color::Blue);
279 
280  aBoard.fillCircle((double)(vectFc.at(i).getPoint(index)[0]), (double)(vectFc.at(i).getPoint(index)[1]), size);
281  }
282 
283  if(vm.count("withProcessing")){
284  std::string processingName = vm["withProcessing"].as<std::string>();
285 
286  std::vector<Z2i::Point> vPts(vectFc.at(i).size()+1);
287  copy ( vectFc.at(i).begin(), vectFc.at(i).end(), vPts.begin() );
288  bool isClosed;
289  if ( vPts.at(0) == vPts.at(vPts.size()-1) ) {
290  isClosed = true;
291  vPts.pop_back();
292  } else isClosed = false;
293 
294  if (processingName == "DSS") {
295 
297  typedef GreedySegmentation<DSS4> Decomposition4;
298 
299  DSS4 computer;
300  Decomposition4 theDecomposition( vPts.begin(),vPts.end(),computer );
301 
302  //for each segment
303  std::string className;
304  for ( Decomposition4::SegmentComputerIterator it = theDecomposition.begin();
305  it != theDecomposition.end(); ++it )
306  {
307  DSS4::Primitive segment(it->primitive());
308 
309  aBoard << SetMode( segment.className(), "BoundingBox" );
310  className = segment.className() + "/BoundingBox";
311  aBoard << CustomStyle( className,
313  aBoard << segment; // draw each segment
314  }
315 
316  } else if (processingName == "MS") {
317 
318  typedef ArithmeticalDSSComputer<std::vector<Z2i::Point>::iterator,int,4> DSS4;
319  typedef SaturatedSegmentation<DSS4> Decomposition4;
320 
321  //Segmentation
322  DSS4 computer;
323  Decomposition4 theDecomposition( vPts.begin(),vPts.end(),computer );
324 
325  //for each segment
326  std::string className;
327  for ( Decomposition4::SegmentComputerIterator it = theDecomposition.begin();
328  it != theDecomposition.end(); ++it )
329  {
330  DSS4::Primitive segment(it->primitive());
331 
332  aBoard << SetMode( segment.className(), "BoundingBox" );
333  className = segment.className() + "/BoundingBox";
334  aBoard << CustomStyle( className,
336  aBoard << segment; // draw each segment
337  }
338 
339  } else if (processingName == "FP") {
340 
342  FP theFP( vPts.begin(),vPts.end() );
343  aBoard << CustomStyle( theFP.className(),
345  aBoard << theFP;
346 
347 
348  } else if (processingName == "MLP") {
349 
350  typedef FP<std::vector<Z2i::Point>::iterator,int,4> FP;
351  FP theFP( vPts.begin(),vPts.end() );
352 
353  std::vector<FP::RealPoint> v( theFP.size() );
354  theFP.copyMLP( v.begin() );
355 
356  //polyline to draw
357  std::vector<LibBoard::Point> polyline;
358  std::vector<FP::RealPoint>::const_iterator it = v.begin();
359  for ( ;it != v.end();++it) {
360  FP::RealPoint p = (*it);
361  polyline.push_back(LibBoard::Point(p[0],p[1]));
362  }
363  if (isClosed) {
364  FP::RealPoint p = (*v.begin());
365  polyline.push_back(LibBoard::Point(p[0],p[1]));
366  }
368  aBoard.drawPolyline(polyline);
369 
370  } else if (processingName == "MDCA") {
372  typedef GridCurve<KSpace> Curve;
373  Curve curve; //grid curve
374  curve.initFromPointsVector( vPts );
375  typedef Curve::IncidentPointsRange Range; //range
376  Range r = curve.getIncidentPointsRange(); //range
377  typedef Range::ConstCirculator ConstCirculator; //iterator
378  typedef StabbingCircleComputer<ConstCirculator> SegmentComputer; //segment computer
379  //typedef GeometricalDCA<ConstIterator> SegmentComputer; //segment computer
380  typedef SaturatedSegmentation<SegmentComputer> Segmentation;
381  //Segmentation theSegmentation( r.begin(), r.end(), SegmentComputer() );
382  Segmentation theSegmentation( r.c(), r.c(), SegmentComputer() );
383  theSegmentation.setMode("Last");
384  // board << curve;
385  Segmentation::SegmentComputerIterator it = theSegmentation.begin();
386  Segmentation::SegmentComputerIterator itEnd = theSegmentation.end();
387  Board2D otherBoard;
388  otherBoard.setPenColor(DGtal::Color::Black);
389  otherBoard << curve;
390  for ( ; it != itEnd; ++it ) {
391  aBoard << SetMode(SegmentComputer().className(), "") << (*it);
392  otherBoard << SetMode(SegmentComputer().className(), "") << (*it);
393  }
394  otherBoard.saveSVG("mdca.svg", Board2D::BoundingBox, 5000 );
395  }
396  }
397 
398  }
399 
400 
401 
402  }
403 
404 
405 
406  if(vm.count("SDP") || vm.count("SFP")){
407  bool drawPoints= vm.count("drawContourPoint");
408  bool invertYaxis = vm.count("invertYaxis");
409  double pointSize=1.0;
410  if(drawPoints){
411  pointSize = vm["drawContourPoint"].as<double>();
412  }
413  std::vector<LibBoard::Point> contourPt;
414  if(vm.count("SDP")){
415  std::string fileName = vm["SDP"].as<std::string>();
416  std::vector< Z2i::Point > contour = PointListReader< Z2i::Point >::getPointsFromFile(fileName);
417  for(unsigned int j=0; j<contour.size(); j++){
418  LibBoard::Point pt((double)(contour.at(j)[0]),
419  (invertYaxis? (double)(-contour.at(j)[1]+contour.at(0)[1]):(double)(contour.at(j)[1])));
420  contourPt.push_back(pt);
421  if(drawPoints){
422  aBoard.fillCircle(pt.x, pt.y, pointSize);
423  }
424  }
425  }
426 
427  if(vm.count("SFP")){
428  std::string fileName = vm["SFP"].as<std::string>();
429  std::vector< PointVector<2,double> > contour =
430  PointListReader< PointVector<2,double> >::getPointsFromFile(fileName);
431  for(unsigned int j=0; j<contour.size(); j++){
432  LibBoard::Point pt((double)(contour.at(j)[0]),
433  (invertYaxis? (double)(-contour.at(j)[1]+contour.at(0)[1]):(double)(contour.at(j)[1])));
434  contourPt.push_back(pt);
435  if(drawPoints){
436  aBoard.fillCircle(pt.x, pt.y, pointSize);
437  }
438  }
439 
440  }
441 
442 
443  aBoard.setPenColor(Color::Red);
444  aBoard.setFillColor(Color::Gray);
446  aBoard.setLineWidth (lineWidth);
447  if(!filled){
448  aBoard.drawPolyline(contourPt);
449  }else{
450  aBoard.fillPolyline(contourPt);
451  }
452  if(vm.count("drawPointOfIndex")){
453  int index = vm["drawPointOfIndex"].as<int>();
454  double size = vm["pointSize"].as<double>();
455  aBoard.fillCircle((double)(contourPt.at(index).x), (double)(contourPt.at(index).y), size);
456  }
457 
458 
459  // display vector field
460  if(vm.count("displayVectorField"))
461  {
462  bool rotate = vm.count("rotateVectorField");
463  double sv = vm["scaleVectorField"].as<double>();
464  std::vector<unsigned int> vIndex = {0,1};
465  if(vm.count("vectorFieldIndex"))
466  {
467  vIndex = vm["vectorFieldIndex"].as<std::vector<unsigned int>>();
468  }
469  std::string vname = vm["displayVectorField"].as<std::string>();
470  std::vector< PointVector<2,double> > vField;
471  if(vm.count("vectorFromAngle"))
472  {
473  unsigned int aIndex = vm["vectorFromAngle"].as<unsigned int>();
474  std::vector<double> vAngles = TableReader<double>::getColumnElementsFromFile(vname, aIndex);
475  for(unsigned int i = 0; i < vAngles.size(); i++)
476  {
477  vField.push_back(Z2i::RealPoint(cos(vAngles[i]),sin(vAngles[i])));
478  }
479  }
480  else
481  {
482  vField = PointListReader< PointVector<2,double> >::getPointsFromFile(vname, vIndex);
483  }
484  for(unsigned int i = 0; i< contourPt.size(); i++)
485  {
486  vField[i] = vField[i].getNormalized();
487  auto p = contourPt[i];
488  if(!rotate)
489  {
490  aBoard.drawArrow(p.x, p.y, p.x+vField[i][0]*sv, p.y+vField[i][1]*sv );
491  }
492  else
493  {
494  aBoard.drawArrow(p.x, p.y, p.x-vField[i][1]*sv, p.y+vField[i][0]*sv );
495  }
496 
497  }
498 
499  }
500  }
501 
502 
503 
504 
505  if(vm.count("outputFile")){
506  std::string outputFileName= vm["outputFile"].as<std::string>();
507  std::string extension = outputFileName.substr(outputFileName.find_last_of(".") + 1);
508 
509  if(extension=="svg"){
510  aBoard.saveSVG(outputFileName.c_str());
511  }
512  #ifdef WITH_CAIRO
513  else
514  if (extension=="eps"){
515  aBoard.saveCairo(outputFileName.c_str(),Board2D::CairoEPS );
516  } else
517  if (extension=="pdf"){
518  aBoard.saveCairo(outputFileName.c_str(),Board2D::CairoPDF );
519  } else
520  if (extension=="png"){
521  aBoard.saveCairo(outputFileName.c_str(),Board2D::CairoPNG );
522  }
523  #endif
524  else if(extension=="eps"){
525  aBoard.saveEPS(outputFileName.c_str());
526  }else if(extension=="fig"){
527  aBoard.saveFIG(outputFileName.c_str(),LibBoard::Board::BoundingBox, 10.0, !vm.count("noXFIGHeader") );
528  }
529  }
530 
531  if (vm.count("outputStreamSVG")){
532  aBoard.saveSVG(std::cout);
533  } else
534  if (vm.count("outputStreamFIG")){
535  aBoard.saveFIG(std::cout, LibBoard::Board::BoundingBox, 10.0, !vm.count("noXFIGHeader"));
536  } else
537  if (vm.count("outputStreamEPS")){
538  aBoard.saveEPS(std::cout);
539  }
540 
541  }
542 
void fillPolyline(const std::vector< Point > &points, int depthValue=-1)
static std::vector< TQuantity > getColumnElementsFromFile(const std::string &aFilename, unsigned int aPosition)
static const Color Black
Board & setLineWidth(double width)
void drawPolyline(const std::vector< Point > &points, int depthValue=-1)
GridCurve< K2 > Curve
void drawImage(std::string filename, double x, double y, double width, double height, int depthValue=-1, double alpha=1.0)
void drawArrow(double x1, double y1, double x2, double y2, bool filled=true, int depthValue=-1)
void saveFIG(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0, bool includeFIGHeader=true) const
void saveCairo(const char *filename, CairoType type=CairoPNG, PageSize size=Board::BoundingBox, double margin=10.0) const
static const Color None
static TContainer import(const std::string &filename, std::vector< unsigned int > dimSpace=std::vector< unsigned int >())
static std::vector< TPoint > getPointsFromFile(const std::string &filename, std::vector< unsigned int > aVectPosition=std::vector< unsigned int >())
void setMode(const std::string &aMode)
void fillCircle(double x, double y, double radius, int depthValue=-1)
static const Color Blue
static const Color Gray
Board & setLineStyle(Shape::LineStyle style)
Board & setFillColor(const DGtal::Color &color)
void saveSVG(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Trace trace(traceWriterTerm)
std::ostream & info()
std::string className() const
void saveEPS(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Board & setPenColor(const DGtal::Color &color)
const Domain & domain() const
void setUnit(Unit unit)
static const Color Red
T abs(const T &a)