A high-performance general-purpose compute library

Performs the opposite of af::unwrap(). More...

Functions

AFAPI array wrap (const array &in, const dim_t ox, const dim_t oy, 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 performing the opposite of unwrap. More...
 
AFAPI af_err af_wrap (af_array *out, const af_array in, const dim_t ox, const dim_t oy, 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 performing the opposite of af::unwrap() More...
 
AFAPI af_err af_wrap_v2 (af_array *out, const af_array in, const dim_t ox, const dim_t oy, 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 the version of af_wrap that accepts a preallocated output array. More...
 

Detailed Description

Performs the opposite of af::unwrap().

More specifically, wrap takes each column (or row if is_column is false) of the \(m \times n\) input array and reshapes them into wx \(\times\) wy patches (where \(m =\) wx \(\times\) wy) of the ox \(\times\) oy output array. Wrap is typically used on an array that has been previously unwrapped - for example, in the case of image processing, one can unwrap an image, process the unwrapped array, and then compose it back into an image using wrap.

The figure below illustrates how wrap works. The process can be visualized as a moving window (orange boxes in the figure) taking a column from the input (top-left), reshaping it into a patch (bottom-left), and then placing that patch on its corresponding position in the output array (right; numbers in yellow show correspondence). It starts placing a patch on the output's top-left corner, then moves sx units along the column, and sy units along the row whenever it exhausts a column. If padding exists in the input array (gray-filled boxes), which typically happens when padding was applied on the previous unwrap, then px and py must be specified in order for the padding to be removed on the output array (in the figure, the output array on the right will actually only contain the inner boxes, size ox \(\times\) oy).

Wrap on a 4x6 input array, using a 2x2 window, 2x2 stride, 1x1 padding. The output array is 3x4

There are some things that must be considered when wrapping a previously unwrapped array. First, wrap must use the same parameters that unwrap used, and must use the original array's size (before unwrap) as ox and oy. This is necessary to correctly elicit wrap's behavior as the opposite of unwrap. Second, one must consider whether the previous unwrap used a distinct or sliding window configuration, since the element-wise mapping from the input array to the output depends on the configuration. If the distinct window configuration (the stride is at least as large as the window size) was used, then the mapping is straightforward - each column will map to a unique section in the output array, and therefore each element in the input will map to a unique position in the output (shown in the figure above). However, in the case of the sliding window configuration (the stride is smaller than the window size), some of the columns will map to overlapping sections in the output array, and so elements from multiple columns will map to the same position on the output array. Recomposing the array then requires some way to choose between competing elements to place in that position. To address this contention, wrap simply sums all of the competing elements and places the sum in that position. The figure below illustrates this behavior: the fourth element of the first column and the third element of the second column in the input array both map to the same position on the output array, and thus their sum is placed on that position (this happens on the second and third column of the input as well - they both map to the third element of the second column in the output). Given this behavior, it is up to the user to pre-process the input (unwrapped) array (or post-process the output (wrapped) array) in a way that somehow takes all of the competing elements into consideration.

Wrap on the same array as above, but with 1x1 stride (sliding window)

For inputs that have more than two dimensions, the wrap 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.

Here are some code examples that demonstrate wrap's usage. The first one shows wrapping a previously unwrapped array that used a 1x1 padding and a distinct window configuration. Notice how the arguments used in unwrap are the same as those used in wrap:

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_unwrapped = 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.
array A_wrapped = wrap(A_unwrapped, 3, 3, // A's size
2, 2, // window size
2, 2, // stride (distinct)
1, 1); // padding
// 1. 4. 7.
// 2. 5. 8.
// 3. 6. 9.

The next one shows what happens when both unwrap and wrap uses the sliding window configuration. Notice how the original array is not recovered through wrap; instead, overlapping elements are summed, just as described above:

float hB[] = {1, 1, 1, 1, 1, 1, 1, 1, 1};
array B(dim4(3, 3), hB);
// 1. 1. 1.
// 1. 1. 1.
// 1. 1. 1.
array B_unwrapped = unwrap(B, 2, 2, // window size
1, 1); // stride (sliding)
// 1. 1. 1. 1.
// 1. 1. 1. 1.
// 1. 1. 1. 1.
// 1. 1. 1. 1.
array B_wrapped = wrap(B_unwrapped, 3, 3, // B's size
2, 2, // window size
1, 1); // stride (sliding)
// 1. 2. 1.
// 2. 4. 2.
// 1. 2. 1.

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


Function Documentation

◆ af_wrap()

AFAPI af_err af_wrap ( af_array out,
const af_array  in,
const dim_t  ox,
const dim_t  oy,
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 performing the opposite of af::unwrap()

Parameters
[out]outis an array with the input's columns (or rows) reshaped as patches
[in]inis the input array
[in]oxis the output's dimension 0 size
[in]oyis the output's dimension 1 size
[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 an output patch is formed from a column (if true) or a row (if false)
Returns
AF_SUCCESS if the color transformation is successful, otherwise an appropriate error code is returned.
Note
Wrap is typically used to recompose an unwrapped image. If this is the case, use the same parameters that were used in af::unwrap(). Also use the original image size (before unwrap) for ox and oy.
The window/patch size, wx \(\times\) wy, must equal input.dims(0) (or input.dims(1) if is_column is false).
sx and sy must be at least 1
px and py must be between [0, wx) and [0, wy), respectively
The number of patches, input.dims(1) (or input.dims(0) if is_column is false), must equal \(nx \times\ ny\), where \(\displaystyle nx = \frac{ox + 2px - wx}{sx} + 1\) and \(\displaystyle ny = \frac{oy + 2py - wy}{sy} + 1\)
Batched wrap can be performed on multiple 2D slices at once if in is three or four-dimensional

◆ af_wrap_v2()

AFAPI af_err af_wrap_v2 ( af_array out,
const af_array  in,
const dim_t  ox,
const dim_t  oy,
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 the version of af_wrap that accepts a preallocated output array.

Parameters
[out]outis an array with the input's columns (or rows) reshaped as patches
[in]inis the input array
[in]oxis the output's dimension 0 size
[in]oyis the output's dimension 1 size
[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 an output patch is formed from a column (if true) or a row (if false)
Returns
AF_SUCCESS if the color transformation is successful, otherwise an appropriate error code is returned.
Note
Wrap is typically used to recompose an unwrapped image. If this is the case, use the same parameters that were used in af::unwrap(). Also use the original image size (before unwrap) for ox and oy.
The window/patch size, wx \(\times\) wy, must equal input.dims(0) (or input.dims(1) if is_column is false).
sx and sy must be at least 1
px and py must be between [0, wx) and [0, wy), respectively
The number of patches, input.dims(1) (or input.dims(0) if is_column is false), must equal \(nx \times\ ny\), where \(\displaystyle nx = \frac{ox + 2px - wx}{sx} + 1\) and \(\displaystyle ny = \frac{oy + 2py - wy}{sy} + 1\)
Batched wrap can be performed on multiple 2D slices at once if in is three or four-dimensional

◆ wrap()

AFAPI array wrap ( const array in,
const dim_t  ox,
const dim_t  oy,
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 performing the opposite of unwrap.

Parameters
[in]inis the input array
[in]oxis the output's dimension 0 size
[in]oyis the output's dimension 1 size
[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 an output patch is formed from a column (if true) or a row (if false)
Returns
an array with the input's columns (or rows) reshaped as patches
Note
Wrap is typically used to recompose an unwrapped image. If this is the case, use the same parameters that were used in unwrap(). Also use the original image size (before unwrap) for ox and oy.
The window/patch size, wx \(\times\) wy, must equal input.dims(0) (or input.dims(1) if is_column is false).
sx and sy must be at least 1
px and py must be between [0, wx) and [0, wy), respectively
The number of patches, input.dims(1) (or input.dims(0) if is_column is false), must equal \(nx \times\ ny\), where \(\displaystyle nx = \frac{ox + 2px - wx}{sx} + 1\) and \(\displaystyle ny = \frac{oy + 2py - wy}{sy} + 1\)
Batched wrap can be performed on multiple 2D slices at once if in is three or four-dimensional