URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox ChangeLog: 2009-03-12 Fabien Freling <fabien.freling@lrde.epita.fr> Create workflow based on small tools. * fabien/bin/dumpl32_to_colorize.cc: New. * fabien/igr/Makefile: Update. * fabien/igr/check.sh: New script shell for testing. * fabien/igr/clo_vol.cc: Implement closing volume. * fabien/igr/grad.cc: Implement gradient. * fabien/igr/graph.cc: Implement graph. * fabien/igr/wst.cc: Implement watershed. --- TODO | 6 bin/dumpl32_to_colorize.cc | 61 ++++++++ igr/Makefile | 40 +++-- igr/check.sh | 32 ++++ igr/clo_vol.cc | 63 ++++++++ igr/grad.cc | 63 ++++++++ igr/graph.cc | 329 +++++++++++++++++++++++++++++++++++++++++++++ igr/wst.cc | 71 +++++++++ 8 files changed, 650 insertions(+), 15 deletions(-) Index: trunk/milena/sandbox/fabien/igr/clo_vol.cc =================================================================== --- trunk/milena/sandbox/fabien/igr/clo_vol.cc (revision 0) +++ trunk/milena/sandbox/fabien/igr/clo_vol.cc (revision 3517) @@ -0,0 +1,63 @@ +#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/io/dump/all.hh> + +#include <mln/value/int_u8.hh> +#include <mln/value/int_u12.hh> + +#include <mln/morpho/closing/volume.hh> + + + +/////////////////// +// // +// Main Function // +// // +/////////////////// + + +int main(int argc, char *argv[]) +{ + using namespace mln; + using value::int_u8; + using value::int_u12; + + if (argc != 4) + { + std::cout << "Usage: " << argv[0] << " <input.dump> <dimensions> <closure_lambda>" + << std::endl; + return 1; + } + + unsigned closure_lambda = atoi(argv[3]); + unsigned dim = atoi(argv[2]); + if (dim != 2 && dim != 3) + { + std::cout << "<dimensions> invalid" << std::endl; + return 1; + } + + if (dim == 2) + { + image2d<int_u12> input; + io::dump::load(input, argv[1]); + image2d<int_u12> clo = morpho::closing::volume(input, c4(), closure_lambda); + io::dump::save(clo, "clo_vol.dump"); + } + else + { + image3d<int_u12> input; + io::dump::load(input, argv[1]); + image3d<int_u12> clo = morpho::closing::volume(input, c6(), closure_lambda); + io::dump::save(clo, "clo_vol.dump"); + } + + return 0; +} Index: trunk/milena/sandbox/fabien/igr/graph.cc =================================================================== --- trunk/milena/sandbox/fabien/igr/graph.cc (revision 0) +++ trunk/milena/sandbox/fabien/igr/graph.cc (revision 3517) @@ -0,0 +1,329 @@ +#include <iostream> +#include <mln/core/image/image2d.hh> +#include <mln/core/image/image3d.hh> +#include <mln/core/image/image_if.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/io/dump/all.hh> +#include <mln/io/dicom/load.hh> +#include <mln/io/pgm/save.hh> + +#include <mln/value/int_u8.hh> +#include <mln/value/int_u12.hh> +#include <mln/value/label_16.hh> +#include <mln/value/label_32.hh> + +#include <mln/morpho/watershed/flooding.hh> + +#include <mln/math/diff_abs.hh> + +#include <mln/labeling/mean_values.hh> + +#include <mln/convert/to_fun.hh> + +#include <mln/make/graph.hh> +#include <mln/util/graph.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/core/alias/vec3d.hh> +#include <mln/debug/draw_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/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::label_16; + using value::label_32; + typedef label_32 L; + + if (argc != 6) + { + std::cout << "Usage: " << argv[0] << " <wst.dump> <dimensions> <ima.dcm> <dist_max> <nbasins>" + << std::endl; + return 1; + } + + unsigned dim = atoi(argv[2]); + unsigned dist_max = atoi(argv[4]); + if (dim != 2 && dim != 3) + { + std::cout << "<dimensions> invalid" << std::endl; + return 1; + } + + L nbasins = atoi(argv[5]); + unsigned nbasins2 = 0; + + if (dim == 2) + { + image2d<L> wshed; + io::dump::load(wshed, argv[1]); + image2d<int_u12> dcm; + io::dicom::load(dcm, argv[3]); + + /// 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); + 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); + + /// 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(wsd_, morpho::elementary::dilation(extend(wshed | (pw::value(wshed) == 0u), wshed), c8())); + data::fill((wshed | (pw::value(wshed) == 0u)).rw(), wsd_); + + 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::stretch(int_u8(), labeling::mean_values(dcm, wshed, nbasins)), "wsd_original.pgm"); + io::pgm::save(level::stretch(int_u8(), labeling::mean_values(dcm, wsd2, nbasins2)), "wsd_mean_colors.pgm"); + } + else + { + // FIXME + } + + std::cout << nbasins2 << std::endl; + + return 0; +} Index: trunk/milena/sandbox/fabien/igr/check.sh =================================================================== --- trunk/milena/sandbox/fabien/igr/check.sh (revision 0) +++ trunk/milena/sandbox/fabien/igr/check.sh (revision 3517) @@ -0,0 +1,32 @@ +#!/bin/zsh + +process_file () +{ + echo "Processing $3..." + dist_max=10 + + ./grad $1 $2 + for lambda_closing in 10 50 100 500 1000 5000 10000 50000; do + echo " for lambda_closing = ${lambda_closing}"; + ./clo_vol grad.dump $2 ${lambda_closing} + nbasins=`./wst clo_vol.dump $2` + ../bin/dumpl32_to_colorize wst.dump $2 $nbasins results/colorize_${3}_${lambda_closing}.ppm + + if [ ${lambda_closing} -eq 100 ]; then + for lambda_dist in 10 50 100; do + nbasins_after=`./graph wst.dump $2 $1 $lambda_dist $nbasins` + mv wsd_original.pgm results/graph_${3}_${lambda_closing}_${lambda_dist}_01.pgm + mv wsd_mean_colors.pgm results/graph_${3}_${lambda_closing}_${lambda_dist}_02.pgm + echo "nbasins was" $nbasins "and now is" $nbasins_after "( diff =" $(($nbasins - $nbasins_after)) ")" + done + fi + done +# rm *.dump +} + +process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0049.dcm" 2 "49" +#process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0052.dcm" 3 "52" +process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0055.dcm" 2 "55" +process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0058.dcm" 2 "58" +#process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0061.dcm" 3 "61" +#process_file "/Users/HiSoKa/Work/IGR/souris18/irm/IM_0064.dcm" 3 "64" Property changes on: trunk/milena/sandbox/fabien/igr/check.sh ___________________________________________________________________ Name: svn:executable + * Index: trunk/milena/sandbox/fabien/igr/wst.cc =================================================================== --- trunk/milena/sandbox/fabien/igr/wst.cc (revision 0) +++ trunk/milena/sandbox/fabien/igr/wst.cc (revision 3517) @@ -0,0 +1,71 @@ +#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/io/dump/all.hh> + +#include <mln/value/int_u8.hh> +#include <mln/value/int_u12.hh> +#include <mln/value/label_16.hh> +#include <mln/value/label_32.hh> + +#include <mln/morpho/watershed/flooding.hh> + + + +/////////////////// +// // +// Main Function // +// // +/////////////////// + + +int main(int argc, char *argv[]) +{ + using namespace mln; + using value::int_u8; + using value::int_u12; + using value::label_16; + using value::label_32; + typedef label_32 L; + + if (argc != 3) + { + std::cout << "Usage: " << argv[0] << " <ima.dcm> <dimensions>" + << std::endl; + return 1; + } + + unsigned dim = atoi(argv[2]); + if (dim != 2 && dim != 3) + { + std::cout << "<dimensions> invalid" << std::endl; + return 1; + } + + L nbasins; + + if (dim == 2) + { + image2d<int_u12> input; + io::dump::load(input, argv[1]); + image2d<L> wshed = morpho::watershed::flooding(input, c4(), nbasins); + io::dump::save(wshed, "wst.dump"); + } + else + { + image3d<int_u12> input; + io::dump::load(input, argv[1]); + image3d<L> wshed = morpho::watershed::flooding(input, c6(), nbasins); + io::dump::save(wshed, "wst.dump"); + } + + std::cout << nbasins << std::endl; + + return 0; +} Index: trunk/milena/sandbox/fabien/igr/grad.cc =================================================================== --- trunk/milena/sandbox/fabien/igr/grad.cc (revision 0) +++ trunk/milena/sandbox/fabien/igr/grad.cc (revision 3517) @@ -0,0 +1,63 @@ +#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/io/dicom/load.hh> +#include <mln/io/dump/save.hh> + +#include <mln/value/int_u8.hh> +#include <mln/value/int_u12.hh> + +#include <mln/morpho/elementary/gradient.hh> + + + +/////////////////// +// // +// Main Function // +// // +/////////////////// + + +int main(int argc, char *argv[]) +{ + using namespace mln; + using value::int_u8; + using value::int_u12; + + if (argc != 3) + { + std::cout << "Usage: " << argv[0] << " <ima.dcm> <dimensions>" + << std::endl; + return 1; + } + + unsigned dim = atoi(argv[2]); + if (dim != 2 && dim != 3) + { + std::cout << "<dimensions> invalid" << std::endl; + return 1; + } + + if (dim == 2) + { + image2d<int_u12> dcm2; + io::dicom::load(dcm2, argv[1]); + image2d<int_u12> grad2 = morpho::elementary::gradient(dcm2, c4()); + io::dump::save(grad2, "grad.dump"); + } + else + { + image3d<int_u12> dcm3; + io::dicom::load(dcm3, argv[1]); + image3d<int_u12> grad3 = morpho::elementary::gradient(dcm3, c6()); + io::dump::save(grad3, "grad.dump"); + } + + return 0; +} Index: trunk/milena/sandbox/fabien/igr/Makefile =================================================================== --- trunk/milena/sandbox/fabien/igr/Makefile (revision 3516) +++ trunk/milena/sandbox/fabien/igr/Makefile (revision 3517) @@ -1,32 +1,46 @@ -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/ -DICOM_LIB = -L/Users/HiSoKa/Downloads/gdcmbin/bin \ +DCM_SRC=/Users/HiSoKa/Downloads/gdcm-2.0.10 +DCM_BIN=/Users/HiSoKa/Downloads/gdcmbin +DICOM_INC = -I${DCM_SRC}/Source/Common/ \ + -I${DCM_BIN}/Source/Common/ \ + -I${DCM_SRC}/Source/DataDictionary/ \ + -I${DCM_SRC}/Source/MediaStorageAndFileFormat/ \ + -I${DCM_SRC}/Source/DataStructureAndEncodingDefinition/ +DICOM_LIBS = -L${DCM_BIN}/bin \ -lgdcmCommon -lgdcmDICT -lgdcmDSED -lgdcmIOD -lgdcmMSFF -lgdcmexpat -lgdcmjpeg12 -lgdcmjpeg16 -lgdcmjpeg8 -lgdcmopenjpeg -lgdcmuuid -lgdcmzlib \ -framework CoreFoundation CXXFLAGS = -DNDEBUG -O1 -all: 2d 3d wsd2d wsd3d +all: 2d 3d wsd2d wsd3d grad 2d: seg_vol_irm.hh seg2d.cc - g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} seg2d.cc -o seg2d + g++ -I../../../ ${DICOM_INC} ${DICOM_LIBS} ${CXXFLAGS} seg2d.cc -o seg2d 3d: seg_vol_irm.hh seg3d.cc - g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} seg3d.cc -o seg3d + g++ -I../../../ ${DICOM_INC} ${DICOM_LIBS} ${CXXFLAGS} seg3d.cc -o seg3d wsd2d: watershed.hh watershed2d.cc - g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o wsd2d + g++ -I../../../ ${DICOM_INC} ${DICOM_LIBS} ${CXXFLAGS} $^ -o wsd2d wsd3d: watershed.hh watershed3d.cc - g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o wsd3d + g++ -I../../../ ${DICOM_INC} ${DICOM_LIBS} ${CXXFLAGS} $^ -o wsd3d wsd3dg: watershed.hh watershed3d.cc - g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} -g $^ -o wsd3dg + g++ -I../../../ ${DICOM_INC} ${DICOM_LIBS} -g $^ -o wsd3dg nbasins: nbasins_finder.cc - g++ -I../../../ ${DICOM_INC} ${DICOM_LIB} ${CXXFLAGS} $^ -o nbasins_finder + g++ -I../../../ ${DICOM_INC} ${DICOM_LIBS} ${CXXFLAGS} $^ -o nbasins_finder + +grad: grad.cc + g++ -I../../../ ${DICOM_INC} ${DICOM_LIBS} ${CXXFLAGS} $^ -o grad + +clo_vol: clo_vol.cc + g++ -I../../../ ${CXXFLAGS} $^ -o clo_vol + +wst: wst.cc + g++ -I../../../ ${CXXFLAGS} $^ -o wst + +graph: graph.cc + g++ -I../../../ ${DICOM_INC} ${DICOM_LIBS} ${CXXFLAGS} $^ -o graph clean: rm -rf *.dump *.p?m *.plot *.log *.csv Index: trunk/milena/sandbox/fabien/TODO =================================================================== --- trunk/milena/sandbox/fabien/TODO (revision 3516) +++ trunk/milena/sandbox/fabien/TODO (revision 3517) @@ -26,5 +26,7 @@ [X] Create 3D US morpho with 2D stack [ ] Create macro for_all_slice [X] Batch process watershed with 2D, 3D and any combination of parameters -[ ] Cut into small tools -[ ] Test 3D workflow on 2D images +[X] Cut into small tools +[X] Test 3D workflow on 2D images +[ ] Create colorized colors for graph +[ ] Diff with % Index: trunk/milena/sandbox/fabien/bin/dumpl32_to_colorize.cc =================================================================== --- trunk/milena/sandbox/fabien/bin/dumpl32_to_colorize.cc (revision 0) +++ trunk/milena/sandbox/fabien/bin/dumpl32_to_colorize.cc (revision 3517) @@ -0,0 +1,61 @@ +#include <mln/core/image/image2d.hh> +#include <mln/make/image3d.hh> +#include <mln/debug/slices_2d.hh> +#include <mln/debug/colorize.hh> + +#include <mln/value/int_u8.hh> +#include <mln/value/int_u12.hh> +#include <mln/value/label_32.hh> +#include <mln/value/rgb8.hh> +#include <mln/core/concept/literal.hh> + +#include <mln/io/dump/load.hh> +#include <mln/io/ppm/save.hh> + + +int usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << " input.dump dim nbasins output.ppm" << std::endl; + return 1; +} + + + +int main(int argc, char* argv[]) +{ + using namespace mln; + using value::int_u8; + using value::int_u12; + using value::label_32; + using value::rgb8; + + if (argc != 5) + return usage(argv); + + unsigned dim = atoi(argv[2]); + unsigned nbasins = atoi(argv[3]); + if (dim != 2 && dim != 3) + { + std::cout << "<dimensions> invalid" << std::endl; + return 1; + } + + if (dim == 2) + { + image2d<label_32> ima2d; + io::dump::load(ima2d, argv[1]); + image2d<rgb8> ima_rgb = debug::colorize(rgb8(), ima2d, nbasins); + io::ppm::save(ima_rgb, argv[4]); + } + else + { + image3d<label_32> ima3d; + io::dump::load(ima3d, argv[1]); + image3d<rgb8> ima_rgb = debug::colorize(rgb8(), ima3d, nbasins); + + image2d<rgb8> ima_result = debug::slices_2d(ima_rgb, 1.f, literal::black); + io::ppm::save(ima_result, argv[4]); + } + + return 0; +}