<h5 dir="auto">System information (version)</h5>

<ul dir="auto">
<li>OpenCV =&gt; 3.4.1</li>
<li>Operating System / Platform =&gt; Ubuntu 16.04 64Bit</li>
<li>Compiler =&gt; gcc 5.4.0</li>
<li>TensorFlow =&gt; 1.4.0</li>
<li>Model =&gt; faster_rcnn_resnet50_coco <a href="http://download.tensorflow.org/models/object_detection/faster_rcnn_resnet50_coco_2018_01_28.tar.gz" rel="nofollow">http://download.tensorflow.org/models/object_detection/faster_rcnn_resnet50_coco_2018_01_28.tar.gz</a></li>
</ul>
<h5 dir="auto">Detailed description</h5>

<p dir="auto">I have trained the original model on myself image set with the form of VOC2007.<br>
But when I try to load the frozen model  in Tensorflow into OpenCV, the following error persists.</p>
<h5 dir="auto">Steps to reproduce</h5>

<p dir="auto">Loading the frozen graphs</p>
<p dir="auto"><code class="notranslate">cvNet = cv.dnn.readNetFromTensorflow('./output_inference_graph/trans_graph.pb', './output_inference_graph/graph.pbtxt')</code></p>
<p dir="auto">I get the error</p>
<p dir="auto"><code class="notranslate">OpenCV(3.4.1) Error: Unspecified error (Input layer not found: FirstStageFeatureExtractor/resnet_v1_50/resnet_v1_50/conv1/BatchNorm/FusedBatchNorm) in connect, file /io/opencv/modules/dnn/src/tensorflow/tf_importer.cpp, line 553 Traceback (most recent call last): File "detect_opencv_tensorflow_2.py", line 3, in &lt;module&gt; cvNet = cv.dnn.readNetFromTensorflow('./output_inference_graph/trans_graph.pb', './output_inference_graph/graph.pbtxt') cv2.error: OpenCV(3.4.1) /io/opencv/modules/dnn/src/tensorflow/tf_importer.cpp:553: error: (-2) Input layer not found: FirstStageFeatureExtractor/resnet_v1_50/resnet_v1_50/conv1/BatchNorm/FusedBatchNorm in function connect</code></p>
<h5 dir="auto">System information (version)</h5>
<ul dir="auto">
<li>OpenCV =&gt; 3.4 installed with pip</li>
<li>Operating System / Platform =&gt; Ubuntu 16.04</li>
<li>Python =&gt; Python 3.5.2</li>
<li>Tensorflow =&gt; 1.5</li>
</ul>
<h5 dir="auto">Detailed description</h5>
<p dir="auto">I'm trying to load in a pretrained MobileNet  model from tensorflow.python.keras.applications. However I'm running into problems importing the model into dnn using cv2.dnn.readNetFromTensorflow(frozen_graph, pb_txt)</p>
<p dir="auto">I followed some of the steps described in  <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="267169120" data-permission-text="Title is private" data-url="https://github.com/opencv/opencv/issues/9894" data-hovercard-type="issue" data-hovercard-url="/opencv/opencv/issues/9894/hovercard" href="https://github.com/opencv/opencv/issues/9894">#9894</a> in addition to some of the other ones decribed by <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/dkurt/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/dkurt">@dkurt</a> in various posts.</p>
<h5 dir="auto">General Steps</h5>
<ul dir="auto">
<li>load in MobileNet from tensorflow.python.keras.applications</li>
<li>Freeze the graph</li>
<li>Save the frozen graph as a .pb file</li>
<li>optimize the graph for inference using the optimize_for_inference tool provided by tensorflow</li>
<li>Remove the constant nodes using a function provided by <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/dkurt/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/dkurt">@dkurt</a> in <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="267169120" data-permission-text="Title is private" data-url="https://github.com/opencv/opencv/issues/9894" data-hovercard-type="issue" data-hovercard-url="/opencv/opencv/issues/9894/hovercard" href="https://github.com/opencv/opencv/issues/9894">#9894</a> to make a .pbtxt</li>
<li>Modify the .pbtxt I can modify the RELU layers to be RELU6 instead of a RELU layer stacked with minimum and maxmium layers (since these are not supported by opencv)</li>
<li>Try to load in the .pb and .pbtxt using readNetFromTensorflow</li>
</ul>
<p dir="auto">The issue stems that when I use the code to generate a .pbtxt file to remove const nodes that openv doesn't use. Specifically it deletes some of the input constants being fed into some of my Fused Batch Normalization layers i.e.<br>
OpenCV Error: Unspecified error (Input layer not found: conv1_bn/FusedBatchNorm) in connect, file /root/opencv/modules/dnn/src/tensorflow/tf_importer.cpp, line 553<br>
Traceback (most recent call last):<br>
File "/opt/PyCharm/helpers/pydev/pydevd.py", line 1596, in <br>
globals = debugger.run(setup['file'], None, None, is_module)<br>
File "/opt/PyCharm/helpers/pydev/pydevd.py", line 974, in run<br>
pydev_imports.execfile(file, globals, locals)  # execute the script<br>
File "/opt/PyCharm/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile<br>
exec(compile(contents+"\n", file, 'exec'), glob, loc)<br>
File "/home/dl_docker_user/opencv_dnn_wrapper/main.py", line 38, in <br>
net = cv2.dnn.readNetFromTensorflow(frozen_graph, pb_txt)<br>
cv2.error: /root/opencv/modules/dnn/src/tensorflow/tf_importer.cpp:553: error: (-2) Input layer not found: conv1_bn/FusedBatchNorm in function connect</p>
<h5 dir="auto">Steps to reproduce</h5>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
    graph = session.graph
    with graph.as_default():
        freeze_var_names = list(set(v.op.name for v in tf.global_variables()).difference(keep_var_names or []))
        output_names = output_names or []
        output_names += [v.op.name for v in tf.global_variables()]
        input_graph_def = graph.as_graph_def()
        if clear_devices:
            for node in input_graph_def.node:
                node.device = &quot;&quot;
        frozen_graph = convert_variables_to_constants(session, input_graph_def,
                                                      output_names, freeze_var_names)
        return frozen_graph

