URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-03-10 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Implement 3D watershed and various tools.
* fabien/bin/dicom2pgm.cc: New tool.
* fabien/bin/dump2pgm.cc: New tool.
* fabien/bin/dump2pgm8b.cc: New tool.
* fabien/bin/dump_mask.cc: New tool.
* fabien/bin/filetype.hh: New.
* fabien/bin/pnms2dump.cc: New tool.
* fabien/igr/Makefile: Update.
* fabien/igr/check2d_wsd.sh: Shell script for testing.
* fabien/igr/check3d_wsd.sh: Shell script for testing.
* fabien/igr/watershed.cc: Rename this...
* fabien/igr/watershed.hh: ...into this.
* fabien/igr/watershed2d.cc: Implement 2D watershed.
* fabien/igr/watershed3d.cc: Implement 3D watershed.
---
TODO | 7 -
bin/dicom2pgm.cc | 34 +++++
bin/dump2pgm.cc | 37 +++++
bin/dump2pgm8b.cc | 38 ++++++
bin/dump_mask.cc | 86 +++++++++++++
bin/filetype.hh | 54 ++++++++
bin/pnms2dump.cc | 97 +++++++++++++++
igr/Makefile | 9 -
igr/check2d_wsd.sh | 32 +++++
igr/check3d_wsd.sh | 34 +++++
igr/watershed.hh | 331 ++++++++++++++++++++++++++++++++++++++++++++++++++++
igr/watershed2d.cc | 331 ++++++++++++++++++++++++++++++++++++++++++++++++++++
igr/watershed3d.cc | 334 +++++++++++++++++++++++++++++++++++++++++++++++++++++
13 files changed, 1419 insertions(+), 5 deletions(-)
Index: trunk/milena/sandbox/fabien/igr/watershed.cc (deleted)
===================================================================
Index: trunk/milena/sandbox/fabien/igr/watershed2d.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/watershed2d.cc (revision 0)
+++ trunk/milena/sandbox/fabien/igr/watershed2d.cc (revision 3503)
@@ -0,0 +1,331 @@
+#include <iostream>
+#include <mln/core/image/image2d.hh>
+
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/window2d.hh>
+#include <mln/core/image/image_if.hh>
+
+#include <mln/io/ppm/save.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/dicom/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/dump/save.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/label_16.hh>
+
+#include <mln/level/transform.hh>
+#include <mln/level/stretch.hh>
+
+#include <mln/labeling/mean_values.hh>
+
+#include <mln/convert/to_fun.hh>
+
+#include <mln/make/graph.hh>
+
+#include <mln/morpho/gradient.hh>
+#include <mln/morpho/closing/area.hh>
+#include <mln/morpho/meyer_wst.hh>
+
+#include <mln/fun/l2l/wrap.hh>
+
+#include <mln/core/var.hh>
+#include <mln/morpho/elementary/dilation.hh>
+
+#include <mln/core/routine/extend.hh>
+
+#include <mln/util/graph.hh>
+
+#include <mln/essential/2d.hh>
+#include <mln/core/alias/vec3d.hh>
+#include <mln/debug/draw_graph.hh>
+#include <mln/util/graph.hh>
+#include <mln/accu/center.hh>
+#include <mln/io/dump/all.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb16.hh>
+#include <mln/accu/compute.hh>
+#include <mln/core/alias/dpoint2d.hh>
+#include <mln/draw/box.hh>
+#include <mln/level/stretch.hh>
+#include <mln/fun/v2v/id.hh>
+#include <mln/fun/l2l/wrap.hh>
+#include <mln/core/image/line_graph_elt_neighborhood.hh>
+#include <mln/morpho/elementary/dilation.hh>
+#include <mln/labeling/mean_values.hh>
+#include <mln/extension/adjust_fill.hh>
+#include <mln/extract/all.hh>
+#include <mln/make/region_adjacency_graph.hh>
+
+
+
+// Given a color image and a wshed image, computes the component graph.
+// Vertex values are computed thanks to a RGB image.
+
+namespace mln
+{
+
+ template <typename V>
+ value::int_u8 dist(const V& c1, const V& c2)
+ {
+ unsigned d = math::diff_abs(c1.red(), c2.red());
+ unsigned d_;
+ d_ = math::diff_abs(c1.green(), c2.green());
+
+ if (d_ > d)
+ d = d_;
+
+ d_ = math::diff_abs(c1.blue(), c2.blue());
+
+ if (d_ > d)
+ d = d_;
+ return d;
+ }
+
+
+ // ima_v, image on graph vertices; value = mean color per vertex (watershed basin)
+ template <typename I>
+ inline
+ pw::image<fun::i2v::array<value::int_u8>,
+ p_edges<util::graph, fun::i2v::array<mln_site(I)> > >
+ make_edge_graph_image(const I& ima_v, const util::graph& g)
+ {
+ // edge sites.
+ typedef fun::i2v::array<mln_site(I)> edge_site_t;
+ edge_site_t edge_site(g.e_nmax(), literal::origin);
+ typedef p_edges<util::graph, edge_site_t > pe_t;
+ pe_t pe(g, edge_site);
+
+ // edge values
+ typedef fun::i2v::array<value::int_u8> edge_values_t;
+ edge_values_t edge_values(g.e_nmax());
+
+ // image on graph edges
+ typedef pw::image<edge_values_t, pe_t> ima_e_t;
+ ima_e_t ima_e = (edge_values | pe);
+
+ mln_piter(ima_e_t) e(ima_e.domain());
+ for_all(e) // in ima_e
+ ima_e(e) = math::diff_abs(ima_v.function()(e.element().v1()),
ima_v.function()(e.element().v2()));
+
+ return ima_e;
+ }
+
+
+ template <typename I, typename J>
+ inline
+ util::array<mln_value(I)>
+ mean_color_values(const I& input, const J& w, mln_value(J) nbasins)
+ {
+ // Cf. sandbox/theo/color/segment_rgb_pixels.cc
+
+ util::array<float> m_3f = labeling::compute(accu::mean<mln_value(I)>(),
+ input, // input color image
+ w, // watershed labeling
+ nbasins);
+ m_3f[0] = literal::zero;
+
+ util::array<mln_value(I)> m;
+ convert::from_to(m_3f, m);
+ m[0] = 150u;
+
+ /*io::ppm::save(level::transform(w,
+ convert::to< fun::i2v::array<mln_value(I)> >(m)),
+ "wst_rag_wshd_color.ppm");*/
+
+ return m;
+ }
+
+
+ template <typename I, typename J>
+ pw::image<fun::i2v::array<mln_value(I)>, p_vertices<util::graph,
fun::i2v::array<mln_site(I)> > >
+ make_vertex_graph_image(const util::graph& g, const I&input, const J& w,
const mln_value(J)& nbasins)
+ {
+ typedef util::array<mln_site(I)> vertex_sites_t;
+ vertex_sites_t site_values;
+ convert::from_to(labeling::compute(accu::center<mln_site(I)>(), w, nbasins),
+ site_values);
+
+ typedef fun::i2v::array<mln_site(J)> f_sites_t;
+ f_sites_t sites;
+ convert::from_to(site_values, sites);
+
+ // p_vertices
+ typedef p_vertices<util::graph, f_sites_t> S;
+ S pv(g, sites);
+
+
+ typedef fun::i2v::array<mln_value(I)> vertex_values_t;
+ vertex_values_t vertex_values;
+ convert::from_to(mean_color_values(input, w, nbasins), vertex_values);
+
+ mln_VAR(ima_v, (vertex_values | pv));
+
+ return ima_v;
+ }
+
+
+ template <typename I, typename V>
+ struct edge_to_color : Function_p2v< edge_to_color<I,V> >
+ {
+ typedef V result;
+
+ edge_to_color(const I& ima)
+ : ima_(ima)
+ {
+ }
+
+ V
+ operator()(const unsigned& e) const
+ {
+ return convert::to<V>(ima_.function()(e));
+ }
+
+ const I& ima_;
+ };
+
+ template <typename V>
+ inline
+ unsigned
+ find_root(util::array<V>& parent, const unsigned& x)
+ {
+ if (parent[x] == x)
+ return x;
+ else
+ return parent[x] = find_root(parent, parent[x]);
+ }
+
+
+ template <typename I, typename V, typename E>
+ inline
+ image2d<mln_value(I)>
+ make_debug_graph_image(const I& input,
+ const V& ima_v, const E& ima_e,
+ unsigned box_size, const value::int_u12& bg)
+ {
+ image2d<mln_value(I)> ima;
+ initialize(ima, input);
+
+ data::fill(ima, bg);
+ debug::draw_graph(ima, ima_v.domain(),
+ pw::cst(150u),
+ edge_to_color<E, mln_value(I)>(ima_e));
+
+ dpoint2d tl(-box_size,-box_size);
+ dpoint2d br(box_size,box_size);
+ mln_piter(V) p(ima_v.domain());
+ for_all(p)
+ {
+ box2d b(p + tl, p + br);
+ b.crop_wrt(ima.domain());
+ data::fill((ima | b).rw(), convert::to<mln_value(I)>(ima_v(p)));
+ }
+
+ return ima;
+ }
+
+}
+
+
+///////////////////
+// //
+// Main Function //
+// //
+///////////////////
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::int_u12;
+ using value::rgb8;
+ using value::label_16;
+
+ if (argc < 4)
+ {
+ std::cout << "Usage: " << argv[0] << "
<ima.dcm> <closure_lambda> <box_size> <dist_max>"
+ << std::endl;
+ return 1;
+ }
+
+ unsigned closure_lambda = atoi(argv[2]);
+ unsigned box_size = atoi(argv[3]);
+ unsigned dist_max = atoi(argv[4]);
+
+ image2d<int_u12> dcm;
+ io::dicom::load(dcm, argv[1]);
+
+ io::pgm::save(level::stretch(int_u8(), dcm), "wsd_01_src.pgm");
+
+ image2d<int_u12> grad = morpho::gradient(dcm, win_c4p());
+ image2d<int_u12> clo = morpho::closing::area(grad, c4(), closure_lambda);
+
+ label_16 nbasins;
+ image2d<label_16> wshed = morpho::meyer_wst(clo, c4(), nbasins);
+
+ io::pgm::save(level::stretch(int_u8(), clo), "wsd_02.pgm");
+ io::pgm::save(level::transform(wshed, fun::l2l::wrap<int_u8>()),
"wsd_03.pgm");
+
+ mln_VAR(vol2_, morpho::elementary::dilation(extend(wshed | (pw::value(wshed) == 0u),
wshed), c8()));
+
+ data::fill((wshed | (pw::value(wshed) == 0u)).rw(), vol2_);
+
+ io::pgm::save(level::transform(wshed, fun::l2l::wrap<int_u8>()),
"wsd_04.pgm");
+
+ /// Build graph
+ util::graph g = make::graph(wshed, c4(), nbasins);
+ // Build graph images and compute distance values with a RGB image.
+ mln_VAR(ima_v, make_vertex_graph_image(g, dcm, wshed, nbasins));
+ mln_VAR(ima_e, make_edge_graph_image(ima_v, g));
+
+ /// Try to merge vertices.
+ mln_piter_(ima_e_t) e(ima_e.domain());
+ util::array<label_16> parent(g.v_nmax());
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ parent[i] = i;
+
+ for_all(e)
+ {
+ unsigned v1 = e.element().v1();
+ unsigned v2 = e.element().v2();
+ if (ima_e(e) <= dist_max && find_root(parent, v1) != find_root(parent,
v2))
+ parent[find_root(parent, v1)] = find_root(parent, v2);
+ }
+
+ fun::i2v::array<label_16> f(parent.nelements());
+ std::vector<unsigned> new_label(parent.nelements(), 0);
+ unsigned nbasins2 = 0;
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ {
+ unsigned p = find_root(parent, i);
+ mln_assertion(parent[p] == find_root(parent, i));
+ if (new_label[p] == 0)
+ new_label[p] = nbasins2++;
+ f(i) = new_label[p];
+ }
+ mln_invariant(f(0) == 0u);
+ --nbasins2; // nbasins2 does not count the basin with label 0.
+ image2d<label_16> wsd2 = level::transform(wshed, f);
+
+ io::pgm::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()),
"wsd_05.pgm");
+
+ /// Reconstruct a graph from the simplified image.
+ util::graph g2 = make::graph(wsd2, c4(), nbasins2);
+
+ // Compute distance values with a RGB image.
+ mln_VAR(ima_v2, make_vertex_graph_image(g2, dcm, wsd2, nbasins2));
+ mln_VAR(ima_e2, make_edge_graph_image(ima_v2, g2));
+
+ mln_VAR(wsd2_, morpho::elementary::dilation(extend(wsd2 | (pw::value(wsd2) == 0u),
wsd2), c8()));
+
+ data::fill((wsd2 | (pw::value(wsd2) == 0u)).rw(), wsd2_);
+
+ io::pgm::save(level::transform(labeling::mean_values(dcm, wsd2, nbasins2),
fun::l2l::wrap<int_u8>()), "wsd_06_mean_colors.pgm");
+ io::pgm::save(level::stretch(int_u8(), make_debug_graph_image(dcm, ima_v2, ima_e2,
box_size, 4095)), "wsd_07_graph_image2_white.pgm");
+ io::pgm::save(level::stretch(int_u8(), make_debug_graph_image(dcm, ima_v2, ima_e2,
box_size, 0)), "wsd_08_graph_image2_black.pgm");
+ io::pgm::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()),
"wsd_99_result.pgm");
+}
Index: trunk/milena/sandbox/fabien/igr/watershed3d.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/watershed3d.cc (revision 0)
+++ trunk/milena/sandbox/fabien/igr/watershed3d.cc (revision 3503)
@@ -0,0 +1,334 @@
+#include <iostream>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/window2d.hh>
+#include <mln/core/alias/neighb3d.hh>
+#include <mln/core/alias/window3d.hh>
+#include <mln/core/image/image_if.hh>
+
+#include <mln/io/ppm/save.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/dicom/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/dump/save.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/label_16.hh>
+
+#include <mln/level/transform.hh>
+#include <mln/level/stretch.hh>
+
+#include <mln/labeling/mean_values.hh>
+
+#include <mln/convert/to_fun.hh>
+
+#include <mln/make/graph.hh>
+
+#include <mln/morpho/gradient.hh>
+#include <mln/morpho/closing/area.hh>
+#include <mln/morpho/meyer_wst.hh>
+
+#include <mln/fun/l2l/wrap.hh>
+
+#include <mln/core/var.hh>
+#include <mln/morpho/elementary/dilation.hh>
+
+#include <mln/core/routine/extend.hh>
+
+#include <mln/util/graph.hh>
+
+#include <mln/essential/2d.hh>
+#include <mln/core/alias/vec3d.hh>
+#include <mln/debug/draw_graph.hh>
+#include <mln/util/graph.hh>
+#include <mln/accu/center.hh>
+#include <mln/io/dump/all.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb16.hh>
+#include <mln/accu/compute.hh>
+#include <mln/core/alias/dpoint2d.hh>
+#include <mln/draw/box.hh>
+#include <mln/level/stretch.hh>
+#include <mln/fun/v2v/id.hh>
+#include <mln/fun/l2l/wrap.hh>
+#include <mln/core/image/line_graph_elt_neighborhood.hh>
+#include <mln/morpho/elementary/dilation.hh>
+#include <mln/labeling/mean_values.hh>
+#include <mln/extension/adjust_fill.hh>
+#include <mln/extract/all.hh>
+#include <mln/make/region_adjacency_graph.hh>
+
+
+
+// Given a color image and a wshed image, computes the component graph.
+// Vertex values are computed thanks to a RGB image.
+
+namespace mln
+{
+
+ template <typename V>
+ value::int_u8 dist(const V& c1, const V& c2)
+ {
+ unsigned d = math::diff_abs(c1.red(), c2.red());
+ unsigned d_;
+ d_ = math::diff_abs(c1.green(), c2.green());
+
+ if (d_ > d)
+ d = d_;
+
+ d_ = math::diff_abs(c1.blue(), c2.blue());
+
+ if (d_ > d)
+ d = d_;
+ return d;
+ }
+
+
+ // ima_v, image on graph vertices; value = mean color per vertex (watershed basin)
+ template <typename I>
+ inline
+ pw::image<fun::i2v::array<value::int_u8>,
+ p_edges<util::graph, fun::i2v::array<mln_site(I)> > >
+ make_edge_graph_image(const I& ima_v, const util::graph& g)
+ {
+ // edge sites.
+ typedef fun::i2v::array<mln_site(I)> edge_site_t;
+ edge_site_t edge_site(g.e_nmax(), literal::origin);
+ typedef p_edges<util::graph, edge_site_t > pe_t;
+ pe_t pe(g, edge_site);
+
+ // edge values
+ typedef fun::i2v::array<value::int_u8> edge_values_t;
+ edge_values_t edge_values(g.e_nmax());
+
+ // image on graph edges
+ typedef pw::image<edge_values_t, pe_t> ima_e_t;
+ ima_e_t ima_e = (edge_values | pe);
+
+ mln_piter(ima_e_t) e(ima_e.domain());
+ for_all(e) // in ima_e
+ ima_e(e) = math::diff_abs(ima_v.function()(e.element().v1()),
ima_v.function()(e.element().v2()));
+
+ return ima_e;
+ }
+
+
+ template <typename I, typename J>
+ inline
+ util::array<mln_value(I)>
+ mean_color_values(const I& input, const J& w, mln_value(J) nbasins)
+ {
+ // Cf. sandbox/theo/color/segment_rgb_pixels.cc
+
+ util::array<float> m_3f = labeling::compute(accu::mean<mln_value(I)>(),
+ input, // input color image
+ w, // watershed labeling
+ nbasins);
+ m_3f[0] = literal::zero;
+
+ util::array<mln_value(I)> m;
+ convert::from_to(m_3f, m);
+ m[0] = 150u;
+
+ /*io::ppm::save(level::transform(w,
+ convert::to< fun::i2v::array<mln_value(I)> >(m)),
+ "wst_rag_wshd_color.ppm");*/
+
+ return m;
+ }
+
+
+ template <typename I, typename J>
+ pw::image<fun::i2v::array<mln_value(I)>, p_vertices<util::graph,
fun::i2v::array<mln_site(I)> > >
+ make_vertex_graph_image(const util::graph& g, const I&input, const J& w,
const mln_value(J)& nbasins)
+ {
+ typedef util::array<mln_site(I)> vertex_sites_t;
+ vertex_sites_t site_values;
+ convert::from_to(labeling::compute(accu::center<mln_site(I)>(), w, nbasins),
+ site_values);
+
+ typedef fun::i2v::array<mln_site(J)> f_sites_t;
+ f_sites_t sites;
+ convert::from_to(site_values, sites);
+
+ // p_vertices
+ typedef p_vertices<util::graph, f_sites_t> S;
+ S pv(g, sites);
+
+
+ typedef fun::i2v::array<mln_value(I)> vertex_values_t;
+ vertex_values_t vertex_values;
+ convert::from_to(mean_color_values(input, w, nbasins), vertex_values);
+
+ mln_VAR(ima_v, (vertex_values | pv));
+
+ return ima_v;
+ }
+
+
+ template <typename I, typename V>
+ struct edge_to_color : Function_p2v< edge_to_color<I,V> >
+ {
+ typedef V result;
+
+ edge_to_color(const I& ima)
+ : ima_(ima)
+ {
+ }
+
+ V
+ operator()(const unsigned& e) const
+ {
+ return convert::to<V>(ima_.function()(e));
+ }
+
+ const I& ima_;
+ };
+
+ template <typename V>
+ inline
+ unsigned
+ find_root(util::array<V>& parent, const unsigned& x)
+ {
+ if (parent[x] == x)
+ return x;
+ else
+ return parent[x] = find_root(parent, parent[x]);
+ }
+
+
+ template <typename I, typename V, typename E>
+ inline
+ image3d<mln_value(I)>
+ make_debug_graph_image(const I& input,
+ const V& ima_v, const E& ima_e,
+ unsigned box_size, const value::int_u12& bg)
+ {
+ image3d<mln_value(I)> ima;
+ initialize(ima, input);
+
+ data::fill(ima, bg);
+ debug::draw_graph(ima, ima_v.domain(),
+ pw::cst(150u),
+ edge_to_color<E, mln_value(I)>(ima_e));
+
+ dpoint3d tl(-box_size,-box_size, -box_size);
+ dpoint3d br(box_size,box_size, -box_size);
+ mln_piter(V) p(ima_v.domain());
+ for_all(p)
+ {
+ box3d b(p + tl, p + br);
+ b.crop_wrt(ima.domain());
+ data::fill((ima | b).rw(), convert::to<mln_value(I)>(ima_v(p)));
+ }
+
+ return ima;
+ }
+
+}
+
+
+///////////////////
+// //
+// Main Function //
+// //
+///////////////////
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::int_u12;
+ using value::rgb8;
+ using value::label_16;
+
+ if (argc < 4)
+ {
+ std::cout << "Usage: " << argv[0] << "
<ima.dcm> <closure_lambda> <box_size> <dist_max>"
+ << std::endl;
+ return 1;
+ }
+
+ unsigned closure_lambda = atoi(argv[2]);
+ unsigned box_size = atoi(argv[3]);
+ unsigned dist_max = atoi(argv[4]);
+
+ image3d<int_u12> dcm;
+ io::dicom::load(dcm, argv[1]);
+
+ io::dump::save(level::stretch(int_u8(), dcm), "wsd_01_src.dump");
+
+ image3d<int_u12> grad = morpho::gradient(dcm, win_c4p_3d());
+ image3d<int_u12> clo = morpho::closing::area(grad, c6(), closure_lambda);
+
+ label_16 nbasins;
+ image3d<label_16> wshed = morpho::meyer_wst(clo, c6(), nbasins);
+
+ io::dump::save(level::stretch(int_u8(), clo), "wsd_02.dump");
+ io::dump::save(level::transform(wshed, fun::l2l::wrap<int_u8>()),
"wsd_03.dump");
+
+ mln_VAR(vol2_, morpho::elementary::dilation(extend(wshed | (pw::value(wshed) == 0u),
wshed), c26()));
+
+ data::fill((wshed | (pw::value(wshed) == 0u)).rw(), vol2_);
+
+ io::dump::save(level::transform(wshed, fun::l2l::wrap<int_u8>()),
"wsd_04.dump");
+
+ /// Build graph
+ util::graph g = make::graph(wshed, c6(), nbasins);
+ // Build graph images and compute distance values with a RGB image.
+ mln_VAR(ima_v, make_vertex_graph_image(g, dcm, wshed, nbasins));
+ mln_VAR(ima_e, make_edge_graph_image(ima_v, g));
+
+ /// Try to merge vertices.
+ mln_piter_(ima_e_t) e(ima_e.domain());
+ util::array<label_16> parent(g.v_nmax());
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ parent[i] = i;
+
+ for_all(e)
+ {
+ unsigned v1 = e.element().v1();
+ unsigned v2 = e.element().v2();
+ if (ima_e(e) <= dist_max && find_root(parent, v1) != find_root(parent,
v2))
+ parent[find_root(parent, v1)] = find_root(parent, v2);
+ }
+
+ fun::i2v::array<label_16> f(parent.nelements());
+ std::vector<unsigned> new_label(parent.nelements(), 0);
+ unsigned nbasins2 = 0;
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ {
+ unsigned p = find_root(parent, i);
+ mln_assertion(parent[p] == find_root(parent, i));
+ if (new_label[p] == 0)
+ new_label[p] = nbasins2++;
+ f(i) = new_label[p];
+ }
+ mln_invariant(f(0) == 0u);
+ --nbasins2; // nbasins2 does not count the basin with label 0.
+ image3d<label_16> wsd2 = level::transform(wshed, f);
+
+ io::dump::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()),
"wsd_05.dump");
+
+ /// Reconstruct a graph from the simplified image.
+ util::graph g2 = make::graph(wsd2, c6(), nbasins2);
+
+ // Compute distance values with a RGB image.
+ mln_VAR(ima_v2, make_vertex_graph_image(g2, dcm, wsd2, nbasins2));
+ mln_VAR(ima_e2, make_edge_graph_image(ima_v2, g2));
+
+ mln_VAR(wsd2_, morpho::elementary::dilation(extend(wsd2 | (pw::value(wsd2) == 0u),
wsd2), c26()));
+
+ data::fill((wsd2 | (pw::value(wsd2) == 0u)).rw(), wsd2_);
+
+ io::dump::save(level::transform(labeling::mean_values(dcm, wsd2, nbasins2),
fun::l2l::wrap<int_u8>()), "wsd_06_mean_colors.dump");
+ //io::dump::save(level::stretch(int_u8(), make_debug_graph_image(dcm, ima_v2, ima_e2,
box_size, 4095)), "wsd_07_graph_image2_white.dump");
+ //io::dump::save(level::stretch(int_u8(), make_debug_graph_image(dcm, ima_v2, ima_e2,
box_size, 0)), "wsd_08_graph_image2_black.dump");
+ io::dump::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()),
"wsd_99_result.dump");
+}
Index: trunk/milena/sandbox/fabien/igr/watershed.hh
===================================================================
--- trunk/milena/sandbox/fabien/igr/watershed.hh (revision 0)
+++ trunk/milena/sandbox/fabien/igr/watershed.hh (revision 3503)
@@ -0,0 +1,331 @@
+#include <iostream>
+#include <mln/core/image/image2d.hh>
+
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/window2d.hh>
+#include <mln/core/image/image_if.hh>
+
+#include <mln/io/ppm/save.hh>
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/dicom/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/dump/save.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/label_16.hh>
+
+#include <mln/level/transform.hh>
+#include <mln/level/stretch.hh>
+
+#include <mln/labeling/mean_values.hh>
+
+#include <mln/convert/to_fun.hh>
+
+#include <mln/make/graph.hh>
+
+#include <mln/morpho/gradient.hh>
+#include <mln/morpho/closing/area.hh>
+#include <mln/morpho/meyer_wst.hh>
+
+#include <mln/fun/l2l/wrap.hh>
+
+#include <mln/core/var.hh>
+#include <mln/morpho/elementary/dilation.hh>
+
+#include <mln/core/routine/extend.hh>
+
+#include <mln/util/graph.hh>
+
+#include <mln/essential/2d.hh>
+#include <mln/core/alias/vec3d.hh>
+#include <mln/debug/draw_graph.hh>
+#include <mln/util/graph.hh>
+#include <mln/accu/center.hh>
+#include <mln/io/dump/all.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb16.hh>
+#include <mln/accu/compute.hh>
+#include <mln/core/alias/dpoint2d.hh>
+#include <mln/draw/box.hh>
+#include <mln/level/stretch.hh>
+#include <mln/fun/v2v/id.hh>
+#include <mln/fun/l2l/wrap.hh>
+#include <mln/core/image/line_graph_elt_neighborhood.hh>
+#include <mln/morpho/elementary/dilation.hh>
+#include <mln/labeling/mean_values.hh>
+#include <mln/extension/adjust_fill.hh>
+#include <mln/extract/all.hh>
+#include <mln/make/region_adjacency_graph.hh>
+
+
+
+// Given a color image and a wshed image, computes the component graph.
+// Vertex values are computed thanks to a RGB image.
+
+namespace mln
+{
+
+ template <typename V>
+ value::int_u8 dist(const V& c1, const V& c2)
+ {
+ unsigned d = math::diff_abs(c1.red(), c2.red());
+ unsigned d_;
+ d_ = math::diff_abs(c1.green(), c2.green());
+
+ if (d_ > d)
+ d = d_;
+
+ d_ = math::diff_abs(c1.blue(), c2.blue());
+
+ if (d_ > d)
+ d = d_;
+ return d;
+ }
+
+
+ // ima_v, image on graph vertices; value = mean color per vertex (watershed basin)
+ template <typename I>
+ inline
+ pw::image<fun::i2v::array<value::int_u8>,
+ p_edges<util::graph, fun::i2v::array<mln_site(I)> > >
+ make_edge_graph_image(const I& ima_v, const util::graph& g)
+ {
+ // edge sites.
+ typedef fun::i2v::array<mln_site(I)> edge_site_t;
+ edge_site_t edge_site(g.e_nmax(), literal::origin);
+ typedef p_edges<util::graph, edge_site_t > pe_t;
+ pe_t pe(g, edge_site);
+
+ // edge values
+ typedef fun::i2v::array<value::int_u8> edge_values_t;
+ edge_values_t edge_values(g.e_nmax());
+
+ // image on graph edges
+ typedef pw::image<edge_values_t, pe_t> ima_e_t;
+ ima_e_t ima_e = (edge_values | pe);
+
+ mln_piter(ima_e_t) e(ima_e.domain());
+ for_all(e) // in ima_e
+ ima_e(e) = math::diff_abs(ima_v.function()(e.element().v1()),
ima_v.function()(e.element().v2()));
+
+ return ima_e;
+ }
+
+
+ template <typename I, typename J>
+ inline
+ util::array<mln_value(I)>
+ mean_color_values(const I& input, const J& w, mln_value(J) nbasins)
+ {
+ // Cf. sandbox/theo/color/segment_rgb_pixels.cc
+
+ util::array<float> m_3f = labeling::compute(accu::mean<mln_value(I)>(),
+ input, // input color image
+ w, // watershed labeling
+ nbasins);
+ m_3f[0] = literal::zero;
+
+ util::array<mln_value(I)> m;
+ convert::from_to(m_3f, m);
+ m[0] = 150u;
+
+ /*io::ppm::save(level::transform(w,
+ convert::to< fun::i2v::array<mln_value(I)> >(m)),
+ "wst_rag_wshd_color.ppm");*/
+
+ return m;
+ }
+
+
+ template <typename I, typename J>
+ pw::image<fun::i2v::array<mln_value(I)>, p_vertices<util::graph,
fun::i2v::array<mln_site(I)> > >
+ make_vertex_graph_image(const util::graph& g, const I&input, const J& w,
const mln_value(J)& nbasins)
+ {
+ typedef util::array<mln_site(I)> vertex_sites_t;
+ vertex_sites_t site_values;
+ convert::from_to(labeling::compute(accu::center<mln_site(I)>(), w, nbasins),
+ site_values);
+
+ typedef fun::i2v::array<mln_site(J)> f_sites_t;
+ f_sites_t sites;
+ convert::from_to(site_values, sites);
+
+ // p_vertices
+ typedef p_vertices<util::graph, f_sites_t> S;
+ S pv(g, sites);
+
+
+ typedef fun::i2v::array<mln_value(I)> vertex_values_t;
+ vertex_values_t vertex_values;
+ convert::from_to(mean_color_values(input, w, nbasins), vertex_values);
+
+ mln_VAR(ima_v, (vertex_values | pv));
+
+ return ima_v;
+ }
+
+
+ template <typename I, typename V>
+ struct edge_to_color : Function_p2v< edge_to_color<I,V> >
+ {
+ typedef V result;
+
+ edge_to_color(const I& ima)
+ : ima_(ima)
+ {
+ }
+
+ V
+ operator()(const unsigned& e) const
+ {
+ return convert::to<V>(ima_.function()(e));
+ }
+
+ const I& ima_;
+ };
+
+ template <typename V>
+ inline
+ unsigned
+ find_root(util::array<V>& parent, const unsigned& x)
+ {
+ if (parent[x] == x)
+ return x;
+ else
+ return parent[x] = find_root(parent, parent[x]);
+ }
+
+
+ template <typename I, typename V, typename E>
+ inline
+ image2d<mln_value(I)>
+ make_debug_graph_image(const I& input,
+ const V& ima_v, const E& ima_e,
+ unsigned box_size, const value::int_u12& bg)
+ {
+ image2d<mln_value(I)> ima;
+ initialize(ima, input);
+
+ data::fill(ima, bg);
+ debug::draw_graph(ima, ima_v.domain(),
+ pw::cst(150u),
+ edge_to_color<E, mln_value(I)>(ima_e));
+
+ dpoint2d tl(-box_size,-box_size);
+ dpoint2d br(box_size,box_size);
+ mln_piter(V) p(ima_v.domain());
+ for_all(p)
+ {
+ box2d b(p + tl, p + br);
+ b.crop_wrt(ima.domain());
+ data::fill((ima | b).rw(), convert::to<mln_value(I)>(ima_v(p)));
+ }
+
+ return ima;
+ }
+
+}
+
+
+///////////////////
+// //
+// Main Function //
+// //
+///////////////////
+
+
+int main(int argc, char *argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::int_u12;
+ using value::rgb8;
+ using value::label_16;
+
+ if (argc < 4)
+ {
+ std::cout << "Usage: " << argv[0] << "
<ima.dcm> <closure_lambda> <box_size> <dist_max>"
+ << std::endl;
+ return 1;
+ }
+
+ unsigned closure_lambda = atoi(argv[2]);
+ unsigned box_size = atoi(argv[3]);
+ unsigned dist_max = atoi(argv[4]);
+
+ image2d<int_u12> dcm;
+ io::dicom::load(dcm, argv[1]);
+
+ io::pgm::save(level::stretch(int_u8(), dcm), "wsd_01_src.pgm");
+
+ image2d<int_u12> grad = morpho::gradient(dcm, win_c4p());
+ image2d<int_u12> clo = morpho::closing::area(grad, c4(), closure_lambda);
+
+ label_16 nbasins;
+ image2d<label_16> wshed = morpho::meyer_wst(clo, c4(), nbasins);
+
+ io::pgm::save(level::stretch(int_u8(), clo), "wsd_02.pgm");
+ io::pgm::save(level::transform(wshed, fun::l2l::wrap<int_u8>()),
"wsd_03.pgm");
+
+ mln_VAR(vol2_, morpho::elementary::dilation(extend(wshed | (pw::value(wshed) == 0u),
wshed), c8()));
+
+ data::fill((wshed | (pw::value(wshed) == 0u)).rw(), vol2_);
+
+ io::pgm::save(level::transform(wshed, fun::l2l::wrap<int_u8>()),
"wsd_04.pgm");
+
+ /// Build graph
+ util::graph g = make::graph(wshed, c4(), nbasins);
+ // Build graph images and compute distance values with a RGB image.
+ mln_VAR(ima_v, make_vertex_graph_image(g, dcm, wshed, nbasins));
+ mln_VAR(ima_e, make_edge_graph_image(ima_v, g));
+
+ /// Try to merge vertices.
+ mln_piter_(ima_e_t) e(ima_e.domain());
+ util::array<label_16> parent(g.v_nmax());
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ parent[i] = i;
+
+ for_all(e)
+ {
+ unsigned v1 = e.element().v1();
+ unsigned v2 = e.element().v2();
+ if (ima_e(e) <= dist_max && find_root(parent, v1) != find_root(parent,
v2))
+ parent[find_root(parent, v1)] = find_root(parent, v2);
+ }
+
+ fun::i2v::array<label_16> f(parent.nelements());
+ std::vector<unsigned> new_label(parent.nelements(), 0);
+ unsigned nbasins2 = 0;
+ for (unsigned i = 0; i < parent.nelements(); ++i)
+ {
+ unsigned p = find_root(parent, i);
+ mln_assertion(parent[p] == find_root(parent, i));
+ if (new_label[p] == 0)
+ new_label[p] = nbasins2++;
+ f(i) = new_label[p];
+ }
+ mln_invariant(f(0) == 0u);
+ --nbasins2; // nbasins2 does not count the basin with label 0.
+ image2d<label_16> wsd2 = level::transform(wshed, f);
+
+ io::pgm::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()),
"wsd_05.pgm");
+
+ /// Reconstruct a graph from the simplified image.
+ util::graph g2 = make::graph(wsd2, c4(), nbasins2);
+
+ // Compute distance values with a RGB image.
+ mln_VAR(ima_v2, make_vertex_graph_image(g2, dcm, wsd2, nbasins2));
+ mln_VAR(ima_e2, make_edge_graph_image(ima_v2, g2));
+
+ mln_VAR(wsd2_, morpho::elementary::dilation(extend(wsd2 | (pw::value(wsd2) == 0u),
wsd2), c8()));
+
+ data::fill((wsd2 | (pw::value(wsd2) == 0u)).rw(), wsd2_);
+
+ io::pgm::save(level::transform(labeling::mean_values(dcm, wsd2, nbasins2),
fun::l2l::wrap<int_u8>()), "wsd_06_mean_colors.pgm");
+ io::pgm::save(level::stretch(int_u8(), make_debug_graph_image(dcm, ima_v2, ima_e2,
box_size, 4095)), "wsd_07_graph_image2_white.pgm");
+ io::pgm::save(level::stretch(int_u8(), make_debug_graph_image(dcm, ima_v2, ima_e2,
box_size, 0)), "wsd_08_graph_image2_black.pgm");
+ io::pgm::save(level::transform(wsd2, fun::l2l::wrap<int_u8>()),
"wsd_99_result.pgm");
+}
Index: trunk/milena/sandbox/fabien/igr/check2d_wsd.sh
===================================================================
--- trunk/milena/sandbox/fabien/igr/check2d_wsd.sh (revision 0)
+++ trunk/milena/sandbox/fabien/igr/check2d_wsd.sh (revision 3503)
@@ -0,0 +1,32 @@
+#!/bin/zsh
+
+process_file ()
+{
+ echo "Processing $2..."
+ box_size=2
+
+ for lambda_closure in 10 50 100 500 1000; do
+ echo " for lambda_closure = ${lambda_closure}";
+
+ for dist_max in 5 10 50 100 500; do
+ echo " for lambda_dist = ${dist_max}";
+
+ ./wsd2d $1 $lambda_closure $box_size $dist_max
+
+ mv wsd_01_src.pgm results/${2}_${lambda_closure}_${dist_max}_01.pgm
+ mv wsd_02.pgm results/${2}_${lambda_closure}_${dist_max}_02.pgm
+ mv wsd_03.pgm results/${2}_${lambda_closure}_${dist_max}_03.pgm
+ mv wsd_04.pgm results/${2}_${lambda_closure}_${dist_max}_04.pgm
+ mv wsd_05.pgm results/${2}_${lambda_closure}_${dist_max}_05.pgm
+ mv wsd_06_mean_colors.pgm results/${2}_${lambda_closure}_${dist_max}_06.pgm
+ mv wsd_07_graph_image2_white.pgm results/${2}_${lambda_closure}_${dist_max}_07.pgm
+ mv wsd_08_graph_image2_black.pgm results/${2}_${lambda_closure}_${dist_max}_08.pgm
+ mv wsd_99_result.pgm results/${2}_${lambda_closure}_${dist_max}_99.pgm
+
+ done;
+ done
+}
+
+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/check2d_wsd.sh
___________________________________________________________________
Name: svn:executable
+ *
Index: trunk/milena/sandbox/fabien/igr/check3d_wsd.sh
===================================================================
--- trunk/milena/sandbox/fabien/igr/check3d_wsd.sh (revision 0)
+++ trunk/milena/sandbox/fabien/igr/check3d_wsd.sh (revision 3503)
@@ -0,0 +1,34 @@
+#!/bin/zsh
+
+process_file ()
+{
+ echo "Processing $2..."
+ box_size=2
+
+ for lambda_closure in 10 50 100 500 1000; do
+ echo " for lambda_closure = ${lambda_closure}";
+
+ for dist_max in 5 10 50 100 500; do
+ echo " for lambda_dist = ${dist_max}";
+
+ ./wsd3d $1 $lambda_closure $box_size $dist_max
+
+ ../bin/dump2pgm8b wsd_01_src.dump
results/${2}_${lambda_closure}_${dist_max}_01.pgm
+ ../bin/dump2pgm8b wsd_02.dump results/${2}_${lambda_closure}_${dist_max}_02.pgm
+ ../bin/dump2pgm8b wsd_03.dump results/${2}_${lambda_closure}_${dist_max}_03.pgm
+ ../bin/dump2pgm8b wsd_04.dump results/${2}_${lambda_closure}_${dist_max}_04.pgm
+ ../bin/dump2pgm8b wsd_05.dump results/${2}_${lambda_closure}_${dist_max}_05.pgm
+ ../bin/dump2pgm8b wsd_06_mean_colors.dump
results/${2}_${lambda_closure}_${dist_max}_06.pgm
+#../bin/dump2pgm8b wsd_07_graph_image2_white.dump
results/${2}_${lambda_closure}_${dist_max}_07.pgm
+#../bin/dump2pgm8b wsd_08_graph_image2_black.dump
results/${2}_${lambda_closure}_${dist_max}_08.pgm
+ ../bin/dump2pgm8b wsd_99_result.dump
results/${2}_${lambda_closure}_${dist_max}_99.pgm
+
+ rm *.dump
+
+ done;
+ done
+}
+
+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/check3d_wsd.sh
___________________________________________________________________
Name: svn:executable
+ *
Index: trunk/milena/sandbox/fabien/igr/Makefile
===================================================================
--- trunk/milena/sandbox/fabien/igr/Makefile (revision 3502)
+++ trunk/milena/sandbox/fabien/igr/Makefile (revision 3503)
@@ -8,7 +8,7 @@
-framework CoreFoundation
CXXFLAGS = -DNDEBUG -O1
-all: 2d 3d wsd
+all: 2d 3d wsd2d wsd3d
2d: seg_vol_irm.hh seg2d.cc
g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} seg2d.cc -o seg2d
@@ -16,8 +16,11 @@
3d: seg_vol_irm.hh seg3d.cc
g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} seg3d.cc -o seg3d
-wsd: watershed.cc
- g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o wsd
+wsd2d: watershed.hh watershed2d.cc
+ g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o wsd2d
+
+wsd3d: watershed.hh watershed3d.cc
+ g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o wsd3d
clean:
rm -rf *.dump *.p?m *.plot *.log *.csv
Index: trunk/milena/sandbox/fabien/TODO
===================================================================
--- trunk/milena/sandbox/fabien/TODO (revision 3502)
+++ trunk/milena/sandbox/fabien/TODO (revision 3503)
@@ -13,7 +13,7 @@
[X] Generate histograms (normal, bg, obj, p_bg, p_obj)
[ ] Test processing chain on US
[X] Create README file for special images
-[ ] Implement watershed
+[X] Implement watershed
[X] Create tool for dicom mask
[X] Check conversion for mask (everything except int_u12(0))
[ ] Extract ROI (projection or fill holes)
@@ -22,4 +22,7 @@
[ ] After threshold, take biggest object and then erode, dilate
[ ] Fix n_max
[ ] Create routine for binary images (keep n big bg & m big objects)
-[ ] US: projection of internal gradient
+[X] US: projection of internal gradient
+[X] Create 3D US morpho with 2D stack
+[ ] Create macro for_all_slice
+[ ] Batch process watershed with 2D, 3D and any combination of parameters
Index: trunk/milena/sandbox/fabien/bin/dump2pgm.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dump2pgm.cc (revision 0)
+++ trunk/milena/sandbox/fabien/bin/dump2pgm.cc (revision 3503)
@@ -0,0 +1,37 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/make/image3d.hh>
+#include <mln/debug/slices_2d.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/io/dump/load.hh>
+#include <mln/io/pgm/save.hh>
+
+#include <mln/literal/colors.hh>
+
+
+int usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.dump
output.pgm" << std::endl;
+ return 1;
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::rgb8;
+
+ if (argc != 3)
+ return usage(argv);
+
+ image3d<int_u12> vol;
+ io::dump::load(vol, argv[1]);
+
+ rgb8 bg = literal::black;
+ image2d<int_u8> ima = debug::slices_2d(vol, 1.f, bg);
+ io::pgm::save(ima, argv[2]);
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/bin/filetype.hh
===================================================================
--- trunk/milena/sandbox/fabien/bin/filetype.hh (revision 0)
+++ trunk/milena/sandbox/fabien/bin/filetype.hh (revision 3503)
@@ -0,0 +1,54 @@
+#include <string>
+
+// 2d
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+
+// 3d
+#include <mln/core/image/image3d.hh>
+#include <mln/core/alias/neighb3d.hh>
+
+
+// pbm
+#include <mln/io/pbm/load.hh>
+#include <mln/io/pbm/save.hh>
+
+// pgm
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+
+// ppm
+#include <mln/io/ppm/load.hh>
+#include <mln/io/ppm/save.hh>
+
+
+//dump
+#include <mln/io/dump/load.hh>
+#include <mln/io/dump/save.hh>
+
+
+namespace mln
+{
+
+ namespace filetype
+ {
+ enum id { pbm, pgm, ppm, dump, unknown };
+ }
+
+ filetype::id
+ get_filetype(const std::string& filename)
+ {
+ if (filename.find(".pbm") == filename.length() - 4)
+ return filetype::pbm;
+ if (filename.find(".pgm") == filename.length() - 4)
+ return filetype::pgm;
+ if (filename.find(".ppm") == filename.length() - 4)
+ return filetype::ppm;
+ if (filename.find(".dump") == filename.length() - 5)
+ return filetype::dump;
+ return filetype::unknown;
+ }
+
+} // mln
+
+
Index: trunk/milena/sandbox/fabien/bin/dump_mask.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dump_mask.cc (revision 0)
+++ trunk/milena/sandbox/fabien/bin/dump_mask.cc (revision 3503)
@@ -0,0 +1,86 @@
+#include <mln/core/concept/image.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+#include <mln/core/image/slice_image.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/neighb3d.hh>
+#include <mln/core/var.hh>
+
+#include <mln/geom/ncols.hh>
+#include <mln/geom/nrows.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/io/dump/load.hh>
+#include <mln/io/pbm/save.hh>
+
+#include <mln/literal/colors.hh>
+#include <mln/morpho/elementary/gradient_internal.hh>
+
+#include <mln/level/transform.hh>
+#include <mln/fun/v2b/threshold.hh>
+
+#include <mln/data/fill.hh>
+#include <mln/pw/all.hh>
+
+
+int usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << "
input.dump" << std::endl;
+ return 1;
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ if (argc != 2)
+ return usage(argv);
+
+ image3d<int_u8> input;
+ io::dump::load(input, argv[1]);
+
+ image3d<bool> ima = level::transform(input,
fun::v2b::threshold<int_u8>(1));
+ mln_VAR(grad_int, morpho::elementary::gradient_internal(ima, c6()));
+
+ util::array<unsigned> xproj(ima.nrows(), 0);
+ util::array<unsigned> yproj(ima.ncols(), 0);
+ util::array<unsigned> xgradproj(grad_int.nrows(), 0);
+ util::array<unsigned> ygradproj(grad_int.ncols(), 0);
+
+ mln_piter_(image3d<bool>) p(ima.domain());
+ for_all(p)
+ {
+ if (ima(p))
+ {
+ ++xproj[p.row()];
+ ++yproj[p.col()];
+ }
+ if (grad_int(p))
+ {
+ ++xgradproj[p.row()];
+ ++ygradproj[p.col()];
+ }
+ }
+
+ // Plot files
+ std::ofstream fout_x("x.plot");
+ std::ofstream fout_xgrad("xgrad.plot");
+ for (unsigned int i = 0; i < xproj.nelements(); ++i)
+ {
+ fout_x << i << " " << xproj[i] << std::endl;
+ fout_xgrad << i << " " << xgradproj[i] <<
std::endl;
+ }
+
+ std::ofstream fout_y("y.plot");
+ std::ofstream fout_ygrad("ygrad.plot");
+ for (unsigned int i = 0; i < yproj.nelements(); ++i)
+ {
+ fout_y << i << " " << yproj[i] << std::endl;
+ fout_ygrad << i << " " << ygradproj[i] <<
std::endl;
+ }
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/bin/dicom2pgm.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dicom2pgm.cc (revision 0)
+++ trunk/milena/sandbox/fabien/bin/dicom2pgm.cc (revision 3503)
@@ -0,0 +1,34 @@
+#include <mln/core/concept/image.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/io/dicom/load.hh>
+#include <mln/io/pgm/save.hh>
+
+
+
+int usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.dcm
output.dump" << std::endl;
+ std::cerr << "\t work for 2D images encoded in int_u8" <<
std::endl;
+ return 1;
+}
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::int_u12;
+
+ if (argc != 3)
+ return usage(argv);
+
+ image2d<int_u8> ima;
+ io::dicom::load(ima, argv[1]);
+ io::pgm::save(ima, argv[2]);
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/bin/dump2pgm8b.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dump2pgm8b.cc (revision 0)
+++ trunk/milena/sandbox/fabien/bin/dump2pgm8b.cc (revision 3503)
@@ -0,0 +1,38 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/make/image3d.hh>
+#include <mln/debug/slices_2d.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/io/dump/load.hh>
+#include <mln/io/pgm/save.hh>
+
+#include <mln/literal/colors.hh>
+
+
+int usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.dump
output.pgm" << std::endl;
+ return 1;
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::rgb8;
+ using value::int_u8;
+
+ if (argc != 3)
+ return usage(argv);
+
+ image3d<int_u8> vol;
+ io::dump::load(vol, argv[1]);
+
+ rgb8 bg = literal::black;
+ image2d<int_u8> ima = debug::slices_2d(vol, 1.f, 0);
+ io::pgm::save(ima, argv[2]);
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/bin/pnms2dump.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/pnms2dump.cc (revision 0)
+++ trunk/milena/sandbox/fabien/bin/pnms2dump.cc (revision 3503)
@@ -0,0 +1,97 @@
+#include "filetype.hh"
+
+#include <mln/make/image3d.hh>
+
+
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " output.dump
input1.xxx .. inputn.xxx" << std::endl;
+ std::cerr << " It works with binary (pbm), gray-level (int_u8), and color
(rgb8) images." << std::endl;
+ abort();
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ if (argc < 3)
+ usage(argv);
+
+ trace::entering("main");
+
+ std::string filename = argv[2];
+
+ switch (get_filetype(argv[2]))
+ {
+ case filetype::pbm:
+ {
+ typedef image2d<bool> I;
+ util::array<I> arr;
+ for (int i = 2; i < argc; ++i)
+ {
+ I ima;
+ io::pbm::load(ima, argv[i]);
+ arr.append(ima);
+ }
+ image3d<bool> vol = make::image3d(arr);
+ io::dump::save(vol, argv[1]);
+ }
+ break;
+
+ case filetype::pgm:
+ {
+ using value::int_u8;
+ typedef image2d<int_u8> I;
+ util::array<I> arr;
+ for (int i = 2; i < argc; ++i)
+ {
+ I ima;
+ io::pgm::load(ima, argv[i]);
+ arr.append(ima);
+ }
+ image3d<int_u8> vol = make::image3d(arr);
+ io::dump::save(vol, argv[1]);
+ }
+ break;
+
+ case filetype::ppm:
+ {
+ using value::rgb8;
+ typedef image2d<rgb8> I;
+ util::array<I> arr;
+ for (int i = 2; i < argc; ++i)
+ {
+ I ima;
+ io::ppm::load(ima, argv[i]);
+ arr.append(ima);
+ }
+ image3d<rgb8> vol = make::image3d(arr);
+ io::dump::save(vol, argv[1]);
+ }
+ break;
+
+ case filetype::dump:
+ {
+ std::cerr << "Output shall not be a dump file!" << std::endl;
+ usage(argv);
+ }
+ break;
+
+ case filetype::unknown:
+ std::cerr << "unknown filename extension!" << std::endl;
+ usage(argv);
+ break;
+
+ default:
+ std::cerr << "file type not handled!" << std::endl;
+ usage(argv);
+ }
+
+ trace::exiting("main");
+
+}