"""TVM operator input resize compute."""
from __future__ import absolute_import
import tvm
+from topi.util import nchw_pack_layout, nchw_xc_layout
from .. import tag
+def get_2d_indices(indices, layout='NCHW'):
+ """ Get 2d indices """
+ (cc, inum, ic) = (0, 0, 0)
+ if layout == 'NHWC':
+ n, y, x, c = indices
+ cc = None
+ elif layout == 'NCHW':
+ n, c, y, x = indices
+ cc = None
+ elif nchw_pack_layout(layout):
+ n, c, y, x, inum, ic = indices
+ else:
+ # else must be NCHWxc
+ assert nchw_xc_layout(layout)
+ n, c, y, x, cc = indices
+
+ return n, c, y, x, cc, inum, ic
+
+def get_2d_pixel(data, layout, boxes, image_height, image_width, n, c, y, x, cc, ib, ic):
+ """ Get 2d pixel """
+ if boxes is None:
+ y = tvm.max(tvm.min(y, image_height - 1), 0)
+ x = tvm.max(tvm.min(x, image_width - 1), 0)
+ if layout == 'NHWC':
+ return data(n, y, x, c).astype('float')
+ if layout == 'NCHW':
+ return data(n, c, y, x).astype('float')
+ if nchw_pack_layout(layout):
+ return data(n, c, y, x, ib, ic).astype('float')
+
+ # else must be NCHWxc
+ assert nchw_xc_layout(layout)
+ return data(n, c, y, x, cc).astype('float')
def resize_nearest_neighbor(indices, data, image_height, image_width,
target_height, target_width, boxes=None,
dtype = data_dtype
return value.astype(dtype)
- def _get_indices(indices, layout='NCHW'):
- if layout == 'NHWC':
- n, y, x, c = indices
- cc = None
- elif layout == 'NCHW':
- n, c, y, x = indices
- cc = None
- else:
- n, c, y, x, cc = indices
- return n, c, y, x, cc
-
- def _get_pixel(data, layout, n, c, y, x, cc):
- if boxes is None:
- y = tvm.max(tvm.min(y, image_height - 1), 0)
- x = tvm.max(tvm.min(x, image_width - 1), 0)
- if layout == 'NHWC':
- return data(n, y, x, c).astype('float')
- if layout == 'NCHW':
- return data(n, c, y, x).astype('float')
- # else must be NCHWxc
- return data(n, c, y, x, cc).astype('float')
-
- n, c, y, x, cc = _get_indices(indices, layout)
+ n, c, y, x, cc, inum, ic = get_2d_indices(indices, layout)
box_idx = box_indices(n) if box_indices is not None else n
if boxes is not None:
y1, x1 = boxes(n, 0), boxes(n, 1)
closest_y_index = tvm.floor(in_y + epsilon).astype('int32')
closest_x_index = tvm.floor(in_x + epsilon).astype('int32')
- value = _get_pixel(data, layout, box_idx, c, closest_y_index, closest_x_index, cc)
+ value = get_2d_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, closest_y_index, closest_x_index, cc, inum, ic)
if extrapolation_value is not None:
out = tvm.if_then_else(in_y < 0,
def _lerp(A, B, t):
return A * (1.0 - t) + B * t
- def _get_indices(indices, layout='NCHW'):
- if layout == 'NHWC':
- n, y, x, c = indices
- cc = None
- elif layout == 'NCHW':
- n, c, y, x = indices
- cc = None
- else:
- n, c, y, x, cc = indices
- return n, c, y, x, cc
-
- def _get_pixel(data, layout, n, c, y, x, cc):
- if boxes is None:
- y = tvm.max(tvm.min(y, image_height - 1), 0)
- x = tvm.max(tvm.min(x, image_width - 1), 0)
- if layout == 'NHWC':
- return data(n, y, x, c).astype('float')
- if layout == 'NCHW':
- return data(n, c, y, x).astype('float')
- # else must be NCHWxc
- return data(n, c, y, x, cc).astype('float')
-
- n, c, y, x, cc = _get_indices(indices, layout=layout)
+ n, c, y, x, cc, inum, ic = get_2d_indices(indices, layout=layout)
box_idx = box_indices(n) if box_indices is not None else n
if boxes is not None:
right_x_index = tvm.ceil(in_x).astype('int32')
x_lerp = in_x - left_x_index
- top_left = _get_pixel(data, layout, box_idx, c, top_y_index, left_x_index, cc)
- top_right = _get_pixel(data, layout, box_idx, c, top_y_index, right_x_index, cc)
- bottom_left = _get_pixel(data, layout, box_idx, c, bottom_y_index, left_x_index, cc)
- bottom_right = _get_pixel(data, layout, box_idx, c, bottom_y_index, right_x_index, cc)
+ top_left = get_2d_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, top_y_index, left_x_index, cc, inum, ic)
+ top_right = get_2d_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, top_y_index, right_x_index, cc, inum, ic)
+ bottom_left = get_2d_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, bottom_y_index, left_x_index, cc, inum, ic)
+ bottom_right = get_2d_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, bottom_y_index, right_x_index, cc, inum, ic)
top = _lerp(top_left, top_right, x_lerp)
bottom = _lerp(bottom_left, bottom_right, x_lerp)
dtype = data_dtype
return value.astype(dtype)
- def _get_indices(indices, layout='NCHW'):
- if layout == 'NHWC':
- n, y, x, c = indices
- cc = None
- elif layout == 'NCHW':
- n, c, y, x = indices
- cc = None
- else:
- n, c, y, x, cc = indices
- return n, c, y, x, cc
-
- def _get_pixel(data, layout, n, c, y, x, cc):
- if boxes is None:
- y = tvm.max(tvm.min(y, image_height - 1), 0)
- x = tvm.max(tvm.min(x, image_width - 1), 0)
- if layout == 'NHWC':
- return data(n, y, x, c).astype('float')
- if layout == 'NCHW':
- return data(n, c, y, x).astype('float')
- # else must be NCHWxc
- return data(n, c, y, x, cc).astype('float')
-
- n, c, y, x, cc = _get_indices(indices, layout)
+ n, c, y, x, cc, inum, ic = get_2d_indices(indices, layout)
box_idx = box_indices(n) if box_indices is not None else n
if boxes is not None:
yfract = in_y - tvm.floor(in_y)
# 1st row
- p00 = _get_pixel(data, layout, box_idx, c, yint - 1, xint - 1, cc)
- p10 = _get_pixel(data, layout, box_idx, c, yint - 1, xint + 0, cc)
- p20 = _get_pixel(data, layout, box_idx, c, yint - 1, xint + 1, cc)
- p30 = _get_pixel(data, layout, box_idx, c, yint - 1, xint + 2, cc)
+ p00 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint - 1, xint - 1, cc, inum, ic)
+ p10 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint - 1, xint + 0, cc, inum, ic)
+ p20 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint - 1, xint + 1, cc, inum, ic)
+ p30 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint - 1, xint + 2, cc, inum, ic)
# 2nd row
- p01 = _get_pixel(data, layout, box_idx, c, yint + 0, xint - 1, cc)
- p11 = _get_pixel(data, layout, box_idx, c, yint + 0, xint + 0, cc)
- p21 = _get_pixel(data, layout, box_idx, c, yint + 0, xint + 1, cc)
- p31 = _get_pixel(data, layout, box_idx, c, yint + 0, xint + 2, cc)
+ p01 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint + 0, xint - 1, cc, inum, ic)
+ p11 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint + 0, xint + 0, cc, inum, ic)
+ p21 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint + 0, xint + 1, cc, inum, ic)
+ p31 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint + 0, xint + 2, cc, inum, ic)
# 3rd row
- p02 = _get_pixel(data, layout, box_idx, c, yint + 1, xint - 1, cc)
- p12 = _get_pixel(data, layout, box_idx, c, yint + 1, xint + 0, cc)
- p22 = _get_pixel(data, layout, box_idx, c, yint + 1, xint + 1, cc)
- p32 = _get_pixel(data, layout, box_idx, c, yint + 1, xint + 2, cc)
+ p02 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint + 1, xint - 1, cc, inum, ic)
+ p12 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint + 1, xint + 0, cc, inum, ic)
+ p22 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint + 1, xint + 1, cc, inum, ic)
+ p32 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint + 1, xint + 2, cc, inum, ic)
# 4th row
- p03 = _get_pixel(data, layout, box_idx, c, yint + 2, xint - 1, cc)
- p13 = _get_pixel(data, layout, box_idx, c, yint + 2, xint + 0, cc)
- p23 = _get_pixel(data, layout, box_idx, c, yint + 2, xint + 1, cc)
- p33 = _get_pixel(data, layout, box_idx, c, yint + 2, xint + 2, cc)
+ p03 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint + 2, xint - 1, cc, inum, ic)
+ p13 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint + 2, xint + 0, cc, inum, ic)
+ p23 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint + 2, xint + 1, cc, inum, ic)
+ p33 = _get_pixel(data, layout, boxes, image_height, image_width,
+ box_idx, c, yint + 2, xint + 2, cc, inum, ic)
# Interpolate bicubically
col0 = _cubic_kernel(p00, p10, p20, p30, xfract)
or [batch, in_height*scale, in_width*scale, channel]
or 5-D with shape [batch, channel-major, in_height*scale, in_width*scale, channel-minor]
"""
+
method = method.lower()
if layout == 'NHWC':
elif layout == 'NCHW':
in_n, in_c, in_h, in_w = data.shape
output_shape = [in_n, in_c, size[0], size[1]]
- elif layout.startswith("NCHW"):# for NCHWxc
+ elif nchw_pack_layout(layout):# for NCHWinic
+ in_n, in_c, in_h, in_w, in_inum, in_ic = data.shape
+ output_shape = [in_n, in_c, size[0], size[1], in_inum, in_ic]
+ elif nchw_xc_layout(layout):# for NCHWxc
in_n, in_c, in_h, in_w, in_cc = data.shape
output_shape = [in_n, in_c, size[0], size[1], in_cc]
else:
"""Bilinear Scale in python"""
import math
import numpy as np
+from topi.util import nchw_pack_layout
def bilinear_resize_python(image, out_size, layout, coordinate_transformation_mode="align_corners"):
""" Bilinear scaling using python"""
(new_h, new_w) = out_size
+ (ib, ic) = (1, 1)
if layout == 'NHWC':
(batch, h, w, channel) = image.shape
scaled_image = np.ones((batch, new_h, new_w, channel))
+ # NCHWinic
+ elif nchw_pack_layout(layout):
+ (batch, channel, h, w, ib, ic) = image.shape
+ scaled_image = np.ones((batch, channel, new_h, new_w, ib, ic))
else:
(batch, channel, h, w) = image.shape
scaled_image = np.ones((batch, channel, new_h, new_w))
def _lerp(A, B, t):
return A * (1.0 - t) + B * t
- for b in range(batch):
- for i in range(channel):
- for j in range(new_h):
- for k in range(new_w):
- if coordinate_transformation_mode == "half_pixel":
- in_y = (j + 0.5) * height_scale - 0.5
- else:
- in_y = j * height_scale
- y0 = int(math.floor(in_y))
- y1 = max(min(y0 + 1, h - 1), 0)
- y0 = max(y0, 0)
- y_lerp = in_y - math.floor(in_y)
+ def _img_scale(b, m, i, n):
+ for j in range(new_h):
+ for k in range(new_w):
+ if coordinate_transformation_mode == "half_pixel":
+ in_y = (j + 0.5) * height_scale - 0.5
+ else:
+ in_y = j * height_scale
+ y0 = int(math.floor(in_y))
+ y1 = max(min(y0 + 1, h - 1), 0)
+ y0 = max(y0, 0)
+ y_lerp = in_y - math.floor(in_y)
+
+ if coordinate_transformation_mode == "half_pixel":
+ in_x = (k + 0.5) * width_scale - 0.5
+ else:
+ in_x = k * width_scale
+ x0 = int(math.floor(in_x))
+ x1 = max(min(x0 + 1, w - 1), 0)
+ x0 = max(x0, 0)
+ x_lerp = in_x - math.floor(in_x)
- if coordinate_transformation_mode == "half_pixel":
- in_x = (k + 0.5) * width_scale - 0.5
- else:
- in_x = k * width_scale
- x0 = int(math.floor(in_x))
- x1 = max(min(x0 + 1, w - 1), 0)
- x0 = max(x0, 0)
- x_lerp = in_x - math.floor(in_x)
+ if layout == 'NHWC':
+ A = image[b][y0][x0][i]
+ B = image[b][y0][x1][i]
+ C = image[b][y1][x0][i]
+ D = image[b][y1][x1][i]
+ elif nchw_pack_layout(layout):
+ A = image[b][i][y0][x0][m][n]
+ B = image[b][i][y0][x1][m][n]
+ C = image[b][i][y1][x0][m][n]
+ D = image[b][i][y1][x1][m][n]
+ else:
+ A = image[b][i][y0][x0]
+ B = image[b][i][y0][x1]
+ C = image[b][i][y1][x0]
+ D = image[b][i][y1][x1]
- if layout == 'NHWC':
- A = image[b][y0][x0][i]
- B = image[b][y0][x1][i]
- C = image[b][y1][x0][i]
- D = image[b][y1][x1][i]
- else:
- A = image[b][i][y0][x0]
- B = image[b][i][y0][x1]
- C = image[b][i][y1][x0]
- D = image[b][i][y1][x1]
+ top = _lerp(A, B, x_lerp)
+ bottom = _lerp(C, D, x_lerp)
- top = _lerp(A, B, x_lerp)
- bottom = _lerp(C, D, x_lerp)
+ pixel = np.float32(_lerp(top, bottom, y_lerp))
- pixel = np.float32(_lerp(top, bottom, y_lerp))
+ if layout == 'NHWC':
+ scaled_image[b][j][k][i] = pixel
+ elif nchw_pack_layout(layout):
+ scaled_image[b][i][j][k][m][n] = pixel
+ else:
+ scaled_image[b][i][j][k] = pixel
- if layout == 'NHWC':
- scaled_image[b][j][k][i] = pixel
- else:
- scaled_image[b][i][j][k] = pixel
+ for b in range(batch):
+ for m in range(ib):
+ for i in range(channel):
+ for n in range(ic):
+ _img_scale(b, m, i, n)
return scaled_image
import topi
import topi.testing
import math
+from topi.util import nchw_pack_layout
from common import get_all_backend
def verify_upsampling(batch, in_channel, in_height, in_width, scale_h, scale_w,
- layout='NCHW', method="nearest_neighbor"):
+ layout='NCHW', method="nearest_neighbor",
+ in_batch_block = 0, in_channel_block = 0):
if layout == 'NCHW':
A = tvm.placeholder((batch, in_channel, in_height, in_width), name='A')
dtype = A.dtype
out_shape = (batch, in_channel, int(round(in_height*scale_h)), int(round(in_width*scale_w)))
a_np = np.random.uniform(size=(batch, in_channel, in_height, in_width)).astype(dtype)
+ elif nchw_pack_layout(layout):
+ A = tvm.placeholder((batch, in_channel, in_height, in_width, in_batch_block, in_channel_block),
+ name='A')
+ dtype = A.dtype
+ out_shape = (batch, in_channel, int(round(in_height*scale_h)), int(round(in_width*scale_w)),
+ in_batch_block, in_channel_block)
+ a_np = np.random.uniform(size=(batch, in_channel, in_height, in_width,
+ in_batch_block, in_channel_block)).astype(dtype)
elif layout == 'NHWC':
A = tvm.placeholder((batch, in_height, in_width, in_channel), name='A')
dtype = A.dtype
verify_upsampling(2, 2, 32, 32, 3.0, 3.0, method="bilinear")
verify_upsampling(1, 64, 22, 32, 1.954545497894287, 2.0, method="bilinear")
+ # nearest_neighbor - NCHWinic
+ verify_upsampling(2, 2, 32, 32, in_batch_block=4, in_channel_block=8,
+ scale_h=2.0, scale_w=2.0)
+ verify_upsampling(2, 2, 64, 64, in_batch_block=1, in_channel_block=16,
+ scale_h=3.0, scale_w=3.0)
+ verify_upsampling(1, 4, 22, 32, in_batch_block=1, in_channel_block=16,
+ scale_h=1.954545497894287, scale_w=2.0)
+
+ # bilinear - NCHWinic
+ verify_upsampling(2, 2, 32, 32, in_batch_block=1, in_channel_block=1,
+ scale_h=2.0, scale_w=2.0, method="bilinear")
+ verify_upsampling(2, 2, 32, 32, in_batch_block=1, in_channel_block=1,
+ scale_h=3.0, scale_w=3.0, method="bilinear")
+ verify_upsampling(2, 4, 22, 32, in_batch_block=1, in_channel_block=16,
+ scale_h=1.954545497894287, scale_w=2.0, layout="NCHW1n16c", method="bilinear")
+
# bilinear - NHWC
verify_upsampling(2, 2, 32, 32, 2.0, 2.0, layout="NHWC", method="bilinear")
verify_upsampling(2, 2, 32, 32, 3.0, 3.0, layout="NHWC", method="bilinear")