33 #include <boost/program_options/options_description.hpp> 34 #include <boost/program_options/parsers.hpp> 35 #include <boost/program_options/variables_map.hpp> 41 #include "DGtal/base/Common.h" 42 #include "DGtal/helpers/StdDefs.h" 44 #include "DGtal/shapes/ShapeFactory.h" 45 #include "DGtal/shapes/Shapes.h" 46 #include "DGtal/topology/helpers/Surfaces.h" 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" 56 #include "DGtal/io/readers/GenericReader.h" 60 #include "DGtal/geometry/curves/FreemanChain.h" 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" 71 #include "DGtal/io/boards/Board2D.h" 72 #include "DGtal/io/boards/CDrawableWithBoard2D.h" 74 using namespace DGtal;
157 namespace po = boost::program_options;
160 int main(
int argc,
char** argv )
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)")
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)")
186 (
"scale", po::value<double>(),
"scale <value> 1: normal; >1 : larger ; <1 lower resolutions )");
191 po::variables_map vm;
193 po::store(po::parse_command_line(argc, argv, general_opt), vm);
194 }
catch(
const std::exception& ex){
196 trace.info()<<
"Error checking program options: "<< ex.what()<< std::endl;
200 if(!parseOK||vm.count(
"help")||argc<=1 || (!(vm.count(
"input")) && !(vm.count(
"SDP")) && !(vm.count(
"SFP"))&&
201 !(vm.count(
"backgroundImage")) ) )
203 trace.info()<<
"Display discrete contours. " <<std::endl <<
"Basic usage: "<<std::endl
204 <<
"\t displayContours [options] --input <fileName> "<<std::endl
205 << general_opt <<
"\n";
211 double lineWidth= vm[
"lineWidth"].as<
double>();
212 bool filled = vm.count(
"fillContour");
214 if(vm.count(
"scale")){
215 scale = vm[
"scale"].as<
double>();
219 aBoard.setUnit (0.05*scale, LibBoard::Board::UCentimeter);
226 if(vm.count(
"alphaBG")){
227 alpha = vm[
"alphaBG"].as<
double>();
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);
239 aBoard.drawImage(imageName, 0-0.5,height-0.5, width, height, -1, alpha );
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);
258 aBoard.fillCircle((
double)(vectFc.at(i).getPoint(index)[0]), (
double)(vectFc.at(i).getPoint(index)[1]), size);
261 if(vm.count(
"withProcessing")){
262 std::string processingName = vm[
"withProcessing"].as<std::string>();
264 std::vector<Z2i::Point> vPts(vectFc.at(i).size()+1);
265 copy ( vectFc.at(i).begin(), vectFc.at(i).end(), vPts.begin() );
267 if ( vPts.at(0) == vPts.at(vPts.size()-1) ) {
270 }
else isClosed =
false;
272 if (processingName ==
"DSS") {
274 typedef ArithmeticalDSSComputer<std::vector<Z2i::Point>::iterator,int,4> DSS4;
275 typedef GreedySegmentation<DSS4> Decomposition4;
278 Decomposition4 theDecomposition( vPts.begin(),vPts.end(),computer );
281 std::string className;
282 for ( Decomposition4::SegmentComputerIterator it = theDecomposition.begin();
283 it != theDecomposition.end(); ++it )
285 DSS4::Primitive segment(it->primitive());
287 aBoard << SetMode( segment.className(),
"BoundingBox" );
288 className = segment.className() +
"/BoundingBox";
289 aBoard << CustomStyle( className,
290 new CustomPenColor( DGtal::Color::Gray ) );
294 }
else if (processingName ==
"MS") {
296 typedef ArithmeticalDSSComputer<std::vector<Z2i::Point>::iterator,int,4> DSS4;
297 typedef SaturatedSegmentation<DSS4> Decomposition4;
301 Decomposition4 theDecomposition( vPts.begin(),vPts.end(),computer );
304 std::string className;
305 for ( Decomposition4::SegmentComputerIterator it = theDecomposition.begin();
306 it != theDecomposition.end(); ++it )
308 DSS4::Primitive segment(it->primitive());
310 aBoard << SetMode( segment.className(),
"BoundingBox" );
311 className = segment.className() +
"/BoundingBox";
312 aBoard << CustomStyle( className,
313 new CustomPenColor( DGtal::Color::Gray ) );
317 }
else if (processingName ==
"FP") {
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 ) );
326 }
else if (processingName ==
"MLP") {
328 typedef FP<std::vector<Z2i::Point>::iterator,int,4> FP;
329 FP theFP( vPts.begin(),vPts.end() );
331 std::vector<FP::RealPoint> v( theFP.size() );
332 theFP.copyMLP( v.begin() );
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]));
342 FP::RealPoint p = (*v.begin());
343 polyline.push_back(LibBoard::Point(p[0],p[1]));
345 aBoard.setPenColor(DGtal::Color::Black);
346 aBoard.drawPolyline(polyline);
348 }
else if (processingName ==
"MDCA") {
349 typedef KhalimskySpaceND<2,int> KSpace;
350 typedef GridCurve<KSpace> Curve;
352 curve.initFromPointsVector( vPts );
353 typedef Curve::IncidentPointsRange Range;
354 Range r = curve.getIncidentPointsRange();
355 typedef Range::ConstCirculator ConstCirculator;
356 typedef StabbingCircleComputer<ConstCirculator> SegmentComputer;
358 typedef SaturatedSegmentation<SegmentComputer> Segmentation;
360 Segmentation theSegmentation( r.c(), r.c(), SegmentComputer() );
361 theSegmentation.setMode(
"Last");
363 Segmentation::SegmentComputerIterator it = theSegmentation.begin();
364 Segmentation::SegmentComputerIterator itEnd = theSegmentation.end();
366 otherBoard.setPenColor(DGtal::Color::Black);
368 for ( ; it != itEnd; ++it ) {
369 aBoard << SetMode(SegmentComputer().className(),
"") << (*it);
370 otherBoard << SetMode(SegmentComputer().className(),
"") << (*it);
372 otherBoard.saveSVG(
"mdca.svg", Board2D::BoundingBox, 5000 );
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;
389 pointSize = vm[
"drawContourPoint"].as<
double>();
391 std::vector<LibBoard::Point> contourPt;
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);
401 aBoard.fillCircle(pt.x, pt.y, pointSize);
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);
415 aBoard.fillCircle(pt.x, pt.y, pointSize);
422 aBoard.setPenColor(Color::Red);
423 aBoard.setFillColor(Color::Gray);
424 aBoard.setLineStyle (LibBoard::Shape::SolidStyle );
425 aBoard.setLineWidth (lineWidth);
427 aBoard.drawPolyline(contourPt);
429 aBoard.fillPolyline(contourPt);
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);
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);
448 if(extension==
"svg"){
449 aBoard.saveSVG(outputFileName.c_str());
453 if (extension==
"eps"){
454 aBoard.saveCairo(outputFileName.c_str(),Board2D::CairoEPS );
456 if (extension==
"pdf"){
457 aBoard.saveCairo(outputFileName.c_str(),Board2D::CairoPDF );
459 if (extension==
"png"){
460 aBoard.saveCairo(outputFileName.c_str(),Board2D::CairoPNG );
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") );
470 if (vm.count(
"outputStreamSVG")){
471 aBoard.saveSVG(std::cout);
473 if (vm.count(
"outputStreamFIG")){
474 aBoard.saveFIG(std::cout, LibBoard::Board::BoundingBox, 10.0, !vm.count(
"noXFIGHeader"));
476 if (vm.count(
"outputStreamEPS")){
477 aBoard.saveEPS(std::cout);