
* apps/mesh-segm-skel/mesh-complex-max-curv-extrema.cc: New. * apps/mesh-segm-skel/test-mesh-complex-max-curv-extrema.in: New. * apps/mesh-segm-skel/Makefile.am (bin_PROGRAMS): Add mesh-complex-max-curv-extrema. (mesh_complex_max_curv_extrema_SOURCES): New. (TESTS): Add test-mesh-complex-max-curv-segm-extrema. (MOSTLYCLEANFILES): Add socket-complex-max-curv-segm-extrema.off and teapot-complex-max-curv-segm-extrema.off. --- milena/ChangeLog | 13 +++ milena/apps/mesh-segm-skel/Makefile.am | 13 ++- ...ax-curv.cc => mesh-complex-max-curv-extrema.cc} | 105 +++++++++++++------- .../test-mesh-complex-max-curv-extrema.in | 10 ++ 4 files changed, 101 insertions(+), 40 deletions(-) copy milena/apps/mesh-segm-skel/{mesh-complex-max-curv.cc => mesh-complex-max-curv-extrema.cc} (64%) create mode 100644 milena/apps/mesh-segm-skel/test-mesh-complex-max-curv-extrema.in diff --git a/milena/ChangeLog b/milena/ChangeLog index b2f2330..f0064f7 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,5 +1,18 @@ 2010-05-11 Roland Levillain <roland@lrde.epita.fr> + New application: mesh-complex-max-curv-extrema. + + * apps/mesh-segm-skel/mesh-complex-max-curv-extrema.cc: New. + * apps/mesh-segm-skel/test-mesh-complex-max-curv-extrema.in: New. + * apps/mesh-segm-skel/Makefile.am (bin_PROGRAMS): Add + mesh-complex-max-curv-extrema. + (mesh_complex_max_curv_extrema_SOURCES): New. + (TESTS): Add test-mesh-complex-max-curv-segm-extrema. + (MOSTLYCLEANFILES): Add socket-complex-max-curv-segm-extrema.off + and teapot-complex-max-curv-segm-extrema.off. + +2010-05-11 Roland Levillain <roland@lrde.epita.fr> + Revive, fix and update application mesh-segm. * apps/mesh-segm-skel/mesh-segm.cc: Catch up with the new diff --git a/milena/apps/mesh-segm-skel/Makefile.am b/milena/apps/mesh-segm-skel/Makefile.am index 501dec0..230ef0a 100644 --- a/milena/apps/mesh-segm-skel/Makefile.am +++ b/milena/apps/mesh-segm-skel/Makefile.am @@ -112,9 +112,16 @@ mesh_complex_max_curv_SOURCES = mesh-complex-max-curv.cc TESTS += test-mesh-complex-max-curv MOSTLYCLEANFILES += teapot-complex-max-curv.off -# FIXME: Write a program showing the local minima (and maxima) of -# scalar-valued complex-based mesh (to see the curvature extrema). -# ... + +# A program computing the max curvature at each (2-)face of the +# surface of a triangle mesh and displaying its local minima +# (in blue) and maxima (in red). +bin_PROGRAMS += mesh-complex-max-curv-extrema +mesh_complex_max_curv_extrema_SOURCES = mesh-complex-max-curv-extrema.cc +TESTS += test-mesh-complex-max-curv-extrema +MOSTLYCLEANFILES += \ + socket-complex-max-curv-extrema.off \ + teapot-complex-max-curv-extrema.off # Segmentation program working on precomputed meshes with curvatures data. bin_PROGRAMS += mesh-complex-segm diff --git a/milena/apps/mesh-segm-skel/mesh-complex-max-curv.cc b/milena/apps/mesh-segm-skel/mesh-complex-max-curv-extrema.cc similarity index 64% copy from milena/apps/mesh-segm-skel/mesh-complex-max-curv.cc copy to milena/apps/mesh-segm-skel/mesh-complex-max-curv-extrema.cc index 8d79839..8f68b3d 100644 --- a/milena/apps/mesh-segm-skel/mesh-complex-max-curv.cc +++ b/milena/apps/mesh-segm-skel/mesh-complex-max-curv-extrema.cc @@ -1,4 +1,5 @@ -// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// Copyright (C) 2008, 2009, 2010 EPITA Research and Development +// Laboratory (LRDE) // // This file is part of the Milena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -25,10 +26,11 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/// \file apps/mesh-segm-skel/mesh-complex-max-curv.cc +/// \file apps/mesh-segm-skel/mesh-complex-max-curv-extrema.cc /// \brief A program computing the max curvature at each (2-)face of -/// the surface of the (triangle) mesh of a statue, using a -/// complex-based image. +/// the surface of the (triangle) mesh of a statue, using +/// complex-based image, and displaying its local minima (in blue) and +/// maxima (in red). #include <cstdlib> #include <cmath> @@ -42,13 +44,20 @@ #include <mln/data/fill.hh> #include <mln/literal/zero.hh> +#include <mln/labeling/regional_minima.hh> +#include <mln/labeling/regional_maxima.hh> + #include <mln/math/max.hh> #include <mln/math/sqr.hh> #include <mln/accu/stat/min_max.hh> #include <mln/fun/v2v/linear.hh> #include <mln/data/transform.hh> +#include <mln/value/label_16.hh> + #include <mln/literal/white.hh> +#include <mln/literal/grays.hh> +#include <mln/literal/colors.hh> #include <mln/io/off/load.hh> #include <mln/io/off/save.hh> @@ -86,16 +95,6 @@ int main(int argc, char* argv[]) mln::bin_2complex_image3df input; mln::io::off::load(input, input_filename); -// // ------------------------------------------------------------ -// // FIXME: TEST. -// mln::complex_image< 2, mln::space_2complex_geometry, mln::algebra::vec<3, float> > -// normal = mesh_normal(input.domain()); -// mln::p_n_faces_fwd_piter<D, G> v_(normal.domain(), 0); -// for_all(v_) -// std::cout << normal(v_) << std::endl; -// std::exit(0); -// // ------------------------------------------------------------ - std::pair<ima_t, ima_t> curv = mln::geom::mesh_curvature(input.domain()); // Compute the max curvature at each vertex. @@ -133,29 +132,61 @@ int main(int argc, char* argv[]) mln_invariant(n <= 3); } - // Normalize values between 0 and 1. - /* Shrink the values of FACE_M into the range 0..1, as these are - the only values accepted a an RGB floating-point component in the - OFF file format. */ - ima_t output(max_curv.domain()); - mln::data::fill(output, mln::literal::zero); - std::pair<float, float> min_max(acc); - // FIXME: Taken from mln/data/stretch.hh (this should be factored). - float min = min_max.first; - float max = min_max.second; - std::cout << min << std::endl; - std::cout << max << std::endl; - // Don't normalize actually if the curvature is constant (i.e., - // if min == max). - if (min != max) - { - float m = 0.0f; - float M = 1.0f; - float a = (M - m) / (max - min); - float b = (m * max - M * min) / (max - min); - mln::fun::v2v::linear<float, float, float> f(a, b); - output = mln::data::transform(max_curv, f); - } + /*----------------. + | Local extrema. | + `----------------*/ + + /// Adjacent triangles are connected by shared edges. + typedef mln::complex_lower_dim_connected_n_face_neighborhood<D, G> nbh_t; + nbh_t nbh; + + typedef mln::value::label_16 label_t; + typedef mln_ch_value_(ima_t, label_t) label_ima_t; + + /* FIXME: We should use something like `ima_t | p_n_faces(2)' instead + of `ima_t' here. Or better: `input' should only associate data + to 2-faces. */ + label_t nminima; + label_ima_t minima = + mln::labeling::regional_minima(max_curv, nbh, nminima); + std::cout << "nminima = " << nminima << std::endl; + + label_t nmaxima; + label_ima_t maxima = + mln::labeling::regional_maxima(max_curv, nbh, nmaxima); + std::cout << "nmaxima = " << nmaxima << std::endl; + + /*-----------------. + | Colored output. | + `-----------------*/ + + typedef mln::rgb8_2complex_image3df output_t; + output_t output(max_curv.domain()); + + for_all(t) + { + if (minima(t) != mln::literal::zero) + { + // Special (unexpected) case: T is both a minimum and a + // maximum. Paint it in magenta (blue + red). + if (maxima(t) != mln::literal::zero) + { + std::cerr + << "warning: " << t << " is both a minimum and a maximum." + << std::endl; + output(t) = mln::literal::magenta; + } + else + // Paint minimum T in blue. + output(t) = mln::literal::blue; + } + else if (maxima(t) != mln::literal::zero) + // Paint maximum T in red. + output(t) = mln::literal::red; + else + // Default color. + output(t) = mln::literal::medium_gray; + } // Output. mln::io::off::save(output, output_filename); diff --git a/milena/apps/mesh-segm-skel/test-mesh-complex-max-curv-extrema.in b/milena/apps/mesh-segm-skel/test-mesh-complex-max-curv-extrema.in new file mode 100644 index 0000000..c6fa1e8 --- /dev/null +++ b/milena/apps/mesh-segm-skel/test-mesh-complex-max-curv-extrema.in @@ -0,0 +1,10 @@ +#! /bin/sh + +set -ex + +mesh_dir=@top_srcdir@/milena/mesh + +time ./mesh-complex-max-curv-extrema $mesh_dir/socket.off socket-complex-max-curv-extrema.off +time ./mesh-complex-max-curv-extrema $mesh_dir/teapot.off teapot-complex-max-curv-extrema.off +# FIXME: Too long. Should be run with (future) target `check-full'. +#time ./mesh-complex-max-curv-extrema $mesh_dir/bunny-holefilled.off bunny-holefilled-complex-max-curv-extrema.off -- 1.5.6.5