<h3 dir="auto">System Information</h3>
<p dir="auto">OpenCV version: 4.7 release<br>
OpenCV Python version: 4.7.0.68<br>
OS: macOS 13.0.1<br>
Python version: 3.9.6<br>
Compiler: Apple clang version 14.0.0 (clang-1400.0.29.202)</p>
<h3 dir="auto">Detailed description</h3>
<p dir="auto">I made two attention models of ONNX format. They have the same structure and the only difference is input shape:</p>
<ul dir="auto">
<li>
<p dir="auto">One is [1, 197, 768], the original shape from a vision transformer; Click to download <a href="https://github.com/opencv/opencv/files/10719607/multi_head_attention.onnx.zip">multi_head_attention.onnx.zip</a>.</p>
</li>
<li>
<p dir="auto">The other one is [1, 5, 12], a shrinked shape for debugging and stuff. Click to download <a href="https://github.com/opencv/opencv/files/10719613/multi_head_attention.onnx.zip">multi_head_attention.onnx.zip</a>.</p>
</li>
</ul>
<p dir="auto">I found if using Python interfaces with the correct shape set, the one of input shape [1, 197, 768] can run successfully, but the other one of input shape [1, 5, 12] fails:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="[ERROR:0@110.035] global net_impl.cpp:1164 getLayerShapesRecursively OPENCV/DNN: [Permute]:(onnx_node_output_0!Transpose.0.out): getMemoryShapes() throws exception. inputs=1 outputs=0/1 blobs=0
[ERROR:0@110.035] global net_impl.cpp:1167 getLayerShapesRecursively     input[0] = [ 1 5 ]
[ERROR:0@110.035] global net_impl.cpp:1177 getLayerShapesRecursively Exception message: OpenCV(4.7.0) /Users/opencv-cn/GHA-OCV-1/_work/opencv-python/opencv-python/opencv/modules/dnn/src/layers/permute_layer.cpp:163: error: (-215:Assertion failed) (int)_numAxes == inputs[0].size() in function 'getMemoryShapes'

Traceback (most recent call last):
  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
cv2.error: OpenCV(4.7.0) /Users/opencv-cn/GHA-OCV-1/_work/opencv-python/opencv-python/opencv/modules/dnn/src/layers/permute_layer.cpp:163: error: (-215:Assertion failed) (int)_numAxes == inputs[0].size() in function 'getMemoryShapes'"><pre class="notranslate"><code class="notranslate">[ERROR:0@110.035] global net_impl.cpp:1164 getLayerShapesRecursively OPENCV/DNN: [Permute]:(onnx_node_output_0!Transpose.0.out): getMemoryShapes() throws exception. inputs=1 outputs=0/1 blobs=0
[ERROR:0@110.035] global net_impl.cpp:1167 getLayerShapesRecursively     input[0] = [ 1 5 ]
[ERROR:0@110.035] global net_impl.cpp:1177 getLayerShapesRecursively Exception message: OpenCV(4.7.0) /Users/opencv-cn/GHA-OCV-1/_work/opencv-python/opencv-python/opencv/modules/dnn/src/layers/permute_layer.cpp:163: error: (-215:Assertion failed) (int)_numAxes == inputs[0].size() in function 'getMemoryShapes'

Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
cv2.error: OpenCV(4.7.0) /Users/opencv-cn/GHA-OCV-1/_work/opencv-python/opencv-python/opencv/modules/dnn/src/layers/permute_layer.cpp:163: error: (-215:Assertion failed) (int)_numAxes == inputs[0].size() in function 'getMemoryShapes'
</code></pre></div>
<p dir="auto">But if I try to debug in C++, for example adding test cases in <code class="notranslate">test_onnx_importer.cpp</code>, they all pass. <strong>So I guess there is something wrong with the python interface</strong>. Reproducers are attached below.</p>
<h3 dir="auto">Steps to reproduce</h3>
<p dir="auto">Python:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import numpy as np
import cv2 as cv

# This passes!
net = cv.dnn.readNet(&quot;original_scale/models/multi_head_attention.onnx&quot;)
x = np.random.rand(1, 197, 768).astype(np.float32)
net.setInput(x)
net.forward()

