• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

constrained-connectivity.cc

00001 // Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
00002 //
00003 // This file is part of Olena.
00004 //
00005 // Olena is free software: you can redistribute it and/or modify it under
00006 // the terms of the GNU General Public License as published by the Free
00007 // Software Foundation, version 2 of the License.
00008 //
00009 // Olena is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with Olena.  If not, see <http://www.gnu.org/licenses/>.
00016 //
00017 // As a special exception, you may use this file as part of a free
00018 // software project without restriction.  Specifically, if other files
00019 // instantiate templates or use macros or inline functions from this
00020 // file, or you compile this file and link it with other files to produce
00021 // an executable, this file does not by itself cause the resulting
00022 // executable to be covered by the GNU General Public License.  This
00023 // exception does not however invalidate any other reasons why the
00024 // executable file might be covered by the GNU General Public License.
00025 
00064 #include <cstdio>
00065 
00066 #include <set>
00067 #include <iostream>
00068 
00069 #include <mln/value/int_u8.hh>
00070 #include <mln/core/image/image2d.hh>
00071 
00072 #include <mln/pw/all.hh>
00073 
00074 #include <mln/fun/vv2v/diff_abs.hh>
00075 #include <mln/world/inter_pixel/immerse.hh>
00076 #include <mln/world/inter_pixel/compute.hh>
00077 #include <mln/world/inter_pixel/neighb2d.hh>
00078 
00079 #include <mln/morpho/watershed/topological.hh>
00080 
00081 #include <mln/morpho/tree/compute_attribute_image.hh>
00082 #include <mln/accu/stat/min.hh>
00083 #include <mln/accu/stat/max.hh>
00084 
00085 #include <mln/io/pgm/load.hh>
00086 #include <mln/debug/println.hh>
00087 
00088 #include <mln/core/var.hh>
00089 
00090 
00091 int main(int argc, char* argv[])
00092 {
00093   if (argc != 2)
00094     {
00095       std::cerr << "Usage: " << argv[0] << " input.pgm" << std::endl;
00096       std::exit(1);
00097     }
00098 
00099   using namespace mln;
00100   using mln::value::int_u8;
00101 
00102   // Load an image.
00103   image2d<int_u8> input;
00104   io::pgm::load(input, argv[1]);
00105 
00106   // Double its resolution.
00107   image2d<int_u8> f_(input.nrows() * 2, input.ncols() * 2);
00108   mln_piter_(image2d<int_u8>) p_ima(f_.domain());
00109   for_all(p_ima)
00110   {
00111     /* This conversion from a ``piter'' type to point2d is required,
00112        since an iterator does not expose the interface of the
00113        underlying point (among which the methods row(), col(),
00114        etc.).  */
00115     point2d p_ima_ = p_ima;
00116     point2d p_f(p_ima_.row() / 2, p_ima_.col() / 2);
00117     f_(p_ima) = input(p_f);
00118   }
00119   debug::println("f_:", f_);
00120 
00121   image_if<image2d<int_u8>, world::inter_pixel::is_pixel> f =
00122     world::inter_pixel::immerse(f_);
00123   debug::println("f:", f);
00124 
00125   // Compute the associated line graph gradient.
00126   mln_VAR(g, world::inter_pixel::compute (f, fun::vv2v::diff_abs<int_u8>()));
00127 
00128   debug::println("g:", g);
00129 
00130   // Compute a topological watershed transform on this gradient.
00131   typedef morpho::watershed::topo_wst<g_t, world::inter_pixel::dbl_neighb2d> tree_t;
00132   tree_t tree(g, world::inter_pixel::e2e());
00133   tree.go();
00134   mln_VAR(w, morpho::watershed::topological(tree));
00135   debug::println("w:", w);
00136 
00137   // Computing the set of values of W.
00138   // FIXME: Milena may provide something simpler than this.
00139   std::set<int_u8> values;
00140   mln_piter_(w_t) p2(w.domain());
00141   for_all(p2)
00142     values.insert(w(p2));
00143 
00144   // Thresholding W for each value of the image.
00145   for (std::set<int_u8>::const_iterator alpha = values.begin();
00146        alpha != values.end(); ++alpha)
00147     {
00148       mln_VAR(alpha_cc, w | (pw::value(w) > pw::cst(*alpha)));
00149       std::cout << *alpha << "-cc:" << std::endl;
00150       /* FIXME: There should be variants of debug::println allowing
00151          the user to pass an optional ``support'' larger than the
00152          actual domain of the image.  For now, use a low-level routine
00153          as a workaround.  */
00154       debug::impl::println(w.unmorph_().domain(), alpha_cc);
00155     }
00156 
00157 
00158   // Compute the height (max - min) of connected components on the line
00159   // graph-based watershed, but with min and max values computed on
00160   // vertices.
00161 
00162   /* FIXME: Of course, we'd like to be able to reuse the component
00163      tree within TREE instead of rebuilding a morpho::tree::data...
00164      This requires some changes in the topological WST implementation,
00165      to make its component tree structure compatible with
00166      morpho::tree::data.  */
00167   typedef p_array<tree_t::site> sites_t;
00168   sites_t sites = data::sort_psites_decreasing(w);
00169   morpho::tree::data<w_t, sites_t> t(w, sites, world::inter_pixel::e2e());
00170 
00171   // Create initial images for min and max values on sites (not components).
00172   mln_ch_value_(w_t, accu::stat::min<int_u8>) init_min_val;
00173   initialize (init_min_val, w);
00174   mln_ch_value_(w_t, accu::stat::max<int_u8>) init_max_val;
00175   initialize (init_max_val, w);
00176 
00177   /* Compute the min and max values on vertices (pixels) adjacent to
00178      edge E.
00179 
00180      Unfortunately, the data structure G does not record any
00181      information from the image F (i.e., the values on
00182      vertices/pixels).  We have to convert the coordinates of V to its
00183      equivalent in F's domain to get the values on vertices.  */
00184   mln_piter_(w_t) e(w.domain());
00185   mln_niter_(world::inter_pixel::dbl_neighb2d)
00186     v_g(world::inter_pixel::e2v(), e);
00187   for_all(e)
00188     for_all(v_g)
00189     {
00190       // Same remark as above avour piter to point2d conversions.
00191       point2d v_g_ = v_g;
00192       point2d v_f(v_g_.row() / 2, v_g_.col() / 2);
00193       init_min_val(e).take(f_(v_f));
00194       init_max_val(e).take(f_(v_f));
00195     }
00196   // Attribute images of min and max values on components.
00197   accu::stat::min<int_u8> min_accu;
00198   mln_ch_value_(w_t, int_u8) min_val =
00199     morpho::tree::compute_attribute_image_from(min_accu, t, init_min_val);
00200   accu::stat::max<int_u8> max_accu;
00201   mln_ch_value_(w_t, int_u8) max_val =
00202     morpho::tree::compute_attribute_image_from(max_accu, t, init_max_val);
00203   // Attribute image of components' height.
00204   mln_ch_value_(w_t, int_u8) height;
00205   initialize(height, w);
00206   for_all(e)
00207     height(e) = max_val(e) - min_val(e);
00208   debug::println(height);
00209 
00210   // Thresholding W using first integer values with a condition on HEIGHT.
00211   for (unsigned alpha = 0; alpha <= 6; ++alpha)
00212     {
00213       mln_VAR(alpha_alpha_cc,
00214               w | (pw::value(w) > pw::cst(alpha)
00215                    || (pw::value(height) > pw::cst(alpha))));
00216       std::cout << "(" << alpha << ", " << alpha << ")-cc:" << std::endl;
00217       // FIXME: Same remark as above about println.
00218       debug::impl::println(w.unmorph_().domain(), alpha_alpha_cc);
00219     }
00220 }

Generated on Fri Sep 16 2011 16:33:26 for Milena (Olena) by  doxygen 1.7.1