from tensorflow.python.keras.applications import MobileNet
from tensorflow.python.keras import backend as K
import tensorflow as tf
from tensorflow.python.framework import graph_util, graph_io
K.set_learning_phase(False)
model = MobileNet(input_shape=(224, 224, 3), weights='mobilenet_1_0_224_tf.h5', include_top=True)
pred_node_names = [None]
pred = [None]
for i in range(1):
    pred_node_names[i] = &quot;output_node&quot; + str(i)
    pred[i] = tf.identity(model.outputs[i], name=pred_node_names[i])
    sess = K.get_session()

frozen_graph = freeze_session(sess, output_names=[&quot;output_node0&quot;])
graph_io.write_graph(frozen_graph, &quot;.&quot;, &quot;model.pb&quot;, as_text=False)"><pre class="notranslate"><span class="pl-k">def</span> <span class="pl-en">freeze_session</span>(<span class="pl-s1">session</span>, <span class="pl-s1">keep_var_names</span><span class="pl-c1">=</span><span class="pl-c1">None</span>, <span class="pl-s1">output_names</span><span class="pl-c1">=</span><span class="pl-c1">None</span>, <span class="pl-s1">clear_devices</span><span class="pl-c1">=</span><span class="pl-c1">True</span>):
    <span class="pl-s1">graph</span> <span class="pl-c1">=</span> <span class="pl-s1">session</span>.<span class="pl-s1">graph</span>
    <span class="pl-k">with</span> <span class="pl-s1">graph</span>.<span class="pl-en">as_default</span>():
        <span class="pl-s1">freeze_var_names</span> <span class="pl-c1">=</span> <span class="pl-en">list</span>(<span class="pl-en">set</span>(<span class="pl-s1">v</span>.<span class="pl-s1">op</span>.<span class="pl-s1">name</span> <span class="pl-k">for</span> <span class="pl-s1">v</span> <span class="pl-c1">in</span> <span class="pl-s1">tf</span>.<span class="pl-en">global_variables</span>()).<span class="pl-en">difference</span>(<span class="pl-s1">keep_var_names</span> <span class="pl-c1">or</span> []))
        <span class="pl-s1">output_names</span> <span class="pl-c1">=</span> <span class="pl-s1">output_names</span> <span class="pl-c1">or</span> []
        <span class="pl-s1">output_names</span> <span class="pl-c1">+=</span> [<span class="pl-s1">v</span>.<span class="pl-s1">op</span>.<span class="pl-s1">name</span> <span class="pl-k">for</span> <span class="pl-s1">v</span> <span class="pl-c1">in</span> <span class="pl-s1">tf</span>.<span class="pl-en">global_variables</span>()]
        <span class="pl-s1">input_graph_def</span> <span class="pl-c1">=</span> <span class="pl-s1">graph</span>.<span class="pl-en">as_graph_def</span>()
        <span class="pl-k">if</span> <span class="pl-s1">clear_devices</span>:
            <span class="pl-k">for</span> <span class="pl-s1">node</span> <span class="pl-c1">in</span> <span class="pl-s1">input_graph_def</span>.<span class="pl-s1">node</span>:
                <span class="pl-s1">node</span>.<span class="pl-s1">device</span> <span class="pl-c1">=</span> <span class="pl-s">""</span>
        <span class="pl-s1">frozen_graph</span> <span class="pl-c1">=</span> <span class="pl-en">convert_variables_to_constants</span>(<span class="pl-s1">session</span>, <span class="pl-s1">input_graph_def</span>,
                                                      <span class="pl-s1">output_names</span>, <span class="pl-s1">freeze_var_names</span>)
        <span class="pl-k">return</span> <span class="pl-s1">frozen_graph</span>

