URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-03-03 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Create small tools for IGR.
* fabien/TODO: New.
* fabien/igr/dump2pbm.cc: Move this...
* fabien/bin/dump2pbm.cc: ...here.
* fabien/igr/dump2ppm.cc: Move this...
* fabien/bin/dump2ppm.cc: ...here.
* fabien/igr/Makefile: Update.
* fabien/igr/launch.sh: New tool.
* fabien/igr/launch2d.sh: New tool.
* fabien/igr/launch3d.sh: New tool.
* fabien/igr/seg2d.cc: New tool.
* fabien/igr/seg3d.cc: New tool.
* fabien/igr/seg_vol_irm.cc: Rename this...
* fabien/igr/seg_vol_irm.hh: ...into this.
---
TODO | 13 ++
bin/dump2pbm.cc | 35 ++++++
bin/dump2ppm.cc | 35 ++++++
igr/Makefile | 23 ++-
igr/launch.sh | 4
igr/launch2d.sh | 26 ++++
igr/launch3d.sh | 24 ++++
igr/seg2d.cc | 40 ++++++
igr/seg3d.cc | 42 +++++++
igr/seg_vol_irm.hh | 309 +++++++++++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 542 insertions(+), 9 deletions(-)
Index: trunk/milena/sandbox/fabien/igr/dump2ppm.cc (deleted)
===================================================================
Index: trunk/milena/sandbox/fabien/igr/seg_vol_irm.cc (deleted)
===================================================================
Index: trunk/milena/sandbox/fabien/igr/dump2pbm.cc (deleted)
===================================================================
Index: trunk/milena/sandbox/fabien/igr/launch.sh
===================================================================
--- trunk/milena/sandbox/fabien/igr/launch.sh (revision 0)
+++ trunk/milena/sandbox/fabien/igr/launch.sh (revision 3471)
@@ -0,0 +1,4 @@
+#!/bin/zsh
+
+./launch2d.sh
+./launch3d.sh
Property changes on: trunk/milena/sandbox/fabien/igr/launch.sh
___________________________________________________________________
Name: svn:executable
+ *
Index: trunk/milena/sandbox/fabien/igr/seg_vol_irm.hh
===================================================================
--- trunk/milena/sandbox/fabien/igr/seg_vol_irm.hh (revision 0)
+++ trunk/milena/sandbox/fabien/igr/seg_vol_irm.hh (revision 3471)
@@ -0,0 +1,309 @@
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+// Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#include <mln/core/concept/image.hh>
+#include <mln/core/concept/neighborhood.hh>
+#include <mln/core/alias/neighb1d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/neighb3d.hh>
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/int_u16.hh>
+#include <mln/value/rgb8.hh>
+
+#include <mln/io/pgm/all.hh>
+#include <mln/io/pbm/all.hh>
+#include <mln/io/ppm/all.hh>
+#include <mln/io/cloud/all.hh>
+#include <mln/io/dump/all.hh>
+#include <mln/io/dicom/load.hh>
+
+#include <mln/labeling/flat_zones.hh>
+#include <mln/labeling/background.hh>
+#include <mln/literal/colors.hh>
+#include <mln/norm/l1.hh>
+
+#include <mln/geom/bbox.hh>
+
+#include <mln/labeling/blobs.hh>
+#include <mln/labeling/compute.hh>
+#include <mln/labeling/fill_holes.hh>
+#include <mln/labeling/n_max.hh>
+
+#include <mln/level/compare.hh>
+#include <mln/level/compute.hh>
+#include <mln/level/convert.hh>
+#include <mln/level/stretch.hh>
+#include <mln/level/transform.hh>
+
+#include <mln/fun/internal/selector.hh>
+
+#include <mln/fun/v2b/threshold.hh>
+#include <mln/level/transform.hh>
+
+#include <mln/accu/count.hh>
+#include <mln/accu/center.hh>
+#include <mln/accu/max.hh>
+#include <mln/accu/sum.hh>
+#include <mln/accu/mean.hh>
+#include <mln/accu/stat/deviation.hh>
+
+#include <mln/histo/compute.hh>
+
+#include <mln/set/compute.hh>
+#include <mln/value/label_16.hh>
+#include <mln/data/fill.hh>
+#include <mln/pw/all.hh>
+
+#include <mln/morpho/elementary/gradient_internal.hh>
+#include <mln/morpho/closing.hh>
+#include <mln/morpho/dilation.hh>
+#include <mln/morpho/erosion.hh>
+
+#include <mln/win/disk2d.hh>
+#include <mln/win/sphere3d.hh>
+
+#include <mln/math/diff_abs.hh>
+
+#include <mln/convert/from_to.hh>
+
+#include <mln/metal/int.hh>
+
+#include <iostream>
+#include <fstream>
+#include <mln/debug/println.hh>
+
+using namespace mln;
+using value::int_u8;
+using value::int_u12;
+using value::int_u16;
+using value::rgb8;
+using value::label_16;
+
+
+
+template <typename T>
+struct L_to_int_u8
+: mln::fun::internal::selector_<int_u8, T, L_to_int_u8<T> >::ret
+{
+ typedef int_u8 result;
+ int_u8 operator()(const T& t) const;
+};
+
+
+
+template <typename T>
+inline
+int_u8
+L_to_int_u8<T>::operator()(const T& t) const
+{
+ return static_cast<int_u8>(t == 0 ? 0 : 1 + ((unsigned) t - 1) % 255);
+}
+
+
+
+template <typename I>
+I
+close_threshold(const Image<I>& input, metal::int_<2>, int dil, int ero)
+{
+ return morpho::erosion(morpho::dilation(input, win::disk2d(dil)), win::disk2d(ero));
+}
+
+
+
+template <typename I>
+I
+close_threshold(const Image<I>& input, metal::int_<3>, int dil, int ero)
+{
+ return morpho::erosion(morpho::dilation(input, win::sphere3d(dil)),
win::sphere3d(ero));
+}
+
+
+
+template <typename I, typename N>
+unsigned
+find_threshold_value(const Image<I>& input, const Neighborhood<N>&
nbh)
+{
+ int bg_thres = 30;
+ int obj_thres = 15;
+
+ mln_ch_value(I, bool) ima_bg;
+ initialize(ima_bg, input);
+ data::fill(ima_bg, false);
+
+ mln_ch_value(I, bool) ima_obj;
+ initialize(ima_obj, input);
+ data::fill(ima_obj, false);
+
+ unsigned result = 0;
+
+ histo::array<mln_value(I)> arr_histo = histo::compute(input);
+ image1d<unsigned> ima_histo;
+ convert::from_to(arr_histo, ima_histo);
+
+ // We remove the 0 value because it is not part of the image.
+ ima_histo(point1d(0)) = 0;
+
+ for (unsigned int i = 1; i < ima_histo.nelements(); ++i)
+ {
+ ima_histo(point1d(i)) += ima_histo(point1d(i - 1));
+ }
+ accu::max<unsigned> max_accu;
+ unsigned max = level::compute(max_accu, ima_histo);
+ bool low_done = false;
+ bool high_done = false;
+ for (unsigned int i = 0; i < ima_histo.nelements(); ++i)
+ {
+ if (!low_done && ((ima_histo(point1d(i)) * 100) / max) > bg_thres)
+ {
+ data::fill((ima_bg | pw::value(input) < pw::cst(i)).rw(), true);
+ low_done = true;
+ }
+ if (!high_done && ((ima_histo(point1d(i)) * 100) / max) > (100 -
obj_thres))
+ {
+ data::fill((ima_obj | pw::value(input) > pw::cst(i)).rw(), true);
+ high_done = true;
+ }
+ }
+
+ // Debug output images
+ if (I::site::dim == 2)
+ {
+ io::pbm::save(ima_bg, "bg.pbm");
+ io::pbm::save(ima_obj, "obj.pbm");
+ }
+ if (I::site::dim == 3)
+ {
+ io::dump::save(ima_bg, "bg.dump");
+ io::dump::save(ima_obj, "obj.dump");
+ }
+
+ ima_bg = close_threshold(ima_bg, metal::int_<I::site::dim>(), 3, 5); // 5, 7?
+ ima_obj = close_threshold(ima_obj, metal::int_<I::site::dim>(), 3, 5);
+
+ // Debug output images
+ mln_ch_value(I, rgb8) out = level::convert(rgb8(), level::stretch(int_u8(), input));
+ data::fill((out | pw::value(morpho::elementary::gradient_internal(ima_bg, nbh)) ==
true).rw(), literal::red);
+ data::fill((out | pw::value(morpho::elementary::gradient_internal(ima_obj, nbh)) ==
true).rw(), literal::green);
+ if (I::site::dim == 2)
+ {
+ io::pbm::save(ima_bg, "bg_closed.pbm");
+ io::pbm::save(ima_obj, "obj_closed.pbm");
+ io::ppm::save(out, "regions_color.ppm");
+ }
+ if (I::site::dim == 3)
+ {
+ io::dump::save(ima_bg, "bg_closed.dump");
+ io::dump::save(ima_obj, "obj_closed.dump");
+ io::dump::save(out, "regions_color.dump");
+ }
+
+ histo::array<mln_value(I)> bg_histo = histo::compute(input | pw::value(ima_bg) ==
true);
+ histo::array<mln_value(I)> obj_histo = histo::compute(input | pw::value(ima_obj)
== true);
+
+ accu::sum<unsigned> sum_accu;
+ image1d<unsigned> ima_bg_histo;
+ convert::from_to(bg_histo, ima_bg_histo);
+ ima_bg_histo(point1d(0)) = 0;
+ unsigned bg_sum = level::compute(sum_accu, ima_bg_histo);
+ // We remove the 0 value because it is not part of the image.
+ std::ofstream fout_bg("bg_histo_norm.plot");
+ for (unsigned int i = 0; i < ima_bg_histo.nelements(); ++i)
+ {
+ ima_bg_histo(point1d(i)) *= 10000;
+ ima_bg_histo(point1d(i)) /= bg_sum;
+ fout_bg << i << " " << ima_bg_histo(point1d(i)) <<
std::endl;
+ }
+
+ image1d<unsigned> ima_obj_histo;
+ convert::from_to(obj_histo, ima_obj_histo);
+ unsigned obj_sum = level::compute(sum_accu, ima_obj_histo);
+ std::ofstream fout_obj("obj_histo_norm.plot");
+ for (unsigned int i = 0; i < ima_obj_histo.nelements(); ++i)
+ {
+ ima_obj_histo(point1d(i)) *= 10000;
+ ima_obj_histo(point1d(i)) /= obj_sum;
+ fout_obj << i << " " << ima_obj_histo(point1d(i))
<< std::endl;
+ }
+
+ // Search for the index with the min distance between histogrammes.
+ unsigned min = math::diff_abs<unsigned>(ima_bg_histo(point1d(1)),
ima_obj_histo(point1d(1)));
+ for (unsigned int i = 1; i < ima_bg_histo.nelements(); ++i)
+ {
+ if (math::diff_abs<unsigned>(ima_bg_histo(point1d(i)),
ima_obj_histo(point1d(i))) < min)
+ {
+ min = math::diff_abs<unsigned>(ima_bg_histo(point1d(i)),
ima_obj_histo(point1d(i)));
+ result = i;
+ }
+ }
+
+ return result;
+}
+
+
+
+template <typename I, typename N>
+unsigned
+find_threshold_mean(const Image<I>& input, const Neighborhood<N>&
nbh)
+{
+ unsigned result = 0;
+
+ accu::mean<unsigned> mean_accu;
+ unsigned mean = level::compute(mean_accu, (input | (pw::value(input) != 0)));
+
+ accu::stat::deviation<unsigned, unsigned, float> dev_accu(mean);
+ float deviation = level::compute(dev_accu, (input | pw::value(input) != 0));
+
+ std::cout << "mean = " << mean << std::endl <<
"deviation = " << deviation << std::endl;
+ return floor(deviation);
+}
+
+
+
+template <typename I, typename N, typename L>
+mln_ch_value(I, bool)
+igr_seg(const Image<I>& input_, const Neighborhood<N>& nbh_, L&
nlabels)
+{
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ // Threshold.
+
+ mln_ch_value(I, bool) ima_thres;
+ initialize(ima_thres, input);
+ data::fill(ima_thres, false);
+ //unsigned threshold_value = find_threshold_value(input, nbh);
+ unsigned threshold_value = find_threshold_mean(input, nbh);
+ data::fill((ima_thres | pw::value(input) < pw::cst(threshold_value)).rw(), true);
+
+ return ima_thres;
+}
Index: trunk/milena/sandbox/fabien/igr/seg2d.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/seg2d.cc (revision 0)
+++ trunk/milena/sandbox/fabien/igr/seg2d.cc (revision 3471)
@@ -0,0 +1,40 @@
+#include <mln/core/concept/image.hh>
+#include <mln/core/concept/neighborhood.hh>
+#include <mln/core/alias/neighb2d.hh>
+
+#include <mln/core/image/image2d.hh>
+
+#include <mln/value/int_u12.hh>
+
+#include <mln/io/pbm/all.hh>
+#include <mln/io/dicom/load.hh>
+
+#include <mln/value/label_16.hh>
+
+#include "seg_vol_irm.hh"
+
+using namespace mln;
+using value::int_u12;
+using value::label_16;
+
+
+
+int usage()
+{
+ std::cout << "Usage: ./seg2d image.dcm" << std::endl;
+
+ return 1;
+}
+
+int main(int argc, char* argv[])
+{
+ if (argc < 2)
+ return usage();
+
+ label_16 nlabels;
+ image2d<int_u12> ima;
+ io::dicom::load(ima, argv[1]);
+ io::pbm::save(igr_seg(ima, c4(), nlabels), "result.pbm");
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/igr/launch2d.sh
===================================================================
--- trunk/milena/sandbox/fabien/igr/launch2d.sh (revision 0)
+++ trunk/milena/sandbox/fabien/igr/launch2d.sh (revision 3471)
@@ -0,0 +1,26 @@
+#!/bin/zsh
+
+process_file ()
+{
+ ./seg2d $1
+ if [ -f result.pbm ]; then
+ mv result.pbm results/${2}_06_result.pbm
+ fi
+
+ if [ -f bg.pbm ]; then
+ mv bg.pbm results/${2}_01_bg.pbm
+ mv obj.pbm results/${2}_03_obj.pbm
+
+ mv bg_closed.pbm results/${2}_02_bg_closed.pbm
+ mv obj_closed.pbm results/${2}_04_obj_closed.pbm
+
+ mv regions_color.ppm results/${2}_05_regions_color.ppm
+
+ mv bg_histo_norm.plot results/${2}_bg.plot
+ mv obj_histo_norm.plot results/${2}_obj.plot
+ fi
+}
+
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0049.dcm" "49"
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0055.dcm" "55"
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0058.dcm" "58"
Property changes on: trunk/milena/sandbox/fabien/igr/launch2d.sh
___________________________________________________________________
Name: svn:executable
+ *
Index: trunk/milena/sandbox/fabien/igr/seg3d.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/seg3d.cc (revision 0)
+++ trunk/milena/sandbox/fabien/igr/seg3d.cc (revision 3471)
@@ -0,0 +1,42 @@
+#include <mln/core/concept/image.hh>
+#include <mln/core/concept/neighborhood.hh>
+#include <mln/core/alias/neighb3d.hh>
+
+#include <mln/core/image/image3d.hh>
+
+#include <mln/value/int_u12.hh>
+
+#include <mln/io/dump/all.hh>
+#include <mln/io/dicom/load.hh>
+
+#include <mln/value/label_16.hh>
+
+#include "seg_vol_irm.hh"
+
+using namespace mln;
+using value::int_u12;
+using value::label_16;
+
+template <typename I, typename N, typename L>
+mln_ch_value(I, bool)
+igr_seg(const Image<I>& input_, const mln::Neighborhood<N>& nbh_,
L& nlabels);
+
+int usage()
+{
+ std::cout << "Usage: ./seg3d image.dcm" << std::endl;
+
+ return 1;
+}
+
+int main(int argc, char* argv[])
+{
+ if (argc < 2)
+ return usage();
+
+ label_16 nlabels;
+ image3d<int_u12> ima;
+ io::dicom::load(ima, argv[1]);
+ io::dump::save(igr_seg(ima, c6(), nlabels), "result.dump");
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/igr/launch3d.sh
===================================================================
--- trunk/milena/sandbox/fabien/igr/launch3d.sh (revision 0)
+++ trunk/milena/sandbox/fabien/igr/launch3d.sh (revision 3471)
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+process_file ()
+{
+ ./seg3d $1
+ ../bin/dump2pbm result.dump results/${2}_06_result.pbm
+
+ ../bin/dump2pbm bg.dump results/${2}_01_bg.pbm
+ ../bin/dump2pbm obj.dump results/${2}_03_obj.pbm
+
+ ../bin/dump2pbm bg_closed.dump results/${2}_02_bg_closed.pbm
+ ../bin/dump2pbm obj_closed.dump results/${2}_04_obj_closed.pbm
+
+#../bin/dump2ppm regions_color.dump results/${2}_05_colors.ppm
+
+ rm *.dump
+
+ mv bg_histo_norm.plot results/${2}_bg.plot
+ mv obj_histo_norm.plot results/${2}_obj.plot
+}
+
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0052.dcm" "52"
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0061.dcm" "61"
+process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0064.dcm" "64"
Property changes on: trunk/milena/sandbox/fabien/igr/launch3d.sh
___________________________________________________________________
Name: svn:executable
+ *
Index: trunk/milena/sandbox/fabien/igr/Makefile
===================================================================
--- trunk/milena/sandbox/fabien/igr/Makefile (revision 3470)
+++ trunk/milena/sandbox/fabien/igr/Makefile (revision 3471)
@@ -1,15 +1,20 @@
-all: seg_vol_irm.cc
- g++ -I../../../ \
- -I/Users/HiSoKa/Downloads/gdcm-2.0.10/Source/Common/ \
+DICOM_INC = -I/Users/HiSoKa/Downloads/gdcm-2.0.10/Source/Common/ \
-I/Users/HiSoKa/Downloads/gdcmbin/Source/Common/ \
-I/Users/HiSoKa/Downloads/gdcm-2.0.10/Source/DataDictionary/ \
-I/Users/HiSoKa/Downloads/gdcm-2.0.10/Source/MediaStorageAndFileFormat/ \
- -I/Users/HiSoKa/Downloads/gdcm-2.0.10/Source/DataStructureAndEncodingDefinition/ \
- -L/Users/HiSoKa/Downloads/gdcmbin/bin \
+ -I/Users/HiSoKa/Downloads/gdcm-2.0.10/Source/DataStructureAndEncodingDefinition/
+DICOM_LIB = -L/Users/HiSoKa/Downloads/gdcmbin/bin \
-lgdcmCommon -lgdcmDICT -lgdcmDSED -lgdcmIOD -lgdcmMSFF -lgdcmexpat -lgdcmjpeg12
-lgdcmjpeg16 -lgdcmjpeg8 -lgdcmopenjpeg -lgdcmuuid -lgdcmzlib \
- -framework CoreFoundation \
- -DNDEBUG -O1 \
- seg_vol_irm.cc -o seg_vol_irm
+ -framework CoreFoundation
+CXXFLAGS = -DNDEBUG -O1
+
+all: 2d 3d
+
+2d: seg_vol_irm.hh seg2d.cc
+ g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} seg2d.cc -o seg2d
+
+3d: seg_vol_irm.hh seg3d.cc
+ g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} seg3d.cc -o seg3d
clean:
- rm -rf *.dump *.p?m
+ rm -rf *.dump *.p?m *.plot *.log *.csv
Index: trunk/milena/sandbox/fabien/TODO
===================================================================
--- trunk/milena/sandbox/fabien/TODO (revision 0)
+++ trunk/milena/sandbox/fabien/TODO (revision 3471)
@@ -0,0 +1,13 @@
+ ___________
+< TODO list >
+ -----------
+ \ ^__^
+ \ (oo)\_______
+ (__)\ )\/\
+ ||----w |
+ || ||
+
+[X] Create binaries
+[X] Create scripts shell
+[ ] Check standard deviation
+
Index: trunk/milena/sandbox/fabien/bin/dump2ppm.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dump2ppm.cc (revision 0)
+++ trunk/milena/sandbox/fabien/bin/dump2ppm.cc (revision 3471)
@@ -0,0 +1,35 @@
+
+#include <mln/core/image/image2d.hh>
+#include <mln/make/image3d.hh>
+#include <mln/debug/slices_2d.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/io/dump/load.hh>
+#include <mln/io/ppm/save.hh>
+
+#include <mln/literal/colors.hh>
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.dump
output.ppm" << std::endl;
+ abort();
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::rgb8;
+
+ if (argc != 3)
+ usage(argv);
+
+ image3d<rgb8> vol;
+ io::dump::load(vol, argv[1]);
+
+ rgb8 bg = literal::black;
+ image2d<rgb8> ima = debug::slices_2d(vol, 1.f, bg);
+ io::ppm::save(ima, argv[2]);
+}
Index: trunk/milena/sandbox/fabien/bin/dump2pbm.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dump2pbm.cc (revision 0)
+++ trunk/milena/sandbox/fabien/bin/dump2pbm.cc (revision 3471)
@@ -0,0 +1,35 @@
+
+#include <mln/core/image/image2d.hh>
+#include <mln/make/image3d.hh>
+#include <mln/debug/slices_2d.hh>
+
+#include <mln/value/int_u16.hh>
+#include <mln/io/dump/load.hh>
+#include <mln/io/pbm/save.hh>
+
+#include <mln/literal/colors.hh>
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.dump
output.pbm" << std::endl;
+ abort();
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u16;
+
+ if (argc != 3)
+ usage(argv);
+
+ image3d<bool> vol;
+ io::dump::load(vol, argv[1]);
+
+ int_u16 bg = 0;
+ image2d<bool> ima = debug::slices_2d(vol, 1.f, bg);
+ io::pbm::save(ima, argv[2]);
+}