* green/tools/annotating/histo/histo.cc: Manage new inputs/outputs. * green/tools/annotating/opening/opening.cc: Manage new inputs/outputs. * green/tools/annotating/iz/Makefile.am: New Makefile. * green/tools/annotating/iz/iz.cc: New file. * green/tools/annotating/regmax/regmax.cc: Manage new inputs/outputs. --- milena/sandbox/ChangeLog | 10 + .../sandbox/green/tools/annotating/histo/histo.cc | 84 +++-- .../tools/annotating/{histo => iz}/Makefile.am | 0 milena/sandbox/green/tools/annotating/iz/iz.cc | 373 ++++++++++++++++++++ .../green/tools/annotating/opening/opening.cc | 76 +++-- .../green/tools/annotating/regmax/regmax.cc | 253 ++++++++++++-- 6 files changed, 714 insertions(+), 82 deletions(-) copy milena/sandbox/green/tools/annotating/{histo => iz}/Makefile.am (100%) create mode 100644 milena/sandbox/green/tools/annotating/iz/iz.cc
diff --git a/milena/sandbox/ChangeLog b/milena/sandbox/ChangeLog index b9d40cb..097ea5c 100644 --- a/milena/sandbox/ChangeLog +++ b/milena/sandbox/ChangeLog @@ -1,3 +1,13 @@ +2010-02-10 Yann Jacquelet jacquelet@lrde.epita.fr + + Fix last details in the image processing chain. + + * green/tools/annotating/histo/histo.cc: Manage new inputs/outputs. + * green/tools/annotating/opening/opening.cc: Manage new inputs/outputs. + * green/tools/annotating/iz/Makefile.am: New Makefile. + * green/tools/annotating/iz/iz.cc: New file. + * green/tools/annotating/regmax/regmax.cc: Manage new inputs/outputs. + 2010-01-05 Yann Jacquelet jacquelet@lrde.epita.fr
Extend the histogram visualization tools for new projection concept. diff --git a/milena/sandbox/green/tools/annotating/histo/histo.cc b/milena/sandbox/green/tools/annotating/histo/histo.cc index ab0b8af..8037e1a 100644 --- a/milena/sandbox/green/tools/annotating/histo/histo.cc +++ b/milena/sandbox/green/tools/annotating/histo/histo.cc @@ -16,14 +16,14 @@
#include <mln/fun/v2v/rgb8_to_rgbn.hh>
-#include <mln/io/dump/save.hh> #include <mln/io/pbm/load.hh> -#include <mln/io/pbm/save.hh> -#include <mln/io/pgm/load.hh> -#include <mln/io/pgm/save.hh> #include <mln/io/ppm/load.hh> +#include <mln/io/dump/save.hh> +#include <mln/io/pgm/save.hh> #include <mln/io/ppm/save.hh>
+#include <mln/literal/colors.hh> + #include <mln/opt/at.hh>
#include <mln/pw/value.hh> @@ -33,15 +33,19 @@
template <unsigned n> -void mk_histo(const std::string& input, - const std::string& output, - const std::string& histo, - const std::string& mask) +void mk_histo(const std::string& input, // in + const std::string& quant, // in + const std::string& histo, // out + const std::string& proj1, // out + const std::string& proj2, // out + const std::string& mask) // [in] { typedef mln::value::int_u8 t_int_u8; + typedef mln::value::int_u<n> t_int_un; typedef mln::value::rgb8 t_rgb8; typedef mln::value::rgb<n> t_rgbn; typedef mln::image2d<t_int_u8> t_image2d_int_u8; + typedef mln::image2d<t_int_un> t_image2d_int_un; typedef mln::image2d<t_rgb8> t_image2d_rgb8; typedef mln::image2d<t_rgbn> t_image2d_rgbn; typedef mln::image2d<bool> t_image2d_bool; @@ -54,7 +58,9 @@ void mk_histo(const std::string& input, t_image2d_rgbn i1_input; // input rgbn t_image2d_bool m0_input; // mask input t_histo3d h1_input; // histo input - t_image2d_int_u8 p1_histo; // histo proj + t_image2d_int_u8 p1_histo1;// histo proj1 + t_image2d_rgbn p1_histo2;// histo proj2 + t_rgbn red(mln::literal::red);
mln::io::ppm::load(i0_input, input.c_str()); i1_input = mln::data::transform(i0_input, t_rgb8_to_rgbn()); @@ -72,9 +78,13 @@ void mk_histo(const std::string& input, // END OF IMAGE PROCESSING CHAIN
// BEGIN DUMPING - p1_histo = mln::display::display_histo3d_unsigned(h1_input); + p1_histo1 = mln::display::display_histo3d_unsigned(h1_input); + p1_histo2 = mln::display::display3_histo3d_unsigned(h1_input, red); + + mln::io::ppm::save(i1_input, quant.c_str()); mln::io::dump::save(h1_input, histo.c_str()); - mln::io::pgm::save(p1_histo, output.c_str()); + mln::io::pgm::save(p1_histo1, proj1.c_str()); + mln::io::ppm::save(p1_histo2, proj2.c_str()); // END DUMPING }
@@ -82,35 +92,47 @@ void mk_histo(const std::string& input, void usage() { std::cout << std::endl; - std::cout << "histo input.ppm q out.ppm histo.dump [msk.pbm]" << std::endl; - std::cout << "where" << std::endl; - std::cout << "input.ppm is the 8 bits color ppm image" << std::endl; - std::cout << "q is the degree of quanification {2,3,4,5,6,7,8}" << std::endl; - std::cout << "out.pgm is the r/g projection of the histogram" << std::endl; - std::cout << "out.dump is the quantified color histogram" << std::endl; - std::cout << "msk.pbm is the mask which select the pixels" << std::endl; + std::cout << "histo input.ppm q quant.ppm histo.dump proj.pgm" + << " proj.ppm [msk.pbm]" << std::endl; + std::cout << std::endl; + std::cout << "where :" << std::endl; + std::cout << "* [ in] input.ppm is the 8 bits color ppm image" << std::endl; + std::cout << "* [ in] q is the degree of quantification" + << " {2,3,4,5,6,7,8}" << std::endl; + std::cout << "* [out] quant.ppm is the q bits quantified input" + << " image" << std::endl; + std::cout << "* [out] histo.dump is the quantified color" + << " histogram" << std::endl; + std::cout << "* [out] proj.pgm is the r/g projection of the" + << " histogram (summing along the blue axe)" << std::endl; + std::cout << "* [out] proj.ppm is the r/g projection of the" + << " histogram with maxima plot on" << std::endl; + std::cout << "* [ in] msk.pbm is the mask which selects the" + << " pixels" << std::endl; std::cout << std::endl; }
int main(int argc, char* args[]) { - if (5 == argc || 6 == argc) + if (7 == argc || 8 == argc) { - const std::string input(args[1]); - const char q = args[2][0]; - const std::string output(args[3]); - const std::string histo(args[4]); - const std::string mask(6 == argc? args[5] : ""); + const std::string input(args[1]); // in + const char q = args[2][0]; // in + const std::string quant(args[3]); // out + const std::string histo(args[4]); // out + const std::string proj1(args[5]); // out + const std::string proj2(args[6]); // out + const std::string mask(8 == argc? args[7] : ""); // [in]
switch(q) { - case '2': mk_histo<2>(input, output, histo, mask); break; - case '3': mk_histo<3>(input, output, histo, mask); break; - case '4': mk_histo<4>(input, output, histo, mask); break; - case '5': mk_histo<5>(input, output, histo, mask); break; - case '6': mk_histo<6>(input, output, histo, mask); break; - case '7': mk_histo<7>(input, output, histo, mask); break; - case '8': mk_histo<8>(input, output, histo, mask); break; + case '2': mk_histo<2>(input, quant, histo, proj1, proj2, mask); break; + case '3': mk_histo<3>(input, quant, histo, proj1, proj2, mask); break; + case '4': mk_histo<4>(input, quant, histo, proj1, proj2, mask); break; + case '5': mk_histo<5>(input, quant, histo, proj1, proj2, mask); break; + case '6': mk_histo<6>(input, quant, histo, proj1, proj2, mask); break; + case '7': mk_histo<7>(input, quant, histo, proj1, proj2, mask); break; + case '8': mk_histo<8>(input, quant, histo, proj1, proj2, mask); break; default: usage(); break; } } diff --git a/milena/sandbox/green/tools/annotating/histo/Makefile.am b/milena/sandbox/green/tools/annotating/iz/Makefile.am similarity index 100% copy from milena/sandbox/green/tools/annotating/histo/Makefile.am copy to milena/sandbox/green/tools/annotating/iz/Makefile.am diff --git a/milena/sandbox/green/tools/annotating/iz/iz.cc b/milena/sandbox/green/tools/annotating/iz/iz.cc new file mode 100644 index 0000000..07e5dd9 --- /dev/null +++ b/milena/sandbox/green/tools/annotating/iz/iz.cc @@ -0,0 +1,373 @@ +// TOOLS ==> influence zone transformation + +#include <iostream> +#include <fstream> +#include <boost/format.hpp> + +#include <mln/accu/stat/histo3d_rgb.hh> + +#include <mln/core/macros.hh> +#include <mln/core/alias/neighb3d.hh> +#include <mln/core/image/image2d.hh> +#include <mln/core/image/image3d.hh> + +#include <mln/data/compute.hh> + +#include <mln/display/display_histo.hh> + +#include <mln/io/dump/load.hh> +#include <mln/io/dump/save.hh> +#include <mln/io/ppm/load.hh> +#include <mln/io/ppm/save.hh> +#include <mln/io/pgm/load.hh> +#include <mln/io/pgm/save.hh> + +#include <mln/literal/colors.hh> + +#include <mln/labeling/compute.hh> +#include <mln/labeling/mean_values.hh> + +#include <mln/transform/influence_zone_geodesic.hh> + +#include <mln/value/int_u8.hh> + +template <unsigned n> +struct t_labeling_rgbn : mln::Function_v2v< t_labeling_rgbn<n> > +{ + typedef mln::value::rgb<n> t_rgbn; + typedef mln::value::label_8 t_lbl8; + typedef t_rgbn argument; + typedef t_lbl8 result; + typedef mln::image3d<t_lbl8> t_label; + + const t_label& _label; + + t_labeling_rgbn(const t_label& label) : _label(label) {} + + result operator()(const argument& c) const + { + t_lbl8 tmp = mln::opt::at(_label, c.blue(), c.red(), c.green()); + + return tmp; + } +}; + +void compute_stats(const mln::image2dmln::value::rgb8& i_input_rgb8, + const mln::image2dmln::value::label_8& l_input_lbl8, + const mln::image3d<unsigned>& h_histo_rgbn, + const mln::image3dmln::value::label_8& l_histo_lbl8, + const mln::value::label_8& n_labels, + const std::string& log) +{ + typedef mln::algebra::vec<3,float> t_vec3f; + typedef mln::accu::math::sum<unsigned,unsigned> t_sum; + typedef mln::accu::stat::mean<t_vec3f,t_vec3f,t_vec3f> t_mean; + typedef mln::util::array<unsigned> t_count_array; + typedef mln::util::array<t_vec3f> t_mean_array; + + mln::util::array<float> abs((unsigned)(n_labels)+1); + mln::util::array<float> rel((unsigned)(n_labels)+1); + unsigned nb = 0; + + for (unsigned i = 0; i <= n_labels; ++i) + { + abs[i] = 0.0; + rel[i] = 0.0; + } + + // COMPUTE THE SUM + t_count_array count = mln::labeling::compute(t_sum(), + h_histo_rgbn, + l_histo_lbl8, + n_labels); + + // COMPUTE THE TOTAL + for (unsigned i = 0; i <= n_labels; ++i) + { + unsigned c = count[i]; + nb += c; + } + + // COMPUTE THE PERCENTAGES + for (unsigned i = 0; i <= n_labels; ++i) + if (0 < count[i]) + { + abs[i] = ((float)count[i] / nb)*100.0; + rel[i] = ((float)count[i] / (nb - count[0]))*100.0; + } + + // COMPUTE THE MEAN + + t_mean_array mean = mln::labeling::compute(t_mean(), + i_input_rgb8, + l_input_lbl8, + n_labels); + + // CORRECT 0 LABEL STATS + rel[0] = 0; + mean[0][0] = 255.0; + mean[0][1] = 255.0; + mean[0][2] = 0.0; + + // PRINT STATS + std::ofstream log_stream(log.c_str()); + + for (unsigned i = 0; i <= n_labels; ++i) + { + const t_vec3f& mean_v = mean[i]; + + log_stream << boost::format("%2i|" + "r = %6.2f, g = %6.2f, b = %6.2f |" + "c = %7i, %%i = %5.2f, %%c = %5.2f") + % i + % mean_v[0] + % mean_v[1] + % mean_v[2] + % count[i] + % abs[i] + % rel[i] + << std::endl; + } + + log_stream << std::endl << std::endl; + log_stream.flush(); + log_stream.close(); +} + +bool expect(std::istream& stream, const std::string expected) +{ + bool result; + std::string got; + + stream >> got; + + result = (got == expected); + + return result; +} + +std::istream& operator>>(std::istream& stream, + mln::algebra::vec<3,float>& color) +{ + unsigned lbl; + + stream >> lbl; + if (expect(stream, std::string("|")) && + expect(stream, std::string("r")) && + expect(stream, std::string("="))) + { + stream >> color[0]; + + if (expect(stream, std::string(",")) && + expect(stream, std::string("g")) && + expect(stream, std::string("="))) + { + stream >> color[1]; + + if (expect(stream, std::string(",")) && + expect(stream, std::string("b")) && + expect(stream, std::string("="))) + { + stream >> color[2]; + } + } + } + + return stream; +} + +void load(mln::util::array< mln::algebra::vec<3,float> >& m2_label, + const char *colormap) +{ + typedef mln::algebra::vec<3,float> t_vec3f; + typedef mln::util::array<t_vec3f> t_mean_array; + + std::ifstream stream(colormap); + std::string buffer; + + getline(stream, buffer); + + while (0 < buffer.size()) + { + std::stringstream line(buffer); + t_vec3f mean_v; + + line >> mean_v; + + m2_label.append(mean_v); + + getline(stream, buffer); + } + + stream.close(); +} + +template<unsigned n> +void mk_iz(const std::string& labeled, // in + const unsigned d, // in + const mln::neighb3d& nbh, // in + const std::string& input, // in + const std::string& quant, // in + const std::string& histo, // in + const std::string& colormap,// in + const std::string& iz, // out + const std::string& proj, // out + const std::string& mean, // out + const std::string& stats) // [out] +{ + typedef mln::value::int_u8 t_int_u8; + typedef mln::value::label_8 t_lbl8; + typedef mln::value::rgb8 t_rgb8; + typedef mln::value::rgb<n> t_rgbn; + typedef mln::algebra::vec<3,float> t_v3f; + typedef mln::image2d<t_int_u8> t_image2d_int_u8; + typedef mln::image2d<t_rgb8> t_image2d_rgb8; + typedef mln::image2d<t_rgbn> t_image2d_rgbn; + typedef mln::image2d<t_lbl8> t_image2d_lbl8; + typedef mln::image3d<unsigned> t_histo3d; + typedef mln::image3d<t_lbl8> t_image3d_lbl8; + typedef mln::accu::meta::stat::histo3d_rgb t_histo3d_fun; + typedef mln::accu::stat::mean<t_v3f,t_v3f,t_v3f> t_mean; + typedef mln::util::array<t_v3f> t_mean_array; + + // START OF IMAGE PROCESSING CHAIN + t_image2d_rgb8 i0_input; // input img + t_image2d_rgbn i1_input; // quant img + t_histo3d h1_input; // histo input + t_histo3d h2_input; // histo input + t_image2d_int_u8 p1_histo; // histo proj + t_image2d_rgb8 p3_histo; // histo proj + t_image3d_lbl8 l2_histo; // label histo + t_image3d_lbl8 l3_histo; // iz label hist + t_mean_array m2_label; // colormap + t_mean_array m3_label; // colormap + t_image2d_lbl8 l3_input; // label input + t_image2d_rgb8 i3_mean; // reconstructed + + t_lbl8 n_lbl; // nb labels + t_rgb8 red(mln::literal::red); + + mln::io::dump::load(l2_histo, labeled.c_str()); + mln::io::ppm::load(i0_input, input.c_str()); + mln::io::ppm::load(i1_input, quant.c_str()); + mln::io::dump::load(h1_input, histo.c_str()); + load(m2_label, colormap.c_str()); + + if (0 == d) + { + l3_histo = mln::transform::influence_zone_geodesic(l2_histo, nbh); + } + else + { + l3_histo = mln::transform::influence_zone_geodesic(l2_histo, nbh, d); + } + // END OF IMAGE PROCESSING CHAIN + + // BEGIN DUMPING + + n_lbl = (t_lbl8)(m2_label.size()-1); + + l3_input = mln::data::transform(i1_input, t_labeling_rgbn<n>(l3_histo)); + i3_mean = mln::labeling::mean_values(i0_input, l3_input, n_lbl); + m3_label = mln::labeling::compute(t_mean(), i0_input, l3_input, n_lbl); + + // CORRECT 0 LABEL STATS + m3_label[0][0] = 255.0; + m3_label[0][1] = 255.0; + m3_label[0][2] = 0.0; + + p3_histo = mln::display::display3_histo3d_unsigned<n>(h1_input, + l3_histo, + m3_label, + red); + mln::io::dump::save(l3_input, iz.c_str()); + mln::io::ppm::save(p3_histo, proj.c_str()); + mln::io::ppm::save(i3_mean, mean.c_str()); + + if (0 < stats.size()) + compute_stats(i0_input, l3_input, h1_input, l3_histo, n_lbl, stats); + + // END DUMPING +} + + +void usage() +{ + std::cout << std::endl; + std::cout << "iz labeled.dump d nbh input.ppm q quant.ppm" + << " histo.dump colormap.txt iz.dump proj.ppm" + << " mean.ppm [stats.txt]" << std::endl; + std::cout << std::endl; + std::cout << "where :" << std::endl; + std::cout << "* [ in] labeled.dump is the labeled 3d histogram" << std::endl; + std::cout << "* [ in] d is the depth for the zone influence" + << " transformation (0 means infinite)" << std::endl; + std::cout << "* [ in] nbh is the 3d neighbourhood {6,18,26}" << std::endl; + std::cout << "* [ in] input.ppm is the 8 bits color ppm image" << std::endl; + std::cout << "* [ in] q is the degree of quantification" + << " {2,3,4,5,6,7,8}" << std::endl; + std::cout << "* [ in] quant.ppm is the q bits quantified input" + << " image" << std::endl; + std::cout << "* [ in] histo.dump is the quantified color" + << " histogram" << std::endl; + std::cout << "* [ in] colormap.txt is the colormap for labels" << std::endl; + std::cout << "* [out] iz.dump is the iz labeled 3d histogram" << std::endl; + std::cout << "* [out] proj.ppm is the r/g projection of the" + << " histogram with maxima label plot on" << std::endl; + std::cout << "* [out] mean.ppm is the mean reconstructed image" << std::endl; + std::cout << "* [out] stats.txt is the statistical label report"<< std::endl; + std::cout << std::endl; +} + +int main(int argc, char* args[]) +{ + if (12 == argc || 13 == argc) + { + const std::string labeled(args[1]); // in + const unsigned d = atoi(args[2]); // in + const char nbh = args[3][0]; // in + const std::string input(args[4]); // in + const char q = args[5][0]; // in + const std::string quant(args[6]); // in + const std::string histo(args[7]); // in + const std::string colormap(args[8]); // in + const std::string iz(args[9]); // out + const std::string proj(args[10]); // out + const std::string mean(args[11]); // out + const std::string stats(13 == argc? args[12] : ""); // [out] + + + mln::neighb3d neighbourhood; + + switch (nbh) + { + case '6': neighbourhood = mln::c6(); break; + case '1': neighbourhood = mln::c18(); break; + case '2': neighbourhood = mln::c26(); break; + default: usage(); return 0; // force usage and quit + } + + switch (q) + { + case '2' : mk_iz<2>(labeled,d,neighbourhood,input,quant, + histo,colormap,iz,proj,mean,stats);break; + case '3' : mk_iz<3>(labeled,d,neighbourhood,input,quant, + histo,colormap,iz,proj,mean,stats);break; + case '4' : mk_iz<4>(labeled,d,neighbourhood,input,quant, + histo,colormap,iz,proj,mean,stats);break; + case '5' : mk_iz<5>(labeled,d,neighbourhood,input,quant, + histo,colormap,iz,proj,mean,stats);break; + case '6' : mk_iz<6>(labeled,d,neighbourhood,input,quant, + histo,colormap,iz,proj,mean,stats);break; + case '7' : mk_iz<7>(labeled,d,neighbourhood,input,quant, + histo,colormap,iz,proj,mean,stats);break; + case '8' : mk_iz<8>(labeled,d,neighbourhood,input,quant, + histo,colormap,iz,proj,mean,stats);break; + default: usage(); break; + } + } + else + usage(); + + return 0; +} diff --git a/milena/sandbox/green/tools/annotating/opening/opening.cc b/milena/sandbox/green/tools/annotating/opening/opening.cc index 3e1dbf2..cdd37fb 100644 --- a/milena/sandbox/green/tools/annotating/opening/opening.cc +++ b/milena/sandbox/green/tools/annotating/opening/opening.cc @@ -15,36 +15,47 @@
#include <mln/io/dump/load.hh> #include <mln/io/dump/save.hh> -#include <mln/io/pgm/load.hh> +#include <mln/io/ppm/save.hh> #include <mln/io/pgm/save.hh>
+#include <mln/literal/colors.hh> + #include <mln/morpho/opening/volume.hh>
+#include <mln/value/rgb.hh> #include <mln/value/int_u8.hh>
-void mk_opening(const std::string& input, - const unsigned min_vol, - const std::string& output, - const std::string& opened) +template <unsigned n> +void mk_opening(const std::string& histo, // in + const unsigned min_vol, // in + const std::string& opened, // out + const std::string& proj1, // out + const std::string& proj2) // out { typedef mln::value::int_u8 t_int_u8; + typedef mln::value::rgb<n> t_rgbn; typedef mln::image2d<t_int_u8> t_image2d_int_u8; + typedef mln::image2d<t_rgbn> t_image2d_rgbn; typedef mln::image3d<unsigned> t_histo3d; typedef mln::accu::meta::stat::histo3d_rgb t_histo3d_fun;
// START OF IMAGE PROCESSING CHAIN t_histo3d h1_input; // histo input t_histo3d h2_input; // histo input - t_image2d_int_u8 p1_histo; // histo proj + t_image2d_int_u8 p1_histo1;// histo proj1 + t_image2d_rgbn p1_histo2;// histo proj2 + t_rgbn red(mln::literal::red);
- mln::io::dump::load(h1_input, input.c_str()); + mln::io::dump::load(h1_input, histo.c_str()); h2_input = mln::morpho::opening::volume(h1_input, mln::c6(), min_vol); // END OF IMAGE PROCESSING CHAIN
// BEGIN DUMPING - p1_histo = mln::display::display_histo3d_unsigned(h2_input); + p1_histo1 = mln::display::display_histo3d_unsigned(h2_input); + p1_histo2 = mln::display::display3_histo3d_unsigned(h2_input, red); mln::io::dump::save(h2_input, opened.c_str()); - mln::io::pgm::save(p1_histo, output.c_str()); + mln::io::pgm::save(p1_histo1, proj1.c_str()); + mln::io::ppm::save(p1_histo2, proj2.c_str()); // END DUMPING }
@@ -52,25 +63,46 @@ void mk_opening(const std::string& input, void usage() { std::cout << std::endl; - std::cout << "opening input.dump v out.dump out.ppm" << std::endl; - std::cout << "where" << std::endl; - std::cout << "input.dump is the 3d color input histo" << std::endl; - std::cout << "v is the minimum size of each composant" << std::endl; - std::cout << "out.pgm is the r/g proj of the opened histogram" << std::endl; - std::cout << "out.dump is the opened histogram" << std::endl; + std::cout << "opening q histo.dump v opened.dump proj.pgm" + << " proj.ppm" << std::endl; + std::cout << std::endl; + std::cout << "where :" << std::endl; + std::cout << "* [ in] q is the degree of quantification" + << " {2,3,4,5,6,7,8}" << std::endl; + std::cout << "* [ in] histo.dump is the quantified color" + << " histogram" << std::endl; + std::cout << "* [ in] v is the minimum size (in pixels) of" + << " each composant" << std::endl; + std::cout << "* [out] opened.dump is the filtered histogram" << std::endl; + std::cout << "* [out] proj.pgm is the r/g projection of the" + << " histogram (summing along the blue axe)" << std::endl; + std::cout << "* [out] proj.ppm is the r/g projection of the" + << " histogram with maxima plot on" << std::endl; std::cout << std::endl; }
int main(int argc, char* args[]) { - if (5 == argc) + if (7 == argc) { - const std::string input(args[1]); - const unsigned min_vol = atoi(args[2]); - const std::string output(args[3]); - const std::string opened(args[4]); - - mk_opening(input, min_vol, output, opened); + const char q = args[1][0]; // in + const std::string histo(args[2]); // in + const unsigned min_vol = atoi(args[3]); // in + const std::string opened(args[4]); // out + const std::string proj1(args[5]); // out + const std::string proj2(args[6]); // out + + switch(q) + { + case '2': mk_opening<2>(histo, min_vol, opened, proj1, proj2); break; + case '3': mk_opening<3>(histo, min_vol, opened, proj1, proj2); break; + case '4': mk_opening<4>(histo, min_vol, opened, proj1, proj2); break; + case '5': mk_opening<5>(histo, min_vol, opened, proj1, proj2); break; + case '6': mk_opening<6>(histo, min_vol, opened, proj1, proj2); break; + case '7': mk_opening<7>(histo, min_vol, opened, proj1, proj2); break; + case '8': mk_opening<8>(histo, min_vol, opened, proj1, proj2); break; + default: usage(); break; + } } else usage(); diff --git a/milena/sandbox/green/tools/annotating/regmax/regmax.cc b/milena/sandbox/green/tools/annotating/regmax/regmax.cc index 2079bc4..0ff4d2e 100644 --- a/milena/sandbox/green/tools/annotating/regmax/regmax.cc +++ b/milena/sandbox/green/tools/annotating/regmax/regmax.cc @@ -1,8 +1,13 @@ // TOOLS ==> regmax on histo
#include <iostream> +#include <fstream> +#include <boost/format.hpp>
#include <mln/accu/stat/histo3d_rgb.hh> +#include <mln/accu/stat/mean.hh> + +#include <mln/algebra/vec.hh>
#include <mln/core/macros.hh> #include <mln/core/alias/neighb3d.hh> @@ -18,9 +23,14 @@ #include <mln/io/dump/save.hh> #include <mln/io/pgm/load.hh> #include <mln/io/pgm/save.hh> +#include <mln/io/ppm/load.hh> #include <mln/io/ppm/save.hh>
#include <mln/labeling/regional_maxima.hh> +#include <mln/labeling/compute.hh> +#include <mln/labeling/mean_values.hh> + +#include <mln/literal/colors.hh>
#include <mln/morpho/opening/volume.hh>
@@ -28,6 +38,8 @@ #include <mln/value/int_u8.hh> #include <mln/value/rgb8.hh>
+#include <mln/util/array.hh> + template <unsigned n> struct t_labeling_rgbn : mln::Function_v2v< t_labeling_rgbn<n> > { @@ -49,19 +61,134 @@ struct t_labeling_rgbn : mln::Function_v2v< t_labeling_rgbn<n> > } };
-void mk_regmax(const std::string& input, - const std::string& quant, - const std::string& histo, - const std::string& label, - const std::string& output) +void compute_stats(const mln::image2dmln::value::rgb8& i_input_rgb8, + const mln::image2dmln::value::label_8& l_input_lbl8, + const mln::image3d<unsigned>& h_histo_rgbn, + const mln::image3dmln::value::label_8& l_histo_lbl8, + const mln::value::label_8& n_labels, + const std::string& log) +{ + typedef mln::algebra::vec<3,float> t_vec3f; + typedef mln::accu::math::sum<unsigned,unsigned> t_sum; + typedef mln::accu::stat::mean<t_vec3f,t_vec3f,t_vec3f> t_mean; + typedef mln::util::array<unsigned> t_count_array; + typedef mln::util::array<t_vec3f> t_mean_array; + + mln::util::array<float> abs((unsigned)(n_labels)+1); + mln::util::array<float> rel((unsigned)(n_labels)+1); + unsigned nb = 0; + + for (unsigned i = 0; i <= n_labels; ++i) + { + abs[i] = 0.0; + rel[i] = 0.0; + } + + // COMPUTE THE SUM + t_count_array count = mln::labeling::compute(t_sum(), + h_histo_rgbn, + l_histo_lbl8, + n_labels); + + // COMPUTE THE TOTAL + for (unsigned i = 0; i <= n_labels; ++i) + { + unsigned c = count[i]; + nb += c; + } + + // COMPUTE THE PERCENTAGES + for (unsigned i = 0; i <= n_labels; ++i) + if (0 < count[i]) + { + abs[i] = ((float)count[i] / nb)*100.0; + rel[i] = ((float)count[i] / (nb - count[0]))*100.0; + } + + // COMPUTE THE MEAN + + t_mean_array mean = mln::labeling::compute(t_mean(), + i_input_rgb8, + l_input_lbl8, + n_labels); + + // CORRECT 0 LABEL STATS + rel[0] = 0; + mean[0][0] = 255.0; + mean[0][1] = 255.0; + mean[0][2] = 0.0; + + // PRINT STATS + std::ofstream log_stream(log.c_str()); + + for (unsigned i = 0; i <= n_labels; ++i) + { + const t_vec3f& mean_v = mean[i]; + + log_stream << boost::format("%2i|" + "r = %6.2f, g = %6.2f, b = %6.2f |" + "c = %7i, %%i = %5.2f, %%c = %5.2f") + % i + % mean_v[0] + % mean_v[1] + % mean_v[2] + % count[i] + % abs[i] + % rel[i] + << std::endl; + } + + log_stream << std::endl << std::endl; + log_stream.flush(); + log_stream.close(); +} + +void save(mln::util::array< mln::algebra::vec<3,float> >& m2_label, + const char *colormap) +{ + typedef mln::algebra::vec<3,float> t_vec3f; + typedef mln::util::array<t_vec3f> t_mean_array; + + std::ofstream stream(colormap); + + for (unsigned i = 0; i < m2_label.size(); ++i) + { + const t_vec3f& mean_v = m2_label[i]; + + stream << boost::format("%2i | r = %6.2f, g = %6.2f, b = %6.2f") + % i + % mean_v[0] + % mean_v[1] + % mean_v[2] + << std::endl; + } + + stream.flush(); + stream.close(); +} + +template <unsigned n> +void mk_regmax(const std::string& input, // in + const std::string& quant, // in + const std::string& histo, // in + const std::string& opened, // in + const mln::neighb3d& nbh, // in + const std::string& labeled, // out + const std::string& proj, // out + const std::string& colormap,// out + const std::string& mean, // out + const std::string& stats) // [out] { typedef mln::value::label_8 t_lbl8; typedef mln::value::rgb8 t_rgb8; - typedef mln::value::rgbn t_rgbn; + typedef mln::value::rgb<n> t_rgbn; typedef mln::value::int_u8 t_int_u8; + typedef mln::value::int_u<n> t_int_un; typedef mln::algebra::vec<3,float> t_v3f; typedef mln::image2d<t_int_u8> t_image2d_int_u8; + typedef mln::image2d<t_int_un> t_image2d_int_un; typedef mln::image2d<t_rgb8> t_image2d_rgb8; + typedef mln::image2d<t_rgbn> t_image2d_rgbn; typedef mln::image3d<t_lbl8> t_image3d_lbl8; typedef mln::image2d<t_lbl8> t_image2d_lbl8; typedef mln::image3d<unsigned> t_histo3d; @@ -71,60 +198,128 @@ void mk_regmax(const std::string& input,
t_image2d_rgb8 i0_input; // input img t_image2d_rgbn i1_input; // quant img + t_histo3d h1_input; // input histo t_histo3d h2_input; // opened histo -// t_image2d_int_u8 p2_label; // histo proj - t_image2d_lbl8 p2_label; // histo proj -// t_image2d_rgb8 p2_label; // histo proj + t_image2d_rgb8 p2_label; // histo proj t_image3d_lbl8 l2_histo; // label histo - t_mean_array m2_label; // palette + t_image2d_lbl8 l2_input; // label input + t_mean_array m2_label; // colormap + t_image2d_rgb8 i2_mean; // reconstructed
t_lbl8 n_lbl; // nb class + t_rgb8 red(mln::literal::red); +
// BEGIN LOADING mln::io::ppm::load(i0_input, input.c_str()); mln::io::ppm::load(i1_input, quant.c_str()); - mln::io::dump::load(h2_input, histo.c_str()); + mln::io::dump::load(h1_input, histo.c_str()); + mln::io::dump::load(h2_input, opened.c_str()); // END LOADING
// BEGIN IMAGE PROCESSING - l2_histo = mln::labeling::regional_maxima(h2_input, mln::c6(), n_lbl); + l2_histo = mln::labeling::regional_maxima(h2_input, nbh, n_lbl); // END IMAGE PROCESSING
// BEGIN SAVING - mln::debug::println(h2_input); mln::io::dump::save(l2_histo, labeled.c_str());
l2_input = mln::data::transform(i1_input, t_labeling_rgbn<n>(l2_histo)); - m2_label = mln::labeling::compute(t_mean(), i0_input, l2_input, n_labels); - p2_label =mln::display::display3_histo3d_unsigned(h2_input,l2_histo,m2_label); + i2_mean = mln::labeling::mean_values(i0_input, l2_input, n_lbl); + m2_label = mln::labeling::compute(t_mean(), i0_input, l2_input, n_lbl); + + // CORRECT 0 LABEL STATS + m2_label[0][0] = 255.0; + m2_label[0][1] = 255.0; + m2_label[0][2] = 0.0; + + p2_label =mln::display::display3_histo3d_unsigned<n>(h1_input, + l2_histo, + m2_label, + red); + + mln::io::ppm::save(p2_label, proj.c_str()); + save(m2_label, colormap.c_str()); + mln::io::ppm::save(i2_mean, mean.c_str()); + + if (0 < stats.size()) + compute_stats(i0_input, l2_input, h1_input, l2_histo, n_lbl, stats);
-// mln::io::pgm::save(p2_label, output.c_str()); - mln::io::ppm::save(p2_label, output.c_str()); - std::cout << "Nb classes : " << n_lbl << std::endl; // END SAVING }
- void usage() { std::cout << std::endl; - std::cout << "regmax input.dump out.dump out.ppm" << std::endl; - std::cout << "where" << std::endl; - std::cout << "input.dump is opened histo" << std::endl; - std::cout << "out.pgm is the r/g proj of the opened histogram" << std::endl; - std::cout << "out.dump is the labeled histogram" << std::endl; + std::cout << "regmax input.ppm q quant.ppm histo.dump" + << " opened.dump nbh labeled.dump proj.ppm" + << " colormap.txt mean.ppm [stats.txt]" << std::endl; + std::cout << std::endl; + std::cout << "where :" << std::endl; + std::cout << "* [ in] input.ppm is the 8 bits color ppm image" << std::endl; + std::cout << "* [ in] q is the degree of quantification" + << " {2,3,4,5,6,7,8}" << std::endl; + std::cout << "* [ in] quant.ppm is the q bits quantified input" + << " image" << std::endl; + std::cout << "* [ in] histo.dump is the quantified color" + << " histogram" << std::endl; + std::cout << "* [ in] opened.dump is the filtered histogram" << std::endl; + std::cout << "* [ in] nbh is the 3d neighbourhood {6,18,26}" << std::endl; + std::cout << "* [out] labeled.dump is the labeled 3d histogram" << std::endl; + std::cout << "* [out] proj.ppm is the r/g projection of the" + << " histogram with maxima label plot on" << std::endl; + std::cout << "* [out] colormap.txt is the colormap for labels" << std::endl; + std::cout << "* [out] mean.ppm is the mean reconstructed image" << std::endl; + std::cout << "* [out] stats.txt is the statistical label report"<< std::endl; std::cout << std::endl; }
int main(int argc, char* args[]) { - if (4 == argc) + if (11 == argc || 12 == argc) { - const std::string input(args[1]); - const std::string output(args[2]); - const std::string labeled(args[3]); + const std::string input(args[1]); // in + const char q = args[2][0]; // in + const std::string quant(args[3]); // in + const std::string histo(args[4]); // in + const std::string opened(args[5]); // in + const char nbh = args[6][0]; // in + const std::string labeled(args[7]); // out + const std::string proj(args[8]); // out + const std::string colormap(args[9]);// out + const std::string mean(args[10]); // out + const std::string stats(12 == argc? args[11] : ""); // [out] + + + mln::neighb3d neighbourhood; + + switch (nbh) + { + case '6': neighbourhood = mln::c6(); break; + case '1': neighbourhood = mln::c18(); break; + case '2': neighbourhood = mln::c26(); break; + default: usage(); return 0; // force usage and quit + } + + switch (q) + {
- mk_regmax(input, output, labeled); + case '2': mk_regmax<2>(input,quant,histo,opened,neighbourhood, + labeled,proj,colormap,mean,stats); break; + case '3': mk_regmax<3>(input,quant,histo,opened,neighbourhood, + labeled,proj,colormap,mean,stats); break; + case '4': mk_regmax<4>(input,quant,histo,opened,neighbourhood, + labeled,proj,colormap,mean,stats); break; + case '5': mk_regmax<5>(input,quant,histo,opened,neighbourhood, + labeled,proj,colormap,mean,stats); break; + case '6': mk_regmax<6>(input,quant,histo,opened,neighbourhood, + labeled,proj,colormap,mean,stats); break; + case '7': mk_regmax<7>(input,quant,histo,opened,neighbourhood, + labeled,proj,colormap,mean,stats); break; + case '8': mk_regmax<8>(input,quant,histo,opened,neighbourhood, + labeled,proj,colormap,mean,stats); break; + default: usage(); break; + } } else usage();