Commit a3b58a0b authored by Michaël Roynard's avatar Michaël Roynard
Browse files

Merge branch 'development/transform_view' into 'development/ranges'

transform view (PR3)

See merge request !34
parents 880799ba 61ce6c25
Pipeline #12793 passed with stages
in 16 minutes
......@@ -56,7 +56,9 @@
"chrono": "cpp",
"ratio": "cpp",
"system_error": "cpp",
"thread": "cpp"
"thread": "cpp",
"queue": "cpp",
"stack": "cpp"
},
"python.pythonPath": "/usr/bin/python3",
"C_Cpp.configurationWarnings": "Disabled"
......
......@@ -15,6 +15,12 @@
"command": "ssh node7 'mkdir -p /work/mroynard/lrde/pylene/build-remote-release'",
"group": "build"
},
{
"label": "mkdir-remote-asan",
"type": "shell",
"command": "ssh node7 'mkdir -p /work/mroynard/lrde/pylene/build-remote-asan'",
"group": "build"
},
{
"label": "conan-remote",
"dependsOn": "mkdir-remote",
......@@ -29,6 +35,13 @@
"command": "ssh node7 'cd /work/mroynard/lrde/pylene/build-remote-release && source ../venv_python371/bin/activate && ../venv_python371/bin/conan install --build missing -o benchmark=True -o gtest=True -o freeimage=True ..'",
"group": "build"
},
{
"label": "conan-remote-asan",
"dependsOn": "mkdir-remote-asan",
"type": "shell",
"command": "ssh node7 'cd /work/mroynard/lrde/pylene/build-remote-asan && source ../venv_python371/bin/activate && ../venv_python371/bin/conan install --build missing -o benchmark=True -o gtest=True -o freeimage=True ..'",
"group": "build"
},
{
"label": "configure-remote",
"dependsOn": "conan-remote",
......@@ -43,6 +56,13 @@
"command": "ssh node7 'cd /work/mroynard/lrde/pylene/build-remote-release && cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..'",
"group": "build"
},
{
"label": "configure-remote-asan",
"dependsOn": "conan-remote-asan",
"type": "shell",
"command": "ssh node7 'cd /work/mroynard/lrde/pylene/build-remote-asan && cmake -G Ninja -DCMAKE_BUILD_TYPE=Asan -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..'",
"group": "build"
},
{
"label": "build-check-remote",
"dependsOn": "configure-remote",
......@@ -58,6 +78,21 @@
"group": "build",
"problemMatcher": "$gcc"
},
{
"label": "build-check-remote-asan",
"dependsOn": "configure-remote-asan",
"type": "shell",
"command": "ssh node7 'cd /work/mroynard/lrde/pylene/build-remote-asan && cmake --build . --target check --config Asan -- -j12'",
"group": "build",
"problemMatcher": "$gcc"
},
{
"label": "only-build-check-remote-asan",
"type": "shell",
"command": "ssh node7 'cd /work/mroynard/lrde/pylene/build-remote-asan && cmake --build . --target check --config Asan -- -j12'",
"group": "build",
"problemMatcher": "$gcc"
},
{
"label": "build-benchmarks-remote-release",
"dependsOn": "configure-remote-release",
......
......@@ -7,15 +7,15 @@ Include :file:`<mln/labeling/local_extrema.hpp>`
#. .. cpp:function:: \
template <class Label_t, class I, class N> \
ch_value_t<I, Label_t> local_minima(const Image<I>& input, const Neighborhood<N>& nbh, int& nlabel)
image_ch_value_t<I, Label_t> local_minima(const Image<I>& input, const Neighborhood<N>& nbh, int& nlabel)
#. .. cpp:function:: \
template <class Label_t, class I, class N> \
ch_value_t<I, Label_t> local_maxima(const Image<I>& input, const Neighborhood<N>& nbh, int& nlabel)
image_ch_value_t<I, Label_t> local_maxima(const Image<I>& input, const Neighborhood<N>& nbh, int& nlabel)
#. .. cpp:function:: \
template <class Label_t, class I, class N, class Compare> \
ch_value_t<I, Label_t> local_minima(const Image<I>& input, const Neighborhood<N>& nbh, int& nlabel, Compare cmp)
image_ch_value_t<I, Label_t> local_minima(const Image<I>& input, const Neighborhood<N>& nbh, int& nlabel, Compare cmp)
Labelize the local minima (1) or maxima (2) of an image with an optional
comparaison function ``cmp`` (3).
......
......@@ -7,7 +7,7 @@ Include :file:`<mln/morpho/watershed.hpp>`
.. cpp:function:: template <class Label_t, class I, class N> \
ch_value_t<I, Label_t> watershed(const Image<I>& ima, const Neighborhood<N>& nbh, int& nlabel)
image_ch_value_t<I, Label_t> watershed(const Image<I>& ima, const Neighborhood<N>& nbh, int& nlabel)
Watershed by immersion as defined in [BM92]_. The catchment basins are
labeled from 1 to n, and the special label 0 is used for watershed lines.
......
......@@ -13,9 +13,11 @@
namespace mln::archetypes
{
struct Image;
struct Image
struct ConcreteImage;
struct ConcreteImage
{
using new_pixel_type = Pixel;
using value_type = pixel_value_t<Pixel>;
......@@ -23,20 +25,26 @@ namespace mln::archetypes
using point_type = domain_point_t<Domain>;
using domain_type = Domain;
using category_type = forward_image_tag;
using concrete_type = Image;
using concrete_type = ConcreteImage;
#ifdef PYLENE_CONCEPT_TS_ENABLED
template <mln::concepts::Value Val>
#else
template <typename Val>
#endif // PYLENE_CONCEPT_TS_ENABLED
using ch_value_type = Image;
using ch_value_type = ConcreteImage;
// additional traits
using extension_category = mln::extension::none_extension_tag;
using indexable = std::false_type;
using accessible = std::false_type;
using view = std::false_type;
ConcreteImage() = default;
ConcreteImage(const ConcreteImage&) = default;
ConcreteImage(ConcreteImage&&) = default;
ConcreteImage& operator=(const ConcreteImage&) = default;
ConcreteImage& operator=(ConcreteImage&&) = default;
#ifdef PYLENE_CONCEPT_TS_ENABLED
template <mln::concepts::Value Val>
......@@ -50,8 +58,8 @@ namespace mln::archetypes
struct PixelRange
{
using value_type = image_pixel_t<Image>;
using reference = image_pixel_t<Image>&;
using value_type = image_pixel_t<ConcreteImage>;
using reference = image_pixel_t<ConcreteImage>&;
new_pixel_type* begin();
new_pixel_type* end();
......@@ -62,16 +70,42 @@ namespace mln::archetypes
struct ValueRange
{
using value_type = image_value_t<Image>;
using reference = image_reference_t<Image>;
using value_type = image_value_t<ConcreteImage>;
using reference = image_reference_t<ConcreteImage>;
image_value_t<Image>* begin();
image_value_t<Image>* end();
image_value_t<ConcreteImage>* begin();
image_value_t<ConcreteImage>* end();
};
ValueRange new_values();
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::ConcreteImage<ConcreteImage>,
"ConcreteImage archetype does not model the ConcreteImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
struct ViewImage : ConcreteImage
{
using view = std::true_type;
ViewImage() = delete;
ViewImage(const ViewImage&) = default;
ViewImage(ViewImage&&) = default;
ViewImage& operator=(const ViewImage&) = delete;
ViewImage& operator=(ViewImage&&) = delete;
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::ViewImage<ViewImage>, "ViewImage archetype does not model the ViewImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
struct Image : ViewImage
{
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::Image<Image>, "Image archetype does not model the Image concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
......@@ -136,9 +170,6 @@ namespace mln::archetypes
using indexable = std::true_type;
image_reference_t<IndexableImage> operator[](image_index_t<IndexableImage>) const;
image_point_t<IndexableImage> point_at_index(image_index_t<IndexableImage>) const;
image_index_t<IndexableImage> index_of_point(image_point_t<IndexableImage>) const;
image_index_t<IndexableImage> delta_index(image_point_t<IndexableImage>) const;
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
......@@ -191,7 +222,7 @@ namespace mln::archetypes
#endif // PYLENE_CONCEPT_TS_ENABLED
struct OutputAccessibleImage final : AccessibleImage
struct OutputAccessibleImage : AccessibleImage
{
using new_pixel_type = OutputPixel;
using reference = pixel_reference_t<OutputPixel>;
......@@ -218,13 +249,54 @@ namespace mln::archetypes
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::AccessibleImage<OutputAccessibleImage> &&
mln::concepts::OutputImage<OutputAccessibleImage>,
"OutputAccessibleImage archetype does not model the OutputImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
struct IndexableAndAccessibleImage : AccessibleImage
{
using index_type = int;
using indexable = std::true_type;
image_reference_t<IndexableAndAccessibleImage> operator[](image_index_t<IndexableAndAccessibleImage>) const;
image_point_t<IndexableAndAccessibleImage> point_at_index(image_index_t<IndexableAndAccessibleImage>) const;
image_index_t<IndexableAndAccessibleImage> index_of_point(image_point_t<IndexableAndAccessibleImage>) const;
image_index_t<IndexableAndAccessibleImage> delta_index(image_point_t<IndexableAndAccessibleImage>) const;
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::IndexableAndAccessibleImage<IndexableAndAccessibleImage>,
"IndexableAndAccessibleImage archetype does not model the IndexableAndAccessibleImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
struct OutputIndexableAndAccessibleImage : OutputAccessibleImage
{
using index_type = int;
using indexable = std::true_type;
image_reference_t<OutputIndexableAndAccessibleImage>
operator[](image_index_t<OutputIndexableAndAccessibleImage>) const;
image_reference_t<OutputIndexableAndAccessibleImage> operator[](image_index_t<OutputIndexableAndAccessibleImage>);
image_point_t<OutputIndexableAndAccessibleImage>
point_at_index(image_index_t<OutputIndexableAndAccessibleImage>) const;
image_index_t<OutputIndexableAndAccessibleImage>
index_of_point(image_point_t<OutputIndexableAndAccessibleImage>) const;
image_index_t<OutputIndexableAndAccessibleImage>
delta_index(image_point_t<OutputIndexableAndAccessibleImage>) const;
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::IndexableAndAccessibleImage<OutputIndexableAndAccessibleImage> &&
mln::concepts::OutputImage<OutputIndexableAndAccessibleImage>,
"OutputIndexableAndAccessibleImage archetype does not model the OutputImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
struct BidirectionalImage : Image
{
using category_type = bidirectional_image_tag;
......@@ -245,7 +317,6 @@ namespace mln::archetypes
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::BidirectionalImage<BidirectionalImage>,
"BidirectionalImage archetype does not model the BidirectionalImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
......@@ -280,22 +351,9 @@ namespace mln::archetypes
#endif // PYLENE_CONCEPT_TS_ENABLED
struct RawImage : Image
struct RawImage : IndexableAndAccessibleImage
{
using category_type = raw_image_tag;
using index_type = int;
using indexable = std::true_type;
using accessible = std::true_type;
image_reference_t<RawImage> operator[](image_index_t<RawImage>) const;
image_point_t<RawImage> point_at_index(image_index_t<RawImage>) const;
image_index_t<RawImage> index_of_point(image_point_t<RawImage>) const;
image_index_t<RawImage> delta_index(image_point_t<RawImage>) const;
image_reference_t<RawImage> operator()(image_point_t<RawImage>) const;
image_reference_t<RawImage> at(image_point_t<RawImage>) const;
image_pixel_t<RawImage> new_pixel(image_point_t<RawImage>) const;
image_pixel_t<RawImage> new_pixel_at(image_point_t<RawImage>) const;
struct ReversiblePixelRange final : Image::PixelRange
......@@ -318,7 +376,6 @@ namespace mln::archetypes
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::RawImage<RawImage>, "RawImage archetype does not model the RawImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
......@@ -369,7 +426,7 @@ namespace mln::archetypes
#endif // PYLENE_CONCEPT_TS_ENABLED
struct ExtendedImage : Image
struct WithExtensionImage : Image
{
struct Extension
{
......@@ -379,11 +436,12 @@ namespace mln::archetypes
using extension_category = mln::extension::custom_extension_tag;
image_extension_t<ExtendedImage> extension() const;
image_extension_t<WithExtensionImage> extension() const;
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::ExtendedImage<ExtendedImage>,
"ExtendedImage archetype does not model the ExtendedImage concept!");
static_assert(mln::concepts::WithExtensionImage<WithExtensionImage>,
"WithExtensionImage archetype does not model the WithExtensionImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
} // namespace mln::archetypes
......@@ -14,13 +14,16 @@ namespace mln::archetypes
using point_type = Point;
using reference = const value_type&;
Pixel() = delete;
Pixel(const Pixel&) = default;
Pixel(Pixel&&) = default;
Pixel& operator=(const Pixel&) = delete;
Pixel& operator=(Pixel&&) = delete;
point_type point() const;
reference val() const;
};
bool operator==(const Pixel& lhs, const Pixel& rhs);
bool operator!=(const Pixel& lhs, const Pixel& rhs);
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::Pixel<Pixel>, "Pixel archetype does not model the Pixel concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
......
......@@ -31,8 +31,11 @@ namespace mln::concepts
// Image
template<typename Ima>
concept Image =
// FIXME : inheritance from New_Image required for the moment
stl::Semiregular<Ima> &&
// FIXME: inheritance from New_Image required for the moment
// Minimum constraint on image object
// Do not requires DefaultConstructible
stl::CopyConstructible<Ima> &&
stl::MoveConstructible<Ima> &&
stl::DerivedFrom<image_category_t<Ima>, forward_image_tag> &&
requires {
typename image_pixel_t<Ima>;
......@@ -47,6 +50,7 @@ namespace mln::concepts
typename image_accessible_t<Ima>;
typename image_extension_category_t<Ima>;
typename image_category_t<Ima>;
typename image_view_t<Ima>;
} &&
Pixel<image_pixel_t<Ima>> &&
Point<image_point_t<Ima>> &&
......@@ -83,7 +87,10 @@ namespace mln::concepts
requires(WIma ima) {
{ ima.new_values() } -> stl::OutputRange<image_value_t<WIma>>&&;
// Check Writability of each pixel of the range
requires OutputPixel<std::common_type_t<image_pixel_t<WIma>, stl::iter_value_t<stl::iterator_t<decltype(ima.new_pixels())>>>>;
requires OutputPixel<
std::common_type_t<
stl::iter_value_t<stl::iterator_t<decltype(ima.new_pixels())>>,
image_pixel_t<WIma>>>;
};
} // namespace detail
......@@ -107,11 +114,8 @@ namespace mln::concepts
typename image_index_t<Ima>;
} &&
image_indexable_v<Ima> &&
requires (Ima ima, const Ima cima, image_index_t<Ima> k, image_point_t<Ima> p) {
{ ima[k] } -> image_reference_t<Ima>; // For concrete image it returns a const_reference
{ cima.point_at_index(k) } -> image_point_t<Ima>;
{ cima.index_of_point(p) } -> image_index_t<Ima>;
{ cima.delta_index(p) } -> image_index_t<Ima>;
requires (Ima ima, image_index_t<Ima> k) {
{ ima[k] } -> image_reference_t<Ima>; // For concrete image it returns a const_reference
};
......@@ -159,6 +163,31 @@ namespace mln::concepts
} // namespace detail
// IndexableAndAccessibleImage
template <typename Ima>
concept IndexableAndAccessibleImage =
IndexableImage<Ima> &&
AccessibleImage<Ima> &&
requires (const Ima cima, image_index_t<Ima> k, image_point_t<Ima> p) {
{ cima.point_at_index(k) } -> image_point_t<Ima>;
{ cima.index_of_point(p) } -> image_index_t<Ima>;
{ cima.delta_index(p) } -> image_index_t<Ima>;
};
namespace detail
{
// WritableIndexableAndAccessibleImage
template<typename WIma>
concept WritableIndexableAndAccessibleImage =
IndexableAndAccessibleImage<WIma> &&
detail::WritableImage<WIma> &&
detail::WritableIndexableImage<WIma>;
} // namespace detail
// BidirectionalImage (not in STL term)
template <typename Ima>
concept BidirectionalImage =
......@@ -185,8 +214,7 @@ namespace mln::concepts
// RawImage (not contiguous, stride = padding)
template <typename Ima>
concept RawImage =
IndexableImage<Ima> &&
AccessibleImage<Ima> &&
IndexableAndAccessibleImage<Ima> &&
BidirectionalImage<Ima> &&
stl::DerivedFrom<image_category_t<Ima>, raw_image_tag> &&
requires (Ima ima, const Ima cima, int dim) {
......@@ -202,8 +230,7 @@ namespace mln::concepts
template<typename WIma>
concept WritableRawImage =
WritableImage<WIma> &&
WritableIndexableImage<WIma> &&
WritableAccessibleImage<WIma> &&
WritableIndexableAndAccessibleImage<WIma> &&
WritableBidirectionalImage<WIma> &&
RawImage<WIma> &&
requires(WIma ima, image_value_t<WIma> v) {
......@@ -218,20 +245,18 @@ namespace mln::concepts
// Usage: RawImage<I> && OutputImage<I>
template <typename Ima>
concept OutputImage =
(Image<Ima>&& detail::WritableImage<Ima> && not IndexableImage<Ima> && not AccessibleImage<Ima> &&
not BidirectionalImage<Ima> && not RawImage<Ima>) ||
(IndexableImage<Ima> && detail::WritableIndexableImage<Ima> && not AccessibleImage<Ima> &&
not BidirectionalImage<Ima> && not RawImage<Ima>) ||
(AccessibleImage<Ima> && detail::WritableAccessibleImage<Ima> && not IndexableImage<Ima> &&
not BidirectionalImage<Ima> && not RawImage<Ima>) ||
(BidirectionalImage<Ima> && detail::WritableBidirectionalImage<Ima> && not IndexableImage<Ima> &&
not AccessibleImage<Ima> && not RawImage<Ima>) ||
(RawImage<Ima> && detail::WritableRawImage<Ima>);
// ExtendedImage
(not ForwardImage<Ima> || (ForwardImage<Ima> && detail::WritableImage<Ima>)) &&
(not IndexableImage<Ima> || (IndexableImage<Ima> && detail::WritableIndexableImage<Ima>)) &&
(not AccessibleImage<Ima> || (AccessibleImage<Ima> && detail::WritableAccessibleImage<Ima>)) &&
(not IndexableAndAccessibleImage<Ima> ||
(IndexableAndAccessibleImage<Ima> && detail::WritableIndexableAndAccessibleImage<Ima>)) &&
(not BidirectionalImage<Ima> || (BidirectionalImage<Ima> && detail::WritableBidirectionalImage<Ima>)) &&
(not RawImage<Ima> || (RawImage<Ima> && detail::WritableRawImage<Ima>));
// WithExtensionImage
template <typename Ima>
concept ExtendedImage =
concept WithExtensionImage =
Image<Ima> &&
requires {
typename image_extension_t<Ima>;
......@@ -242,7 +267,19 @@ namespace mln::concepts
};
// TODO: think about ViewImage vs. ConcreteImage
// ConcreteImage
template <typename Ima>
concept ConcreteImage =
Image<Ima> &&
stl::Semiregular<Ima> && // A concrete image is default constructible
not image_view_v<Ima>;
// ViewImage
template <typename Ima>
concept ViewImage =
Image<Ima> &&
image_view_v<Ima>;
#endif // PYLENE_CONCEPT_TS_ENABLED
......
......@@ -18,7 +18,10 @@ namespace mln::concepts
// Pixel
template<typename Pix>
concept Pixel =
stl::Regular<Pix> &&
// Minimum constraint on image object
// Do not requires DefaultConstructible
stl::CopyConstructible<Pix> &&
stl::MoveConstructible<Pix> &&
requires {
typename pixel_value_t<Pix>;
typename pixel_reference_t<Pix>;
......
......@@ -37,8 +37,8 @@ namespace mln
struct image2d : ndimage_base<T, 2, image2d<T>>
{
private:
typedef ndimage_base<T, 2, image2d<T>> base_type;
typedef ndimage_base<T, 2, image2d<T>> base;
using base_type = ndimage_base<T, 2, image2d<T>>;
using base = ndimage_base<T, 2, image2d<T>>;
public:
typedef typename base_type::domain_type domain_type;
......@@ -48,6 +48,7 @@ namespace mln
using base::base;
// FIXME:
// Required because of a MS bug
// (https://developercommunity.visualstudio.com/content/problem/47799/vc-default-constructor-deleted.html)
image2d() = default;
......@@ -86,7 +87,7 @@ namespace mln
for (const std::initializer_list<T>& row : l)
{
mln_assertion(row.size() == nc);
for (const T *val = row.begin(); val != row.end(); ++val, v.next())
for (const T* val = row.begin(); val != row.end(); ++val, v.next())
*v = *val;
}
}
......
......@@ -38,12 +38,13 @@ namespace mln
struct image3d : ndimage_base<T, 3, image3d<T>>
{
private:
typedef ndimage_base<T, 3, image3d<T>> base_type;
typedef ndimage_base<T, 3, image3d<T>> base;
using base_type = ndimage_base<T, 3, image3d<T>>;
using base = ndimage_base<T, 3, image3d<T>>;
public:
typedef typename base_type::domain_type domain_type;
using domain_type = typename base_type::domain_type;
using base::base;
explicit image3d(unsigned border = 3)
: ndimage_base<T, 3, image3d<T>>(border)
......@@ -94,7 +95,7 @@ namespace mln
for (const auto& row : slice)
{
mln_assertion(row.size() == nc);
for (const T *val = row.begin(); val != row.end(); ++val, v.next())
for (const T* val = row.begin(); val != row.end(); ++val, v.next())
*v = *val;
}
}
......
......@@ -23,7 +23,7 @@ namespace mln
{
typedef I type;
};
}
} // namespace internal
struct init
{
......@@ -216,7 +216,7 @@ namespace mln
int m_border;
};
} // end of namespace mln::internal
} // namespace internal
template <typename V, class I>