3565: Add some executable source.

https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Add some executable source. * theo/icdar: New directory. * theo/icdar/dibco: New directory. * theo/icdar/hsc: New directory. * theo/icdar/hsc/fuzzy.sh: New. * theo/icdar/hsc/dist.sh: New. * theo/icdar/hsc/exec: New directory. * theo/icdar/hsc/exec/iz_lines.cc: New. * theo/icdar/hsc/exec/relabel_lines.cc: New. * theo/icdar/hsc/exec/show_lines_pbm.cc: New. * theo/icdar/hsc/exec/show_lines.cc: New. * theo/exec/watershed_superpose.cc: New. * theo/exec/gaussian_directional_2d__float.cc: New. * theo/exec/distance_thick.cc: New. * theo/exec/closing_rectangle.cc: Add pbm case. * theo/exec/opening_rectangle.cc: New. * theo/exec/closing_isotropic.cc: Add pgm case. exec/closing_isotropic.cc | 10 + exec/closing_rectangle.cc | 26 ++ exec/distance_thick.cc | 46 +++++ exec/gaussian_directional_2d__float.cc | 99 +++++++++++ exec/opening_rectangle.cc | 62 ++++++ exec/watershed_superpose.cc | 36 ++++ icdar/hsc/dist.sh | 8 icdar/hsc/exec/iz_lines.cc | 106 +++++++++++ icdar/hsc/exec/relabel_lines.cc | 296 +++++++++++++++++++++++++++++++++ icdar/hsc/exec/show_lines.cc | 53 +++++ icdar/hsc/exec/show_lines_pbm.cc | 44 ++++ icdar/hsc/fuzzy.sh | 18 ++ 12 files changed, 801 insertions(+), 3 deletions(-) Index: theo/icdar/hsc/fuzzy.sh --- theo/icdar/hsc/fuzzy.sh (revision 0) +++ theo/icdar/hsc/fuzzy.sh (revision 0) @@ -0,0 +1,18 @@ +#! /bin/sh + +convert -geometry 25% -depth 8 +compress $1 small.pgm +./+bin/gaussian_directional_2d__float small.pgm 1 1 31 fuz.pgm + +./+bin/closing_rectangle fuz.pgm 7 31 tmp.pgm +./+bin/watershed_flooding tmp.pgm ws_txt.pgm + +convert -negate fuz.pgm -depth 8 +compress tmp.pgm + +./+bin/closing_rectangle tmp.pgm 7 31 tmp.pgm +./+bin/watershed_flooding tmp.pgm ws_spc.pgm + +./+bin/relabel_lines ws_txt.pgm ws_spc.pgm tmp.ppm + +./+bin/show_lines small.pgm tmp.ppm ${1%pbm}ppm + +rm fuz.pgm tmp.pgm ws_txt.pgm ws_spc.pgm small.pgm tmp.ppm Property changes on: theo/icdar/hsc/fuzzy.sh ___________________________________________________________________ Added: svn:executable + * Index: theo/icdar/hsc/exec/iz_lines.cc --- theo/icdar/hsc/exec/iz_lines.cc (revision 0) +++ theo/icdar/hsc/exec/iz_lines.cc (revision 0) @@ -0,0 +1,106 @@ +#include "../exec/filetype.hh" + +#include <mln/core/alias/point2d.hh> +#include <mln/core/alias/dpoint2d.hh> + +#include <mln/core/image/image_if.hh> + +#include <mln/data/fill.hh> +#include <mln/data/paste.hh> +#include <mln/pw/all.hh> + +// #include <mln/debug/colorize.hh> + +#include <mln/transform/influence_zone_geodesic.hh> + +// #include <mln/level/transform.hh> +// #include <mln/fun/l2l/wrap.hh> + + +using mln::value::int_u8; + + + +namespace mln +{ + + + template <typename L> + image2d<int_u8> + left_iz(const image2d<bool>& in, const image2d<L>& ws_txt) + { + box2d b = ws_txt.domain(); + + image2d<int_u8> ima(b); + data::fill(ima, 0); + + unsigned nrows = ima.nrows(); + int_u8 l = 0; + for (unsigned row = 0; row < nrows; ++row) + if (ws_txt.at_(row, 0) == 0) + ima.at_(row, 0) = ++l; + + io::pgm::save(ima, "tmp_iz_start.pgm"); + + data::paste( transform::influence_zone_geodesic(ima | (pw::value(ws_txt) == pw::cst(0)), + c8(), + mln_max(unsigned)), + ima ); + + image2d<int_u8> out(in.domain()); + data::fill(out, false); + data::fill((out | pw::value(in)).rw(), 255); + + mln_piter(box2d) p(out.domain()); + for_all(p) +// if (in(p) == true) + { + point2d p_(p.row() / 4, p.col() / 4); + if (! ima.has(p_) || ima(p_) == 0) + continue; + out(p) = ima(p_); + } + + return out; + } + + +} // ! mln + + + +void usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << " input.pbm ws_txt.pgm output.ppm" << std::endl + << " Label lines." << std::endl + << " input is the large binary image;" << std::endl + << " ws_txt is a small (25p) watershed image thru text." << std::endl; + std::abort(); +} + + + +int main(int argc, char* argv[]) +{ + using namespace mln; + + if (argc != 4) + usage(argv); + + trace::entering("main"); + + image2d<bool> in; + io::pbm::load(in, argv[1]); + + image2d<int_u8> ws_txt, out; + io::pgm::load(ws_txt, argv[2]); + + out = left_iz(in, ws_txt); + + io::pgm::save(out, argv[3]); + +// io::ppm::save(debug::colorize(value::rgb8(), out, 254), +// argv[3]); + + trace::exiting("main"); +} Index: theo/icdar/hsc/exec/relabel_lines.cc --- theo/icdar/hsc/exec/relabel_lines.cc (revision 0) +++ theo/icdar/hsc/exec/relabel_lines.cc (revision 0) @@ -0,0 +1,296 @@ +#include "../exec/filetype.hh" + +#include <mln/core/alias/point2d.hh> +#include <mln/core/alias/dpoint2d.hh> + +#include <mln/value/label_8.hh> +#include <mln/core/image/image_if.hh> + +#include <mln/data/fill.hh> +#include <mln/pw/all.hh> +#include <mln/labeling/blobs.hh> +// #include <mln/labeling/compute.hh> +#include <mln/accu/maj_h.hh> + +#include <mln/morpho/elementary/dilation.hh> +#include <mln/debug/colorize.hh> + +#include <mln/transform/influence_zone_geodesic.hh> +#include <mln/level/transform.hh> +#include <mln/fun/l2l/wrap.hh> + + +namespace mln +{ + + typedef value::int_u8 L; + + enum { max_L = 256 - 1 }; + + typedef L par_t[max_L]; + typedef std::vector<L> labels_t[max_L]; + + + L find_root(par_t& par, L l) + { + if (par[l] == l) + return l; + return par[l] = find_root(par, par[l]); + } + + + image2d<L> doit(const image2d<L>& ws_txt, + const image2d<L>& ws_spc) + { + labels_t left_, right_; + +// image2d<bool> cross(ws_txt.domain()); +// data::fill(cross, false); + + box2d b = ws_txt.domain(); + mln_piter_(box2d) p(b); + for_all(p) + { + if (ws_txt(p) != 0 || ws_spc(p) != 0) + continue; + if (ws_txt(p + left) == 0 && ws_txt(p + right) == 0 + // text = locally horizontal: + // o o o + && + ws_spc(p + left) != 0 && ws_spc(p + right) != 0 + // region frontiere = locally roughly vertical: + // x . + // o + // . x + ) + { + L l1 = ws_spc(p + left), + l2 = ws_spc(p + right); + if (l1 == 0 || l2 == 0) + continue; + if (l2 == l1) + continue; + right_[l1].push_back(l2); + left_[l2].push_back(l1); +// cross(p) = true; + } + } + +// io::pbm::save(cross, "tmp_cross.pbm"); + + + // debug code: + +// for (L l = 0; l < max_L; ++l) +// if (right_[l].size()) +// { +// std::cout << l << " -> "; +// const std::vector<L>& lab = right_[l]; +// for (L i = 0; i < lab.size(); ++i) +// { +// std::cout << lab[i] << ' '; +// const std::vector<L>& rev_lab = left_[ lab[i] ]; +// if (rev_lab.size()) +// { +// std::cout << '('; +// for (L j = 0; j < rev_lab.size(); ++j) +// std::cout << rev_lab[j] << ','; +// std::cout << ')'; +// } +// } +// std::cout << std::endl; +// } + + + par_t par; + for (L l = 0; l < max_L; ++l) + par[l] = l; + + for (L l = 1; l < max_L; ++l) + if (right_[l].size() == 1) + { + L l2 = right_[l][0]; + mln_invariant(l2 != 0); + if (left_[l2].size() != 0 && left_[l2][0] == l) + { + mln_invariant(l != 0 && l2 != l); + // Union. + par[l] = l2; // l --right--> l2 + } + } + + for (L l = 1; l < max_L; ++l) + par[l] = find_root(par, l); + +// // debug code: + +// for (L l = 1; l < max_L; ++l) +// if (par[l] != l) +// std::cout << l << " -> " << par[l] << " "; +// std::cout << std::endl; + + + image2d<L> out(b); + for_all(p) + out(p) = par[ ws_spc(p) ]; + + return out; + } + + + void left_iz(const image2d<bool>& ws) + { + using value::int_u8; + image2d<int_u8> ima(ws.domain()); + data::fill(ima, 0); + unsigned nrows = ima.nrows(); + int_u8 l = 0; + for (unsigned row = 0; row < nrows; ++row) + if (ws.at_(row, 0) == true) + ima.at_(row, 0) = ++l; + io::pgm::save(ima, "tmp_iz_start.pgm"); + + data::paste( transform::influence_zone_geodesic(ima | pw::value(ws), + c8(), + mln_max(unsigned)), + ima ); + + io::pgm::save(ima, "tmp_iz.pgm"); + } + + + + image2d<L> doit_cut(const image2d<L>& ws_txt, + const image2d<L>& ws_spc) + { + + box2d b = ws_txt.domain(); + + image2d<bool> lines(b); + data::fill(lines, (pw::value(ws_txt) == pw::cst(0)) | b); + + left_iz(lines); // THIS IS A TEST! + + + //debug: + io::pbm::save(lines, "tmp_ws_line.pbm"); + + mln_piter_(box2d) p(b); + for_all(p) + if (ws_txt(p) == 0 && + ws_txt(p + up) == 0 && + ws_txt(p + down) == 0) + lines(p) = false; + + //debug: + io::pbm::save(lines, "tmp_lines.pbm"); + + typedef value::int_u<12> L2; + L2 n_lines; + image2d<L2> line_lab = labeling::blobs(lines, c8(), n_lines); + + { + io::pgm::save(level::transform(line_lab, + fun::l2l::wrap<value::int_u8>()), + "tmp_lines.pgm"); + } + + // Cannot be used with int_u* (only with label_*): + // util::array<L2> arr = labeling::compute(accu::maj_h<L2>(), + // line_lab | (pw::value(line_lab) != pw::cst(0)), + // ws_spc, + // max_L); + + util::array< accu::maj_h<L2> > arr(max_L + 1); // L -> L2 + for_all(p) + { + if (line_lab(p) == 0) // not on a line + continue; + L l = ws_spc(p); // l = label of a region + if (l == 0) + continue; + arr[l].take(line_lab(p)); + } + + util::array<L2> arr_(max_L); // L -> L2 + for (L l = 1; l < max_L; ++l) + arr_[l] = arr[l].to_result(); + +// // debug: +// for (L l = 1; l < max_L; ++l) +// std::cout << l << " -> " << arr_[l] << " "; +// std::cout << std::endl; + + L2 l2_max = 0; + for (L l = 1; l < max_L; ++l) + if (arr_[l] > l2_max) + l2_max = arr_[l]; + + for (L l = 1; l < max_L; ++l) + if (arr_[l] == 0) + arr_[l] = ++l2_max; + +// // debug: +// std::cout << std::endl << std::endl; +// for (L l = 1; l < max_L; ++l) +// std::cout << l << " -> " << arr_[l] << " "; +// std::cout << std::endl; + + util::array<L> newl(l2_max + 1); + for (unsigned i = 0; i <= l2_max; ++i) + newl[i] = 0; + + L cur = 1; + for (L l = 1; l < max_L; ++l) + { + L2 l2 = arr_[l]; + if (newl[l2] == 0) + newl[l2] = cur++; + } + + image2d<L> out(b); + for_all(p) + if (ws_spc(p) == 0) + out(p) = 0; + else + out(p) = newl[ arr_[ws_spc(p)] ]; + + out = morpho::elementary::dilation(out, c4()); // c2_row + + return out; + } + + +} // ! mln + + +void usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << " ws_txt.pgm ws_spc.pgm output.ppm" << std::endl + << " Label lines." << std::endl; + std::abort(); +} + + + +int main(int argc, char* argv[]) +{ + using namespace mln; + using value::int_u8; + + if (argc != 4) + usage(argv); + + trace::entering("main"); + + image2d<L> ws_txt, ws_spc; + io::pgm::load(ws_txt, argv[1]); + io::pgm::load(ws_spc, argv[2]); + + image2d<L> out = doit_cut(ws_txt, ws_spc); + + io::ppm::save(debug::colorize(value::rgb8(), out, 254), + argv[3]); + + trace::exiting("main"); +} Index: theo/icdar/hsc/exec/show_lines_pbm.cc --- theo/icdar/hsc/exec/show_lines_pbm.cc (revision 0) +++ theo/icdar/hsc/exec/show_lines_pbm.cc (revision 0) @@ -0,0 +1,44 @@ +#include "../exec/filetype.hh" + +#include <mln/core/alias/point2d.hh> +#include <mln/core/alias/dpoint2d.hh> + + + +void usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << " input.pbm regions.ppm output.ppm" << std::endl + << " 'input' is PBM: dark text / light background" << std::endl + << " 'regions': one color per region." << std::endl; + std::abort(); +} + + +int main(int argc, char* argv[]) +{ + using namespace mln; + using value::int_u8; + using value::rgb8; + + if (argc != 4) + usage(argv); + + trace::entering("main"); + + image2d<bool> input; + io::pbm::load(input, argv[1]); + box2d b = input.domain(); + + image2d<rgb8> reg, out(b); + io::ppm::load(reg, argv[2]); + + data::fill(out, rgb8(0,0,0)); + + mln_piter_(box2d) p(b); + for_all(p) if (input(p)) + out(p) = reg.at_(p.row() / 4, p.col() / 4); + + io::ppm::save(out, argv[3]); + + trace::exiting("main"); +} Index: theo/icdar/hsc/exec/show_lines.cc --- theo/icdar/hsc/exec/show_lines.cc (revision 0) +++ theo/icdar/hsc/exec/show_lines.cc (revision 0) @@ -0,0 +1,53 @@ +#include "../exec/filetype.hh" + +#include <mln/core/alias/point2d.hh> +#include <mln/core/alias/dpoint2d.hh> + + + +void usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << " input.pgm regions.ppm output.ppm" << std::endl + << " 'input': dark text / light background" << std::endl + << " 'regions': one color per region." << std::endl; + std::abort(); +} + + +const mln::value::int_u8 +foo(const mln::value::int_u8& c, + const mln::value::int_u8& g) +{ + float ratio = 1.f - float(g) / 256.f; + return unsigned(ratio * c); +} + + +int main(int argc, char* argv[]) +{ + using namespace mln; + using value::int_u8; + using value::rgb8; + + if (argc != 4) + usage(argv); + + trace::entering("main"); + + image2d<int_u8> input; + io::pgm::load(input, argv[1]); + box2d b = input.domain(); + + image2d<rgb8> reg, out(b); + io::ppm::load(reg, argv[2]); + + mln_piter_(box2d) p(b); + for_all(p) + out(p) = rgb8( foo(reg(p).red(), input(p)), + foo(reg(p).green(), input(p)), + foo(reg(p).blue(), input(p)) ); + + io::ppm::save(out, argv[3]); + + trace::exiting("main"); +} Index: theo/icdar/hsc/dist.sh --- theo/icdar/hsc/dist.sh (revision 0) +++ theo/icdar/hsc/dist.sh (revision 0) @@ -0,0 +1,8 @@ +#! /bin/sh + +./+bin/distance_thick $1 out.pgm +convert -depth 8 +compress $1 ${1%pbm}pgm +./+bin/closing_rectangle out.pgm 11 101 out2.pgm +./+bin/watershed_flooding out2.pgm out3.pgm +./+bin/watershed_superpose ${1%pbm}pgm out3.pgm ${1%pbm}ppm +rm out.pgm out2.pgm out3.pgm Property changes on: theo/icdar/hsc/dist.sh ___________________________________________________________________ Added: svn:executable + * Index: theo/exec/watershed_superpose.cc --- theo/exec/watershed_superpose.cc (revision 0) +++ theo/exec/watershed_superpose.cc (revision 0) @@ -0,0 +1,36 @@ +#include "filetype.hh" + +#include <mln/morpho/watershed/superpose.hh> +#include <mln/data/fill.hh> +#include <mln/pw/all.hh> + + + +void usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << " input.pgm watershed.pgm output.ppm" << std::endl + << " Superpose the watershed line over the input image." << std::endl; + std::abort(); +} + + + +int main(int argc, char* argv[]) +{ + using namespace mln; + using value::int_u8; + + if (argc != 4) + usage(argv); + + trace::entering("main"); + + image2d<int_u8> ima, ws; + io::pgm::load(ima, argv[1]); + io::pgm::load(ws, argv[2]); + + io::ppm::save(morpho::watershed::superpose(ima, ws), + argv[3]); + + trace::exiting("main"); +} Index: theo/exec/gaussian_directional_2d__float.cc --- theo/exec/gaussian_directional_2d__float.cc (revision 0) +++ theo/exec/gaussian_directional_2d__float.cc (revision 0) @@ -0,0 +1,99 @@ + +# define MLN_FLOAT float + +#include "filetype.hh" +#include "./gaussian_directional_2d.hh" + +#include <mln/io/pgm/load.hh> +#include <mln/io/pgm/save.hh> + +#include <mln/pw/all.hh> + +#include <mln/data/fill.hh> +#include <mln/level/saturate.hh> + + + + + +void usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << " input.xxx bdr dir sigma output.pgm" << std::endl + << " xxx is pbm or pgm" << std::endl + << " bdr is the outer border value" << std::endl + << " dir = 0 (vertical blur) or 1 (horizontal blur)" << std::endl + << " sigma > 0" << std::endl + << " Directional gaussian blur." << std::endl; + std::abort(); +} + + + +int main(int argc, char* argv[]) +{ + + using namespace mln; + using value::int_u8; + + trace::entering("main"); + + if (argc != 6) + usage(argv); + + + int dir = atoi(argv[3]); + if (dir != 0 && dir != 1) + usage(argv); + + MLN_FLOAT sigma = atof(argv[4]); + if (sigma <= 0.f) + usage(argv); + + + switch (get_filetype(argv[1])) + { + case filetype::pbm: + { + int bdr = atoi(argv[2]); + if (bdr != 0 && bdr != 1) + usage(argv); + + image2d<bool> ima; + io::pbm::load(ima, argv[1]); + + image2d<MLN_FLOAT> temp(ima.domain()), out; + data::fill(temp, ima); + + out = linear::gaussian_directional_2d(temp, dir, sigma, bdr); + + io::pgm::save(level::saturate(int_u8(), + (pw::value(out) * pw::cst(255.f)) | out.domain()), + argv[5]); + } + break; + + case filetype::pgm: + { + int bdr = atoi(argv[2]); + if (bdr < 0 || bdr > 255) + usage(argv); + + image2d<int_u8> ima; + io::pgm::load(ima, argv[1]); + + image2d<MLN_FLOAT> temp(ima.domain()), out; + data::fill(temp, ima); + + out = linear::gaussian_directional_2d(temp, dir, sigma, bdr); + + io::pgm::save(level::saturate(int_u8(), out), argv[5]); + } + break; + + default: + std::cerr << "file type not handled!" << std::endl; + usage(argv); + } + + trace::exiting("main"); +} Index: theo/exec/distance_thick.cc --- theo/exec/distance_thick.cc (revision 0) +++ theo/exec/distance_thick.cc (revision 0) @@ -0,0 +1,46 @@ +#include "filetype.hh" + +#include <mln/transform/distance_front.hh> +#include <mln/make/w_window2d_int.hh> +#include <mln/level/stretch.hh> + + + +void usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << " input.pbm dmap.pgm" << std::endl + << " Distance is stretch (from int_u12) to int_u8." << std::endl; + std::abort(); +} + + + +int main(int argc, char* argv[]) +{ + using namespace mln; + using value::int_u8; + typedef value::int_u<12> int_u12; + + if (argc != 3) + usage(argv); + + trace::entering("main"); + + image2d<bool> ima; + io::pbm::load(ima, argv[1]); + + int ws[] = { 00, 11, 0, 11, 0, + 11, 7, 5, 7, 11, + 00, 5, 0, 5, 0, + 11, 7, 5, 7, 11, + 00, 11, 0, 11, 0 }; + + image2d<int_u12> dmap = transform::distance_front(ima, + c4(), make::w_window2d_int(ws), + mln_max(int_u12)); + + io::pgm::save(level::stretch(int_u8(), dmap), + argv[2]); + + trace::exiting("main"); +} Index: theo/exec/closing_rectangle.cc --- theo/exec/closing_rectangle.cc (revision 3564) +++ theo/exec/closing_rectangle.cc (working copy) @@ -6,9 +6,10 @@ void usage(char* argv[]) { - std::cerr << "usage: " << argv[0] << " input.pgm height width output.pgm" << std::endl + std::cerr << "usage: " << argv[0] << " input.xxx height width output.xxx" << std::endl << " Height and width are odd positive integers." << std::endl - << " Rectangle closing." << std::endl; + << " xxx is pbm or pgm." << std::endl + << " Rectangle closing on a 2D image." << std::endl; std::abort(); } @@ -32,11 +33,30 @@ if (width < 0 || width % 2 == 0) usage(argv); + + std::string filename = argv[1]; + + switch (get_filetype(argv[1])) + { + case filetype::pbm: + { + image2d<bool> ima, clo; + io::pbm::load(ima, argv[1]); + clo = morpho::closing::structural(ima, win::rectangle2d(height, width)); + io::pbm::save(clo, argv[4]); + } + break; + + case filetype::pgm: + { image2d<int_u8> ima, clo; io::pgm::load(ima, argv[1]); - clo = morpho::closing::structural(ima, win::rectangle2d(height, width)); io::pgm::save(clo, argv[4]); + } + break; + }; + trace::exiting("main"); } Index: theo/exec/opening_rectangle.cc --- theo/exec/opening_rectangle.cc (revision 0) +++ theo/exec/opening_rectangle.cc (revision 0) @@ -0,0 +1,62 @@ +#include "filetype.hh" + +#include <mln/morpho/opening/structural.hh> + + + +void usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << " input.xxx height width output.xxx" << std::endl + << " Height and width are odd positive integers." << std::endl + << " xxx is pbm or pgm." << std::endl + << " Rectangle opening on a 2D image." << std::endl; + std::abort(); +} + + + +int main(int argc, char* argv[]) +{ + using namespace mln; + using value::int_u8; + + trace::entering("main"); + + if (argc != 5) + usage(argv); + + int height = atoi(argv[2]); + if (height < 0 || height % 2 == 0) + usage(argv); + + int width = atoi(argv[3]); + if (width < 0 || width % 2 == 0) + usage(argv); + + + std::string filename = argv[1]; + + switch (get_filetype(argv[1])) + { + case filetype::pbm: + { + image2d<bool> ima, ope; + io::pbm::load(ima, argv[1]); + ope = morpho::opening::structural(ima, win::rectangle2d(height, width)); + io::pbm::save(ope, argv[4]); + } + break; + + case filetype::pgm: + { + image2d<int_u8> ima, ope; + io::pgm::load(ima, argv[1]); + ope = morpho::opening::structural(ima, win::rectangle2d(height, width)); + io::pgm::save(ope, argv[4]); + } + break; + }; + + + trace::exiting("main"); +} Index: theo/exec/closing_isotropic.cc --- theo/exec/closing_isotropic.cc (revision 3564) +++ theo/exec/closing_isotropic.cc (working copy) @@ -19,6 +19,7 @@ int main(int argc, char* argv[]) { using namespace mln; + using value::int_u8; if (argc != 4) usage(argv); @@ -46,6 +47,15 @@ } break; + case filetype::pgm: + { + image2d<int_u8> ima, out; + io::pgm::load(ima, argv[1]); + out = morpho::closing::structural(ima, win::disk2d(2 * r + 1)); + io::pgm::save(out, argv[3]); + } + break; + case filetype::dump: { image3d<bool> ima, out;
participants (1)
-
Thierry Geraud