Commit cee613b7 authored by Thierry Geraud's avatar Thierry Geraud
Browse files

Augment morphology.

	* mln/value/cast.hh: Rename as...
	* mln/core/cast_image.hh: ...this.
	Update.
	* mln/core/concept/value.hh (cast): Move to and rename as...
	* mln/value/cast.hh (cast_image): ...this, here.
	* tests/cast_image.cc: Update.

	* mln/morpho/thickening.hh: New.
	* mln/morpho/laplacian.hh: New.
	* mln/morpho/thick_miss.hh: New.
	* mln/morpho/thin_fit.hh: New.
	* mln/morpho/thinning.hh: New.
	* tests/morpho_thinning.cc: New.
	* tests/morpho_laplacian.cc: New.
	* tests/morpho_hit_or_miss.cc: Update.

	* mln/morpho/plus.hh (mln_postcondition): Remove.
	* mln/morpho/minus.hh: Remove dead lines.
	* mln/morpho/hit_or_miss.hh: Augment doc.
	Add postconditions.
	Add a FIXME.
	* mln/io/save_pgm.hh: Rewrite.
	* mln/arith/plus.hh (plus_cst, plus_cst_inplace): New.
	* img/picasso.pgm: Invert.


git-svn-id: https://svn.lrde.epita.fr/svn/oln/trunk@1064 4aad255d-cdde-0310-9447-f3009e2ae8c0
parent f5d52c2f
2007-08-31 Thierry Geraud <thierry.geraud@lrde.epita.fr>
Augment morphology.
* mln/value/cast.hh: Rename as...
* mln/core/cast_image.hh: ...this.
Update.
* mln/core/concept/value.hh (cast): Move to and rename as...
* mln/value/cast.hh (cast_image): ...this, here.
* tests/cast_image.cc: Update.
* mln/morpho/thickening.hh: New.
* mln/morpho/laplacian.hh: New.
* mln/morpho/thick_miss.hh: New.
* mln/morpho/thin_fit.hh: New.
* mln/morpho/thinning.hh: New.
* tests/morpho_thinning.cc: New.
* tests/morpho_laplacian.cc: New.
* tests/morpho_hit_or_miss.cc: Update.
* mln/morpho/plus.hh (mln_postcondition): Remove.
* mln/morpho/minus.hh: Remove dead lines.
* mln/morpho/hit_or_miss.hh: Augment doc.
Add postconditions.
Add a FIXME.
* mln/io/save_pgm.hh: Rewrite.
* mln/arith/plus.hh (plus_cst, plus_cst_inplace): New.
* img/picasso.pgm: Invert.
2007-08-31 Thierry Geraud <thierry.geraud@lrde.epita.fr>
Add hit-or-miss and p2v ternary+elif functions.
......
No preview for this file type
......@@ -31,10 +31,15 @@
/*! \file mln/arith/plus.hh
*
* \brief Point-wise addition between images.
*
* \todo Speedup versions with cst.
*/
# include <mln/core/concept/image.hh>
# include <mln/pw/cst.hh>
# include <mln/pw/image.hh>
namespace mln
{
......@@ -54,6 +59,18 @@ namespace mln
void plus(const Image<L>& lhs, const Image<R>& rhs, Image<O>& output);
/*! Point-wise addition of the value \p val to image \p input.
*
* \param[in] input The image.
* \param[in] val The value.
* \param[out] output The result image.
*
* \pre \p output.domain == \p input.domain
*/
template <typename I, typename V, typename O>
void plus_cst(const Image<I>& input, const V& val, Image<O>& output);
/*! Point-wise addition of image \p rhs in image \p lhs.
*
* \param[in] lhs First operand image (subject to addition).
......@@ -127,6 +144,13 @@ namespace mln
impl::plus_(exact(lhs), exact(rhs), exact(output));
}
template <typename I, typename V, typename O>
void plus_cst(const Image<I>& input, const V& val, Image<O>& output)
{
mln_precondition(exact(output).domain() == exact(input).domain());
plus(input, pw::cst(val) | exact(input).domain(), output); // Calls the previous version.
}
template <typename L, typename R>
void plus_inplace(Image<L>& lhs, const Image<R>& rhs)
{
......@@ -134,6 +158,13 @@ namespace mln
impl::plus_inplace_(exact(lhs), exact(rhs));
}
template <typename I, typename V>
void plus_cst_inplace(Image<I>& input, const V& val)
{
mln_precondition(exact(input).has_data());
plus_inplace(input, pw::cst(val) | exact(input).domain()); // Calls the previous version.
}
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::arith
......
......@@ -25,151 +25,147 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
#ifndef MLN_VALUE_CAST_HH
# define MLN_VALUE_CAST_HH
#ifndef MLN_CORE_CAST_IMAGE_HH
# define MLN_CORE_CAST_IMAGE_HH
/*! \file mln/value/cast.hh
/*! \file mln/core/cast_image.hh
*
* \brief Definition of an image class FIXME
*/
# include <mln/core/concept/image.hh>
# include <mln/value/set.hh>
# include <mln/value/cast.hh>
namespace mln
{
namespace value
/*! \brief FIXME
*
*/
template <typename T, typename I>
struct cast_image_ : public mln::internal::image_base_< mln_pset(I), cast_image_<T,I> >
{
/// Point_Site associated type.
typedef mln_psite(I) psite;
/*! \brief FIXME
*
*/
template <typename T, typename I>
struct cast_image : public mln::internal::image_base_< mln_pset(I), cast_image<T,I> >
{
/// Point_Site associated type.
typedef mln_psite(I) psite;
/// Point_Set associated type.
typedef mln_pset(I) pset;
/// Point_Set associated type.
typedef mln_pset(I) pset;
/// Value associated type.
typedef T value;
/// Value associated type.
typedef T value;
/// Return type of read-only access.
typedef T rvalue;
/// Return type of read-only access.
typedef T rvalue;
/// Return type of read-write access.
typedef T lvalue;
/// Return type of read-write access.
typedef void lvalue; // FIXME
/// Value set associated type.
typedef mln::value::set<T> vset;
/// Value set associated type.
typedef mln::value::set<T> vset;
/// Constructor.
cast_image_(const Image<I>& ima);
/// Constructor.
cast_image(const Image<I>& ima);
/// Test if this image has been initialized.
bool has_data() const;
/// Test if this image has been initialized.
bool has_data() const;
/// Test if a pixel value is accessible at \p p.
bool owns_(const psite& p) const;
/// Test if a pixel value is accessible at \p p.
bool owns_(const psite& p) const;
/// Give the definition domain.
const mln_pset(I)& domain() const;
/// Give the definition domain.
const mln_pset(I)& domain() const;
/// Read-only access of pixel value at point site \p p.
T operator()(const psite& p) const;
/// Read-only access of pixel value at point site \p p.
T operator()(const psite& p) const;
/// Mutable access is only OK for reading (not writing).
T operator()(const psite& p);
/// Read-write access is present but disabled.
void operator()(const psite&);
/// Give the set of values of the image.
const vset& values() const;
/// Give the set of values of the image.
const vset& values() const;
/// Change value type.
template <typename U>
/// Change value type.
template <typename U>
struct change_value
{
typedef mln_ch_value(I, U) ret;
};
protected:
const I& ima_;
};
protected:
const I& ima_;
};
template <typename T, typename I>
cast_image<T,I>
cast(const Image<I>& ima)
{
mln_precondition(exact(ima).has_data());
cast_image<T,I> tmp(ima);
return tmp;
}
template <typename T, typename I>
cast_image_<T,I>
cast_image(const Image<I>& ima)
{
mln_precondition(exact(ima).has_data());
cast_image_<T,I> tmp(ima);
return tmp;
}
# ifndef MLN_INCLUDE_ONLY
template <typename T, typename I>
cast_image<T,I>::cast_image(const Image<I>& ima)
: ima_(exact(ima))
{
mln_precondition(exact(ima).has_data());
}
template <typename T, typename I>
bool cast_image<T,I>::has_data() const
{
mln_invariant(ima_.has_data());
return true;
}
template <typename T, typename I>
bool cast_image<T,I>::owns_(const psite& p) const
{
return ima_.owns_(p);
}
template <typename T, typename I>
const mln_pset(I)&
cast_image<T,I>::domain() const
{
return ima_.domain();
}
template <typename T, typename I>
T
cast_image<T,I>::operator()(const psite& p) const
{
mln_precondition(ima_.owns_(p));
return ima_(p);
}
template <typename T, typename I>
void
cast_image<T,I>::operator()(const psite&)
{
mln_invariant(0); // FIXME: Turn into a compile-time error...
}
template <typename T, typename I>
const mln::value::set<T>&
cast_image<T,I>::values() const
{
return vset::the();
}
template <typename T, typename I>
cast_image_<T,I>::cast_image_(const Image<I>& ima)
: ima_(exact(ima))
{
mln_precondition(exact(ima).has_data());
}
template <typename T, typename I>
bool cast_image_<T,I>::has_data() const
{
mln_invariant(ima_.has_data());
return true;
}
template <typename T, typename I>
bool cast_image_<T,I>::owns_(const psite& p) const
{
return ima_.owns_(p);
}
template <typename T, typename I>
const mln_pset(I)&
cast_image_<T,I>::domain() const
{
return ima_.domain();
}
template <typename T, typename I>
T
cast_image_<T,I>::operator()(const psite& p) const
{
mln_precondition(ima_.owns_(p));
return mln::value::cast<T>( ima_(p) );
}
template <typename T, typename I>
T
cast_image_<T,I>::operator()(const psite& p)
{
return mln::value::cast<T>( ima_(p) );
}
template <typename T, typename I>
const mln::value::set<T>&
cast_image_<T,I>::values() const
{
return vset::the();
}
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::value
} // end of namespace mln
#endif // ! MLN_VALUE_CAST_HH
#endif // ! MLN_CORE_CAST_IMAGE_HH
......@@ -63,17 +63,6 @@ namespace mln
namespace value
{
/// Cast a value \p src from type \c Src to type \c Dest.
template <typename Dest, typename Src>
Dest cast(const Src& src);
} // end of namespace mln::value
# ifndef MLN_INCLUDE_ONLY
template <typename E>
......@@ -99,43 +88,12 @@ namespace mln
return exact(*this);
}
namespace value
{
namespace internal
{
template <typename S>
const S&
cast_(const S& src, ...)
{
return src;
}
template <typename T, typename S>
typename S::equiv
cast_(const T&, const Value<S>& src)
{
return exact(src);
}
} // end of namespace mln::value::internal
template <typename Dest, typename Src>
Dest cast(const Src& src)
{
return internal::cast_(src, src);
}
} // end of namespace mln::value
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln
# include <mln/value/cast.hh>
#endif // ! MLN_CORE_CONCEPT_VALUE_HH
......@@ -32,56 +32,116 @@
# include <iostream>
# include <fstream>
# include <mln/core/image2d_b.hh>
# include <mln/geom/size2d.hh>
# include <mln/value/int_u8.hh>
# include <mln/metal/equal.hh>
# include <mln/metal/bexpr.hh>
namespace mln
{
// Fwd decl.
namespace value {
template <unsigned> class int_u;
template <unsigned> class int_u_sat;
}
namespace io
{
void save_pgm(const image2d_b<value::int_u8>& ima, const std::string& filename)
template <typename I>
void save_pgm(const Image<I>& ima, const std::string& filename);
# ifndef MLN_INCLUDE_ONLY
namespace impl
{
std::ofstream file(filename.c_str());
if (! file)
{
std::cerr << "error: cannot open file '" << filename
<< "'!";
abort();
}
file << "P5" << std::endl;
file << "# olena" << std::endl;
file << geom::ncols(ima) << ' ' << geom::nrows(ima) << std::endl;
file << "255" << std::endl;
const int
min_row = geom::min_row(ima),
max_row = geom::max_row(ima);
point2d p;
if (sizeof(value::int_u8) == 1)
{
p.col() = geom::min_col(ima);
size_t len = geom::ncols(ima);
for (p.row() = min_row; p.row() <= max_row; ++p.row())
file.write((char*)(& ima(p)), len);
}
else
{
// FIXME: code for g++-2.95 when sizeof(int_u8) == 2!!!
const int
min_col = geom::min_col(ima),
max_col = geom::max_col(ima);
for (p.row() = min_row; p.row() <= max_row; ++p.row())
for (p.col() = min_col; p.col() <= max_col; ++p.col())
{
unsigned char c = ima(p);
file.write((char*)(&c), 1);
}
}
template <typename I>
void save_pgm_header_(const I& ima, const std::string& filename,
std::ofstream& file)
{
if (! file)
{
std::cerr << "error: cannot open file '" << filename
<< "'!";
abort();
}
file << "P5" << std::endl;
file << "# milena" << std::endl;
file << geom::ncols(ima) << ' ' << geom::nrows(ima) << std::endl;
file << "255" << std::endl;
}
template <typename I>
void save_pgm_(const Fast_Image<I>& ima_, const std::string& filename)
{
const I& ima = exact(ima_);
std::ofstream file(filename.c_str());
save_pgm_header_(ima, filename, file);
const int
min_row = geom::min_row(ima),
max_row = geom::max_row(ima);
point2d p;
if (sizeof(mln_value(I)) == 1)
{
p.col() = geom::min_col(ima);
size_t len = geom::ncols(ima);
for (p.row() = min_row; p.row() <= max_row; ++p.row())
file.write((char*)(& ima(p)), len);
}
else
{
// FIXME: code for g++-2.95 when sizeof(int_u8) == 2!!!
const int
min_col = geom::min_col(ima),
max_col = geom::max_col(ima);
for (p.row() = min_row; p.row() <= max_row; ++p.row())
for (p.col() = min_col; p.col() <= max_col; ++p.col())
{
unsigned char c = ima(p);
file.write((char*)(&c), 1);
}
}
}
template <typename I>
void save_pgm_(const Image<I>& ima_, const std::string& filename)
{
const I& ima = exact(ima_);
std::ofstream file(filename.c_str());
save_pgm_header_(ima, filename, file);
const int
min_row = geom::min_row(ima),
max_row = geom::max_row(ima),
min_col = geom::min_col(ima),
max_col = geom::max_col(ima);
point2d p;
for (p.row() = min_row; p.row() <= max_row; ++p.row())
for (p.col() = min_col; p.col() <= max_col; ++p.col())
{
unsigned char c = ima(p);
file.write((char*)(&c), 1);
}
}
} // end of namespace mln::io::impl
template <typename I>
void save_pgm(const Image<I>& ima, const std::string& filename)
{
mln::metal::or_<
mln::metal::equal<mln_value(I), value::int_u<8> >,
mln::metal::equal<mln_value(I), value::int_u_sat<8> >
>::check();
impl::save_pgm_(exact(ima), filename);
}
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::io
} // end of namespace mln
......
......@@ -61,7 +61,7 @@ namespace mln
/*! Morphological hit-or-miss opening.
*
* This operator is d_(-Bh) o HMT_(Bh,Bm).
* This operator is HMTope_(Bh,Bm) = d_(-Bh) o HMT_(Bh,Bm).
*/
template <typename I, typename Wh, typename Wm, typename O>
void hit_or_miss_opening(const Image<I>& input,
......@@ -70,7 +70,7 @@ namespace mln
/*! Morphological hit-or-miss opening of the background.
*
* This operator is FIXME.
* This operator is HMTopeBG = HMTope_(Bm,Bh) o C = d_(-Bm) o HMT_(Bh,Bm).
*/
template <typename I, typename Wh, typename Wm, typename O>
void hit_or_miss_background_opening(const Image<I>& input,
......@@ -79,7 +79,7 @@ namespace mln
/*! Morphological hit-or-miss closing.
*
* This operator is FIXME.
* This operator is C o HMTope o C.
*/
template <typename I, typename Wh, typename Wm, typename O>
void hit_or_miss_closing(const Image<I>& input,
......@@ -88,7 +88,7 @@ namespace mln
/*! Morphological hit-or-miss closing of the background.
*
* This operator is FIXME.
* This operator is C o HMTopeBG o C.
*/
template <typename I, typename Wh, typename Wm, typename O>
void hit_or_miss_background_closing(const Image<I>& input,
......@@ -150,7 +150,8 @@ namespace mln
erosion(input, win_hit, ero_fg);
dilation(input, win_miss, dil_bg);
level::fill(output,
fun::p2v::ternary(pw::value(input) == pw::value(ero_fg) && pw::value(dil_bg) < pw::value(input),
fun::p2v::ternary(pw::value(input) == pw::value(ero_fg)
&& pw::value(dil_bg) < pw::value(input),
pw::value(input) - pw::value(dil_bg),
pw::cst(V::zero)));
}
......@@ -160,12 +161,13 @@ namespace mln
erosion(input, win_miss, ero_bg);
dilation(input, win_hit, dil_fg);
level::fill(output,