`Augmentor.AggregateThenMapFun`

— Type`AggregateThenMapFun <: Augmentor.Operation`

**Description**

Compute some aggregated value of the current image using the given function `aggfun`

, and map that value over the current image using the given function `mapfun`

.

This is particularly useful for achieving effects such as per-image normalization.

**Usage**

`AggregateThenMapFun(aggfun, mapfun)`

**Arguments**

: A function that takes the whole current image as input and which result will also be passed to`aggfun`

`mapfun`

. It should have a signature of`img -> agg`

, where`img`

will the the current image. What type and value`agg`

should be is up to the user.: The binary function that should be mapped over all individual array elements. It should have a signature of`mapfun`

`(px, agg) -> new_px`

where`px`

is a single element of the current image, and`agg`

is the output of`aggfun`

.

**See also**

`MapFun`

, `ConvertEltype`

, `augment`

**Examples**

```
using Augmentor
img = testpattern()
# subtract the average RGB value of the current image
augment(img, AggregateThenMapFun(img -> mean(img), (px, agg) -> px - agg))
```

`Augmentor.CacheImage`

— Type`CacheImage <: Augmentor.ImageOperation`

**Description**

Write the current state of the image into the working memory. Optionally a user has the option to specify a preallocated `buffer`

to write the image into. Note that if a `buffer`

is provided, then it has to be of the correct size and eltype.

Even without a preallocated `buffer`

it can be beneficial in some situations to cache the image. An example for such a scenario is when chaining a number of affine transformations after an elastic distortion, because performing that lazily requires nested interpolation.

**Usage**

```
CacheImage()
CacheImage(buffer)
```

**Arguments**

: Optional. A preallocated`buffer`

`AbstractArray`

of the appropriate size and eltype.

**See also**

**Examples**

```
using Augmentor
# make pipeline that forces caching after elastic distortion
pl = ElasticDistortion(3,3) |> CacheImage() |> Rotate(-10:10) |> ShearX(-5:5)
# cache output of elastic distortion into the allocated
# 20x20 Matrix{Float64}. Note that for this case this assumes that
# the input image is also a 20x20 Matrix{Float64}
pl = ElasticDistortion(3,3) |> CacheImage(zeros(20,20)) |> Rotate(-10:10)
# convenience syntax with the same effect as above.
pl = ElasticDistortion(3,3) |> zeros(20,20) |> Rotate(-10:10)
```

`Augmentor.CacheImageInto`

— Type`CacheImageInto <: Augmentor.ImageOperation`

see `CacheImage`

`Augmentor.ColorJitter`

— Type`ColorJitter <: ColorOperation`

**Description**

Adjusts the brightness and contrast of an image according to the formula `α * image[i] + β * M`

, where `M`

is either `mean(image)`

or the maximum intensity value.

**Usage**

```
ColorJitter()
ColorJitter(α, β; [usemax])
```

**Arguments**

:`α`

`Real`

or`AbstractVector`

of`Real`

that denote the coefficient(s) for contrast adjustment. Defaults to`0.8:0.1:1.2`

.:`β`

`Real`

or`AbstractVector`

of`Real`

that denote the coefficient(s) for brightness adjustment. Defaults to`-0.2:0.1:0.2`

.: Optional. If`usemax::Bool`

`true`

, the brightness will be adjusted by the maximum intensity value; otherwise, the image mean will be used. Defaults to`true`

.

**Examples**

```
using Augmentor
img = testpattern()
# use exactly 1.2 for contrast, and one of 0.5 and 0.8 for brightness
augment(img, ColorJitter(1.2, [0.5, 0.8]))
# pick the coefficients randomly from the specified ranges
augment(img, ColorJitter(0.8:0.1:2.0, 0.5:0.1:1.1))
```

`Augmentor.CombineChannels`

— Type`CombineChannels <: Augmentor.Operation`

**Description**

Combines the first dimension of a given array into a colorant of type `colortype`

using the function `ImageCore.colorview`

. The main difference is that a separate color channel is also expected for Gray images.

The shape of the input image has to be appropriate for the given `colortype`

, which also means that the separated color channel has to be the first dimension of the array. See `PermuteDims`

if that is not the case.

**Usage**

`CombineChannels(colortype)`

**Arguments**

: The color type of the resulting image. Must be a subtype of`colortype`

`ColorTypes.Colorant`

and match the color channel of the given image.

**See also**

`SplitChannels`

, `PermuteDims`

, `augment`

**Examples**

```
julia> using Augmentor, Colors
julia> A = rand(3, 10, 10) # three color channels
3×10×10 Array{Float64,3}:
[...]
julia> augment(A, CombineChannels(RGB))
10×10 Array{RGB{Float64},2}:
[...]
julia> B = rand(1, 10, 10) # singleton color channel
1×10×10 Array{Float64,3}:
[...]
julia> augment(B, CombineChannels(Gray))
10×10 Array{Gray{Float64},2}:
[...]
```

`Augmentor.ConvertEltype`

— Type`ConvertEltype <: Augmentor.Operation`

**Description**

Convert the element type of the given array/image into the given `eltype`

. This operation is especially useful for converting color images to grayscale (or the other way around). That said, the operation is not specific to color types and can also be used for numeric arrays (e.g. with separated channels).

Note that this is an element-wise convert function. Thus it can not be used to combine or separate color channels. Use `SplitChannels`

