https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)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;