onnx2tf 1.29.17__py3-none-any.whl → 1.29.19__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- onnx2tf/__init__.py +1 -1
- onnx2tf/ops/Col2Im.py +108 -64
- onnx2tf/ops/DFT.py +245 -0
- onnx2tf/ops/DeformConv.py +399 -0
- onnx2tf/ops/ImageDecoder.py +147 -0
- onnx2tf/ops/NegativeLogLikelihoodLoss.py +237 -0
- onnx2tf/ops/RMSNormalization.py +175 -0
- onnx2tf/ops/RegexFullMatch.py +108 -0
- onnx2tf/ops/RotaryEmbedding.py +285 -0
- onnx2tf/ops/Scan.py +438 -0
- onnx2tf/ops/SoftmaxCrossEntropyLoss.py +289 -0
- onnx2tf/ops/StringConcat.py +128 -0
- onnx2tf/ops/StringNormalizer.py +54 -39
- onnx2tf/ops/StringSplit.py +156 -0
- onnx2tf/ops/TensorScatter.py +223 -0
- {onnx2tf-1.29.17.dist-info → onnx2tf-1.29.19.dist-info}/METADATA +15 -14
- {onnx2tf-1.29.17.dist-info → onnx2tf-1.29.19.dist-info}/RECORD +19 -7
- {onnx2tf-1.29.17.dist-info → onnx2tf-1.29.19.dist-info}/WHEEL +1 -1
- {onnx2tf-1.29.17.dist-info → onnx2tf-1.29.19.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import random
|
|
3
|
+
random.seed(0)
|
|
4
|
+
import numpy as np
|
|
5
|
+
np.random.seed(0)
|
|
6
|
+
import tensorflow as tf
|
|
7
|
+
import onnx_graphsurgeon as gs
|
|
8
|
+
from onnx2tf.utils.common_functions import (
|
|
9
|
+
get_constant_or_variable,
|
|
10
|
+
get_weights_constant_or_variable,
|
|
11
|
+
print_node_info,
|
|
12
|
+
inverted_operation_enable_disable,
|
|
13
|
+
make_tf_node_info,
|
|
14
|
+
get_replacement_parameter,
|
|
15
|
+
pre_process_transpose,
|
|
16
|
+
post_process_transpose,
|
|
17
|
+
transpose_with_flexing_deterrence,
|
|
18
|
+
)
|
|
19
|
+
from onnx2tf.utils.logging import *
|
|
20
|
+
|
|
21
|
+
INF_INDEX_VALUE: int = 4294967296
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _to_int_tensor(value, name=None):
|
|
25
|
+
if isinstance(value, tf.Tensor):
|
|
26
|
+
return tf.cast(value, tf.int32)
|
|
27
|
+
return tf.constant(value, dtype=tf.int32, name=name)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _bilinear_sample_2d(
|
|
31
|
+
image,
|
|
32
|
+
coords,
|
|
33
|
+
):
|
|
34
|
+
"""
|
|
35
|
+
image: [N, H, W, C]
|
|
36
|
+
coords: [N, oH, oW, kH, kW, 2] in absolute coords (y, x)
|
|
37
|
+
"""
|
|
38
|
+
coord_dtype = coords.dtype
|
|
39
|
+
h = tf.shape(image)[1]
|
|
40
|
+
w = tf.shape(image)[2]
|
|
41
|
+
h_f = tf.cast(h, coord_dtype)
|
|
42
|
+
w_f = tf.cast(w, coord_dtype)
|
|
43
|
+
max_y = h_f - 1.0
|
|
44
|
+
max_x = w_f - 1.0
|
|
45
|
+
|
|
46
|
+
y, x = tf.split(coords, num_or_size_splits=2, axis=-1)
|
|
47
|
+
|
|
48
|
+
y0 = tf.floor(y)
|
|
49
|
+
x0 = tf.floor(x)
|
|
50
|
+
y1 = y0 + 1.0
|
|
51
|
+
x1 = x0 + 1.0
|
|
52
|
+
|
|
53
|
+
dy = y - y0
|
|
54
|
+
dx = x - x0
|
|
55
|
+
|
|
56
|
+
w00 = (1.0 - dy) * (1.0 - dx)
|
|
57
|
+
w10 = dy * (1.0 - dx)
|
|
58
|
+
w11 = dy * dx
|
|
59
|
+
w01 = (1.0 - dy) * dx
|
|
60
|
+
|
|
61
|
+
def _in_bounds(y_idx, x_idx):
|
|
62
|
+
return tf.logical_and(
|
|
63
|
+
tf.logical_and(y_idx >= 0.0, y_idx <= max_y),
|
|
64
|
+
tf.logical_and(x_idx >= 0.0, x_idx <= max_x),
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
m00 = _in_bounds(y0, x0)
|
|
68
|
+
m10 = _in_bounds(y1, x0)
|
|
69
|
+
m11 = _in_bounds(y1, x1)
|
|
70
|
+
m01 = _in_bounds(y0, x1)
|
|
71
|
+
|
|
72
|
+
y0c = tf.clip_by_value(y0, 0.0, max_y)
|
|
73
|
+
x0c = tf.clip_by_value(x0, 0.0, max_x)
|
|
74
|
+
y1c = tf.clip_by_value(y1, 0.0, max_y)
|
|
75
|
+
x1c = tf.clip_by_value(x1, 0.0, max_x)
|
|
76
|
+
|
|
77
|
+
y0i = tf.cast(y0c, tf.int32)
|
|
78
|
+
x0i = tf.cast(x0c, tf.int32)
|
|
79
|
+
y1i = tf.cast(y1c, tf.int32)
|
|
80
|
+
x1i = tf.cast(x1c, tf.int32)
|
|
81
|
+
|
|
82
|
+
input_flat = tf.reshape(image, tf.stack([tf.shape(image)[0], h * w, tf.shape(image)[3]]))
|
|
83
|
+
|
|
84
|
+
def _gather(y_idx, x_idx):
|
|
85
|
+
linear = y_idx * w + x_idx
|
|
86
|
+
linear = tf.squeeze(linear, axis=-1)
|
|
87
|
+
return tf.gather(input_flat, linear, batch_dims=1)
|
|
88
|
+
|
|
89
|
+
v00 = _gather(y0i, x0i)
|
|
90
|
+
v10 = _gather(y1i, x0i)
|
|
91
|
+
v11 = _gather(y1i, x1i)
|
|
92
|
+
v01 = _gather(y0i, x1i)
|
|
93
|
+
|
|
94
|
+
m00 = tf.cast(m00, image.dtype)
|
|
95
|
+
m10 = tf.cast(m10, image.dtype)
|
|
96
|
+
m11 = tf.cast(m11, image.dtype)
|
|
97
|
+
m01 = tf.cast(m01, image.dtype)
|
|
98
|
+
|
|
99
|
+
output = w00 * m00 * v00 + w10 * m10 * v10 + w11 * m11 * v11 + w01 * m01 * v01
|
|
100
|
+
return output
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@print_node_info
|
|
104
|
+
@inverted_operation_enable_disable
|
|
105
|
+
@get_replacement_parameter
|
|
106
|
+
def make_node(
|
|
107
|
+
*,
|
|
108
|
+
graph_node: gs.Node,
|
|
109
|
+
tf_layers_dict: dict,
|
|
110
|
+
**kwargs: dict,
|
|
111
|
+
):
|
|
112
|
+
"""DeformConv
|
|
113
|
+
|
|
114
|
+
Parameters
|
|
115
|
+
----------
|
|
116
|
+
graph_node: gs.Node
|
|
117
|
+
graph_surgeon Node
|
|
118
|
+
|
|
119
|
+
tf_layers_dict: dict
|
|
120
|
+
optype, shape, dtype, tensorflow graph
|
|
121
|
+
"""
|
|
122
|
+
before_op_output_shape_trans_1 = \
|
|
123
|
+
tf_layers_dict.get(graph_node.inputs[0].name, {}).get('before_op_output_shape_trans', True)
|
|
124
|
+
before_op_output_shape_trans_3 = \
|
|
125
|
+
tf_layers_dict.get(graph_node.inputs[2].name, {}).get('before_op_output_shape_trans', True)
|
|
126
|
+
before_op_output_shape_trans_4 = \
|
|
127
|
+
tf_layers_dict.get(graph_node.inputs[3].name, {}).get('before_op_output_shape_trans', True) \
|
|
128
|
+
if len(graph_node.inputs) >= 4 else True
|
|
129
|
+
before_op_output_shape_trans_5 = \
|
|
130
|
+
tf_layers_dict.get(graph_node.inputs[4].name, {}).get('before_op_output_shape_trans', True) \
|
|
131
|
+
if len(graph_node.inputs) >= 5 else True
|
|
132
|
+
|
|
133
|
+
graph_node_input_1 = get_constant_or_variable(
|
|
134
|
+
graph_node.inputs[0],
|
|
135
|
+
before_op_output_shape_trans_1,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
kernel_shape = graph_node.attrs.get('kernel_shape', [])
|
|
139
|
+
if kernel_shape == [] and graph_node.inputs[1].shape is not None:
|
|
140
|
+
kernel_shape = graph_node.inputs[1].shape[2:]
|
|
141
|
+
kernel_size = len(kernel_shape) if kernel_shape != [] else 2
|
|
142
|
+
|
|
143
|
+
graph_node_input_2 = get_weights_constant_or_variable(
|
|
144
|
+
const_or_var=graph_node.inputs[1],
|
|
145
|
+
kernel_size=kernel_size,
|
|
146
|
+
)
|
|
147
|
+
graph_node_input_3 = get_constant_or_variable(
|
|
148
|
+
graph_node.inputs[2],
|
|
149
|
+
before_op_output_shape_trans_3,
|
|
150
|
+
)
|
|
151
|
+
graph_node_input_4 = get_constant_or_variable(
|
|
152
|
+
graph_node.inputs[3],
|
|
153
|
+
before_op_output_shape_trans_4,
|
|
154
|
+
) if len(graph_node.inputs) >= 4 else None
|
|
155
|
+
graph_node_input_5 = get_constant_or_variable(
|
|
156
|
+
graph_node.inputs[4],
|
|
157
|
+
before_op_output_shape_trans_5,
|
|
158
|
+
) if len(graph_node.inputs) >= 5 else None
|
|
159
|
+
|
|
160
|
+
graph_node_output: gs.Variable = graph_node.outputs[0]
|
|
161
|
+
output_tensor_shape = graph_node_output.shape
|
|
162
|
+
dtype = graph_node_output.dtype
|
|
163
|
+
|
|
164
|
+
input_tensor = tf_layers_dict[graph_node_input_1.name]['tf_node'] \
|
|
165
|
+
if isinstance(graph_node_input_1, gs.Variable) else graph_node_input_1
|
|
166
|
+
weights = tf_layers_dict[graph_node_input_2.name]['tf_node'] \
|
|
167
|
+
if isinstance(graph_node_input_2, gs.Variable) else graph_node_input_2
|
|
168
|
+
offset = tf_layers_dict[graph_node_input_3.name]['tf_node'] \
|
|
169
|
+
if isinstance(graph_node_input_3, gs.Variable) else graph_node_input_3
|
|
170
|
+
bias = tf_layers_dict[graph_node_input_4.name]['tf_node'] \
|
|
171
|
+
if isinstance(graph_node_input_4, gs.Variable) else graph_node_input_4
|
|
172
|
+
mask = tf_layers_dict[graph_node_input_5.name]['tf_node'] \
|
|
173
|
+
if isinstance(graph_node_input_5, gs.Variable) else graph_node_input_5
|
|
174
|
+
|
|
175
|
+
input_tensor_shape = input_tensor.shape
|
|
176
|
+
|
|
177
|
+
if input_tensor_shape is not None and len(input_tensor_shape) != 4:
|
|
178
|
+
error('DeformConv currently supports only 2D inputs (N, C, H, W).')
|
|
179
|
+
sys.exit(1)
|
|
180
|
+
|
|
181
|
+
# Preserving Graph Structure (Dict)
|
|
182
|
+
tf_layers_dict[graph_node_output.name] = {
|
|
183
|
+
'optype': graph_node.op,
|
|
184
|
+
'shape': output_tensor_shape,
|
|
185
|
+
'dtype': dtype,
|
|
186
|
+
'nhwc': True,
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
# Pre-process transpose
|
|
190
|
+
input_tensor = pre_process_transpose(
|
|
191
|
+
value_before_transpose=input_tensor,
|
|
192
|
+
param_target='inputs',
|
|
193
|
+
param_name=graph_node.inputs[0].name,
|
|
194
|
+
**kwargs,
|
|
195
|
+
)
|
|
196
|
+
offset = pre_process_transpose(
|
|
197
|
+
value_before_transpose=offset,
|
|
198
|
+
param_target='inputs',
|
|
199
|
+
param_name=graph_node.inputs[2].name,
|
|
200
|
+
**kwargs,
|
|
201
|
+
)
|
|
202
|
+
if mask is not None:
|
|
203
|
+
mask = pre_process_transpose(
|
|
204
|
+
value_before_transpose=mask,
|
|
205
|
+
param_target='inputs',
|
|
206
|
+
param_name=graph_node.inputs[4].name,
|
|
207
|
+
**kwargs,
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
input_dtype = input_tensor.dtype
|
|
211
|
+
if weights is not None and weights.dtype != input_dtype:
|
|
212
|
+
weights = tf.cast(weights, input_dtype)
|
|
213
|
+
if offset is not None and offset.dtype != input_dtype:
|
|
214
|
+
offset = tf.cast(offset, input_dtype)
|
|
215
|
+
if bias is not None and bias.dtype != input_dtype:
|
|
216
|
+
bias = tf.cast(bias, input_dtype)
|
|
217
|
+
if mask is not None and mask.dtype != input_dtype:
|
|
218
|
+
mask = tf.cast(mask, input_dtype)
|
|
219
|
+
|
|
220
|
+
# Workaround to avoid as many conversion failures as possible
|
|
221
|
+
onnx_input_shape = [
|
|
222
|
+
dim if isinstance(dim, int) else None for dim in graph_node.inputs[0].shape
|
|
223
|
+
] if graph_node.inputs[0].shape is not None else None
|
|
224
|
+
tf_input_shape = [
|
|
225
|
+
dim if isinstance(dim, int) else None for dim in input_tensor.shape
|
|
226
|
+
]
|
|
227
|
+
if onnx_input_shape is not None \
|
|
228
|
+
and len(onnx_input_shape) > 1 and len(tf_input_shape) > 1 \
|
|
229
|
+
and onnx_input_shape == tf_input_shape:
|
|
230
|
+
|
|
231
|
+
shape_for_judging_skip = [
|
|
232
|
+
dim if dim is not None else INF_INDEX_VALUE for dim in onnx_input_shape[1:]
|
|
233
|
+
]
|
|
234
|
+
if shape_for_judging_skip.count(shape_for_judging_skip[0]) != len(shape_for_judging_skip):
|
|
235
|
+
input_tensor = transpose_with_flexing_deterrence(
|
|
236
|
+
input_tensor=input_tensor,
|
|
237
|
+
perm=[0,2,3,1],
|
|
238
|
+
**kwargs,
|
|
239
|
+
)
|
|
240
|
+
offset = transpose_with_flexing_deterrence(
|
|
241
|
+
input_tensor=offset,
|
|
242
|
+
perm=[0,2,3,1],
|
|
243
|
+
**kwargs,
|
|
244
|
+
)
|
|
245
|
+
if mask is not None:
|
|
246
|
+
mask = transpose_with_flexing_deterrence(
|
|
247
|
+
input_tensor=mask,
|
|
248
|
+
perm=[0,2,3,1],
|
|
249
|
+
**kwargs,
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
# Attributes
|
|
253
|
+
dilations = graph_node.attrs.get('dilations', [1, 1])
|
|
254
|
+
group = graph_node.attrs.get('group', 1)
|
|
255
|
+
offset_group = graph_node.attrs.get('offset_group', 1)
|
|
256
|
+
pads = graph_node.attrs.get('pads', [0, 0, 0, 0])
|
|
257
|
+
strides = graph_node.attrs.get('strides', [1, 1])
|
|
258
|
+
|
|
259
|
+
dilation_h, dilation_w = dilations
|
|
260
|
+
stride_h, stride_w = strides
|
|
261
|
+
pad_top, pad_left, pad_bottom, pad_right = pads
|
|
262
|
+
|
|
263
|
+
# Input prep
|
|
264
|
+
if pad_top != 0 or pad_bottom != 0 or pad_left != 0 or pad_right != 0:
|
|
265
|
+
input_tensor = tf.pad(
|
|
266
|
+
input_tensor,
|
|
267
|
+
paddings=[[0, 0], [pad_top, pad_bottom], [pad_left, pad_right], [0, 0]],
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
batch = tf.shape(input_tensor)[0]
|
|
271
|
+
in_h = tf.shape(input_tensor)[1]
|
|
272
|
+
in_w = tf.shape(input_tensor)[2]
|
|
273
|
+
in_c = tf.shape(input_tensor)[3]
|
|
274
|
+
|
|
275
|
+
offset_shape = tf.shape(offset)
|
|
276
|
+
out_h = offset_shape[1]
|
|
277
|
+
out_w = offset_shape[2]
|
|
278
|
+
|
|
279
|
+
# Kernel shape
|
|
280
|
+
if kernel_shape != []:
|
|
281
|
+
kh = _to_int_tensor(kernel_shape[0])
|
|
282
|
+
kw = _to_int_tensor(kernel_shape[1])
|
|
283
|
+
else:
|
|
284
|
+
kh = _to_int_tensor(tf.shape(weights)[0])
|
|
285
|
+
kw = _to_int_tensor(tf.shape(weights)[1])
|
|
286
|
+
|
|
287
|
+
# Base grid: [oH, oW, kH, kW, 2]
|
|
288
|
+
oy = tf.range(out_h, dtype=input_dtype) * tf.cast(stride_h, input_dtype)
|
|
289
|
+
ox = tf.range(out_w, dtype=input_dtype) * tf.cast(stride_w, input_dtype)
|
|
290
|
+
ky = tf.range(kh, dtype=input_dtype) * tf.cast(dilation_h, input_dtype)
|
|
291
|
+
kx = tf.range(kw, dtype=input_dtype) * tf.cast(dilation_w, input_dtype)
|
|
292
|
+
|
|
293
|
+
oy = tf.reshape(oy, tf.stack([out_h, 1, 1, 1]))
|
|
294
|
+
ox = tf.reshape(ox, tf.stack([1, out_w, 1, 1]))
|
|
295
|
+
ky = tf.reshape(ky, tf.stack([1, 1, kh, 1]))
|
|
296
|
+
kx = tf.reshape(kx, tf.stack([1, 1, 1, kw]))
|
|
297
|
+
|
|
298
|
+
y = oy + ky
|
|
299
|
+
x = ox + kx
|
|
300
|
+
target_shape = tf.stack([out_h, out_w, kh, kw])
|
|
301
|
+
y = tf.broadcast_to(y, target_shape)
|
|
302
|
+
x = tf.broadcast_to(x, target_shape)
|
|
303
|
+
base_grid = tf.stack([y, x], axis=-1)
|
|
304
|
+
|
|
305
|
+
# Offset reshape: [N, oH, oW, Goff, kH, kW, 2]
|
|
306
|
+
offset = tf.reshape(
|
|
307
|
+
offset,
|
|
308
|
+
tf.stack([batch, out_h, out_w, offset_group, kh, kw, 2]),
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
coords = base_grid[None, :, :, None, :, :, :] + offset
|
|
312
|
+
coords = tf.transpose(coords, [0, 3, 1, 2, 4, 5, 6])
|
|
313
|
+
coords = tf.reshape(coords, tf.stack([batch * offset_group, out_h, out_w, kh, kw, 2]))
|
|
314
|
+
|
|
315
|
+
# Input grouping for offset_group
|
|
316
|
+
c_per_offset = tf.math.floordiv(in_c, offset_group)
|
|
317
|
+
input_tensor = tf.reshape(
|
|
318
|
+
input_tensor,
|
|
319
|
+
tf.stack([batch, in_h, in_w, offset_group, c_per_offset]),
|
|
320
|
+
)
|
|
321
|
+
input_tensor = tf.transpose(input_tensor, [0, 3, 1, 2, 4])
|
|
322
|
+
input_tensor = tf.reshape(
|
|
323
|
+
input_tensor,
|
|
324
|
+
tf.stack([batch * offset_group, in_h, in_w, c_per_offset]),
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
sampled = _bilinear_sample_2d(input_tensor, coords)
|
|
328
|
+
sampled = tf.reshape(
|
|
329
|
+
sampled,
|
|
330
|
+
tf.stack([batch, offset_group, out_h, out_w, kh, kw, c_per_offset]),
|
|
331
|
+
)
|
|
332
|
+
sampled = tf.transpose(sampled, [0, 2, 3, 1, 4, 5, 6])
|
|
333
|
+
|
|
334
|
+
if mask is not None:
|
|
335
|
+
mask = tf.reshape(
|
|
336
|
+
mask,
|
|
337
|
+
tf.stack([batch, out_h, out_w, offset_group, kh, kw, 1]),
|
|
338
|
+
)
|
|
339
|
+
sampled = sampled * tf.cast(mask, sampled.dtype)
|
|
340
|
+
|
|
341
|
+
# Merge offset_group back to channel dim: [N, oH, oW, kH, kW, C]
|
|
342
|
+
sampled = tf.reshape(
|
|
343
|
+
sampled,
|
|
344
|
+
tf.stack([batch, out_h, out_w, kh, kw, in_c]),
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
# Grouped convolution via batched matmul
|
|
348
|
+
out_c = tf.shape(weights)[3]
|
|
349
|
+
c_per_group = tf.math.floordiv(in_c, group)
|
|
350
|
+
out_c_per_group = tf.math.floordiv(out_c, group)
|
|
351
|
+
|
|
352
|
+
cols = tf.reshape(sampled, tf.stack([batch * out_h * out_w, kh * kw * in_c]))
|
|
353
|
+
cols = tf.reshape(cols, tf.stack([batch * out_h * out_w, group, kh * kw * c_per_group]))
|
|
354
|
+
cols = tf.transpose(cols, [1, 0, 2])
|
|
355
|
+
|
|
356
|
+
weights = tf.reshape(weights, tf.stack([kh, kw, c_per_group, group, out_c_per_group]))
|
|
357
|
+
weights = tf.transpose(weights, [3, 0, 1, 2, 4])
|
|
358
|
+
weights = tf.reshape(weights, tf.stack([group, kh * kw * c_per_group, out_c_per_group]))
|
|
359
|
+
|
|
360
|
+
output = tf.matmul(cols, weights)
|
|
361
|
+
output = tf.transpose(output, [1, 0, 2])
|
|
362
|
+
output = tf.reshape(output, tf.stack([batch, out_h, out_w, out_c]))
|
|
363
|
+
|
|
364
|
+
if bias is not None:
|
|
365
|
+
output += tf.reshape(bias, tf.stack([1, 1, 1, out_c]))
|
|
366
|
+
|
|
367
|
+
if output.dtype != input_dtype:
|
|
368
|
+
output = tf.cast(output, input_dtype)
|
|
369
|
+
|
|
370
|
+
# Post-process transpose
|
|
371
|
+
tf_layers_dict[graph_node_output.name]['tf_node'] = post_process_transpose(
|
|
372
|
+
value_before_transpose=output,
|
|
373
|
+
param_target='outputs',
|
|
374
|
+
param_name=graph_node.outputs[0].name,
|
|
375
|
+
**kwargs,
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
# Generation of Debug Info
|
|
379
|
+
tf_layers_dict[graph_node_output.name]['tf_node_info'] = \
|
|
380
|
+
make_tf_node_info(
|
|
381
|
+
node_info={
|
|
382
|
+
'tf_op_type': 'DeformConv',
|
|
383
|
+
'tf_inputs': {
|
|
384
|
+
'input_tensor': input_tensor,
|
|
385
|
+
'weights': weights,
|
|
386
|
+
'offset': offset,
|
|
387
|
+
'bias': bias,
|
|
388
|
+
'mask': mask,
|
|
389
|
+
'strides': strides,
|
|
390
|
+
'dilations': dilations,
|
|
391
|
+
'pads': pads,
|
|
392
|
+
'group': group,
|
|
393
|
+
'offset_group': offset_group,
|
|
394
|
+
},
|
|
395
|
+
'tf_outputs': {
|
|
396
|
+
'output': tf_layers_dict[graph_node_output.name]['tf_node'],
|
|
397
|
+
},
|
|
398
|
+
}
|
|
399
|
+
)
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import random
|
|
2
|
+
random.seed(0)
|
|
3
|
+
import numpy as np
|
|
4
|
+
np.random.seed(0)
|
|
5
|
+
import tensorflow as tf
|
|
6
|
+
import onnx_graphsurgeon as gs
|
|
7
|
+
import cv2
|
|
8
|
+
from onnx2tf.utils.common_functions import (
|
|
9
|
+
get_constant_or_variable,
|
|
10
|
+
print_node_info,
|
|
11
|
+
inverted_operation_enable_disable,
|
|
12
|
+
make_tf_node_info,
|
|
13
|
+
get_replacement_parameter,
|
|
14
|
+
pre_process_transpose,
|
|
15
|
+
post_process_transpose,
|
|
16
|
+
)
|
|
17
|
+
from onnx2tf.utils.logging import *
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _as_tensor(value):
|
|
21
|
+
if isinstance(value, np.ndarray):
|
|
22
|
+
return tf.convert_to_tensor(value)
|
|
23
|
+
if isinstance(value, (np.generic, int, float, bool, str, bytes)):
|
|
24
|
+
return tf.convert_to_tensor(value)
|
|
25
|
+
return value
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _decode_image_np(encoded_stream, pixel_format):
|
|
29
|
+
if encoded_stream is None:
|
|
30
|
+
return np.zeros((0, 0, 0), dtype=np.uint8)
|
|
31
|
+
if encoded_stream.dtype != np.uint8:
|
|
32
|
+
encoded_stream = encoded_stream.astype(np.uint8)
|
|
33
|
+
if encoded_stream.size == 0:
|
|
34
|
+
return np.zeros((0, 0, 0), dtype=np.uint8)
|
|
35
|
+
if encoded_stream.ndim != 1:
|
|
36
|
+
encoded_stream = encoded_stream.reshape(-1)
|
|
37
|
+
try:
|
|
38
|
+
if pixel_format == 'Grayscale':
|
|
39
|
+
flag = cv2.IMREAD_GRAYSCALE
|
|
40
|
+
else:
|
|
41
|
+
flag = cv2.IMREAD_COLOR
|
|
42
|
+
decoded = cv2.imdecode(encoded_stream, flag)
|
|
43
|
+
if decoded is None:
|
|
44
|
+
raise ValueError('cv2.imdecode failed')
|
|
45
|
+
if pixel_format == 'RGB':
|
|
46
|
+
decoded = cv2.cvtColor(decoded, cv2.COLOR_BGR2RGB)
|
|
47
|
+
if pixel_format == 'Grayscale' and decoded.ndim == 2:
|
|
48
|
+
decoded = decoded[..., np.newaxis]
|
|
49
|
+
return decoded.astype(np.uint8)
|
|
50
|
+
except Exception:
|
|
51
|
+
if pixel_format == 'Grayscale':
|
|
52
|
+
return np.zeros((0, 0, 1), dtype=np.uint8)
|
|
53
|
+
return np.zeros((0, 0, 3), dtype=np.uint8)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@print_node_info
|
|
57
|
+
@inverted_operation_enable_disable
|
|
58
|
+
@get_replacement_parameter
|
|
59
|
+
def make_node(
|
|
60
|
+
*,
|
|
61
|
+
graph_node: gs.Node,
|
|
62
|
+
tf_layers_dict: dict,
|
|
63
|
+
**kwargs: dict,
|
|
64
|
+
):
|
|
65
|
+
"""ImageDecoder
|
|
66
|
+
|
|
67
|
+
Parameters
|
|
68
|
+
----------
|
|
69
|
+
graph_node: gs.Node
|
|
70
|
+
graph_surgeon Node
|
|
71
|
+
|
|
72
|
+
tf_layers_dict: dict
|
|
73
|
+
optype, shape, dtype, tensorflow graph
|
|
74
|
+
"""
|
|
75
|
+
before_op_output_shape_trans_1 = \
|
|
76
|
+
tf_layers_dict.get(graph_node.inputs[0].name, {}).get('before_op_output_shape_trans', True)
|
|
77
|
+
before_op_output_shape_trans = \
|
|
78
|
+
before_op_output_shape_trans_1
|
|
79
|
+
|
|
80
|
+
graph_node_input = get_constant_or_variable(
|
|
81
|
+
graph_node.inputs[0],
|
|
82
|
+
before_op_output_shape_trans,
|
|
83
|
+
)
|
|
84
|
+
graph_node_output: gs.Variable = graph_node.outputs[0]
|
|
85
|
+
shape = graph_node_output.shape
|
|
86
|
+
dtype = graph_node_output.dtype
|
|
87
|
+
|
|
88
|
+
input_tensor = tf_layers_dict[graph_node_input.name]['tf_node'] \
|
|
89
|
+
if isinstance(graph_node_input, gs.Variable) else graph_node_input
|
|
90
|
+
|
|
91
|
+
# Preserving Graph Structure (Dict)
|
|
92
|
+
tf_layers_dict[graph_node_output.name] = {
|
|
93
|
+
'optype': graph_node.op,
|
|
94
|
+
'shape': shape,
|
|
95
|
+
'dtype': dtype,
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
# Pre-process transpose
|
|
99
|
+
input_tensor = pre_process_transpose(
|
|
100
|
+
value_before_transpose=input_tensor,
|
|
101
|
+
param_target='inputs',
|
|
102
|
+
param_name=graph_node.inputs[0].name,
|
|
103
|
+
**kwargs,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Generation of TF OP
|
|
107
|
+
input_tensor = _as_tensor(input_tensor)
|
|
108
|
+
pixel_format = graph_node.attrs.get('pixel_format', 'RGB')
|
|
109
|
+
if pixel_format not in ['RGB', 'BGR', 'Grayscale']:
|
|
110
|
+
error(
|
|
111
|
+
f'ImageDecoder pixel_format={pixel_format} is not supported.\n' +
|
|
112
|
+
f'graph_node.name: {graph_node.name}'
|
|
113
|
+
)
|
|
114
|
+
pixel_format = 'RGB'
|
|
115
|
+
|
|
116
|
+
decoded = tf.numpy_function(
|
|
117
|
+
func=lambda x: _decode_image_np(x, pixel_format),
|
|
118
|
+
inp=[input_tensor],
|
|
119
|
+
Tout=tf.uint8,
|
|
120
|
+
name=graph_node.name,
|
|
121
|
+
)
|
|
122
|
+
channels = 1 if pixel_format == 'Grayscale' else 3
|
|
123
|
+
decoded = tf.ensure_shape(decoded, [None, None, channels])
|
|
124
|
+
tf_layers_dict[graph_node_output.name]['tf_node'] = decoded
|
|
125
|
+
|
|
126
|
+
# Post-process transpose
|
|
127
|
+
tf_layers_dict[graph_node_output.name]['tf_node'] = post_process_transpose(
|
|
128
|
+
value_before_transpose=tf_layers_dict[graph_node_output.name]['tf_node'],
|
|
129
|
+
param_target='outputs',
|
|
130
|
+
param_name=graph_node.outputs[0].name,
|
|
131
|
+
**kwargs,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
# Generation of Debug Info
|
|
135
|
+
tf_layers_dict[graph_node_output.name]['tf_node_info'] = \
|
|
136
|
+
make_tf_node_info(
|
|
137
|
+
node_info={
|
|
138
|
+
'tf_op_type': 'ImageDecoder',
|
|
139
|
+
'tf_inputs': {
|
|
140
|
+
'encoded_stream': input_tensor,
|
|
141
|
+
'pixel_format': pixel_format,
|
|
142
|
+
},
|
|
143
|
+
'tf_outputs': {
|
|
144
|
+
'output': tf_layers_dict[graph_node_output.name]['tf_node'],
|
|
145
|
+
},
|
|
146
|
+
}
|
|
147
|
+
)
|