or `CombineChannels`

for those purposes.

**Usage**

`ConvertEltype(eltype)`

**Arguments**

: The eltype of the resulting array/image.`eltype`

**See also**

`CombineChannels`

, `SplitChannels`

, `augment`

**Examples**

```
julia> using Augmentor, Colors
julia> A = rand(RGB, 10, 10) # three color channels
10×10 Array{RGB{Float64},2}:
[...]
julia> augment(A, ConvertEltype(Gray{Float32})) # convert to grayscale
10×10 Array{Gray{Float32},2}:
[...]
```

`Augmentor.Crop`

— Type`Crop <: Augmentor.ImageOperation`

**Description**

Crops out the area denoted by the specified pixel ranges.

For example the operation `Crop(5:100, 2:10)`

would denote a crop for the rectangle that starts at `x=2`

and `y=5`

in the top left corner and ends at `x=10`

and `y=100`

in the bottom right corner. As we can see the y-axis is specified first, because that is how the image is stored in an array. Thus the order of the provided axes ranges needs to reflect the order of the array dimensions.

**Usage**

```
Crop(indices)
Crop(indices...)
```

**Arguments**

:`indices`

`NTuple`

or`Vararg`

of`UnitRange`

that denote the cropping range for each array dimension. This is very similar to how the axes for`view`

are specified.

**See also**

`CropNative`

, `CropSize`

, `CropRatio`

, `augment`

**Examples**

```
julia> using Augmentor
julia> img = testpattern()
300×400 Array{RGBA{N0f8},2}:
[...]
julia> augment(img, Crop(1:30, 361:400)) # crop upper right corner
30×40 Array{RGBA{N0f8},2}:
[...]
```

`Augmentor.CropNative`

— Type`CropNative <: Augmentor.ImageOperation`

**Description**

Crops out the area denoted by the specified pixel ranges.

For example the operation `CropNative(5:100, 2:10)`

would denote a crop for the rectangle that starts at `x=2`

and `y=5`

in the top left corner of native space and ends at `x=10`

and `y=100`

in the bottom right corner of native space.

In contrast to `Crop`

, the position `x=1`

`y=1`

is not necessarily located at the top left of the current image, but instead depends on the cumulative effect of the previous transformations. The reason for this is because affine transformations are usually performed around the center of the image, which is reflected in "native space". This is useful for combining transformations such as `Rotate`

or `ShearX`

with a crop around the center area.

**Usage**

```
CropNative(indices)
CropNative(indices...)
```

**Arguments**

:`indices`

`NTuple`

or`Vararg`

of`UnitRange`

that denote the cropping range for each array dimension. This is very similar to how the axes for`view`

are specified.

**See also**

`Crop`

, `CropSize`

, `CropRatio`

, `augment`

**Examples**

```
using Augmentor
img = testpattern()
# cropped at top left corner
augment(img, Rotate(45) |> Crop(1:300, 1:400))
# cropped around center of rotated image
augment(img, Rotate(45) |> CropNative(1:300, 1:400))
```

`Augmentor.CropRatio`

— Type`CropRatio <: Augmentor.ImageOperation`

**Description**

Crops out the biggest area around the center of the given image such that the output image satisfies the specified aspect ratio (i.e. width divided by height).

For example the operation `CropRatio(1)`

would denote a crop for the biggest square around the center of the image.

For randomly placed crops take a look at `RCropRatio`

.

**Usage**

```
CropRatio(ratio)
CropRatio(; ratio = 1)
```

**Arguments**

: Optional. A number denoting the aspect ratio. For example specifying`ratio::Number`

`ratio=16/9`

would denote a 16:9 aspect ratio. Defaults to`1`

, which describes a square crop.

**See also**

`RCropRatio`

, `CropSize`

, `Crop`

, `CropNative`

, `augment`

**Examples**

```
using Augmentor
img = testpattern()
# crop biggest square around the image center
augment(img, CropRatio(1))
```

`Augmentor.CropSize`

— Type`CropSize <: Augmentor.ImageOperation`

**Description**

Crops out the area of the specified pixel size around the center of the input image.

For example the operation `CropSize(10, 50)`

would denote a crop for a rectangle of height 10 and width 50 around the center of the input image.

**Usage**

```
CropSize(size)
CropSize(size...)
```

**Arguments**

:`size`

`NTuple`

or`Vararg`

of`Int`

that denote the output size in pixel for each dimension.

**See also**

`CropRatio`

, `Crop`

, `CropNative`

, `augment`

**Examples**

```
using Augmentor
img = testpattern()
# cropped around center of rotated image
augment(img, Rotate(45) |> CropSize(300, 400))
```

`Augmentor.Either`

— Type`Either <: Augmentor.ImageOperation`

**Description**

Chooses between the given `operations`

at random when applied. This is particularly useful if one for example wants to first either rotate the image 90 degree clockwise or anticlockwise (but never both), and then apply some other operation(s) afterwards.

When compiling a pipeline, `Either`

will analyze the provided `operations`

in order to identify the preferred formalism to use when applied. The chosen formalism is chosen such that it is supported by all given `operations`

. This way the output of applying `Either`

will be inferable and the whole pipeline will remain type-stable (even though randomness is involved).

By default each specified image operation has the same probability of occurrence. This default behaviour can be overwritten by specifying the `chance`

manually.

**Usage**

