summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorGuo, Yejun <yejun.guo@intel.com>2019-10-21 20:38:03 +0800
committerPedro Arthur <bygrandao@gmail.com>2019-10-30 10:31:55 -0300
commitdff39ea9f0154ec52b7548b122a4a5332df3c2c6 (patch)
treea435c8d24d80bc9c38ecd4b93c51113c47acad05 /tools
parenta269fa044b1364af1654456c33b7d45407822876 (diff)
downloadffmpeg-dff39ea9f0154ec52b7548b122a4a5332df3c2c6.tar.gz
dnn: add tf.nn.conv2d support for native model
Unlike other tf.*.conv2d layers, tf.nn.conv2d does not create many nodes (within a scope) in the graph, it just acts like other layers. tf.nn.conv2d only creates one node in the graph, and no internal nodes such as 'kernel' are created. The format of native model file is also changed, a flag named has_bias is added, so change the version number. Signed-off-by: Guo, Yejun <yejun.guo@intel.com> Signed-off-by: Pedro Arthur <bygrandao@gmail.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/python/convert_from_tensorflow.py54
-rw-r--r--tools/python/convert_header.py4
2 files changed, 51 insertions, 7 deletions
diff --git a/tools/python/convert_from_tensorflow.py b/tools/python/convert_from_tensorflow.py
index a663b34004..605158a32e 100644
--- a/tools/python/convert_from_tensorflow.py
+++ b/tools/python/convert_from_tensorflow.py
@@ -118,7 +118,7 @@ class TFConverter:
return knode, bnode, dnode, anode
- def dump_conv2d_to_file(self, node, f):
+ def dump_complex_conv2d_to_file(self, node, f):
assert(node.op == 'Conv2D')
self.layer_number = self.layer_number + 1
self.converted_nodes.add(node.name)
@@ -153,7 +153,8 @@ class TFConverter:
kernel = kernel.reshape(filter_height, filter_width, in_channels, out_channels)
kernel = np.transpose(kernel, [3, 0, 1, 2])
- np.array([self.op2code[node.op], dilation, padding, self.conv_activations[activation], in_channels, out_channels, filter_height], dtype=np.uint32).tofile(f)
+ has_bias = 1
+ np.array([self.op2code[node.op], dilation, padding, self.conv_activations[activation], in_channels, out_channels, filter_height, has_bias], dtype=np.uint32).tofile(f)
kernel.tofile(f)
btensor = bnode.attr['value'].tensor
@@ -173,6 +174,41 @@ class TFConverter:
np.array([input_operand_index, output_operand_index], dtype=np.uint32).tofile(f)
+ def dump_simple_conv2d_to_file(self, node, f):
+ assert(node.op == 'Conv2D')
+ self.layer_number = self.layer_number + 1
+ self.converted_nodes.add(node.name)
+
+ node0 = self.name_node_dict[node.input[0]]
+ node1 = self.name_node_dict[node.input[1]]
+ if node0.op == 'Const':
+ knode = node0
+ input_name = node.input[1]
+ else:
+ knode = node1
+ input_name = node.input[0]
+
+ ktensor = knode.attr['value'].tensor
+ filter_height = ktensor.tensor_shape.dim[0].size
+ filter_width = ktensor.tensor_shape.dim[1].size
+ in_channels = ktensor.tensor_shape.dim[2].size
+ out_channels = ktensor.tensor_shape.dim[3].size
+ kernel = np.frombuffer(ktensor.tensor_content, dtype=np.float32)
+ kernel = kernel.reshape(filter_height, filter_width, in_channels, out_channels)
+ kernel = np.transpose(kernel, [3, 0, 1, 2])
+
+ has_bias = 0
+ dilation = 1
+ padding = node.attr['padding'].s.decode("utf-8")
+ np.array([self.op2code[node.op], dilation, self.conv_paddings[padding], self.conv_activations['None'],
+ in_channels, out_channels, filter_height, has_bias], dtype=np.uint32).tofile(f)
+ kernel.tofile(f)
+
+ input_operand_index = self.add_operand(input_name, Operand.IOTYPE_INPUT)
+ output_operand_index = self.add_operand(node.name, Operand.IOTYPE_OUTPUT)
+ np.array([input_operand_index, output_operand_index], dtype=np.uint32).tofile(f)
+
+
def dump_depth2space_to_file(self, node, f):
assert(node.op == 'DepthToSpace')
self.layer_number = self.layer_number + 1
@@ -222,10 +258,12 @@ class TFConverter:
scope_name = TFConverter.get_scope_name(node.name)
if scope_name in self.conv2d_scope_names:
if node.op == 'Conv2D':
- self.dump_conv2d_to_file(node, f)
+ self.dump_complex_conv2d_to_file(node, f)
continue
- if node.op == 'DepthToSpace':
+ if node.op == 'Conv2D':
+ self.dump_simple_conv2d_to_file(node, f)
+ elif node.op == 'DepthToSpace':
self.dump_depth2space_to_file(node, f)
elif node.op == 'MirrorPad':
self.dump_mirrorpad_to_file(node, f)
@@ -312,10 +350,16 @@ class TFConverter:
def generate_conv2d_scope_info(self):
- # conv2d is a sub block in graph, get the scope name
+ # mostly, conv2d is a sub block in graph, get the scope name
for node in self.nodes:
if node.op == 'Conv2D':
scope = TFConverter.get_scope_name(node.name)
+ # for the case tf.nn.conv2d is called directly
+ if scope == '':
+ continue
+ # for the case tf.nn.conv2d is called within a scope
+ if scope + '/kernel' not in self.name_node_dict:
+ continue
self.conv2d_scope_names.add(scope)
# get the input name to the conv2d sub block
diff --git a/tools/python/convert_header.py b/tools/python/convert_header.py
index 3c2acd5b15..67672b2785 100644
--- a/tools/python/convert_header.py
+++ b/tools/python/convert_header.py
@@ -20,7 +20,7 @@
str = 'FFMPEGDNNNATIVE'
# increase major and reset minor when we have to re-convert the model file
-major = 0
+major = 1
# increase minor when we don't have to re-convert the model file
-minor = 2
+minor = 0