1 | initial version |
@Rodrigo2019, I'm sorry for the delay. The problem is that at OpenCV 3.3.0 reshape layer had a kind of condition to make a data permutation (like from NHWC data layout to NCHW). We've removed it. Shortly your model is a sequence of the following layers:
Placeholder conv2d_1_input
Const conv2d_1/kernel
Conv2D conv2d_1/convolution
Const conv2d_1/bias
BiasAdd conv2d_1/BiasAdd
Relu activation_1/Relu
MaxPool max_pooling2d_1/MaxPool
Const conv2d_2/kernel
Conv2D conv2d_2/convolution
Const conv2d_2/bias
BiasAdd conv2d_2/BiasAdd
Relu activation_2/Relu
MaxPool max_pooling2d_2/MaxPool
Const reshape_1/Reshape/shape
Reshape reshape_1/Reshape
Const dense_1/kernel
MatMul dense_1/MatMul
Const dense_1/bias
BiasAdd dense_1/BiasAdd
Relu activation_3/Relu
Const dense_2/kernel
MatMul dense_2/MatMul
Const dense_2/bias
BiasAdd dense_2/BiasAdd
Softmax activation_4/Softmax
And we have to add one permutation manually to indicate that fully-connected layer expects NHWC input (default TensorFlow data layout).
The easiest way is to use text graph representation. To do it just run the following script:
import tensorflow as tf
# Read the graph.
with tf.gfile.FastGFile('model_final.pb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
# Remove Const nodes.
for i in reversed(range(len(graph_def.node))):
if graph_def.node[i].op == 'Const':
del graph_def.node[i]
for attr in ['T', 'data_format', 'Tshape', 'N', 'Tidx', 'Tdim',
'use_cudnn_on_gpu', 'Index', 'Tperm', 'is_training',
'Tpaddings']:
if attr in graph_def.node[i].attr:
del graph_def.node[i].attr[attr]
# Save as text.
tf.train.write_graph(graph_def, "", "model_final.pbtxt", as_text=True)
And replace
node {
name: "reshape_1/Reshape"
op: "Reshape"
input: "max_pooling2d_2/MaxPool"
input: "reshape_1/Reshape/shape"
}
onto
node {
name: "order"
op: "Const"
attr {
key: "value"
value {
tensor {
dtype: DT_INT32
tensor_shape {
}
int_val: 0
int_val: 1
int_val: 2
int_val: 3
}
}
}
}
node {
name: "max_pooling2d_2/MaxPool/transpose"
op: "Transpose"
input: "max_pooling2d_2/MaxPool"
input: "order"
}
node {
name: "reshape_1/Reshape"
op: "Reshape"
input: "max_pooling2d_2/MaxPool/transpose"
input: "reshape_1/Reshape/shape"
}
Now the following script that matches TensorFlow's output with OpenCV's one produces 2.91038e-11
maximal absolute difference.
import numpy as np
import tensorflow as tf
import time
with tf.gfile.FastGFile('model_final.pb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
with tf.Session() as sess:
sess.graph.as_default()
tf.import_graph_def(graph_def, name='')
for node in graph_def.node:
print node.op, node.name
# Generate input
np.random.seed(2701)
inp = np.random.standard_normal([1, 28, 92, 1]).astype(np.float32)
# Get output tensor
outTensor = sess.graph.get_tensor_by_name('activation_4/Softmax:0')
out = sess.run(outTensor, feed_dict={'conv2d_1_input:0': inp})
import cv2 as cv
cvNet = cv.dnn.readNetFromTensorflow('model_final.pb', 'model_final.pbtxt')
cvNet.setInput(inp.transpose(0, 3, 1, 2))
cvOut = cvNet.forward()
print np.max(np.abs(cvOut - out))