This function is useful for the doc. It should be used
each time the output value is an image of labels (most of
them are dark).
Index: olena/ChangeLog
from Niels Van Vliet <niels(a)lrde.epita.fr>
* olena/oln/convert/stretch.hh: Add stretch_balance. Add comments.
Index: olena/oln/convert/stretch.hh
--- olena/oln/convert/stretch.hh Thu, 31 Jul 2003 18:08:39 +0200
burrus_n (oln/f/51_stretch.hh 1.13 600)
+++ olena/oln/convert/stretch.hh Sat, 13 Mar 2004 17:01:12 +0100
van-vl_n (oln/f/51_stretch.hh 1.13 600)
@@ -1,4 +1,4 @@
-// Copyright (C) 2001, 2002, 2003 EPITA Research and Development
Laboratory
+// Copyright (C) 2001, 2002, 2003, 2004 EPITA Research and Development
Laboratory
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -34,10 +34,35 @@
# include <oln/convert/abstract/conversion.hh>
+# include <set>
+
namespace oln {
namespace convert {
+ /*! Functor to stretch a value from a range Input to a range Output.
+ **
+ ** \see stretch_balance
+ ** \code
+ ** #include <oln/basics2d.hh>
+ ** #include <oln/convert/stretch.hh>
+ ** #include <ntg/all.hh>
+ ** #include <iostream>
+ **
+ ** int main()
+ ** {
+ ** oln::image2d<ntg::int_u8> lena = oln::load(IMG_IN
"lena256.pgm");
+ **
+ ** oln::io::save(apply(oln::convert::stretch<ntg::int_u<3> >(),
lena),
+ ** IMG_OUT "oln_convert_stretch.pgm");
+ ** }
+ ** \endcode
+ ** \image html lena256.png
+ ** \image latex lena256.png
+ ** =>
+ ** \image html oln_convert_stretch.png
+ ** \image latex oln_convert_stretch.png
+ */
template<class Output, class Exact = mlc::final>
struct stretch
: public abstract::conversion_to_type<Output, typename
mlc::exact_vt<stretch<Output, Exact>, Exact>::ret >
@@ -62,7 +87,124 @@
}
};
+ /*! Stretch the value of an image.
+ **
+ ** This function stretches values between \a min_in and \a max_in
+ ** of an image \in, to a range that goes from \a min_out to \a max_out.
+ ** \arg in Input image, must be have scalar values
+ ** \arg min_in Lower bound of the range in the input. All values
smaller
+ ** than min_in are converted to \a min_out.
+ ** \arg max_in Upper bound of the range in the input. All values
+ ** greater than max_in
+ ** are converted to \a max_out.
+ ** \arg min_out Low bound of the range in the output.
+ ** \arg max_out Upper bound of the range in the output.
+ **
+ ** Difference between "apply(stretch<T>(), im)" and
"stretch_balance<T>(im)":
+ ** the first one stretches all the range of oln_value_type(T), the
second
+ ** stretches only values that appear is the image:
+ ** \code
+ ** #include <oln/basics1d.hh>
+ ** #include <oln/convert/stretch.hh>
+ ** #include <ntg/all.hh>
+ ** #include <iostream>
+ **
+ ** int main()
+ ** {
+ **
+ ** oln::image1d<ntg::int_u<17> > im(4);
+ ** im(0) = 0; im(1) = 2; im(2) = 5000; im(3) = 4000;
+ **
+ ** // print "0 170 511 340"
+ ** //(values of the *image* are dispatched on the range [0..2^9-1])
+ ** std::cout << oln::convert::stretch_balance<ntg::int_u<9> >(im)
<< std::endl;
+ **
+ ** //print " 0 0 19 16" (19 is the result of 5000 * 2^9 / 2^17)
+ ** //(values of *int_u<17>* are dispatched on the range [0..2^9-1])
+ ** std::cout << apply(oln::convert::stretch<ntg::int_u<9> >(),
im) << std::endl;
+ ** }
+ ** \endcode
+ **
+ ** This function is useful to stretch images of label:
+ ** \code
+ ** #include <oln/basics2d.hh>
+ ** #include <oln/convert/stretch.hh>
+ ** #include <oln/level/cc.hh>
+ ** #include <ntg/all.hh>
+ ** #include <iostream>
+ **
+ ** int main()
+ ** {
+ ** oln::image2d<ntg::bin> light = oln::load(IMG_IN "face_se.pbm");
+ **
+ ** //Extraction of the connected components:
+ ** unsigned card;
+ ** oln::image2d<ntg::int_u8> cc
+ ** = oln::level::frontp_connected_component<ntg::int_u8>(light,
+ ** oln::neighb_c8(),
+ ** card);
+ ** oln::io::save(cc, "oln_convert_stretch_dark.pgm");
+ ** oln::io::save(oln::convert::stretch_balance<ntg::int_u8>(cc),
+ ** "oln_convert_stretch_balance.pgm");
+ ** }
+ ** \endcode
+ ** \image html face_se.png
+ ** \image latex face_se.png
+ ** => Without stretch_balance:
+ ** \image html oln_convert_stretch_dark.png
+ ** \image latex oln_convert_stretch_dark.png
+ ** => With stretch_balance:
+ ** \image html oln_convert_stretch_balance.png
+ ** \image latex oln_convert_stretch_balance.png
+ */
+ template<class DestValue, class I>
+ typename mute<I, DestValue>::ret
+ stretch_balance(const oln::abstract::non_vectorial_image<I> &in,
+ const oln_value_type(I) & min_in
+ = ntg_min_val(oln_value_type(I)),
+ const oln_value_type(I) & max_in
+ = ntg_max_val(oln_value_type(I)),
+ const DestValue & min_out = ntg_min_val(DestValue),
+ const DestValue & max_out = ntg_max_val(DestValue))
+ {
+ typedef typename
+ ntg_is_a(DestValue, ntg::non_vectorial)::ensure_type ensure_type;
+
+ typename mute<I, DestValue>::ret out(in.size());
+ //FIXME: I would like to remove the static_cast.
+ ntg_cumul_type(DestValue) tab[static_cast<int>(max_in - min_in + 1)];
+ typedef typename std::set<oln_value_type(I)> set_type;
+ set_type s;
+ oln_iter_type(I) it(in);
+
+ for_all(it)
+ if (in[it] <= max_in && in[it] >= min_in)
+ s.insert(in[it]);
+ if (s.size() == 1)
+ {
+ for_all(it)
+ out[it] = ntg_zero_val(DestValue);
+ return out;
+ }
+ {
+ unsigned cpt = 0;
+ for (typename set_type::const_iterator it(s.begin());
+ it != s.end(); ++it, ++cpt)
+ tab[*it - min_in] = cpt * (max_out - min_out) / (s.size() - 1);
+ }
+ for_all(it)
+ if (min_in <= in[it])
+ {
+ if (in[it] <= max_in)
+ out[it] = tab[in[it] - min_in] + min_out;
+ else
+ out[it] = max_out;
+ }
+ else
+ out[it] = min_out;
+ return out;
+ }
} // end of convert.
} // end of oln.