<span class="pl-k">from</span> <span class="pl-s1">tensorflow</span>.<span class="pl-s1">python</span>.<span class="pl-s1">keras</span>.<span class="pl-s1">applications</span> <span class="pl-k">import</span> <span class="pl-v">MobileNet</span>
<span class="pl-k">from</span> <span class="pl-s1">tensorflow</span>.<span class="pl-s1">python</span>.<span class="pl-s1">keras</span> <span class="pl-k">import</span> <span class="pl-s1">backend</span> <span class="pl-k">as</span> <span class="pl-v">K</span>
<span class="pl-k">import</span> <span class="pl-s1">tensorflow</span> <span class="pl-k">as</span> <span class="pl-s1">tf</span>
<span class="pl-k">from</span> <span class="pl-s1">tensorflow</span>.<span class="pl-s1">python</span>.<span class="pl-s1">framework</span> <span class="pl-k">import</span> <span class="pl-s1">graph_util</span>, <span class="pl-s1">graph_io</span>
<span class="pl-v">K</span>.<span class="pl-en">set_learning_phase</span>(<span class="pl-c1">False</span>)
<span class="pl-s1">model</span> <span class="pl-c1">=</span> <span class="pl-v">MobileNet</span>(<span class="pl-s1">input_shape</span><span class="pl-c1">=</span>(<span class="pl-c1">224</span>, <span class="pl-c1">224</span>, <span class="pl-c1">3</span>), <span class="pl-s1">weights</span><span class="pl-c1">=</span><span class="pl-s">'mobilenet_1_0_224_tf.h5'</span>, <span class="pl-s1">include_top</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)
<span class="pl-s1">pred_node_names</span> <span class="pl-c1">=</span> [<span class="pl-c1">None</span>]
<span class="pl-s1">pred</span> <span class="pl-c1">=</span> [<span class="pl-c1">None</span>]
<span class="pl-k">for</span> <span class="pl-s1">i</span> <span class="pl-c1">in</span> <span class="pl-en">range</span>(<span class="pl-c1">1</span>):
    <span class="pl-s1">pred_node_names</span>[<span class="pl-s1">i</span>] <span class="pl-c1">=</span> <span class="pl-s">"output_node"</span> <span class="pl-c1">+</span> <span class="pl-en">str</span>(<span class="pl-s1">i</span>)
    <span class="pl-s1">pred</span>[<span class="pl-s1">i</span>] <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-en">identity</span>(<span class="pl-s1">model</span>.<span class="pl-s1">outputs</span>[<span class="pl-s1">i</span>], <span class="pl-s1">name</span><span class="pl-c1">=</span><span class="pl-s1">pred_node_names</span>[<span class="pl-s1">i</span>])
    <span class="pl-s1">sess</span> <span class="pl-c1">=</span> <span class="pl-v">K</span>.<span class="pl-en">get_session</span>()