```
Either(operations, [chances])
Either(operations...; [chances])
Either(pairs...)
*(operations...)
*(pairs...)
```

**Arguments**

:`operations`

`NTuple`

or`Vararg`

of`Augmentor.ImageOperation`

that denote the possible choices to sample from when applied.: Optional. Denotes the relative chances for an operation to be sampled. Has to contain the same number of elements as`chances`

`operations`

. Either an`NTuple`

of numbers if specified as positional argument, or alternatively a`AbstractVector`

of numbers if specified as a keyword argument. If omitted every operation will have equal probability of occurring.:`pairs`

`Vararg`

of`Pair{<:Real,<:Augmentor.ImageOperation}`

. A compact way to specify an operation and its chance of occurring together.

**See also**

**Examples**

```
using Augmentor
img = testpattern()
# all three operations have equal chance of occuring
augment(img, Either(FlipX(), FlipY(), NoOp()))
augment(img, FlipX() * FlipY() * NoOp())
# NoOp is twice as likely as either FlipX or FlipY
augment(img, Either(1=>FlipX(), 1=>FlipY(), 2=>NoOp()))
augment(img, Either(FlipX(), FlipY(), NoOp(), chances=[1,1,2]))
augment(img, Either((FlipX(), FlipY(), NoOp()), (1,1,2)))
augment(img, (1=>FlipX()) * (1=>FlipY()) * (2=>NoOp()))
```

`Augmentor.ElasticDistortion`

— Type`ElasticDistortion <: Augmentor.ImageOperation`

**Description**

Distorts the given image using a randomly (uniform) generated vector field of the given grid size. This field will be stretched over the given image when applied, which in turn will morph the original image into a new image using a linear interpolation of both the image and the vector field.

In contrast to [`RandomDistortion`

], the resulting vector field is also smoothed using a Gaussian filter with of parameter `sigma`

. This will result in a less chaotic vector field and thus resemble a more natural distortion.

**Usage**

```
ElasticDistortion(gridheight, gridwidth, scale, sigma, [iter=1], [border=false], [norm=true])
ElasticDistortion(gridheight, gridwidth, scale; [sigma=2], [iter=1], [border=false], [norm=true])
ElasticDistortion(gridheight, [gridwidth]; [scale=0.2], [sigma=2], [iter=1], [border=false], [norm=true])
```

**Arguments**

: The grid height of the displacement vector field. This effectively specifies the number of vertices along the Y dimension used as landmarks, where all the positions between the grid points are interpolated.`gridheight`

: The grid width of the displacement vector field. This effectively specifies the number of vertices along the Y dimension used as landmarks, where all the positions between the grid points are interpolated.`gridwidth`

: Optional. The scaling factor applied to all displacement vectors in the field. This effectively defines the "strength" of the deformation. There is no theoretical upper limit to this factor, but a value somewhere between`scale`

`0.01`

and`1.0`

seem to be the most reasonable choices. Default to`0.2`

.: Optional. Sigma parameter of the Gaussian filter. This parameter effectively controls the strength of the smoothing. Defaults to`sigma`

`2`

.: Optional. The number of times the smoothing operation is applied to the displacement vector field. This is especially useful if`iter`

`border = false`

because the border will be reset to zero after each pass. Thus the displacement is a little less aggressive towards the borders of the image than it is towards its center. Defaults to`1`

.: Optional. Specifies if the borders should be distorted as well. If`border`

`false`

, the borders of the image will be preserved. This effectively pins the outermost vertices on their original position and the operation thus only distorts the inner content of the image. Defaults to`false`

.: Optional. If`norm`

`true`

, the displacement vectors of the field will be normalized by the norm of the field. This will have the effect that the`scale`

factor should be more or less independent of the grid size. Defaults to`true`

.

**See also**

**Examples**

```
using Augmentor
img = testpattern()
# distort with pinned borders
augment(img, ElasticDistortion(15, 15; scale = 0.1))
# distort everything more smoothly.
augment(img, ElasticDistortion(10, 10; sigma = 4, iter=3, border=true))
```

`Augmentor.FlipX`

— Type`FlipX <: Augmentor.AffineOperation`

**Description**

Reverses the x-order of each pixel row. Another way of describing it would be that it mirrors the image on the y-axis, or that it mirrors the image horizontally.

If created using the parameter `p`

, the operation will be lifted into `Either(p=>FlipX(), 1-p=>NoOp())`

, where `p`

denotes the probability of applying `FlipX`

and `1-p`

the probability for applying `NoOp`

. See the documentation of `Either`

for more information.

**Usage**

```
FlipX()
FlipX(p)
```

**Arguments**

: Optional. Probability of applying the operation. Must be in the interval [0,1].`p::Number`

**See also**

**Examples**

```
julia> using Augmentor
julia> img = [200 150; 50 1]
2×2 Matrix{Int64}:
200 150
50 1
julia> img_new = augment(img, FlipX())
2×2 Matrix{Int64}:
150 200
1 50
```

`Augmentor.FlipY`

— Type`FlipY <: Augmentor.AffineOperation`

**Description**

Reverses the y-order of each pixel column. Another way of describing it would be that it mirrors the image on the x-axis, or that it mirrors the image vertically.

If created using the parameter `p`

, the operation will be lifted into `Either(p=>FlipY(), 1-p=>NoOp())`

, where `p`

