<p dir="auto">I implemented the custom operator that named 'test_custom' with reference to <a href="https://pytorch.org/tutorials/advanced/torch_script_custom_ops.html" rel="nofollow">torch_script_custom_ops</a>，then I convert the pytorch model to onnx，<br>
When I load the onnx model by dnn module, I have get the following error.<br>
<a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/20365125/142836118-31e4a9a3-3fea-4b1c-a416-55868efe6694.png"><img src="https://user-images.githubusercontent.com/20365125/142836118-31e4a9a3-3fea-4b1c-a416-55868efe6694.png" alt="image" style="max-width: 100%;"></a></p>
<p dir="auto"><strong>System information</strong></p>
<ul dir="auto">
<li>OS Platform and Distribution (Windows10):</li>
<li>ONNX Runtime installed from (pip install onnxruntime):</li>
<li>ONNX Runtime version:(1.9.0)</li>
<li>ONNX version : (1.10.2)</li>
<li>Python version: 3.7.4</li>
<li>Visual Studio version (2019):</li>
<li>OpenCV: 4.2.0</li>
</ul>
<p dir="auto">The step and code:</p>
<ul dir="auto">
<li>**step1: ** Implemented the custom ops in C++, test.cpp</li>
</ul>
<div class="highlight highlight-source-c++ notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="#include &quot;torch/script.h&quot;

torch::Tensor test_custom(torch::Tensor image, torch::Tensor warp) {
    return image.clone();
}

static auto registry = torch::RegisterOperators(&quot;my_ops::test_custom&quot;, &amp;test_custom);"><pre class="notranslate">#<span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds">"</span>torch/script.h<span class="pl-pds">"</span></span>

torch::Tensor <span class="pl-en">test_custom</span>(torch::Tensor image, torch::Tensor warp) {
    <span class="pl-k">return</span> image.<span class="pl-c1">clone</span>();
}

<span class="pl-k">static</span> <span class="pl-k">auto</span> registry = torch::RegisterOperators(<span class="pl-s"><span class="pl-pds">"</span>my_ops::test_custom<span class="pl-pds">"</span></span>, &amp;test_custom);</pre></div>
<ul dir="auto">
<li>**step2: **  Compiled my code by Cmake and get the shared library: <code class="notranslate">test_custom.dll</code>, CMakeLists.txt</li>
</ul>
<div class="highlight highlight-text-adblock notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
project(test_custom)

set(CMAKE_VERBOSE_MAKEFILE ON)

# Torch
set(TORCH_ROOT &quot;D:/python/Lib/site-packages/torch&quot;)  
include_directories(${TORCH_ROOT}/include)
link_directories(${TORCH_ROOT}/lib/)

# Define our library target
add_library(${PROJECT_NAME} SHARED test.cpp)

# Enable C++14
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_14)

# Link against Torch
target_link_libraries(${PROJECT_NAME} 
	c10
	torch_cpu
)"><pre class="notranslate">cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
project(test_custom)

set(CMAKE_VERBOSE_MAKEFILE ON)

<span class="pl-c"># Torch</span>
set(TORCH_ROOT "D:/python/Lib/site-packages/torch")  
include_directories(<span class="pl-k">$</span>{TORCH_ROOT}/include)
link_directories(<span class="pl-k">$</span>{TORCH_ROOT}/lib/)

<span class="pl-c"># Define our library target</span>
add_library(<span class="pl-k">$</span>{PROJECT_NAME} SHARED test.cpp)

<span class="pl-c"># Enable C++14</span>
target_compile_features(<span class="pl-k">$</span>{PROJECT_NAME} PRIVATE cxx_std_14)

<span class="pl-c"># Link against Torch</span>
target_link_libraries(<span class="pl-k">$</span>{PROJECT_NAME} 
	c10
	torch_cpu
)</pre></div>
<ul dir="auto">
<li>**step3: ** export the pytorch model to onnx</li>
</ul>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import torch
torch.ops.load_library(&quot;test_custom.dll&quot;)


class MyNet(torch.nn.Module):
    def __init__(self, num_classes):
        super(MyNet, self).__init__()
        self.num_classes = num_classes

    def forward(self, xyz, other):
        return torch.ops.my_ops.test_custom(xyz, other)


def my_custom(g, xyz, other):
    return g.op(&quot;my_ops::test_custom&quot;, xyz, other)
torch.onnx.register_custom_op_symbolic(&quot;my_ops::test_custom&quot;, my_custom, 9)


