Images

Images defined by a vector of point -> value are not accessible (ima(p))

Forsee to add pdim (point) and vdim (value) for dimension constant in iamge concept

Description & Design Overview

An image f is basically a function associating a point p to a value f(p). The pair (point,value) is called a pixel. An image is defined over a domain which is an ordered range of points. Depending on the image properties, an image type enables a set of operations.

Images have pointer semantics

FIXME Explain that:

  • Images have shallow copy (pointers semantics)

  • Owner vs non-owner images

Images (generally) do not have const-semantics

FIXME: Explain how to pass images to function.

Images are iterables

Most images provide 3 ways of traversing.

  • Iterating on points through the domain

  • Iterating on values

  • Iterating on pixels

As a consequence, such an image f provide:

  • f.domain() The range of the image points

  • f.values() The range of the image values

  • f.pixels() The range of the image pixels

An image can be a BidirectionalImage and allows to be traversed in the reverse order. In that case, the ranges are ReversibleRange.

Below is an example of image traversal:

mln::image2d<uint8_t> f = {{1,2,3}, {4,5,6}};

mln_foreach(auto p, f.domain())
    std::cout << p << ":" << f(p) << "\n";


mln_foreach(auto v, f.values())
    std::cout << v << "\n";


mln_foreach(auto px, f.pixels())
    std::cout << px.point() << ":" << px.val() << "\n";


mln_foreach(auto p, mln::ranges::view::reverse(f.domain()))
    std::cout << p << ":" << f(p) << "\n";


mln_foreach(auto v, mln::ranges::view::reverse(f.values()))
    std::cout << v << "\n";


mln_foreach(auto px, mln::ranges::view::reverse(f.pixels()))
    std::cout << px.point() << ":" << px.val() << "\n";

It produces the following output.

== Traversing forward ==
Traversing through points.
[0,0]:1
[0,1]:2
[0,2]:3
[1,0]:4
[1,1]:5
[1,2]:6
Traversing on values.
1
2
3
4
5
6
Traversing with pixels.
[0,0]:1
[0,1]:2
[0,2]:3
[1,0]:4
[1,1]:5
[1,2]:6

== Traversing backward ==
Traversing through points.
[1,2]:6
[1,1]:5
[1,0]:4
[0,2]:3
[0,1]:2
[0,0]:1
Traversing on values.
6
5
4
3
2
1
Traversing with pixels.
[1,2]:6
[1,1]:5
[1,0]:4
[0,2]:3
[0,1]:2
[0,0]:1

Note

Not all image provide the access of the value associated to a point (the f(p) syntax). This is available for AccessibleImage images.

Note

The macro mln_foreach is just a shortcut to iterate over rows in an efficient way.

To iterate over several images in the same time, use mln::ranges::view::zip() to pack the value or pixel ranges of each image:

auto&& v_rng = mln::ranges::view::zip(f1.values(), f2.values())
mln_foreach((auto [v1, v2]), v_rng)
    std::cout << v1 << " " << v2 << "\n";

Images can be initialized from other images

It is quite common to use temporary images for computation or to return new images whose type depend on the image input type. As a consequence, we may need to initialize images from other images, this is called concretization.

The effects of the concretization are:

Given a image f, the concretization of f gives an image g, with a domain equal to f’s, which can store values and such that any write to f or g does not have any side-affect on the other.

Two methods enable to create a new image g from a prototype f. The second allows to use another value type:

I f = ...;
mln::concrete_t<I>  g1 = f.concretize();
mln::ch_value_t<I, OtherType> g2 = f.template ch_value<OtherType>()

Because the syntax of a call to a template method is quite cumbersome, free functions can be used:

I f = ...;
mln::concrete_t<I>            g1 = mln::imconcretize(f);
mln::ch_value_t<I, OtherType> g2 = mln::imchvalue<OtherType>(f);

Warning

The type returned by concretize et al. are not images but image builders that support advanced parameterization of the initialization. So you should not use auto type deduction for variables (or by calling explicitly build() - see below):

I f = ...;
auto g1 = mln::imconcretize(f).build();
auto g2 = mln::imchvalue<OtherType>(f).build();

Advanced initialization with image builders

image builders (see Image Builder) follow the Named parameter Idiom and provides additional init parameters. Note that it may fail to fulfill the requirements, so a status code may be queried to check if everything succeeded.

set_init_value(v)

Requires the image to be set to v

set_border(k)

Requires the image to have border of size k.

adjust(se)

Requires the extension of the image to be wide enough to hold the StructuringElement se

get_status(&status)

Get the status code

build()

Build and return the new image.

Example:

I f = ...;
mln::image_build_error_code st_code;
mln::concrete_t<I> g1 = mln::imconcretize(f).adjust(mln::c4).get_status(&st_code);
if (st_code == 0)
    // run with g1
else
    // g1 may not have the adequate extension

Initialization constructor

Advanced initialization require an initialization constructor that enables an image to be initialized from another image and deduces the initialization configuration from it.

It has the form:

I(const I& other, mln::image_build_params params)

Initializes from other but overrides init-parameters with those from params.

Image Concepts

Image Properties

Image concepts are property-based. An image concept is group of images types sharing some properties.

Image (traversal) category

The image category describes how an image can be traversed. It can be forward, bidirectional (can be traversed backward and forward), or raw (buffer encoded image with contiguous line buffer)

Image Accessibility