denotes the probability of applying `FlipY`

and `1-p`

the probability for applying `NoOp`

. See the documentation of `Either`

for more information.

**Usage**

```
FlipY()
FlipY(p)
```

**Arguments**

: Optional. Probability of applying the operation. Must be in the interval [0,1].`p::Number`

**See also**

**Examples**

```
julia> using Augmentor
julia> img = [200 150; 50 1]
2×2 Matrix{Int64}:
200 150
50 1
julia> img_new = augment(img, FlipY())
2×2 Matrix{Int64}:
50 1
200 150
```

`Augmentor.GaussianBlur`

— Type`GaussianBlur <: ColorOperation`

**Description**

Blurs an image using a Gaussian filter.

**Usage**

`GaussianBlur(k, [σ])`

**Arguments**

:`k`

`Integer`

or`AbstractVector`

of`Integer`

that denote the kernel size. It must be an odd positive number.: Optional.`σ`

`Real`

or`AbstractVector`

of`Real`

that denote the standard deviation. It must be a positive number. Defaults to`0.3 * ((k - 1) / 2 - 1) + 0.8`

.

**Examples**

```
using Augmentor
img = testpattern()
# use exactly k=3 and σ=1.0
augment(img, GaussianBlur(3, 1.0))
# pick k and σ randomly from the specified ranges
augment(img, GaussianBlur(3:2:7, 1.0:0.1:2.0))
```

`Augmentor.MapFun`

— Type`MapFun <: Augmentor.Operation`

**Description**

Maps the given function over all individual array elements.

This means that the given function is called with an individual elements and is expected to return a transformed element that should take the original's place. This further implies that the function is expected to be unary. It is encouraged that the function should be consistent with its return type and type-stable.

**Usage**

`MapFun(fun)`

**Arguments**

: The unary function that should be mapped over all individual array elements.`fun`

**See also**

`AggregateThenMapFun`

, `ConvertEltype`

, `augment`

**Examples**

```
using Augmentor, ColorTypes
img = testpattern()
# subtract the constant RGBA value from each pixel
augment(img, MapFun(px -> px - RGBA(0.5, 0.3, 0.7, 0.0)))
# separate channels to scale each numeric element by a constant value
pl = SplitChannels() |> MapFun(el -> el * 0.5) |> CombineChannels(RGBA)
augment(img, pl)
```

`Augmentor.Mask`

— TypeMask wraps a segmentation mask.

`Augmentor.NoOp`

— Type`NoOp <: Augmentor.AffineOperation`

Identity transformation that does not do anything with the given image, but instead passes it along unchanged (without copying).

Usually used in combination with `Either`

to denote a "branch" that does not perform any computation.

`Augmentor.PermuteDims`

— Type`PermuteDims <: Augmentor.Operation`

**Description**

Permute the dimensions of the given array with the predefined permutation `perm`

. This operation is particularly useful if the order of the dimensions needs to be different than the default "julian" layout (described below).

Augmentor expects the given images to be in vertical-major layout for which the colors are encoded in the element type itself. Many deep learning frameworks however require their input in a different order. For example it is not untypical that separate color channels are expected to be encoded in the third dimension.

**Usage**

```
PermuteDims(perm)
PermuteDims(perm...)
```

**Arguments**

: The concrete dimension permutation that should be used. Has to be specified as a`perm`

`Vararg{Int}`

or as a`NTuple`

of`Int`

. The length of`perm`

has to match the number of dimensions of the expected input image to that operation.

**See also**

`SplitChannels`

, `CombineChannels`

, `augment`

**Examples**

```
julia> using Augmentor, Colors
julia> A = rand(10, 5, 3) # width=10, height=5, and 3 color channels
10×5×3 Array{Float64,3}:
[...]
julia> img = augment(A, PermuteDims(3,2,1) |> CombineChannels(RGB))
5×10 Array{RGB{Float64},2}:
[...]
julia> img2 = testpattern()
300×400 Array{RGBA{N0f8},2}:
[...]
julia> B = augment(img2, SplitChannels() |> PermuteDims(3,2,1))
400×300×4 Array{N0f8,3}:
[...]
```

`Augmentor.RCropRatio`

— Type`RCropRatio <: Augmentor.ImageOperation`

**Description**

Crops out the biggest possible area at some random position of the given image, such that the output image satisfies the specified aspect ratio (i.e. width divided by height).

For example the operation `RCropRatio(1)`

would denote a crop for the biggest possible square. If there is more than one such square, then one will be selected at random.

**Usage**

```
RCropRatio(ratio)
RCropRatio(; ratio = 1)
```

**Arguments**

: Optional. A number denoting the aspect ratio. For example specifying`ratio::Number`

`ratio=16/9`

would denote a 16:9 aspect ratio. Defaults to`1`

, which describes a square crop.

**See also**

`RCropSize`

, `CropRatio`

, `CropSize`

, `Crop`

, `CropNative`

, `augment`

**Examples**

```
using Augmentor
img = testpattern()
# crop a randomly placed square of maxmimum size
augment(img, RCropRatio(1))
```

`Augmentor.RCropSize`

— Type`RCropSize <: Augmentor.ImageOperation`

**Description**

Crops out an area of predefined size at some random position of the given image.

For example the operation `RCropSize(128, 64)`

denotes a random crop with height 128 and width 64. `RCropSize(64)`