if __name__ == &quot;__main__&quot;:
    net = MyNet(2)
    xyz = torch.rand((2, 3))
    other = torch.rand((1, 3))

    print(&quot;xyz: &quot;, xyz)
    out = net(xyz, other)
    print(&quot;out: &quot;, out)

    # export onnx
    torch.onnx.export(net,
            (xyz, other),
            &quot;./model.onnx&quot;,
            input_names=[&quot;points&quot;, &quot;cate&quot;],
            output_names=[&quot;cls_prob&quot;],
            custom_opsets={&quot;my_ops&quot;: 11},
            dynamic_axes={
                &quot;points&quot;: {0: &quot;channel&quot;, 1: &quot;n_point&quot;},
                &quot;cls_prob&quot;: {0: &quot;channel&quot;, 1: &quot;n&quot;}
            }
            )"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">torch</span>
<span class="pl-s1">torch</span>.<span class="pl-s1">ops</span>.<span class="pl-en">load_library</span>(<span class="pl-s">"test_custom.dll"</span>)


<span class="pl-k">class</span> <span class="pl-v">MyNet</span>(<span class="pl-s1">torch</span>.<span class="pl-s1">nn</span>.<span class="pl-v">Module</span>):
    <span class="pl-k">def</span> <span class="pl-en">__init__</span>(<span class="pl-s1">self</span>, <span class="pl-s1">num_classes</span>):
        <span class="pl-en">super</span>(<span class="pl-v">MyNet</span>, <span class="pl-s1">self</span>).<span class="pl-en">__init__</span>()
        <span class="pl-s1">self</span>.<span class="pl-s1">num_classes</span> <span class="pl-c1">=</span> <span class="pl-s1">num_classes</span>

    <span class="pl-k">def</span> <span class="pl-en">forward</span>(<span class="pl-s1">self</span>, <span class="pl-s1">xyz</span>, <span class="pl-s1">other</span>):
        <span class="pl-k">return</span> <span class="pl-s1">torch</span>.<span class="pl-s1">ops</span>.<span class="pl-s1">my_ops</span>.<span class="pl-en">test_custom</span>(<span class="pl-s1">xyz</span>, <span class="pl-s1">other</span>)


<span class="pl-k">def</span> <span class="pl-en">my_custom</span>(<span class="pl-s1">g</span>, <span class="pl-s1">xyz</span>, <span class="pl-s1">other</span>):
    <span class="pl-k">return</span> <span class="pl-s1">g</span>.<span class="pl-en">op</span>(<span class="pl-s">"my_ops::test_custom"</span>, <span class="pl-s1">xyz</span>, <span class="pl-s1">other</span>)
<span class="pl-s1">torch</span>.<span class="pl-s1">onnx</span>.<span class="pl-en">register_custom_op_symbolic</span>(<span class="pl-s">"my_ops::test_custom"</span>, <span class="pl-s1">my_custom</span>, <span class="pl-c1">9</span>)


<span class="pl-k">if</span> <span class="pl-s1">__name__</span> <span class="pl-c1">==</span> <span class="pl-s">"__main__"</span>:
    <span class="pl-s1">net</span> <span class="pl-c1">=</span> <span class="pl-v">MyNet</span>(<span class="pl-c1">2</span>)
    <span class="pl-s1">xyz</span> <span class="pl-c1">=</span> <span class="pl-s1">torch</span>.<span class="pl-en">rand</span>((<span class="pl-c1">2</span>, <span class="pl-c1">3</span>))
    <span class="pl-s1">other</span> <span class="pl-c1">=</span> <span class="pl-s1">torch</span>.<span class="pl-en">rand</span>((<span class="pl-c1">1</span>, <span class="pl-c1">3</span>))

    <span class="pl-en">print</span>(<span class="pl-s">"xyz: "</span>, <span class="pl-s1">xyz</span>)
    <span class="pl-s1">out</span> <span class="pl-c1">=</span> <span class="pl-en">net</span>(<span class="pl-s1">xyz</span>, <span class="pl-s1">other</span>)
    <span class="pl-en">print</span>(<span class="pl-s">"out: "</span>, <span class="pl-s1">out</span>)

    <span class="pl-c"># export onnx</span>
    <span class="pl-s1">torch</span>.<span class="pl-s1">onnx</span>.<span class="pl-en">export</span>(<span class="pl-s1">net</span>,
            (<span class="pl-s1">xyz</span>, <span class="pl-s1">other</span>),
            <span class="pl-s">"./model.onnx"</span>,
            <span class="pl-s1">input_names</span><span class="pl-c1">=</span>[<span class="pl-s">"points"</span>, <span class="pl-s">"cate"</span>],
            <span class="pl-s1">output_names</span><span class="pl-c1">=</span>[<span class="pl-s">"cls_prob"</span>],
            <span class="pl-s1">custom_opsets</span><span class="pl-c1">=</span>{<span class="pl-s">"my_ops"</span>: <span class="pl-c1">11</span>},
            <span class="pl-s1">dynamic_axes</span><span class="pl-c1">=</span>{
                <span class="pl-s">"points"</span>: {<span class="pl-c1">0</span>: <span class="pl-s">"channel"</span>, <span class="pl-c1">1</span>: <span class="pl-s">"n_point"</span>},
                <span class="pl-s">"cls_prob"</span>: {<span class="pl-c1">0</span>: <span class="pl-s">"channel"</span>, <span class="pl-c1">1</span>: <span class="pl-s">"n"</span>}
            }
            )</pre></div>
