1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
//
// This confidential and proprietary software may be used only as
// authorised by a licensing agreement from ARM Limited
// (C) COPYRIGHT 2020 ARM Limited
// ALL RIGHTS RESERVED
// The entire notice above must be reproduced on all authorised
// copies and copies may only be made to the extent permitted
// by a licensing agreement from ARM Limited.
=== Image Operators
==== RESIZE
Resizes a tensor. Resize is only allowed in the H and W dimensions. In expected use, stride_y is approximately (IH<<shift)/OH and stride_x is approximately (IW<<shift)/OW. OH and OW are also supplied as inputs since there may be off by one errors if calculating OH and OW from the strides.
*Arguments:*
|===
|Argument|Type|Name|Shape|Description
|Input|in_t*|input|[N,IH,IW,C]|Input tensor
|Attribute|int*|output_size|[2]|[OH,OW]
|Attribute|scale_t*|stride|[2]|[stride_y, stride_x]
|Attribute|scale_t*|offset|[2]|[offset_y, offset_x]
|Attribute|int|shift|Shift value (must be zero if scale_t is float)
|Attribute|mode_t|mode|-|BILINEAR or NEAREST
|Output|out_t*|output|[N,OH,OW,C]|Output tensor
|===
*Quantization Parameters:*
None
*Operation Function*
[source,c]
----
// scale assert prevents int32_t accumulator overflow for in_t==int8_t
assert((scale_t==float && shift==0)||(0<shift && shift<=11));
assert(stride_x>0 && stride_y>0);
for_each (0<=n<N, 0<=oy<OH, 0<=ox<OW; 0<=c<C) {
unit = (scale_t==float) ? 1.0 : (1<<shift);
y = oy * stride_y + offset_y
x = ox * stride_x + offset_x
if (scale_t==float) {
iy = (int)floor(y); dy = y - (float)iy;
ix = (int)floor(x); dx = x - (float)ix;
} else {
iy = y >> shift; dy = y - (iy<<shift);
ix = x >> shift; dx = x - (ix<<shift);
}
iy0 = apply_max(iy,0);
iy1 = apply_min(iy+1,IH-1);
ix0 = apply_max(ix,0);
ix1 = apply_min(ix+1,IW-1);
assert(ix0<=ix1 && iy0<=iy1);
if (mode==BILINEAR) {
v00 = tensor_read<in_t>(input, [N,IH,IW,C], [n,iy0,ix0,c])
v01 = tensor_read<in_t>(input, [N,IH,IW,C], [n,iy0,ix1,c])
v10 = tensor_read<in_t>(input, [N,IH,IW,C], [n,iy1,ix0,c])
v11 = tensor_read<in_t>(input, [N,IH,IW,C], [n,iy1,ix1,c])
out_t acc = v00*(unit-dy)*(unit-dx) + v01*(unit-dy)*dx
acc = acc + v10*dy*(unit-dx) + v11*dy*dx;
tensor_write<out_t>(output, [N,OH,OW,C], [n,oy,ox,c], acc)
} else if (mode==NEAREST) {
iy = (dy >= unit/2) ? iy1 : iy0;
ix = (dx >= unit/2) ? ix1 : ix0;
v = tensor_read<in_t>(input, [N,IH,IW,C], [n,iy,ix,c]);
tensor_write<out_t>(output, [N,OH,OW,C], [n,oy,ox,c], v)
}
}
----
*Supported Data Types:*
|===
|Profile|Mode|scale_t|in_t|out_t
|Any|signed 8, bilinear|int16|int8|int32
|Any|signed 8, nearest |int16|int8|int8
|Any|signed 16, bilinear|int16|int16|int48
|Any|signed 16, nearest |int16|int16|int16
|MI,MT|float |float|float|float
|===
*Scaling Modes:*
|===
|Mode|Description
|NEAREST|Nearest Neighbor
|BILINEAR|Bilinear interpoloation
|===
|