<span class="pl-s1">frozen_graph</span> <span class="pl-c1">=</span> <span class="pl-en">freeze_session</span>(<span class="pl-s1">sess</span>, <span class="pl-s1">output_names</span><span class="pl-c1">=</span>[<span class="pl-s">"output_node0"</span>])
<span class="pl-s1">graph_io</span>.<span class="pl-en">write_graph</span>(<span class="pl-s1">frozen_graph</span>, <span class="pl-s">"."</span>, <span class="pl-s">"model.pb"</span>, <span class="pl-s1">as_text</span><span class="pl-c1">=</span><span class="pl-c1">False</span>)</pre></div>
<p dir="auto">Then I used the optimize for inference tool provided by tensorflow</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="python /usr/local/lib/python3.5/dist-packages/tensorflow/python/tools/optimize_for_inference.py --input model.pb --output opt_model.pb --input_names input_1 --output_names output_node0 --frozen_graph True"><pre class="notranslate"><code class="notranslate">python /usr/local/lib/python3.5/dist-packages/tensorflow/python/tools/optimize_for_inference.py --input model.pb --output opt_model.pb --input_names input_1 --output_names output_node0 --frozen_graph True
</code></pre></div>
<p dir="auto">Then I create the .pbtxt file using</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="def create_pbtxt_compatible_with_opencv(pb_path, pbtxt_path):
    import tensorflow as tf

    # Read the graph.
    with tf.gfile.FastGFile(pb_path, 'rb') 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, &quot;&quot;, pbtxt_path, as_text=True)"><pre class="notranslate"><span class="pl-k">def</span> <span class="pl-en">create_pbtxt_compatible_with_opencv</span>(<span class="pl-s1">pb_path</span>, <span class="pl-s1">pbtxt_path</span>):
    <span class="pl-k">import</span> <span class="pl-s1">tensorflow</span> <span class="pl-k">as</span> <span class="pl-s1">tf</span>

    <span class="pl-c"># Read the graph.</span>
    <span class="pl-k">with</span> <span class="pl-s1">tf</span>.<span class="pl-s1">gfile</span>.<span class="pl-v">FastGFile</span>(<span class="pl-s1">pb_path</span>, <span class="pl-s">'rb'</span>) <span class="pl-k">as</span> <span class="pl-s1">f</span>:
        <span class="pl-s1">graph_def</span> <span class="pl-c1">=</span> <span class="pl-s1">tf</span>.<span class="pl-v">GraphDef</span>()
        <span class="pl-s1">graph_def</span>.<span class="pl-v">ParseFromString</span>(<span class="pl-s1">f</span>.<span class="pl-en">read</span>())

    <span class="pl-c"># Remove Const nodes.</span>
    <span class="pl-k">for</span> <span class="pl-s1">i</span> <span class="pl-c1">in</span> <span class="pl-en">reversed</span>(<span class="pl-en">range</span>(<span class="pl-en">len</span>(<span class="pl-s1">graph_def</span>.<span class="pl-s1">node</span>))):
        <span class="pl-k">if</span> <span class="pl-s1">graph_def</span>.<span class="pl-s1">node</span>[<span class="pl-s1">i</span>].<span class="pl-s1">op</span> <span class="pl-c1">==</span> <span class="pl-s">'Const'</span>:
            <span class="pl-k">del</span> <span class="pl-s1">graph_def</span>.<span class="pl-s1">node</span>[<span class="pl-s1">i</span>]
        <span class="pl-k">for</span> <span class="pl-s1">attr</span> <span class="pl-c1">in</span> [<span class="pl-s">'T'</span>, <span class="pl-s">'data_format'</span>, <span class="pl-s">'Tshape'</span>, <span class="pl-s">'N'</span>, <span class="pl-s">'Tidx'</span>, <span class="pl-s">'Tdim'</span>,
                     <span class="pl-s">'use_cudnn_on_gpu'</span>, <span class="pl-s">'Index'</span>, <span class="pl-s">'Tperm'</span>, <span class="pl-s">'is_training'</span>,
                     <span class="pl-s">'Tpaddings'</span>]:
            <span class="pl-k">if</span> <span class="pl-s1">attr</span> <span class="pl-c1">in</span> <span class="pl-s1">graph_def</span>.<span class="pl-s1">node</span>[<span class="pl-s1">i</span>].<span class="pl-s1">attr</span>:
                <span class="pl-k">del</span> <span class="pl-s1">graph_def</span>.<span class="pl-s1">node</span>[<span class="pl-s1">i</span>].<span class="pl-s1">attr</span>[<span class="pl-s1">attr</span>]

    <span class="pl-c"># Save as text.</span>
    <span class="pl-s1">tf</span>.<span class="pl-s1">train</span>.<span class="pl-en">write_graph</span>(<span class="pl-s1">graph_def</span>, <span class="pl-s">""</span>, <span class="pl-s1">pbtxt_path</span>, <span class="pl-s1">as_text</span><span class="pl-c1">=</span><span class="pl-c1">True</span>)</pre></div>