<p dir="auto">the model structure  is as follows<br>
<a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/20365125/142835198-57841834-49a3-41c6-98ba-dc3fd22e2260.png"><img src="https://user-images.githubusercontent.com/20365125/142835198-57841834-49a3-41c6-98ba-dc3fd22e2260.png" alt="image" style="max-width: 100%;"></a></p>
<ul dir="auto">
<li>**step4: **  call the onnx model by dnn</li>
</ul>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import cv2

# load model
onnx_path = &quot;./model.onnx&quot;
cv2.cv2.dnn.readNetFromONNX(onnx_path )"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">cv2</span>

<span class="pl-c"># load model</span>
<span class="pl-s1">onnx_path</span> <span class="pl-c1">=</span> <span class="pl-s">"./model.onnx"</span>
<span class="pl-s1">cv2</span>.<span class="pl-s1">cv2</span>.<span class="pl-s1">dnn</span>.<span class="pl-en">readNetFromONNX</span>(<span class="pl-s1">onnx_path</span> )</pre></div>
<p dir="auto">I want to know how to call the custom operator in dnn module? someone can help me?</p>
<p dir="auto">I implemented the custom operator that named 'test_custom' with reference to <a href="https://pytorch.org/tutorials/advanced/torch_script_custom_ops.html" rel="nofollow">torch_script_custom_ops</a>，then I convert the pytorch model to onnx，<br>
When I load the onnx model by dnn module, I have get the following error.<br>
<a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/20365125/142836118-31e4a9a3-3fea-4b1c-a416-55868efe6694.png"><img src="https://user-images.githubusercontent.com/20365125/142836118-31e4a9a3-3fea-4b1c-a416-55868efe6694.png" alt="image" style="max-width: 100%;"></a></p>
<p dir="auto"><strong>System information</strong></p>
<ul dir="auto">
<li>OS Platform and Distribution (Windows10):</li>
<li>ONNX Runtime installed from (pip install onnxruntime):</li>
<li>ONNX Runtime version:(1.9.0)</li>
<li>ONNX version : (1.10.2)</li>
<li>Python version: 3.7.4</li>
<li>Visual Studio version (2019):</li>
<li>GCC/Compiler version (if compiling from source):</li>
<li>CUDA/cuDNN version:</li>
<li>GPU model and memory: CPU only</li>
<li>OpenCV: 4.2.0</li>
</ul>
<p dir="auto">The step and code:</p>
<ul dir="auto">
<li>**step1: ** Implemented the custom ops in C++, test.cpp</li>
</ul>
<div class="highlight highlight-source-c++ notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="#include &quot;torch/script.h&quot;

torch::Tensor test_custom(torch::Tensor image, torch::Tensor warp) {
    return image.clone();
}

static auto registry = torch::RegisterOperators(&quot;my_ops::test_custom&quot;, &amp;test_custom);"><pre class="notranslate">#<span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds">"</span>torch/script.h<span class="pl-pds">"</span></span>

torch::Tensor <span class="pl-en">test_custom</span>(torch::Tensor image, torch::Tensor warp) {
    <span class="pl-k">return</span> image.<span class="pl-c1">clone</span>();
}

<span class="pl-k">static</span> <span class="pl-k">auto</span> registry = torch::RegisterOperators(<span class="pl-s"><span class="pl-pds">"</span>my_ops::test_custom<span class="pl-pds">"</span></span>, &amp;test_custom);</pre></div>
<ul dir="auto">
<li>**step2: **  Compiled my code by Cmake and get the shared library: <code class="notranslate">test_custom.dll</code>, CMakeLists.txt</li>
</ul>
<div class="highlight highlight-text-adblock notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
project(test_custom)

