DGtalTools  0.9.2
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/Color.h"
55 
56  #include "DGtal/io/readers/GenericReader.h"
57 
58 
59 //contour
60 #include "DGtal/geometry/curves/FreemanChain.h"
61 
62 //processing
63 #include "DGtal/geometry/curves/ArithmeticalDSSComputer.h"
64 #include "DGtal/geometry/curves/GreedySegmentation.h"
65 #include "DGtal/geometry/curves/SaturatedSegmentation.h"
66 #include "DGtal/geometry/curves/FP.h"
67 #include "DGtal/geometry/curves/StabbingCircleComputer.h"
68 #include "DGtal/geometry/curves/SaturatedSegmentation.h"
69 #include "DGtal/geometry/curves/SegmentComputerUtils.h"
70 
71 #include "DGtal/io/boards/Board2D.h"
72 #include "DGtal/io/boards/CDrawableWithBoard2D.h"
73 
74 using namespace DGtal;
75 
76 
77 
157 namespace po = boost::program_options;
159 
160 int main( int argc, char** argv )
161 {
162 
163  // parse command line ----------------------------------------------
164  po::options_description general_opt("Allowed options are: ");
165  general_opt.add_options()
166  ("help,h", "display this message")
167  ("input,i", po::value<std::string>(), "input FreemanChain file name")
168  ("SDP", po::value<std::string>(), "Import a contour as a Sequence of Discrete Points (SDP format)")
169  ("SFP", po::value<std::string>(), "Import a contour as a Sequence of Floating Points (SFP format)")
170  ("drawContourPoint", po::value<double>(), "<size> display contour points as disk of radius <size>")
171  ("fillContour", "fill the contours with default color (gray)")
172  ("lineWidth", po::value<double>()->default_value(1.0), "Define the linewidth of the contour (SDP format)")
173  ("drawPointOfIndex", po::value<int>(), "<index> Draw the contour point of index <index> (default 0) ")
174  ("pointSize", po::value<double>()->default_value(2.0), "<size> Set the display point size of the point displayed by drawPointofIndex option (default 2.0) ")
175  ("noXFIGHeader", " to exclude xfig header in the resulting output stream (no effect with option -outputFile).")
176  ("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}")
177  ("outputFile,o", po::value<std::string>(), " <filename> save output file automatically according the file format extension.")
178  ("outputStreamEPS", " specify eps for output stream format.")
179  ("outputStreamSVG", " specify svg for output stream format.")
180  ("outputStreamFIG", " specify fig for output stream format.")
181  ("invertYaxis", " invertYaxis invert the Y axis for display contours (used only with --SDP)")
182 
183  ("backgroundImage", po::value<std::string>(), "backgroundImage <filename> : display image as background ")
184  ("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)")
185 
186  ("scale", po::value<double>(), "scale <value> 1: normal; >1 : larger ; <1 lower resolutions )");
187 
188 
189 
190  bool parseOK=true;
191  po::variables_map vm;
192  try{
193  po::store(po::parse_command_line(argc, argv, general_opt), vm);
194  }catch(const std::exception& ex){
195  parseOK=false;
196  trace.info()<< "Error checking program options: "<< ex.what()<< std::endl;
197  }
198 
199  po::notify(vm);
200  if(!parseOK||vm.count("help")||argc<=1 || (!(vm.count("input")) && !(vm.count("SDP")) && !(vm.count("SFP"))&&
201  !(vm.count("backgroundImage")) ) )
202  {
203  trace.info()<< "Display discrete contours. " <<std::endl << "Basic usage: "<<std::endl
204  << "\t displayContours [options] --input <fileName> "<<std::endl
205  << general_opt << "\n";
206  return 0;
207  }
208 
209 
210 
211  double lineWidth= vm["lineWidth"].as<double>();
212  bool filled = vm.count("fillContour");
213  double scale=1.0;
214  if(vm.count("scale")){
215  scale = vm["scale"].as<double>();
216  }
217 
218  Board2D aBoard;
219  aBoard.setUnit (0.05*scale, LibBoard::Board::UCentimeter);
220 
221 
222 
223 
224 
225  double alpha=1.0;
226  if(vm.count("alphaBG")){
227  alpha = vm["alphaBG"].as<double>();
228  }
229 
230  if(vm.count("backgroundImage")){
231  std::string imageName = vm["backgroundImage"].as<std::string>();
232  typedef ImageSelector<Z2i::Domain, unsigned char>::Type Image;
233  Image img = DGtal::GenericReader<Image>::import( imageName );
234  Z2i::Point ptInf = img.domain().lowerBound();
235  Z2i::Point ptSup = img.domain().upperBound();
236  unsigned int width = abs(ptSup[0]-ptInf[0]+1);
237  unsigned int height = abs(ptSup[1]-ptInf[1]+1);
238 
239  aBoard.drawImage(imageName, 0-0.5,height-0.5, width, height, -1, alpha );
240  }
241 
242 
243 
244 
245  if(vm.count("input")){
246  std::string fileName = vm["input"].as<std::string>();
247  std::vector< FreemanChain<int> > vectFc = PointListReader< Z2i::Point>:: getFreemanChainsFromFile<int> (fileName);
248  aBoard << CustomStyle( vectFc.at(0).className(),
249  new CustomColors( Color::Red , filled? Color::Gray: Color::None ) );
250  aBoard.setLineWidth (lineWidth);
251  for(unsigned int i=0; i<vectFc.size(); i++){
252  aBoard << vectFc.at(i) ;
253  if(vm.count("drawPointOfIndex")){
254  int index = vm["drawPointOfIndex"].as<int>();
255  double size = vm["pointSize"].as<double>();
256  aBoard.setPenColor(Color::Blue);
257 
258  aBoard.fillCircle((double)(vectFc.at(i).getPoint(index)[0]), (double)(vectFc.at(i).getPoint(index)[1]), size);
259  }
260 
261  if(vm.count("withProcessing")){
262  std::string processingName = vm["withProcessing"].as<std::string>();
263 
264  std::vector<Z2i::Point> vPts(vectFc.at(i).size()+1);
265  copy ( vectFc.at(i).begin(), vectFc.at(i).end(), vPts.begin() );
266  bool isClosed;
267  if ( vPts.at(0) == vPts.at(vPts.size()-1) ) {
268  isClosed = true;
269  vPts.pop_back();
270  } else isClosed = false;
271 
272  if (processingName == "DSS") {
273 
274  typedef ArithmeticalDSSComputer<std::vector<Z2i::Point>::iterator,int,4> DSS4;
275  typedef GreedySegmentation<DSS4> Decomposition4;
276 
277  DSS4 computer;
278  Decomposition4 theDecomposition( vPts.begin(),vPts.end(),computer );
279 
280  //for each segment
281  std::string className;
282  for ( Decomposition4::SegmentComputerIterator it = theDecomposition.begin();
283  it != theDecomposition.end(); ++it )
284  {
285  DSS4::Primitive segment(it->primitive());
286 
287  aBoard << SetMode( segment.className(), "BoundingBox" );
288  className = segment.className() + "/BoundingBox";
289  aBoard << CustomStyle( className,
290  new CustomPenColor( DGtal::Color::Gray ) );
291  aBoard << segment; // draw each segment
292  }
293 
294  } else if (processingName == "MS") {
295 
296  typedef ArithmeticalDSSComputer<std::vector<Z2i::Point>::iterator,int,4> DSS4;
297  typedef SaturatedSegmentation<DSS4> Decomposition4;
298 
299  //Segmentation
300  DSS4 computer;
301  Decomposition4 theDecomposition( vPts.begin(),vPts.end(),computer );
302 
303  //for each segment
304  std::string className;
305  for ( Decomposition4::SegmentComputerIterator it = theDecomposition.begin();
306  it != theDecomposition.end(); ++it )
307  {
308  DSS4::Primitive segment(it->primitive());
309 
310  aBoard << SetMode( segment.className(), "BoundingBox" );
311  className = segment.className() + "/BoundingBox";
312  aBoard << CustomStyle( className,
313  new CustomPenColor( DGtal::Color::Gray ) );
314  aBoard << segment; // draw each segment
315  }
316 
317  } else if (processingName == "FP") {
318 
319  typedef FP<std::vector<Z2i::Point>::iterator,int,4> FP;
320  FP theFP( vPts.begin(),vPts.end() );
321  aBoard << CustomStyle( theFP.className(),
322  new CustomPenColor( DGtal::Color::Black ) );
323  aBoard << theFP;
324 
325 
326  } else if (processingName == "MLP") {
327 
328  typedef FP<std::vector<Z2i::Point>::iterator,int,4> FP;
329  FP theFP( vPts.begin(),vPts.end() );
330 
331  std::vector<FP::RealPoint> v( theFP.size() );
332  theFP.copyMLP( v.begin() );
333 
334  //polyline to draw
335  std::vector<LibBoard::Point> polyline;
336  std::vector<FP::RealPoint>::const_iterator it = v.begin();
337  for ( ;it != v.end();++it) {
338  FP::RealPoint p = (*it);
339  polyline.push_back(LibBoard::Point(p[0],p[1]));
340  }
341  if (isClosed) {
342  FP::RealPoint p = (*v.begin());
343  polyline.push_back(LibBoard::Point(p[0],p[1]));
344  }
345  aBoard.setPenColor(DGtal::Color::Black);
346  aBoard.drawPolyline(polyline);
347 
348  } else if (processingName == "MDCA") {
349  typedef KhalimskySpaceND<2,int> KSpace;
350  typedef GridCurve<KSpace> Curve;
351  Curve curve; //grid curve
352  curve.initFromPointsVector( vPts );
353  typedef Curve::IncidentPointsRange Range; //range
354  Range r = curve.getIncidentPointsRange(); //range
355  typedef Range::ConstCirculator ConstCirculator; //iterator
356  typedef StabbingCircleComputer<ConstCirculator> SegmentComputer; //segment computer
357  //typedef GeometricalDCA<ConstIterator> SegmentComputer; //segment computer
358  typedef SaturatedSegmentation<SegmentComputer> Segmentation;
359  //Segmentation theSegmentation( r.begin(), r.end(), SegmentComputer() );
360  Segmentation theSegmentation( r.c(), r.c(), SegmentComputer() );
361  theSegmentation.setMode("Last");
362  // board << curve;
363  Segmentation::SegmentComputerIterator it = theSegmentation.begin();
364  Segmentation::SegmentComputerIterator itEnd = theSegmentation.end();
365  Board2D otherBoard;
366  otherBoard.setPenColor(DGtal::Color::Black);
367  otherBoard << curve;
368  for ( ; it != itEnd; ++it ) {
369  aBoard << SetMode(SegmentComputer().className(), "") << (*it);
370  otherBoard << SetMode(SegmentComputer().className(), "") << (*it);
371  }
372  otherBoard.saveSVG("mdca.svg", Board2D::BoundingBox, 5000 );
373  }
374  }
375 
376  }
377 
378 
379 
380  }
381 
382 
383 
384  if(vm.count("SDP") || vm.count("SFP")){
385  bool drawPoints= vm.count("drawContourPoint");
386  bool invertYaxis = vm.count("invertYaxis");
387  double pointSize=1.0;
388  if(drawPoints){
389  pointSize = vm["drawContourPoint"].as<double>();
390  }
391  std::vector<LibBoard::Point> contourPt;
392  if(vm.count("SDP")){
393  std::string fileName = vm["SDP"].as<std::string>();
394  std::vector< Z2i::Point > contour =
395  PointListReader< Z2i::Point >::getPointsFromFile(fileName);
396  for(unsigned int j=0; j<contour.size(); j++){
397  LibBoard::Point pt((double)(contour.at(j)[0]),
398  (invertYaxis? (double)(-contour.at(j)[1]+contour.at(0)[1]):(double)(contour.at(j)[1])));
399  contourPt.push_back(pt);
400  if(drawPoints){
401  aBoard.fillCircle(pt.x, pt.y, pointSize);
402  }
403  }
404  }
405 
406  if(vm.count("SFP")){
407  std::string fileName = vm["SFP"].as<std::string>();
408  std::vector< PointVector<2,double> > contour =
409  PointListReader< PointVector<2,double> >::getPointsFromFile(fileName);
410  for(unsigned int j=0; j<contour.size(); j++){
411  LibBoard::Point pt((double)(contour.at(j)[0]),
412  (invertYaxis? (double)(-contour.at(j)[1]+contour.at(0)[1]):(double)(contour.at(j)[1])));
413  contourPt.push_back(pt);
414  if(drawPoints){
415  aBoard.fillCircle(pt.x, pt.y, pointSize);
416  }
417  }
418 
419  }
420 
421 
422  aBoard.setPenColor(Color::Red);
423  aBoard.setFillColor(Color::Gray);
424  aBoard.setLineStyle (LibBoard::Shape::SolidStyle );
425  aBoard.setLineWidth (lineWidth);
426  if(!filled){
427  aBoard.drawPolyline(contourPt);
428  }else{
429  aBoard.fillPolyline(contourPt);
430  }
431  if(vm.count("drawPointOfIndex")){
432  int index = vm["drawPointOfIndex"].as<int>();
433  double size = vm["pointSize"].as<double>();
434  aBoard.fillCircle((double)(contourPt.at(index).x), (double)(contourPt.at(index).y), size);
435  }
436 
437 
438 
439  }
440 
441 
442 
443 
444  if(vm.count("outputFile")){
445  std::string outputFileName= vm["outputFile"].as<std::string>();
446  std::string extension = outputFileName.substr(outputFileName.find_last_of(".") + 1);
447 
448  if(extension=="svg"){
449  aBoard.saveSVG(outputFileName.c_str());
450  }
451  #ifdef WITH_CAIRO
452  else
453  if (extension=="eps"){
454  aBoard.saveCairo(outputFileName.c_str(),Board2D::CairoEPS );
455  } else
456  if (extension=="pdf"){
457  aBoard.saveCairo(outputFileName.c_str(),Board2D::CairoPDF );
458  } else
459  if (extension=="png"){
460  aBoard.saveCairo(outputFileName.c_str(),Board2D::CairoPNG );
461  }
462  #endif
463  else if(extension=="eps"){
464  aBoard.saveEPS(outputFileName.c_str());
465  }else if(extension=="fig"){
466  aBoard.saveFIG(outputFileName.c_str(),LibBoard::Board::BoundingBox, 10.0, !vm.count("noXFIGHeader") );
467  }
468  }
469 
470  if (vm.count("outputStreamSVG")){
471  aBoard.saveSVG(std::cout);
472  } else
473  if (vm.count("outputStreamFIG")){
474  aBoard.saveFIG(std::cout, LibBoard::Board::BoundingBox, 10.0, !vm.count("noXFIGHeader"));
475  } else
476  if (vm.count("outputStreamEPS")){
477  aBoard.saveEPS(std::cout);
478  }
479 
480  }
481