# This fails!
net = cv.dnn.readNet(&quot;scale_1_5_12/models/multi_head_attention.onnx&quot;)
x = np.random.rand(1, 5, 12).astype(np.float32)
net.setInput(x)
net.forward()"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</span>
<span class="pl-k">import</span> <span class="pl-s1">cv2</span> <span class="pl-k">as</span> <span class="pl-s1">cv</span>

<span class="pl-c"># This passes!</span>
<span class="pl-s1">net</span> <span class="pl-c1">=</span> <span class="pl-s1">cv</span>.<span class="pl-s1">dnn</span>.<span class="pl-en">readNet</span>(<span class="pl-s">"original_scale/models/multi_head_attention.onnx"</span>)
<span class="pl-s1">x</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-s1">random</span>.<span class="pl-en">rand</span>(<span class="pl-c1">1</span>, <span class="pl-c1">197</span>, <span class="pl-c1">768</span>).<span class="pl-en">astype</span>(<span class="pl-s1">np</span>.<span class="pl-s1">float32</span>)
<span class="pl-s1">net</span>.<span class="pl-en">setInput</span>(<span class="pl-s1">x</span>)
<span class="pl-s1">net</span>.<span class="pl-en">forward</span>()

<span class="pl-c"># This fails!</span>
<span class="pl-s1">net</span> <span class="pl-c1">=</span> <span class="pl-s1">cv</span>.<span class="pl-s1">dnn</span>.<span class="pl-en">readNet</span>(<span class="pl-s">"scale_1_5_12/models/multi_head_attention.onnx"</span>)
<span class="pl-s1">x</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-s1">random</span>.<span class="pl-en">rand</span>(<span class="pl-c1">1</span>, <span class="pl-c1">5</span>, <span class="pl-c1">12</span>).<span class="pl-en">astype</span>(<span class="pl-s1">np</span>.<span class="pl-s1">float32</span>)
<span class="pl-s1">net</span>.<span class="pl-en">setInput</span>(<span class="pl-s1">x</span>)
<span class="pl-s1">net</span>.<span class="pl-en">forward</span>()</pre></div>
<p dir="auto">C++: Add the following test cases in <code class="notranslate">test_onnx_importer.cpp</code></p>
<div class="highlight highlight-source-c++ notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="TEST_P(Test_ONNX_layers, MHA_ORIG)
{
    Net net = readNet(findDataFile(&quot;original_scale/models/multi_head_attention.onnx&quot;, true));

    std::vector&lt;int&gt; blob_shape{1, 197, 768};
    Mat blob(blob_shape, CV_32FC1);
    randn(blob, 1.f, 0.f);

    net.setInput(blob);
    net.forward();
}

TEST_P(Test_ONNX_layers, MHA_SMALL_SCALE)
{
    Net net = readNet(findDataFile(&quot;scale_1_5_12/models/multi_head_attention.onnx&quot;, true));

    std::vector&lt;int&gt; blob_shape{1, 5, 12};
    Mat blob(blob_shape, CV_32FC1);
    randn(blob, 1.f, 0.f);

    net.setInput(blob);
    net.forward();
}"><pre class="notranslate"><span class="pl-en">TEST_P</span>(Test_ONNX_layers, MHA_ORIG)
{
    Net net = <span class="pl-c1">readNet</span>(<span class="pl-c1">findDataFile</span>(<span class="pl-s"><span class="pl-pds">"</span>original_scale/models/multi_head_attention.onnx<span class="pl-pds">"</span></span>, <span class="pl-c1">true</span>));

    std::vector&lt;<span class="pl-k">int</span>&gt; blob_shape{<span class="pl-c1">1</span>, <span class="pl-c1">197</span>, <span class="pl-c1">768</span>};
    Mat <span class="pl-smi">blob</span>(blob_shape, CV_32FC1);
    <span class="pl-c1">randn</span>(blob, <span class="pl-c1">1</span>.<span class="pl-smi">f</span>, <span class="pl-c1">0</span>.<span class="pl-smi">f</span>);

    net.<span class="pl-c1">setInput</span>(blob);
    net.<span class="pl-c1">forward</span>();
}