set(CMAKE_VERBOSE_MAKEFILE ON)

# Torch
set(TORCH_ROOT &quot;D:/python/Lib/site-packages/torch&quot;)  
include_directories(${TORCH_ROOT}/include)
link_directories(${TORCH_ROOT}/lib/)

# Define our library target
add_library(${PROJECT_NAME} SHARED test.cpp)

# Enable C++14
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_14)

# Link against Torch
target_link_libraries(${PROJECT_NAME} 
	c10
	torch_cpu
)"><pre class="notranslate">cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
project(test_custom)

set(CMAKE_VERBOSE_MAKEFILE ON)

<span class="pl-c"># Torch</span>
set(TORCH_ROOT "D:/python/Lib/site-packages/torch")  
include_directories(<span class="pl-k">$</span>{TORCH_ROOT}/include)
link_directories(<span class="pl-k">$</span>{TORCH_ROOT}/lib/)

<span class="pl-c"># Define our library target</span>
add_library(<span class="pl-k">$</span>{PROJECT_NAME} SHARED test.cpp)

<span class="pl-c"># Enable C++14</span>
target_compile_features(<span class="pl-k">$</span>{PROJECT_NAME} PRIVATE cxx_std_14)

<span class="pl-c"># Link against Torch</span>
target_link_libraries(<span class="pl-k">$</span>{PROJECT_NAME} 
	c10
	torch_cpu
)</pre></div>
<ul dir="auto">
<li>**step3: ** export the pytorch model to onnx</li>
</ul>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import torch
torch.ops.load_library(&quot;test_custom.dll&quot;)


class MyNet(torch.nn.Module):
    def __init__(self, num_classes):
        super(MyNet, self).__init__()
        self.num_classes = num_classes

    def forward(self, xyz, other):
        return torch.ops.my_ops.test_custom(xyz, other)


def my_custom(g, xyz, other):
    return g.op(&quot;my_ops::test_custom&quot;, xyz, other)
torch.onnx.register_custom_op_symbolic(&quot;my_ops::test_custom&quot;, my_custom, 9)


if __name__ == &quot;__main__&quot;:
    net = MyNet(2)
    xyz = torch.rand((2, 3))
    other = torch.rand((1, 3))

    print(&quot;xyz: &quot;, xyz)
    out = net(xyz, other)
    print(&quot;out: &quot;, out)

    # export onnx
    torch.onnx.export(net,
            (xyz, other),
            &quot;./model.onnx&quot;,
            input_names=[&quot;points&quot;, &quot;cate&quot;],
            output_names=[&quot;cls_prob&quot;],
            custom_opsets={&quot;my_ops&quot;: 11},
            dynamic_axes={
                &quot;points&quot;: {0: &quot;channel&quot;, 1: &quot;n_point&quot;},
                &quot;cls_prob&quot;: {0: &quot;channel&quot;, 1: &quot;n&quot;}
            }
            )"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">torch</span>
<span class="pl-s1">torch</span>.<span class="pl-s1">ops</span>.<span class="pl-en">load_library</span>(<span class="pl-s">"test_custom.dll"</span>)


<span class="pl-k">class</span> <span class="pl-v">MyNet</span>(<span class="pl-s1">torch</span>.<span class="pl-s1">nn</span>.<span class="pl-v">Module</span>):
    <span class="pl-k">def</span> <span class="pl-en">__init__</span>(<span class="pl-s1">self</span>, <span class="pl-s1">num_classes</span>):
        <span class="pl-en">super</span>(<span class="pl-v">MyNet</span>, <span class="pl-s1">self</span>).<span class="pl-en">__init__</span>()
        <span class="pl-s1">self</span>.<span class="pl-s1">num_classes</span> <span class="pl-c1">=</span> <span class="pl-s1">num_classes</span>

    <span class="pl-k">def</span> <span class="pl-en">forward</span>(<span class="pl-s1">self</span>, <span class="pl-s1">xyz</span>, <span class="pl-s1">other</span>):
        <span class="pl-k">return</span> <span class="pl-s1">torch</span>.<span class="pl-s1">ops</span>.<span class="pl-s1">my_ops</span>.<span class="pl-en">test_custom</span>(<span class="pl-s1">xyz</span>, <span class="pl-s1">other</span>)


