
* mln/transform/hough.hh: new routine. * tests/transform/Makefile.am, * tests/transform/hough.cc: new associated test. --- milena/ChangeLog | 9 ++ milena/mln/transform/hough.hh | 216 ++++++++++++++++++++++++++++++++++++ milena/tests/transform/Makefile.am | 2 + milena/tests/transform/hough.cc | 59 ++++++++++ 4 files changed, 286 insertions(+), 0 deletions(-) create mode 100644 milena/mln/transform/hough.hh create mode 100644 milena/tests/transform/hough.cc diff --git a/milena/ChangeLog b/milena/ChangeLog index fb68d60..40f9f88 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,3 +1,12 @@ +2009-05-15 Guillaume Lazzara <lazzara@lrde.epita.fr> + + Add hough transform. + + * mln/transform/hough.hh: new routine. + + * tests/transform/Makefile.am, + * tests/transform/hough.cc: new associated test. + 2009-05-15 Roland Levillain <roland@lrde.epita.fr> Regen Makefile helpers. diff --git a/milena/mln/transform/hough.hh b/milena/mln/transform/hough.hh new file mode 100644 index 0000000..61ecc4f --- /dev/null +++ b/milena/mln/transform/hough.hh @@ -0,0 +1,216 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory +// (LRDE) +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +#ifndef MLN_TRANSFORM_HOUGH_HH +# define MLN_TRANSFORM_HOUGH_HH + +/// \file mln/transform/hough.hh +/// +/// Compute the hough transform. + + +# include <mln/core/image/image2d.hh> +# include <mln/data/fill.hh> + +# include <mln/geom/nrows.hh> +# include <mln/geom/ncols.hh> +# include <mln/geom/bbox.hh> + +# include <mln/opt/at.hh> + +# include <mln/math/sin.hh> +# include <mln/math/cos.hh> +# include <mln/math/pi.hh> + +# include <mln/make/box2d.hh> + +# include <mln/value/int_u8.hh> + + +//FIXME: to be removed. For debug purpose. +//#include <mln/level/convert.hh> +//#include <mln/value/rgb8.hh> +//#include <mln/draw/line.hh> +//#include <mln/literal/colors.hh> +//#include <mln/io/ppm/save.hh> + + +namespace mln +{ + + namespace transform + { + + /// Compute the hough transform from a binary image. + /// Objects used for computation must be set to 'true'. + /// + /// \param[in] input_ A binary image. + /// \param[in] min_angle Minimum angle which can be found. + /// \param[in] max_angle Maximum angle which can be found. + /// + /// \return A 2D image of float. Rows are used for the distance and + /// columns are used for the angles. Angles go from 0 to 359. + /// Distance goes from 0 to the maximum distance between the center and a + /// corner. + /// The site having the maximum value indicates through its column index + /// the document inclination. + // + template <typename I> + image2d<float> + hough(const Image<I>& input_, int min_angle, int max_angle); + + + /// \overload + template <typename I> + image2d<float> + hough(const Image<I>& input); + + +# ifndef MLN_INCLUDE_ONLY + + + template <typename I> + image2d<float> + hough(const Image<I>& input_, int min_angle, int max_angle) + { + trace::entering("mln::transform::hough"); + mln_precondition(min_angle < max_angle); + + const I& input = exact(input_); + mlc_equal(mln_value(I), bool)::check(); + mln_precondition(input.is_valid()); + + math::round<int> rd; + double deg2rad = math::pi / 180.0f; + int range = rd(sqrt((double)(geom::ncols(input) * geom::ncols(input) + + geom::nrows(input) * geom::nrows(input)))); + + long temp = min_angle; + min_angle = 450 - max_angle; + max_angle = 450 - temp; + + // Pre-compute sin and cos values. + util::array<double> sin_cache(360), + cos_cache(360); + for (int omega = 0; omega < 360; ++omega) + { + sin_cache[omega] = math::sin((double)(omega * deg2rad)); + cos_cache[omega] = math::cos((double)(omega * deg2rad)); + } + + image2d<float> output(make::box2d(range,360)); + data::fill(output, 0); + + mln_piter(I) p(input.domain()); + for_all(p) + if (input(p)) // Is this site part of an objet? + { + + long teta1 = min_angle; + long teta2 = max_angle; + for (int omega = teta1; omega < teta2; ++omega) + { + long tetad = omega%360; + long r = rd(p.col() * sin_cache[tetad] + + p.row() * cos_cache[tetad]); + if (r > 0 && r < range) + output.at_(r, tetad) += 1; + } + + teta1 = min_angle + 180; + teta2 = max_angle + 180; + for (int omega = teta1; omega < teta2; ++omega) + { + long tetad = omega%360; + long r = rd(p.col() * sin_cache[tetad] + + p.row() * cos_cache[tetad]); + if (r > 0 && r < range) + output.at_(r, tetad) += 1; + } + + } + +// { +// point2d max_p(0,0); +// mln_piter_(image2d<float>) p(output.domain()); +// for_all(p) +// if (output(max_p) < output(p)) +// max_p = p; +// +// point2d b,e; +// b.col() = 0; +// b.row() = max_p.row()/cos(deg2rad*max_p.col()); +// if (b.row() < 0) +// { +// b.row() = 0; +// b.col() = max_p.row()/sin(deg2rad*max_p.col()); +// } else if (b.row() >= input.nrows()) +// { +// b.row() = input.nrows() - 1; +// b.col() = max_p.row() - b.row() * cos(deg2rad*max_p.col())/sin(deg2rad*max_p.col()); +// } +// +// e.col() = input.ncols() - 1; +// e.row() = max_p.row() - e.col() * sin(deg2rad*max_p.col()) / cos(deg2rad*max_p.col()); +// if (e.row() < 0) +// { +// e.row() = 0; +// e.col() = max_p.row()/sin(deg2rad*max_p.col()); +// } else if (e.row() >= input.nrows()) +// { +// e.row() = input.nrows() - 1; +// e.col() = max_p.row() - e.row() * cos(deg2rad*max_p.col())/sin(deg2rad*max_p.col()); +// } +// +// std::cout << b << " - " << e << std::endl; +// +// image2d<value::rgb8> toto = level::convert(value::rgb8(), input); +// draw::line(toto, b, e, literal::red); +// io::ppm::save(toto, "tmp_input.ppm"); +// } + trace::exiting("mln::transform::hough"); + return output; + } + + + template <typename I> + image2d<float> + hough(const Image<I>& input) + { + return hough(input, -180, 180); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::transform + +} // end of namespace mln + + +#endif // ! MLN_TRANSFORM_HOUGH_HH + diff --git a/milena/tests/transform/Makefile.am b/milena/tests/transform/Makefile.am index a1a9788..f5ff98d 100644 --- a/milena/tests/transform/Makefile.am +++ b/milena/tests/transform/Makefile.am @@ -7,6 +7,7 @@ check_PROGRAMS = \ distance_and_closest_point_geodesic \ distance_front \ distance_geodesic \ + hough \ influence_zone_front \ influence_zone_geodesic @@ -14,6 +15,7 @@ bench_closest_point_geodesic_SOURCES = bench_closest_point_geodesic.cc distance_and_closest_point_geodesic_SOURCES = distance_and_closest_point_geodesic.cc distance_front_SOURCES = distance_front.cc distance_geodesic_SOURCES = distance_geodesic.cc +hough_SOURCES = hough.cc influence_zone_front_SOURCES = influence_zone_front.cc influence_zone_geodesic_SOURCES = influence_zone_geodesic.cc diff --git a/milena/tests/transform/hough.cc b/milena/tests/transform/hough.cc new file mode 100644 index 0000000..dd42043 --- /dev/null +++ b/milena/tests/transform/hough.cc @@ -0,0 +1,59 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +/// \file tests/transform/hough.cc +/// +/// Test on mln::transform::hough. + +# include <mln/core/image/image2d.hh> +# include <mln/transform/hough.hh> +# include <mln/make/image.hh> + +int main() +{ + using namespace mln; + + bool values[][5] = { { 0, 0, 0, 0, 0 }, + { 1, 0, 0, 0, 0 }, + { 0, 1, 1, 1, 0 }, + { 0, 0, 0, 0, 1 }, + { 0, 0, 0, 0, 0 } }; + + image2d<bool> ima = make::image(values); + + image2d<float> hough = transform::hough(ima); + + point2d max_p(0,0); + mln_piter_(image2d<float>) p(hough.domain()); + for_all(p) + if (hough(max_p) < hough(p)) + max_p = p; + + // Checking angle value. + mln_assertion(max_p.col() == 335); +} + -- 1.5.6.5
participants (1)
-
Guillaume Lazzara