<span class="pl-en">TEST_P</span>(Test_ONNX_layers, MHA_SMALL_SCALE)
{
    Net net = <span class="pl-c1">readNet</span>(<span class="pl-c1">findDataFile</span>(<span class="pl-s"><span class="pl-pds">"</span>scale_1_5_12/models/multi_head_attention.onnx<span class="pl-pds">"</span></span>, <span class="pl-c1">true</span>));

    std::vector&lt;<span class="pl-k">int</span>&gt; blob_shape{<span class="pl-c1">1</span>, <span class="pl-c1">5</span>, <span class="pl-c1">12</span>};
    Mat <span class="pl-smi">blob</span>(blob_shape, CV_32FC1);
    <span class="pl-c1">randn</span>(blob, <span class="pl-c1">1</span>.<span class="pl-smi">f</span>, <span class="pl-c1">0</span>.<span class="pl-smi">f</span>);

    net.<span class="pl-c1">setInput</span>(blob);
    net.<span class="pl-c1">forward</span>();
}</pre></div>
<h3 dir="auto">Issue submission checklist</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I report the issue, it's not a question</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I checked the problem with documentation, FAQ, open issues, forum.opencv.org, Stack Overflow, etc and have not found any solution</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I updated to the latest OpenCV version and the issue is still there</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> There is reproducer code and related data files (videos, images, onnx, etc)</li>
</ul>
<p dir="auto">Currently OpenCV Python bindings "automatically" converts 3D NumPy arrays into 2D <code class="notranslate">cv::Mat</code> with wrapping last dimension onto number of channels (to simulate <code class="notranslate">Image</code> with colors):</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="a = np.zeros((2,3,4), dtype='f')
print(a.shape)
info = cv.utils.dumpInputArray(a)
print(info)"><pre class="notranslate"><code class="notranslate">a = np.zeros((2,3,4), dtype='f')
print(a.shape)
info = cv.utils.dumpInputArray(a)
print(info)
</code></pre></div>
<p dir="auto">output:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="(2, 3, 4)
InputArray: empty()=false kind=0x00010000 flags=0x01010000 total(-1)=6 dims(-1)=2 size(-1)=3x2 type(-1)=CV_32FC4"><pre class="notranslate"><code class="notranslate">(2, 3, 4)
InputArray: empty()=false kind=0x00010000 flags=0x01010000 total(-1)=6 dims(-1)=2 size(-1)=3x2 type(-1)=CV_32FC4
</code></pre></div>
<hr>
<p dir="auto">Related code is <a href="https://github.com/opencv/opencv/blame/dd1494eebf205b0262c362bbdc57cef212464d1d/modules/python/src2/cv2.cpp#L507">here</a> (previous variant of similar code is <a href="https://github.com/opencv/opencv/blame/a717b7cbedd50b129428d72b2a15ab0168a4c46c/modules/python/src2/cv2.cpp#L262">here</a> from 2010). By initial design there is support for 2D matrices and 1D arrays only.</p>
<p dir="auto">So currently there is no way to pass 3D <code class="notranslate">cv::Mat</code> (1-channel) from Python to C++ code.</p>
<p dir="auto">Just changing of mentioned code is not an option due to breaking of many user applications.<br>
Compatibility should be preserved.</p>
<p dir="auto"><strong>Note</strong>: There is such issue in Java because Java's <code class="notranslate">Mat</code> type is used.<br>
Python's bindings relies on <code class="notranslate">np.array</code> type which leads to mentioned reinterpretation issues.</p>
<hr>
<p dir="auto">relates <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="616851584" data-permission-text="Title is private" data-url="https://github.com/opencv/opencv/issues/17272" data-hovercard-type="issue" data-hovercard-url="/opencv/opencv/issues/17272/hovercard" href="https://github.com/opencv/opencv/issues/17272">#17272</a><br>
relates <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="756166051" data-permission-text="Title is private" data-url="https://github.com/opencv/opencv/issues/19001" data-hovercard-type="issue" data-hovercard-url="/opencv/opencv/issues/19001/hovercard" href="https://github.com/opencv/opencv/issues/19001">#19001</a><br>
probably relates <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="708334893" data-permission-text="Title is private" data-url="https://github.com/opencv/opencv/issues/18413" data-hovercard-type="issue" data-hovercard-url="/opencv/opencv/issues/18413/hovercard" href="https://github.com/opencv/opencv/issues/18413">#18413</a> <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="629320425" data-permission-text="Title is private" data-url="https://github.com/opencv/opencv/issues/17456" data-hovercard-type="issue" data-hovercard-url="/opencv/opencv/issues/17456/hovercard" href="https://github.com/opencv/opencv/issues/17456">#17456</a></p>