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

artificial_line_graph_image_wst.cc

00001 // Copyright (C) 2008, 2009, 2010 EPITA Research and Development
00002 // Laboratory (LRDE)
00003 //
00004 // This file is part of Olena.
00005 //
00006 // Olena is free software: you can redistribute it and/or modify it under
00007 // the terms of the GNU General Public License as published by the Free
00008 // Software Foundation, version 2 of the License.
00009 //
00010 // Olena is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Olena.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software project without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to produce
00022 // an executable, this file does not by itself cause the resulting
00023 // executable to be covered by the GNU General Public License.  This
00024 // exception does not however invalidate any other reasons why the
00025 // executable file might be covered by the GNU General Public License.
00026 
00027 /* FIXME: We should factor as much things as possible between
00028    tests/morpho/lena_line_graph_image_wst1.cc,
00029    tests/morpho/lena_line_graph_image_wst2.cc and this file, starting
00030    with conversion routines.  */
00031 
00049 #include <mln/core/image/image2d.hh>
00050 #include <mln/core/alias/point2d.hh>
00051 #include <mln/core/alias/window2d.hh>
00052 #include <mln/core/alias/neighb2d.hh>
00053 
00055 #include <mln/core/image/edge_image.hh>
00056 #include <mln/pw/all.hh>
00057 #include <mln/fun/i2v/array.hh>
00058 #include <mln/util/graph.hh>
00059 
00060 #include <mln/morpho/line_gradient.hh>
00061 #include <mln/morpho/closing/area_on_vertices.hh>
00062 #include <mln/morpho/meyer_wst.hh>
00063 #include <mln/data/stretch.hh>
00064 
00065 #include <mln/value/int_u8.hh>
00066 #include <mln/value/int_u16.hh>
00067 #include <mln/value/rgb8.hh>
00068 #include <mln/literal/black.hh>
00069 #include <mln/literal/colors.hh>
00070 
00071 #include <mln/io/pgm/load.hh>
00072 #include <mln/io/pgm/save.hh>
00073 #include <mln/io/ppm/save.hh>
00074 
00075 #include <mln/math/max.hh>
00076 #include <mln/math/abs.hh>
00077 
00078 #include <mln/opt/at.hh>
00079 
00080 #include "tests/data.hh"
00081 
00082 
00083 
00084 int main()
00085 {
00086   using namespace mln;
00087   using value::int_u8;
00088   using value::int_u16;
00089   using value::rgb8;
00090 
00091   /*--------.
00092   | Input.  |
00093   `--------*/
00094 
00095   // Dimensions.
00096   const unsigned nrows = 100;
00097   const unsigned ncols = 100;
00098   const unsigned square_length = 3;
00099   typedef int_u8 input_val_t;
00100   // Create a checkboard image.
00101   image2d<input_val_t> input (nrows, ncols);
00102   for (unsigned  r = 0; r < nrows; ++r)
00103     for (unsigned c = 0; c < ncols; ++c)
00104       opt::at(input, r,c) =
00105         ((r / square_length) % 2 == (c / square_length) % 2)
00106         ? mln_min(input_val_t)
00107         : mln_max(input_val_t);
00108   mln_assertion((nrows * ncols) == 10000);
00109   mln_assertion((2 * nrows * ncols - (nrows + ncols)) == 19800);
00110 
00111   /*----------------.
00112   | Line gradient.  |
00113   `----------------*/
00114 
00115   // Line graph image.
00116   typedef edge_image<util::site_pair<point2d>, input_val_t, util::graph> lg_ima_t;
00117   lg_ima_t lg_ima = morpho::line_gradient(input);
00118 
00119   /*------.
00120   | WST.  |
00121   `------*/
00122 
00123   typedef lg_ima_t::nbh_t nbh_t;
00124   nbh_t nbh;
00125 
00126   // Perform a Watershed Transform.
00127   typedef edge_image<util::site_pair<point2d>, unsigned, util::graph> wshed_t;
00128   unsigned nbasins;
00129   wshed_t wshed = morpho::meyer_wst(lg_ima, nbh, nbasins);
00130   mln_assertion(nbasins == 1155);
00131 
00132   /*---------.
00133   | Output.  |
00134   `---------*/
00135 
00136   // FIXME: Inlined conversion, to be reifed into a routine.
00137 
00138   // Save the result in gray levels (data) + color (wshed).
00139 
00140   // Data.
00141   typedef rgb8 output_val_t;
00142   typedef image2d<output_val_t> output_t;
00143   point2d output_pmin = input.domain().pmin();
00144   point2d output_pmax(input.domain().pmax()[0] * 2,
00145                       input.domain().pmax()[1] * 2);
00146   output_t output(box2d(output_pmin, output_pmax));
00147   data::fill(output, literal::black);
00148   mln_fwd_piter_(image2d<input_val_t>) p(input.domain());
00149   for_all(p)
00150   {
00151     // Equivalent of P in OUTPUT.
00152     point2d q(p[0] * 2, p[1] * 2);
00153     input_val_t v = input(p);
00154     /* FIXME: Use a conversion function from input_val_t to
00155        output_val_t instead of an explicit construction.  */
00156     output(q) = output_val_t(v, v, v);
00157   }
00158   // Interpolate missing points in OUTPUT.
00159   mln_piter_(output_t) p_out(output.domain());
00160   for_all(p_out)
00161   {
00162     // Process points on even rows and odd columns
00163     if (p_out[0] % 2 == 0 && p_out[1] % 2 == 1)
00164       output(p_out) = (output(p_out + left) + output(p_out + right)) / 2;
00165     // Process points on odd rows and even columns
00166     if (p_out[0] % 2 == 1 && p_out[1] % 2 == 0)
00167       output(p_out) = (output(p_out + up) + output(p_out + down)) / 2;
00168     // Process points on odd rows and odd columns
00169     if (p_out[0] % 2 == 1 && p_out[1] % 2 == 1)
00170       output(p_out) =
00171         (output(p_out + dpoint2d(-1, -1)) +
00172          output(p_out + dpoint2d(-1, +1)) +
00173          output(p_out + dpoint2d(+1, -1)) +
00174          output(p_out + dpoint2d(+1, +1))) / 4;
00175   }
00176   // Draw the watershed.
00177   /* FIXME: We should draw the watershed on another image and
00178      superimpose it on OUTPUT instead of drawing it directly into
00179      OUTPUT.  */
00180   mln_piter_(wshed_t) pw(wshed.domain());
00181   for_all(pw)
00182   {
00183     if (wshed(pw) == 0)
00184       {
00185         mln_psite_(lg_ima_t) pp(pw);
00186         // Equivalent of the line (edge) PP in OUTPUT.
00187         int row1 = pp.first()[0] * 2;
00188         int col1 = pp.first()[1] * 2;
00189         int row2 = pp.second()[0] * 2;
00190         int col2 = pp.second()[1] * 2;
00191         point2d q((row1 + row2) / 2, (col1 + col2) / 2);
00192         // Print the watershed in red.
00193         output(q) = literal::red;
00194       }
00195   }
00196   // Fill the holes, so that the watershed looks connected.
00197   /* FIXME: This approach is bad: it creates thick lines of watershed.
00198      We should probably solve this when we ``paint'' the watershed
00199      over the ``doubled'' image.
00200 
00201      A better approach is probably to iterate over the set of vertices,
00202      and ``connect'' edges according to patterns (vertically or
00203      horizontally connected egdes member of the watershed, etc.).  */
00204   // Reuse the piter on OUTPUT.
00205   for_all (p_out)
00206     // Only handle points on odd rows and columns.
00207     if (p_out[0] % 2 == 1 && p_out[1] % 2 == 1)
00208   {
00209     // Count the number of adjacent watershed points.  If there are
00210     // two or more, consider, create a watershed point.
00211     /* FIXME: Iterating over a c4 window would be more elegant, of
00212        course.  */
00213     unsigned nwsheds =
00214       (output.has(p_out + up   ) && output(p_out + up   ) == literal::red) +
00215       (output.has(p_out + down ) && output(p_out + down ) == literal::red) +
00216       (output.has(p_out + left ) && output(p_out + right) == literal::red) +
00217       (output.has(p_out + right) && output(p_out + left ) == literal::red);
00218     if (nwsheds >= 2)
00219       output(p_out) = literal::red;
00220   }
00221   io::ppm::save(output, "artificial_line_graph_image_wst-out.ppm");
00222 }

Generated on Tue Oct 4 2011 15:23:24 for Milena (Olena) by  doxygen 1.7.1