A high-performance general-purpose compute library

- Main Page
- Tutorials
- Release Notes
- Examples

Functions
wrap
ArrayFire Functions | ArrayFire Functions by Category » Image Processing » Wrapping and unwrapping image windows

## 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.
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()
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.

## 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] | out | is an array with the input's columns (or rows) reshaped as patches
  [in] | in | is the input array
  [in] | ox | is the output's dimension 0 size
  [in] | oy | is the output's dimension 1 size
  [in] | wx | is the window size along dimension 0
  [in] | wy | is the window size along dimension 1
  [in] | sx | is the stride along dimension 0
  [in] | sy | is the stride along dimension 1
  [in] | px | is the padding along dimension 0
  [in] | py | is the padding along dimension 1
  [in] | is_column | determines 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] | out | is an array with the input's columns (or rows) reshaped as patches
  [in] | in | is the input array
  [in] | ox | is the output's dimension 0 size
  [in] | oy | is the output's dimension 1 size
  [in] | wx | is the window size along dimension 0
  [in] | wy | is the window size along dimension 1
  [in] | sx | is the stride along dimension 0
  [in] | sy | is the stride along dimension 1
  [in] | px | is the padding along dimension 0
  [in] | py | is the padding along dimension 1
  [in] | is_column | determines 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] | in | is the input array
  [in] | ox | is the output's dimension 0 size
  [in] | oy | is the output's dimension 1 size
  [in] | wx | is the window size along dimension 0
  [in] | wy | is the window size along dimension 1
  [in] | sx | is the stride along dimension 0
  [in] | sy | is the stride along dimension 1
  [in] | px | is the padding along dimension 0
  [in] | py | is the padding along dimension 1
  [in] | is_column | determines 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