# Geometric Transformations¶

Several geometric image transformations are implemented in Lima:

pixel binning,

crop (also known as Region-of-Interest: RoI),

vertical (top-down) / horizontal (left-right) flip and

rotation by 90 degrees, both clockwise (CW) and counter-clockwise (CCW), and 180 degrees.

These operations are normally applied on the generated images on user demand. Several detectors can implement pixel binning and or RoIs, typically increasing the effective frame rate or reducing the data bandwidth. Other operations like flip do not affect the detector timing but avoids the need of extra software processing, so hardware-acceleration is preferred.

Isometric transformations like flip and rotation are also necessary to reconstruct the raw images sent by tiled detectors, in which constrains in the detector head design impose different readout sequences for different modules. Lima follows the default image convention where column index X increases towards the right direction and row index Y increases towards the bottom, so <0,0> is the top-left corner. The corresponding flip and/or rotation must be performed before assembling each elemental region in order to follow this rule.

The `lima::processing::geom`

namespace provides helpers to manipulate the coordinates during the application of geometric transformations.

## Affine Transformation Matrix¶

Each geometric transformation can be described by an affine Boost.Gil 3x2 matrix (actually a 3x3 matrix whose last column is always <0,0,1>). The matrix converts the coordinates of a pixel at the input of the transformation to its corresponding pixel in the output:

The third dimension allows translations in the coordinate system.

For scaling transformations, such as binning, the arithmetic precision can be guarantied with rational number arithmetic (e.g. Boost.Rational) or arbitrary precision arithmetic (e.g. Boost.Multiprecision):

```
using integral_t = std::ptrdiff_t;
using point_t = boost::gil::point<integral_t>;
using rational_t = boost::rational<integral_t>;
using affine_t = boost::gil::matrix3x2<rational_t>;
```

The affine matrix associated to a sequence of transformation is the multiplication of the individual matrices:

The `boost::gil::inverse`

function returns a transformation matrix to input coordinates from output ones:

```
point_t output = input * xform_affine;
BOOST_CHECK(input == output * boost::gil::inverse(xform_affine));
```

To get the coordinate of a pixel after a given transformation, a number of step

Transform the pixel coordinate to geometric coordinate (e.g. offset to the center of the pixel p’ = p + {0.5, 0.5})

Move the image to the center of the coordinate system

Apply the transformation matrix m (p’ = m * p)

Move the image back to the first quadrant of the coordinate system

Transform the geometric coordinate to pixel coordinate (e.g. offset to the center of the pixel p’ = p - {0.5, 0.5})

## Available basic transformations¶

`bin`

`crop`

`flip_up_down`

`flip_left_right`

`rotate_90ccw`

`rotate_180`

`rotate_90cw`

## Isometric transformations¶

Eight isometric transformations are identified in Lima:

isometric_xform_none

isometric_xform_vflip

isometric_xform_hflip

isometric_xform_rot90ccw

isometric_xform_rot180

isometric_xform_rot90cw

isometric_xform_vflip_rot90ccw

isometric_xform_hflip_rot90ccw

The *any_isometric_xform_t* is a *std::variant* of these transformations.

The implementation represents an isometric transformation as a combination of three basic operations: vertical flip, horizontal flip and rotation 90 CCW. In particular, it is a Boost.Hana tuple of three booleans:

```
#define LIMA_ISO_XFORM_TUPLE(v, h, r) \
boost::hana::tuple<boost::hana::bool_<v>, \
boost::hana::bool_<h>, \
boost::hana::bool_<r>>
```

The result of the successive application of two transformations, which is
also an isometric transformation, is given by the *operator +*. It is implemented
to provide a constexpr, as well as its inverse *operator -*. For any given
transformation, its *inverse* can always obtained:

```
template <bool V, bool H, bool R>
constexpr auto inverse(const isometric_xform_base_t<V, H, R>& t)
{
return isometric_xform_none() - t;
}
```

## Helpers¶

The following helpers are also defined in `lima::processing::geometry`

:

`rectangle`

: represents a selection in a image, providing inclusion and overlapping calculationsget_affine: function template returning the affine matrix of an arbitrary transformation

get_output_dimensions: function template returning the output dimensions after an arbitrary transformation

apply_isometric_xform: result of an rectangle after a transformation