denotes a square shaped crop of size 64.

**Usage**

```
RCropSize(height, width)
RCropSize(width)
```

**Arguments**

: Height of cropped region`height::Number`

: Width of cropped region`width::Number`

**See also**

`RCropRatio`

, `CropRatio`

, `CropSize`

, `Crop`

, `CropNative`

, `augment`

**Examples**

```
using Augmentor
img = testpattern()
# crop a randomly placed square of size 100
augment(img, RCropSize(100))
```

`Augmentor.Reshape`

— Type`Reshape <: Augmentor.Operation`

**Description**

Reinterpret the shape of the given array of numbers or colorants. This is useful for example to create singleton-dimensions that deep learning frameworks may need for colorless images, or for converting an image array to a feature vector (and vice versa).

**Usage**

```
Reshape(dims)
Reshape(dims...)
```

**Arguments**

: The new sizes for each dimension of the output image. Has to be specified as a`dims`

`Vararg{Int}`

or as a`NTuple`

of`Int`

.

**See also**

**Examples**

```
julia> using Augmentor, Colors
julia> A = rand(10,10)
10×10 Array{Float64,2}:
[...]
julia> augment(A, Reshape(10,10,1)) # add trailing singleton dimension
10×10×1 Array{Float64,3}:
[...]
```

`Augmentor.Resize`

— Type`Resize <: Augmentor.ImageOperation`

**Description**

Rescales the image to a fixed pre-specified pixel size.

This operation does not take any measures to preserve aspect ratio of the source image. Instead, the original image will simply be resized to the given dimensions. This is useful when one needs a set of images to all be of the exact same size.

**Usage**

```
Resize(; height=64, width=64)
Resize(size)
Resize(size...)
```

**Arguments**

:`size`

`NTuple`

or`Vararg`

of`Int`

that denote the output size in pixel for each dimension.

**See also**

**Examples**

```
using Augmentor
img = testpattern()
augment(img, Resize(30, 40))
```

`Augmentor.Rotate`

— Type`Rotate <: Augmentor.AffineOperation`

**Description**

Rotate the image upwards for the given `degree`

. This operation can only be performed as an affine transformation and will in general cause other operations of the pipeline to use their affine formulation as well (if they have one).