An image is said accessible whenever it allows to access the value associated to a point, i.e. it allows to write f(p). While it may seem trivial, not all image are accessible (for example image defined by a vector of pair (p, f(p)).

Image Indexability

An image is indexable whenever it enables to access values with an index localisator. Usually, accessing through an index is faster than accessing by a point.

Image Writability

An image writable can be used as an output image to store the result of a processing. Some image are read-only as images that compute values on-the-fly and are not buffer-encoded.

The figure below illustrates image properties and some of the image concept.

../_images/image-concepts.svg

Image concepts and properties.

Image Concept

  1. template<typename I>
    concept Image
  2. template<typename I>
    concept InputImage
  3. template<typename I>
    concept ForwardImage

    Image (also ForwardImage and InputImage) is the minimal concept for modeling images. It provides read access and multi-pass traversal (not that in the STL input ranges are not necessary forward ranges). Images are std::CopyConstructible and std::MoveConstructible so that they can be passed by copy in algorithms or copied in image adapters.

    Type definition

    Type

    Abbr

    Definition

    Requirements

    point_type

    P

    domain_type

    A model of Domain

    value_type

    V

    reference

    VRef

    pixel_type

    Pix

    A model of Pixel

    concrete_type

    A model of OutputImage

    ch_value_type<V2>

    A model of OutputImage

    • The type of the domain must be compatible with the image, that is, the type of points of the domain are convertible to image point type

    • The type of pixel must be compatible with the image typedefs, that is, given a pixel pix of type Pix, pix.val() must be convertible to VRef and pix.point() convertible to P

    Traits

    Type Property

    Value

    Description

    category

    forward_image_tag

    Tag for the traversal category of the image

    extension_category

    none_extension_tag

    Tag for extension category of the image

    accessible

    std::false_type

    Tag for the image accessibility property

    indexable

    std::false_type

    Tag for the image Indexability property

    Valid expression

    Expression

    Return Type

    Precondition

    Sementics

    ima.domain()

    domain_type

    The domain of the image.

    ima.values()

    std::ForwardRange

    A range that allows to traverse image values. The elements of the range are convertible to VRef.

    ima.pixels()

    std::ForwardRange

    A range that allows to traverse image pixels. The elements of the range are convertible to Pix.

    ima.concretize()

    auto

    Returns a concrete image initialized from this

    ima.ch_value<V2>()

    auto

    Returns a concrete image initialized from this with value type V2

Output Image Concept

template<class I>
concept OutputImage

Output Images extends the concept InputImage for images that are writable.

Type definition

Type

Abbr

Definition

Requirements

reference

VRef

An object of type V is assignable to Vref

pixel_type

Pix

A model of WritablePixel

Valid expression

Expression

Return Type

Precondition

Sementics

ima.values()

std::OutputRange

A range that allows to traverse image values. The elements of the range are convertible to VRef.

ima.pixels()

std::ForwardRange

A range that allows to traverse image pixels. The elements of the range are convertible to Pix.

Bidirectional Image Concept

template<class I>
concept BidirectionalImage

Bidirectional Images extends the concept InputImage for images that are traversed forward and backward. Traversing in both direction is required by some algorithms like the chamfer distance transform. Note that Bidirectional does not have the same semantic as in the STL. Bidirectional means ReversibleRange.

Type definition

Type

Abbr

Definition

Requirements

domain_type

A model of Domain and ReversibleRange

Traits

Type Property

Value

Description

category

Bidirectional_image_tag

Tag for the traversal category of the image

Valid expression

Expression

Return Type

Precondition

Sementics

ima.domain()

domain_type

The domain of the image.

ima.values()

std::ReversibleRange

A range that allows to traverse image values both ways.

ima.pixels()

std::ReversibleRange

A range that allows to traverse image pixels both ways.

Accessible Image Concept

template<class I>
concept AccessibleImage

Images that provides the accessibility* property. Values can be access from any point.

Traits

Type Property

Value

Description

accessible

std::true_type

Tag for the image accessibility property

Valid expression

Expression

Return Type

Precondition

Sementics

ima(p)

I::reference

ima.domain().has(p)

Value access with bound checking.

ima.pixel(p)

I::pixel_type

ima.domain().has(p)

Pixel access with bound checking.

ima.at(p)

I::reference

Value access without bound checking.

ima.pixel_at(p)

I::pixel_type

Pixel access without bound checking.

Indexable Image Concept

template<class I>
concept IndexableImage

Output Images extends the concept InputImage for images that are writable.

Images that provides the indexability* property. Values can be access through an index. Every point has unique index and index may not be compatible between images. In other words, (p₁ = p₂) ⇏ (ima.index_of_point(p₁) = ima.index_of_point(p₂).

Type definition

Type

Abbr

Definition

Requirements

index_type

Idx

A model of std::Integral

Traits

Type Property

Value

Description

indexable

std::true_type

Tag for the image Indexability property

Valid expression

Expression

Return Type

Precondition

Sementics

ima[k]

reference

Returns the value at index k (no bound checking)

Moreover, if the image is both Indexable and Accessible, then the following expressions are valid:

cima.index_of_point(p)

index_type

Get the index of point p

cima.point_at_index(k)

point_type

Get the point at index p

cima.delta_index(dp)

index_type

Get the index difference for a shift of dp

Image Traits

template<class I>
using image_concrete_t = I::concrete_type
template<class I, class V>
using image_ch_value_t = I::ch_value_type<V>

Get the concrete of an image (a type that is writable and can be resized). In the second, it requests an image whose value type is V.

template<class I>
using image_value_t = I::value_type
template<class I>
using image_reference_t = I::reference

Get the type of the values of an image. Value type is the naked type, reference is the type returned by the expression ima(p) which is generally T&.

template<class I>
using image_domain_t = I::domain_type
template<class I>
using image_point_t = I::point_type

Get the type of the domain and the type of the points (points being the domain values)

template<class I>
using image_index_t = I::index_type

Get the type of the index of Indexable images.

Image Views

Predefined images types