<p dir="auto">Lastly, I use this dnn call on the .pb and .pbtxt files</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="frozen_graph = &quot;opt_model.pb&quot;

I've also attached the pbtxt file for reference. Note I'm aware I need to replace the RELU functions followed by min and max with a relu6 layer instead. Thanks for the help!
[opt_model_pbtxt.txt](https://github.com/opencv/opencv/files/1725401/opt_model_pbtxt.txt)

pb_txt = &quot;opt_model.pbtxt&quot;


net = cv2.dnn.readNetFromTensorflow(frozen_graph, pb_txt)"><pre class="notranslate"><span class="pl-s1">frozen_graph</span> <span class="pl-c1">=</span> <span class="pl-s">"opt_model.pb"</span>

<span class="pl-v">I</span><span class="pl-s">'ve also attached the pbtxt file for reference. Note I'</span><span class="pl-s1">m</span> <span class="pl-s1">aware</span> <span class="pl-v">I</span> <span class="pl-s1">need</span> <span class="pl-s1">to</span> <span class="pl-s1">replace</span> <span class="pl-s1">the</span> <span class="pl-v">RELU</span> <span class="pl-s1">functions</span> <span class="pl-s1">followed</span> <span class="pl-s1">by</span> <span class="pl-s1">min</span> <span class="pl-c1">and</span> <span class="pl-s1">max</span> <span class="pl-s1">with</span> <span class="pl-s1">a</span> <span class="pl-s1">relu6</span> <span class="pl-s1">layer</span> <span class="pl-s1">instead</span>. <span class="pl-v">Thanks</span> <span class="pl-s1">for</span> <span class="pl-s1">the</span> <span class="pl-s1">help</span>!
[<span class="pl-s1">opt_model_pbtxt</span>.<span class="pl-s1">txt</span>](<span class="pl-s1">https</span>:<span class="pl-c1">//</span><span class="pl-s1">github</span>.<span class="pl-s1">com</span><span class="pl-c1">/</span><span class="pl-s1">opencv</span><span class="pl-c1">/</span><span class="pl-s1">opencv</span><span class="pl-c1">/</span><span class="pl-s1">files</span><span class="pl-c1">/</span><span class="pl-c1">1725401</span><span class="pl-c1">/</span><span class="pl-s1">opt_model_pbtxt</span>.<span class="pl-s1">txt</span>)

<span class="pl-s1">pb_txt</span> <span class="pl-c1">=</span> <span class="pl-s">"opt_model.pbtxt"</span>


<span class="pl-s1">net</span> <span class="pl-c1">=</span> <span class="pl-s1">cv2</span>.<span class="pl-s1">dnn</span>.<span class="pl-en">readNetFromTensorflow</span>(<span class="pl-s1">frozen_graph</span>, <span class="pl-s1">pb_txt</span>)</pre></div>
<p dir="auto">Resulting in,<br>
OpenCV Error: Unspecified error (Input layer not found: conv1_bn/FusedBatchNorm) in connect, file /root/opencv/modules/dnn/src/tensorflow/tf_importer.cpp, line 553<br>
Traceback (most recent call last):<br>
File "/opt/PyCharm/helpers/pydev/pydevd.py", line 1596, in <br>
globals = debugger.run(setup['file'], None, None, is_module)<br>
File "/opt/PyCharm/helpers/pydev/pydevd.py", line 974, in run<br>
pydev_imports.execfile(file, globals, locals)  # execute the script<br>
File "/opt/PyCharm/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile<br>
exec(compile(contents+"\n", file, 'exec'), glob, loc)<br>
File "/home/dl_docker_user/opencv_dnn_wrapper/main.py", line 38, in <br>
net = cv2.dnn.readNetFromTensorflow(frozen_graph, pb_txt)<br>
cv2.error: /root/opencv/modules/dnn/src/tensorflow/tf_importer.cpp:553: error: (-2) Input layer not found: conv1_bn/FusedBatchNorm in function connect</p>