Milena (Olena)
User documentation 2.0a Id
|
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 }