In contrast to the special case rotations (e.g. `Rotate90`

, the type `Rotate`

can describe any arbitrary number of degrees. It will always perform the rotation around the center of the image. This can be particularly useful when combining the operation with `CropNative`

.

**Usage**

`Rotate(degree)`

**Arguments**

:`degree`

`Real`

or`AbstractVector`

of`Real`

that denote the rotation angle(s) in degree. If a vector is provided, then a random element will be sampled each time the operation is applied.

**See also**

`Rotate90`

, `Rotate180`

, `Rotate270`

, `CropNative`

, `augment`

**Examples**

```
using Augmentor
img = testpattern()
# rotate exactly 45 degree
augment(img, Rotate(45))
# rotate between 10 and 20 degree upwards
augment(img, Rotate(10:20))
# rotate one of the five specified degrees
augment(img, Rotate([-10, -5, 0, 5, 10]))
```

`Augmentor.Rotate180`

— Type`Rotate180 <: Augmentor.AffineOperation`

**Description**

Rotates the image 180 degrees. This is a special case rotation because it can be performed very efficiently by simply rearranging the existing pixels. Furthermore, the output image will have the same dimensions as the input image.

If created using the parameter `p`

, the operation will be lifted into `Either(p=>Rotate180(), 1-p=>NoOp())`

, where `p`

denotes the probability of applying `Rotate180`

and `1-p`

the probability for applying `NoOp`

. See the documentation of `Either`

for more information.

**Usage**

```
Rotate180()
Rotate180(p)
```

**Arguments**

: Optional. Probability of applying the operation. Must be in the interval [0,1].`p::Number`

**See also**

`Rotate90`

, `Rotate270`

, `Rotate`

, `Either`

, `augment`

**Examples**

```
julia> using Augmentor
julia> img = [200 150; 50 1]
2×2 Matrix{Int64}:
200 150
50 1
julia> img_new = augment(img, Rotate180())
2×2 Matrix{Int64}:
1 50
150 200
```

`Augmentor.Rotate270`

— Type`Rotate270 <: Augmentor.AffineOperation`

**Description**

Rotates the image upwards 270 degrees, which can also be described as rotating the image downwards 90 degrees. This is a special case rotation, because it can be performed very efficiently by simply rearranging the existing pixels. However, it is generally not the case that the output image will have the same size as the input image, which is something to be aware of.

If created using the parameter `p`

, the operation will be lifted into `Either(p=>Rotate270(), 1-p=>NoOp())`

, where `p`

denotes the probability of applying `Rotate270`

and `1-p`

the probability for applying `NoOp`

. See the documentation of `Either`

for more information.

**Usage**

```
Rotate270()
Rotate270(p)
```

**Arguments**

: Optional. Probability of applying the operation. Must be in the interval [0,1].`p::Number`

**See also**

`Rotate90`

, `Rotate180`

, `Rotate`

, `Either`

, `augment`

**Examples**

```
julia> using Augmentor
julia> img = [200 150; 50 1]
2×2 Matrix{Int64}:
200 150
50 1
julia> img_new = augment(img, Rotate270())
2×2 Matrix{Int64}:
50 200
1 150
```

`Augmentor.Rotate90`

— Type`Rotate90 <: Augmentor.AffineOperation`

**Description**

Rotates the image upwards 90 degrees. This is a special case rotation because it can be performed very efficiently by simply rearranging the existing pixels. However, it is generally not the case that the output image will have the same size as the input image, which is something to be aware of.

If created using the parameter `p`

, the operation will be lifted into `Either(p=>Rotate90(), 1-p=>NoOp())`

, where `p`

denotes the probability of applying `Rotate90`

and `1-p`

the probability for applying `NoOp`

. See the documentation of `Either`

for more information.

**Usage**

```
Rotate90()
Rotate90(p)
```

**Arguments**

: Optional. Probability of applying the operation. Must be in the interval [0,1].`p::Number`

**See also**

`Rotate180`

, `Rotate270`

, `Rotate`

, `Either`

, `augment`

**Examples**

```
julia> using Augmentor
julia> img = [200 150; 50 1]
2×2 Matrix{Int64}:
200 150
50 1
julia> img_new = augment(img, Rotate90())
2×2 Matrix{Int64}:
150 1
200 50
```

`Augmentor.Scale`

— Type`Scale <: Augmentor.AffineOperation`

**Description**

Multiplies the image height and image width by the specified `factors`

. This means that the size of the output image depends on the size of the input image.

The provided `factors`

can either be numbers or vectors of numbers.

If numbers are provided, then the operation is deterministic and will always scale the input image with the same factors.

In the case vectors are provided, then each time the operation is applied a valid index is sampled and the elements corresponding to that index are used as scaling factors.

The scaling is performed relative to the image center, which can be useful when following the operation with `CropNative`

.

**Usage**

```
Scale(factors)
Scale(factors...)
```

**Arguments**

:`factors`

`NTuple`

or`Vararg`

of`Real`

or`AbstractVector`

that denote the scale factor(s) for each array dimension. If only one variable is specified it is assumed that height and width should be scaled by the same factor(s).

**See also**

**Examples**

```
using Augmentor
img = testpattern()
# half the image size
augment(img, Scale(0.5))
# uniformly scale by a random factor from 1.2, 1.3, or 1.4
augment(img, Scale([1.2, 1.3, 1.4]))
# scale by either 0.5x0.7 or by 0.6x0.8
augment(img, Scale([0.5, 0.6], [0.7, 0.8]))
```

`Augmentor.SemanticWrapper`

— TypeA SemanticWrapper determines the semantics of data that it wraps. Any subtype needs to implement function `unwrap(wrapper)`

that returns the wrapped data.

`Augmentor.ShearX`

— Type`ShearX <: Augmentor.AffineOperation`

**Description**

Shear the image horizontally for the given `degree`

. This operation can only be performed as an affine transformation and will in general cause other operations of the pipeline to use their affine formulation as well (if they have one).

It will always perform the transformation around the center of the image. This can be particularly useful when combining the operation with `CropNative`

.

**Usage**

`ShearX(degree)`

**Arguments**

:`degree`

`Real`

or`AbstractVector`

of`Real`

that denote the shearing angle(s) in degree. If a vector is provided, then a random element will be sampled each time the operation is applied.

**See also**

**Examples**

```
using Augmentor
img = testpattern()
# shear horizontally exactly 5 degree
augment(img, ShearX(5))
# shear horizontally between 10 and 20 degree to the right
augment(img, ShearX(10:20))
# shear horizontally one of the five specified degrees
augment(img, ShearX([-10, -5, 0, 5, 10]))
```

`Augmentor.ShearY`

— Type`ShearY <: Augmentor.AffineOperation`

**Description**

Shear the image vertically for the given `degree`

. This operation can only be performed as an affine transformation and will in general cause other operations of the pipeline to use their affine formulation as well (if they have one).

It will always perform the transformation around the center of the image. This can be particularly useful when combining the operation with `CropNative`

.

**Usage**

`ShearY(degree)`

**Arguments**

:`degree`

`Real`

or`AbstractVector`

of`Real`

that denote the shearing angle(s) in degree. If a vector is provided, then a random element will be sampled each time the operation is applied.

**See also**

**Examples**

```
using Augmentor
img = testpattern()
# shear vertically exactly 5 degree
augment(img, ShearY(5))
# shear vertically between 10 and 20 degree upwards
augment(img, ShearY(10:20))
# shear vertically one of the five specified degrees
augment(img, ShearY([-10, -5, 0, 5, 10]))
```

`Augmentor.SplitChannels`

— Type`SplitChannels <: Augmentor.Operation`

**Description**

Splits out the color channels of the given image using the function `ImageCore.channelview`

. This will effectively create a new array dimension for the colors in the front. In contrast to `ImageCore.channelview`

it will also result in a new dimension for gray images.

This operation is mainly useful at the end of a pipeline in combination with `PermuteDims`

in order to prepare the image for the training algorithm, which often requires the color channels to be separate.

**Usage**

`SplitChannels()`

**See also**

`PermuteDims`

, `CombineChannels`

, `augment`

**Examples**

```
julia> using Augmentor
julia> img = testpattern()
300×400 Array{RGBA{N0f8},2}:
[...]
julia> augment(img, SplitChannels())
4×300×400 Array{N0f8,3}:
[...]
julia> augment(img, SplitChannels() |> PermuteDims(3,2,1))
400×300×4 Array{N0f8,3}:
[...]
```

`Augmentor.Zoom`

— Type`Zoom <: Augmentor.ImageOperation`

**Description**

Scales the image height and image width by the specified `factors`

, but crops the image such that the original size is preserved.

The provided `factors`

can either be numbers or vectors of numbers.

If numbers are provided, then the operation is deterministic and will always scale the input image with the same factors.

In the case vectors are provided, then each time the operation is applied a valid index is sampled and the elements corresponding to that index are used as scaling factors.

In contrast to `Scale`

the size of the output image is the same as the size of the input image, while the content is scaled the same way. The same effect could be achieved by following a `Scale`

with a `CropSize`

, with the caveat that one would need to know the exact size of the input image before-hand.

**Usage**

```
Zoom(factors)
Zoom(factors...)
```

**Arguments**

:`factors`

`NTuple`

or`Vararg`

of`Real`

or`AbstractVector`

that denote the scale factor(s) for each array dimension. If only one variable is specified it is assumed that height and width should be scaled by the same factor(s).

**See also**

**Examples**

```
using Augmentor
img = testpattern()
# half the image size
augment(img, Zoom(0.5))
# uniformly scale by a random factor from 1.2, 1.3, or 1.4
augment(img, Zoom([1.2, 1.3, 1.4]))
# scale by either 0.5x0.7 or by 0.6x0.8
augment(img, Zoom([0.5, 0.6], [0.7, 0.8]))
```

`Augmentor.augment!`

— Method`augment!(out, img, pipeline) -> out`

Apply the operations of the given `pipeline`

sequentially to the image `img`

and write the resulting image into the preallocated parameter `out`

. For convenience `out`

is also the function's return-value.

```
img = testpattern()
out = similar(img)
augment!(out, img, FlipX() |> FlipY())
```

The parameter `img`

can either be a single image, or a tuple of multiple images. In case `img`

is a tuple of images, the parameter `out`

has to be a tuple of the same length and ordering. See `augment`

for more information.

```
imgs = (testpattern(), Gray.(testpattern()))
outs = (similar(imgs[1]), similar(imgs[2]))
augment!(outs, imgs, FlipX() |> FlipY())
```

The parameter `pipeline`

can be a `Augmentor.Pipeline`

, a tuple of `Augmentor.Operation`

, or a single `Augmentor.Operation`

.

```
img = testpattern()
out = similar(img)
augment!(out, img, FlipX() |> FlipY())
augment!(out, img, (FlipX(), FlipY()))
augment!(out, img, FlipX())
```

`Augmentor.augment`

— Method```
augment([img], pipeline) -> out
augment(img=>mask, pipeline) -> out
```

Apply the operations of the given `pipeline`

sequentially to the given image `img`

and return the resulting image `out`

. For the second method, see Semantic wrappers below.

```
julia> img = testpattern();
julia> out = augment(img, FlipX() |> FlipY())
3×2 Array{Gray{N0f8},2}:
[...]
```

The parameter `img`

can either be a single image, or a tuple of multiple images. In case `img`

is a tuple of images, its elements will be assumed to be conceptually connected. Consequently, all images in the tuple will take the exact same path through the pipeline; even when randomness is involved. This is useful for the purpose of image segmentation, for which the input and output are both images that need to be transformed exactly the same way.

```
img1 = testpattern()
img2 = Gray.(testpattern())
out1, out2 = augment((img1, img2), FlipX() |> FlipY())
```

The parameter `pipeline`

can be a `Augmentor.Pipeline`

, a tuple of `Augmentor.Operation`

, or a single `Augmentor.Operation`

.

```
img = testpattern()
augment(img, FlipX() |> FlipY())
augment(img, (FlipX(), FlipY()))
augment(img, FlipX())
```

If `img`

is omitted, Augmentor will use the augmentation test image provided by the function `testpattern`

as the input image.

`augment(FlipX())`

**Semantic wrappers**

It is possible to define more flexible augmentation pipelines by wrapping the input into a semantic wrapper. Semantic wrappers determine meaning of an input, and ensure that only appropriate operations are applied on that input.

Currently implemented semantic wrappers are:

`Augmentor.Mask`

: Wraps a segmentation mask. Allows only spatial transformations.The convenient usage for this is

`augment(img => mask, pipeline)`

.

**Example**

```
using Augmentor
using Augmentor: unwrap, Mask
img, mask = testpattern(), testpattern()
pl = Rotate90() |> GaussianBlur(3)
aug_img, aug_mask = unwrap.(augment((img, Mask(mask)), pl))
# Equivalent usage
aug_img, aug_mask = augment(img => mask, pl)
# GaussianBlur will be skipped for our `mask`
aug_mask == augment(mask, Rotate90())
# output
true
```

`Augmentor.augmentbatch!`

— Method`augmentbatch!([resource], outs, imgs, pipeline, [obsdim]) -> outs`

Apply the operations of the given `pipeline`

to the images in `imgs`

and write the resulting images into `outs`

.

Both `outs`

and `imgs`

have to contain the same number of images. Each of these two variables can either be in the form of a higher dimensional array, in the form of a vector of arrays for which each vector element denotes an image.

```
# create five example observations of size 3x3
imgs = rand(3,3,5)
# create output arrays of appropriate shape
outs = similar(imgs)
# transform the batch of images
augmentbatch!(outs, imgs, FlipX() |> FlipY())
```

If one (or both) of the two parameters `outs`

and `imgs`

is a higher dimensional array, then the optional parameter `obsdim`

can be used specify which dimension denotes the observations (defaults to `ObsDim.Last()`

),

```
# create five example observations of size 3x3
imgs = rand(5,3,3)
# create output arrays of appropriate shape
outs = similar(imgs)
# transform the batch of images
augmentbatch!(outs, imgs, FlipX() |> FlipY(), ObsDim.First())
```

Similar to `augment!`

, it is also allowed for `outs`

and `imgs`

to both be tuples of the same length. If that is the case, then each tuple element can be in any of the forms listed above. This is useful for tasks such as image segmentation, where each observations is made up of more than one image.

```
# create five example observations where each observation is
# made up of two conceptually linked 3x3 arrays
imgs = (rand(3,3,5), rand(3,3,5))
# create output arrays of appropriate shape
outs = similar.(imgs)
# transform the batch of images
augmentbatch!(outs, imgs, FlipX() |> FlipY())
```

The parameter `pipeline`

can be a `Augmentor.Pipeline`

, a tuple of `Augmentor.Operation`

, or a single `Augmentor.Operation`

.

```
augmentbatch!(outs, imgs, FlipX() |> FlipY())
augmentbatch!(outs, imgs, (FlipX(), FlipY()))
augmentbatch!(outs, imgs, FlipX())
```

The optional first parameter `resource`

can either be `CPU1()`

(default) or `CPUThreads()`

. In the later case the images will be augmented in parallel. For this to make sense make sure that the environment variable `JULIA_NUM_THREADS`

is set to a reasonable number so that `Threads.nthreads()`

is greater than 1.

```
# transform the batch of images in parallel using multithreading
augmentbatch!(CPUThreads(), outs, imgs, FlipX() |> FlipY())
```

`Augmentor.contiguous`

— Method```
contiguous(A::AbstractArray)
contiguous(A::Tuple)
```

Return a memory contiguous array for better performance.

Data copy only happens when necessary. For example, views returned by `view`

, `PermutedDimsArray`

are such cases.

See also: `plain_array`

, `plain_axes`

`Augmentor.gaussian_field`

— Method`gaussian_field(gridwidth, gridheight[, scale=0.2, sigma=2, iterations=1, border=true, normalize=true]) -> Array{Float64,3}`

Generate a 2D vector field by placing uniformly random generated displacement vectors on an equally spaced grid of size `gridheight × gridwidth`

. Additionally, this vector field is smoothed using a gaussian filter with parameter `sigma`

. This will result in a less chaotic vector field than `uniform_field`

and be much more similar to an elastic distortion.

The resulting array will have 3 dimensions, for which the first dimension will always have a size of 2, which denotes the y and x dimension of the vectors.

`Augmentor.plain_array`

— Method```
plain_array(A::AbstractArray)
plain_array(A::Tuple)
```

Return a memory contiguous plain array for better performance. A plain array is either an `Array`

or a `StaticArray`

.

Data copy only happens when necessary. For example, views returned by `view`

, `PermutedDimsArray`

are such cases.

See also: `contiguous`

, `plain_axes`

`Augmentor.plain_axes`

— Method`plain_axes(A::AbstractArray)`

Generate a 1-based array from `A`

without data copy.

See also: `contiguous`

, `plain_array`

`Augmentor.prepareaffine`

— Method`prepareaffine(img)`

Make sure `img`

is either a `InvWarpedView`

or a `SubArray`

of one. If that is already the case, `img`

will be returned as is. Otherwise `invwarpedview`

will be called using a `Flat()`

extrapolation scheme.

Doing this will tell subsequent operations that they should also participate as affine operations (i.e. use `AffineMap`

if they can).

`Augmentor.seek_connected`

— Method`seek_connected(f, N::Int, head::DataType, tail::Tuple) -> (N, remainder)`

Recursively scan a tuple of `DataType`

(split into its `head`

and `tail`

) to compute the length `N`

of the uninterrupted sequence of adjacent operations where the predicate `f`

is true. Additionally the `remainder`

of the tuple (without that sequence) is also returned.

`Augmentor.shouldapply`

— Method```
shouldapply(op, wrapper)
shouldapply(typeof(op), typeof(wrapper))
```

Determines if operation `op`

should be applied to semantic wrapper `wrapper`

.

`Augmentor.testpattern`

— Method`testpattern([T=RGBA{N0f8}]; ratio=1.0) -> Matrix{RGBA{N0f8}}`

Load and return the provided 300x400 test image. Additional args and kwargs are passed to `imresize`

.

The returned image was specifically designed to be informative about the effects of the applied augmentation operations. It is thus well suited to prototype an augmentation pipeline, because it makes it easy to see what kind of effects one can achieve with it.

`Augmentor.uniform_field`

— Method`uniform_field(gridwidth, gridheight[, scale=0.2, border=true, normalize=true]) -> Array{Float64,3}`

Generate a 2D vector field by placing uniformly random generated displacement vectors on an equally spaced grid of size `gridheight × gridwidth`

.

The resulting array will have 3 dimensions, for which the first dimension will always have a size of 2, which denotes the y and x dimension of the vectors.

`Augmentor.unwrap`

— Method`unwrap(sw::SemanticWrapper)`

Returns the original object.