Introduction
Overview
Pylene is an open-source image processing library that aims at proving a generic framework to develop IP algorithms with safety, simplicity and performance in Mind. It is originated from Milena with the following objectives:
Simplicity: simple modern C++ syntax with Python binding (in development)
Efficiency: write algorithms in a simple way and run them as if they were written in C .We follow one guideline: zero-cost abstraction.
Genericity: write algorithms that are able to run on many kind of images with, yet, zero-cost abstraction.
Interoperability: run algorithms on image coming from and to external libraries (even on your own image type).
Pylene features ready-to-use image data structures (regular 2D, 3D images) and focus (but is not limited to Mathematical Morphology Operators).
Usage
The library provides ready-to-use building blocks for Mathematical Morphology. If you are just interested in using and chaining pre-built operators, just include and use the corresponding file.
template <class I, class N>
requires (mln::concepts::Image<I> &&
mln::concepts::Neighborhood<N, mln::image_point_t<I>> &&
std::unsigned_integral<mln::image_value_t<I>>)
auto chain_1(I input, N nbh, int lambda)
{
using V = mln::image_value_t<I>;
int nlabel = -1;
auto negate = mln::transform(input, [](V x) -> V { return std::numeric_limits<V>::max() - x; });
auto c = mln::morpho::area_closing(negate, nbh, lambda);
auto s = mln::morpho::watershed<int8_t>(c, nbh, nlabel);
return mln::transform(s, regions_lut);
}
Genericity
A generic algorithm is defined in an abstract way so that it can be used with a wide varieties of inputs. Such algorithms are written once, and can then be reused with data of many different types.
The previous snippet of code could be moved in its own routine to improve reusabilityCol
could have been written with more genericity as:
template <class I, class N>
requires (mln::concepts::Image<I> &&
mln::concepts::Neighborhood<N, mln::image_point_t<I>> &&
std::unsigned_integral<mln::image_value_t<I>>)
auto chain_1(I input, N nbh, int lambda)
{
using V = mln::image_value_t<I>;
int nlabel = -1;
auto negate = mln::transform(input, [](V x) -> V { return std::numeric_limits<V>::max() - x; });
auto c = mln::morpho::area_closing(negate, nbh, lambda);
auto s = mln::morpho::watershed<int8_t>(c, nbh, nlabel);
return mln::transform(s, regions_lut);
}
Each input must satisfy constraints corresponding to the nature of the data expected by the algorithm. E.g. in the
previous algorithm, the first argument must be an image, the second argument must be neighborhood (compatible with the
type of point of ima), and the value type of image must be unsigned
, to be negated.
2D gradient image |
Graph with distance on egdes |
Triangle mesh (weighted with curvature information), seen as a simplicial 2-complex |
---|---|---|
Views and Lazy-computation
Inspired by many most C++ mathematical libraries (Eigen, Blitz++), and following the Modern C++ trends of Views (Range-v3), Pylene allows to build expression templates that delays the execution later in the pipeline.
Instead of calling the transform algorithm, we use the transform view to change the input and delay the evaluation
while processing area_closing
:
auto negate = mln::view::transform(input, [](uint8_t x) -> uint8_t { return 255 - x; });
Arithmetic operators on images allow to build views with a simple syntax:
auto negate = uint8_t(255) - input
Generic framework made simple
Writing a generic algorithm and efficient is made simple with Pylene. For example, the algorithm transform is as simple as:
template <mln::concepts::Image I, class F>
auto transform(I input, F fun)
{
using R = std::invoke_result_t<F, mln::image_value_t<I>>; // Deduce the value type of the output
mln::image_ch_value_t<I, R> out = mln::imchavalue<R>(input); // Create a writtable image similar to the input
auto zz = mln::view::zip(input, out);
mln_foreach((auto&& [vin, vout]), zz.values())
vout = fun(vin);
return out;
}
It works for every image type (graph, 2D, 3D) and is as-efficient as if we had written the specific code for each of these types.
Comparison with other libraries
FIXME