A high-performance general-purpose compute library

Rearrange windowed sections of an array into columns (or rows) More...

Functions

AFAPI array unwrap (const array &in, const dim_t wx, const dim_t wy, const dim_t sx, const dim_t sy, const dim_t px=0, const dim_t py=0, const bool is_column=true)
 C++ Interface for rearranging windowed sections of an input into columns (or rows) More...
 
AFAPI af_err af_unwrap (af_array *out, const af_array in, const dim_t wx, const dim_t wy, const dim_t sx, const dim_t sy, const dim_t px, const dim_t py, const bool is_column)
 C Interface for rearranging windowed sections of an input into columns (or rows) More...
 

Detailed Description

Rearrange windowed sections of an array into columns (or rows)

The figure below illustrates how unwrap works. A moving window (marked by orange boxes in the figure) of size wx \(\times \) wy captures sections of the input array, and flattens them into columns (or rows if is_column is false) of the output array (illustrated in the right image). It starts at the top-left section of the input array and moves in column-major order, each time moving in strides of sx units along the column and sy units along the row, whenever it exhausts a column (stride size illustrated as the white arrows in the left image, and window movement illustrated as the progression of the small yellow numbers on the corner of each window). When the remainder of the column or row is not big enough to accomodate the window, that remainder is skipped and the window moves on (in the figure, the last row is not captured in any of the windows).

Optionally, one can specify that the input image's border be padded (with zeros, represented as the gray boxes in the figure) before the moving window starts capturing sections. The width of the padding is defined by px for the top and bottom and py for the left and right sides, with maximum values of wx-1 and wy-1, respectively. The moving window then captures sections as if the padding is part of the input image, and thus the padding also becomes part of the output array's columns (illustrated in the bottom of the right image).

Unwrap on a 3x4 input array, using a 2x2 window, 2x2 stride, 1x1 padding

In the figure, the stride is set to be equally large as the window size (both 2x2), and thus the sections that the window captures are distinct. However, when the stride is set to the minimum (1x1) and is smaller than the window size, the sections overlap (which in turn makes the output's columns overlap as well). The window then acts as a perfect "sliding window" in this case (see the first code example below). In general, there will be some overlap as long as the stride is smaller than the window size (though the overlap decreases as the stride approaches the window size), and when the stride is equal or greater than the window size, each section (and output column) will be distinct.

For inputs that have more than two dimensions, the unwrap operation will be applied to each 2D slice of the input. This is especially useful for independently processing each channel of an image (or set of images) - each channel (along the third dimension) on the input corresponds to the same channel on the output, and each image (along the fourth dimension) on the input corresponds to the same image on the output.

The size of the output is shown below. nsections_dim0 and nsections_dim1 denote how many windows can fit along the column and row, given the padded image size, window size, strides, and skips (if any):

dim4(
wx * wy, // No. of rows (column height)
nsections_dim0 * nsections_dim1, // No. of columns per channel
input.dims(2), // No. of channels
input.dims(3) // No. of images
)

Here are some code examples that demonstrate unwrap's usage:

float hA[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
array A(dim4(3, 3), hA);
// 1. 4. 7.
// 2. 5. 8.
// 3. 6. 9.
array A_simple = unwrap(A, 2, 2, // window size
1, 1); // stride (sliding window)
// 1. 2. 4. 5.
// 2. 3. 5. 6.
// 4. 5. 7. 8.
// 5. 6. 8. 9.
array A_padded = unwrap(A, 2, 2, // window size
2, 2, // stride (distinct)
1, 1); // padding
// 0. 0. 0. 5.
// 0. 0. 4. 6.
// 0. 2. 0. 8.
// 1. 3. 7. 9.

One context where unwrap can be used is pre-processing an array or image for making window operations efficient (i.e. convolutions, computing the average pixel intensity around a point in an image, etc). Since each window capture is laid out as a column in an unwrapped array, vectorized operations can be executed efficiently on it (as opposed to strided access of each row in a window in the original array).

Note that the actual implementation of unwrap may not match the way the operation is described above, but the effect should be the same.


Function Documentation

◆ af_unwrap()

AFAPI af_err af_unwrap ( af_array out,
const af_array  in,
const dim_t  wx,
const dim_t  wy,
const dim_t  sx,
const dim_t  sy,
const dim_t  px,
const dim_t  py,
const bool  is_column 
)

C Interface for rearranging windowed sections of an input into columns (or rows)

Parameters
[out]outis an array with the input's sections rearraged as columns (or rows)
[in]inis the input array
[in]wxis the window size along dimension 0
[in]wyis the window size along dimension 1
[in]sxis the stride along dimension 0
[in]syis the stride along dimension 1
[in]pxis the padding along dimension 0
[in]pyis the padding along dimension 1
[in]is_columndetermines whether the section becomes a column (if true) or a row (if false)
Returns
AF_SUCCESS if unwrap is successful, otherwise an appropriate error code is returned.
Note
in can hold multiple images for processing if it is three or four-dimensional
wx and wy must be between [1, input.dims(0 (1)) + px (py)]
sx and sy must be greater than 1
px and py must be between [0, wx (wy) - 1]. Padding becomes part of the input image prior to the windowing

◆ unwrap()

AFAPI array unwrap ( const array in,
const dim_t  wx,
const dim_t  wy,
const dim_t  sx,
const dim_t  sy,
const dim_t  px = 0,
const dim_t  py = 0,
const bool  is_column = true 
)

C++ Interface for rearranging windowed sections of an input into columns (or rows)

Parameters
[in]inis the input array
[in]wxis the window size along dimension 0
[in]wyis the window size along dimension 1
[in]sxis the stride along dimension 0
[in]syis the stride along dimension 1
[in]pxis the padding along dimension 0
[in]pyis the padding along dimension 1
[in]is_columndetermines whether the section becomes a column (if true) or a row (if false)
Returns
an array with the input's sections rearraged as columns (or rows)
Note
in can hold multiple images for processing if it is three or four-dimensional
wx and wy must be between [1, input.dims(0 (1)) + px (py)]
sx and sy must be greater than 1
px and py must be between [0, wx (wy) - 1]. Padding becomes part of the input image prior to the windowing