<span class="pl-k">def</span> <span class="pl-en">my_custom</span>(<span class="pl-s1">g</span>, <span class="pl-s1">xyz</span>, <span class="pl-s1">other</span>):
    <span class="pl-k">return</span> <span class="pl-s1">g</span>.<span class="pl-en">op</span>(<span class="pl-s">"my_ops::test_custom"</span>, <span class="pl-s1">xyz</span>, <span class="pl-s1">other</span>)
<span class="pl-s1">torch</span>.<span class="pl-s1">onnx</span>.<span class="pl-en">register_custom_op_symbolic</span>(<span class="pl-s">"my_ops::test_custom"</span>, <span class="pl-s1">my_custom</span>, <span class="pl-c1">9</span>)


<span class="pl-k">if</span> <span class="pl-s1">__name__</span> <span class="pl-c1">==</span> <span class="pl-s">"__main__"</span>:
    <span class="pl-s1">net</span> <span class="pl-c1">=</span> <span class="pl-v">MyNet</span>(<span class="pl-c1">2</span>)
    <span class="pl-s1">xyz</span> <span class="pl-c1">=</span> <span class="pl-s1">torch</span>.<span class="pl-en">rand</span>((<span class="pl-c1">2</span>, <span class="pl-c1">3</span>))
    <span class="pl-s1">other</span> <span class="pl-c1">=</span> <span class="pl-s1">torch</span>.<span class="pl-en">rand</span>((<span class="pl-c1">1</span>, <span class="pl-c1">3</span>))

    <span class="pl-en">print</span>(<span class="pl-s">"xyz: "</span>, <span class="pl-s1">xyz</span>)
    <span class="pl-s1">out</span> <span class="pl-c1">=</span> <span class="pl-en">net</span>(<span class="pl-s1">xyz</span>, <span class="pl-s1">other</span>)
    <span class="pl-en">print</span>(<span class="pl-s">"out: "</span>, <span class="pl-s1">out</span>)

    <span class="pl-c"># export onnx</span>
    <span class="pl-s1">torch</span>.<span class="pl-s1">onnx</span>.<span class="pl-en">export</span>(<span class="pl-s1">net</span>,
            (<span class="pl-s1">xyz</span>, <span class="pl-s1">other</span>),
            <span class="pl-s">"./model.onnx"</span>,
            <span class="pl-s1">input_names</span><span class="pl-c1">=</span>[<span class="pl-s">"points"</span>, <span class="pl-s">"cate"</span>],
            <span class="pl-s1">output_names</span><span class="pl-c1">=</span>[<span class="pl-s">"cls_prob"</span>],
            <span class="pl-s1">custom_opsets</span><span class="pl-c1">=</span>{<span class="pl-s">"my_ops"</span>: <span class="pl-c1">11</span>},
            <span class="pl-s1">dynamic_axes</span><span class="pl-c1">=</span>{
                <span class="pl-s">"points"</span>: {<span class="pl-c1">0</span>: <span class="pl-s">"channel"</span>, <span class="pl-c1">1</span>: <span class="pl-s">"n_point"</span>},
                <span class="pl-s">"cls_prob"</span>: {<span class="pl-c1">0</span>: <span class="pl-s">"channel"</span>, <span class="pl-c1">1</span>: <span class="pl-s">"n"</span>}
            }
            )</pre></div>
<p dir="auto">the model structure  is as follows<br>
<a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/20365125/142835198-57841834-49a3-41c6-98ba-dc3fd22e2260.png"><img src="https://user-images.githubusercontent.com/20365125/142835198-57841834-49a3-41c6-98ba-dc3fd22e2260.png" alt="image" style="max-width: 100%;"></a></p>
<ul dir="auto">
<li>**step4: **  call the onnx model by dnn</li>
</ul>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import cv2

# load model
onnx_path = &quot;./model.onnx&quot;
cv2.cv2.dnn.readNetFromONNX(onnx_path )"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">cv2</span>

<span class="pl-c"># load model</span>
<span class="pl-s1">onnx_path</span> <span class="pl-c1">=</span> <span class="pl-s">"./model.onnx"</span>
<span class="pl-s1">cv2</span>.<span class="pl-s1">cv2</span>.<span class="pl-s1">dnn</span>.<span class="pl-en">readNetFromONNX</span>(<span class="pl-s1">onnx_path</span> )</pre></div>
<p dir="auto">I want to know how to call the custom operator in dnn module?</p>