OpenCV DNN changing my input dimension

I’m loading a ONNX model using OpenCV DNN, after converting it from TensorFlow. This model has the input layer dimension as [?, 30, 30, 3]. Can be visualized using neutron:

enter image description here
But after loading in OpenCV DNN my InputLayer has the dimensions [1 30 3 30]. Why?

...
cv::dnn::Net modelPB = cv::dnn::readNetFromONNX("modelPB.onnx");

cv::Mat input(30, 30, CV_32FC3, cv::Scalar(0, 0, 0)); // 30x30 matrix with 3 channels

// fill cv::Mat input with the data
// ...

cv::Mat blobPB = cv::dnn::blobFromImage(input, 1.0 / 255, cv::Size2i::Size_(30, 30), 0.0, false, false, CV_32F);
// input blob has the dimensions [ 1 x 3 x 30 x 30]

auto output = modelPB.forward(); <-
...

I don’t understand why my model has the wrong input dimensions after loading by OpenCV DNN and using this correct cv::Mat input as blob.

Exception: 
OpenCV(4.7.0-dev) Error: Assertion failed (ngroups > 0 && inpCn % ngroups == 0 && outCn % ngroups == 0)
in cv::dnn::ConvolutionLayerImpl::getMemoryShapes,
 file C:\opencv\opencv-4.x\modules\dnn\src\layers\convolution_layer.cpp, line 421

enter image description here

looks like unfortunate conversion between NCHW and NWHC.

something interpreted (-1, 30, 30, 3) as NCHW (C=30, H=30, W=3) and turned it into NHWC (H=30, W=3, C=30)

first is probably a typo ? in the end, it’s [ 1 x 3 x 30 x 30] , right ?

blobFromImage() splits interleaved pixel images into seperate color planes. if this is wrong for your network, you can still try to avoid that and make your own blob (just wrap a 4d Mat around your (float) image):

int sz[] = {1,30,30,3}; //orig dimension, batch extended
Mat blob(sz, 4, CV_32F, image.ptr(0));

on the other hand, a close look at your graph shows a ‘transpose’ node before the 1st conv layer, and it looks, as if it is changing to NCHW there anyway, please check & report back !

A typo ? I don’t think so
I use TF2 to train a model and use
python -m tf2onnx.convert --saved-model my_model --output my_model.onnx --opset 11
to convert tf2 model onnx (opencv does not like TF2 model)
May be as you?

[DEBUG:0@0.049] global system.cpp:2842 cv::details::setFPDenormalsIgnoreHint core: update FP mxcsr flags = 0x00009fe0
[DEBUG:0@0.049] global onnx_importer.cpp:269 cv::dnn::dnn4_v20221220::ONNXImporter::ONNXImporter DNN/ONNX: processing ONNX model from file: C:/tmp/model2b.onnx
[ INFO:0@0.257] global onnx_importer.cpp:835 cv::dnn::dnn4_v20221220::ONNXImporter::populateNet DNN/ONNX: loading ONNX v8 model produced by 'tf2onnx':1.14.0 8f8d49. Number of nodes = 54, initializers = 45, inputs = 1, outputs = 1
[DEBUG:0@0.257] global onnx_importer.cpp:723 cv::dnn::dnn4_v20221220::ONNXImporter::parseOperatorSet DNN/ONNX: using non-standard ONNX opset[1]: domain='ai.onnx.ml' version=2
[DEBUG:0@0.258] global onnx_importer.cpp:723 cv::dnn::dnn4_v20221220::ONNXImporter::parseOperatorSet DNN/ONNX: using non-standard ONNX opset[2]: domain='ai.onnx.contrib' version=1
[ INFO:0@0.258] global onnx_importer.cpp:728 cv::dnn::dnn4_v20221220::ONNXImporter::parseOperatorSet DNN/ONNX: ONNX opset version = 15
[ INFO:0@0.258] global onnx_importer.cpp:743 cv::dnn::dnn4_v20221220::ONNXImporter::parseOperatorSet DNN/ONNX: unknown domain='ai.onnx.contrib' version=15. No dispatch map, you may need to register 'custom' layers.
[ INFO:0@0.258] global onnx_importer.cpp:743 cv::dnn::dnn4_v20221220::ONNXImporter::parseOperatorSet DNN/ONNX: unknown domain='ai.onnx.ml' version=15. No dispatch map, you may need to register 'custom' layers.
[DEBUG:0@0.264] global onnx_importer.cpp:842 cv::dnn::dnn4_v20221220::ONNXImporter::populateNet DNN/ONNX: graph simplified to 54 nodes
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[0 as 'scales__176'] shape=[ 4 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[1 as 'roi__163'] shape=[ 0 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[2 as 'new_shape__187'] shape=[ 4 ] data_type=7
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[3 as 'Func/StatefulPartitionedCall/input/_9__34'] shape=[ 256 128 3 3 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[4 as 'Func/StatefulPartitionedCall/input/_8__33'] shape=[ 128 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[5 as 'Func/StatefulPartitionedCall/input/_7__31'] shape=[ 128 128 3 3 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[6 as 'Func/StatefulPartitionedCall/input/_6__27'] shape=[ 128 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[7 as 'Func/StatefulPartitionedCall/input/_5__23'] shape=[ 128 64 3 3 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[8 as 'Func/StatefulPartitionedCall/input/_4__32'] shape=[ 64 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[9 as 'Func/StatefulPartitionedCall/input/_42__18'] shape=[ 1 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[10 as 'Func/StatefulPartitionedCall/input/_41__12'] shape=[ 1 32 5 5 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[11 as 'Func/StatefulPartitionedCall/input/_40__28'] shape=[ 32 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[12 as 'Func/StatefulPartitionedCall/input/_3__41'] shape=[ 64 64 3 3 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[13 as 'Func/StatefulPartitionedCall/input/_39__30'] shape=[ 32 64 5 5 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[14 as 'Func/StatefulPartitionedCall/input/_38__26'] shape=[ 64 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[15 as 'Func/StatefulPartitionedCall/input/_37__22'] shape=[ 64 128 5 5 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[16 as 'Func/StatefulPartitionedCall/input/_36__17'] shape=[ 128 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[17 as 'Func/StatefulPartitionedCall/input/_35__11'] shape=[ 128 256 5 5 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[18 as 'Func/StatefulPartitionedCall/input/_34__6'] shape=[ 256 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[19 as 'Func/StatefulPartitionedCall/input/_33__25'] shape=[ 256 512 5 5 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[20 as 'Func/StatefulPartitionedCall/input/_32__21'] shape=[ 512 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[21 as 'Func/StatefulPartitionedCall/input/_31__16'] shape=[ 512 512 5 5 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[22 as 'Func/StatefulPartitionedCall/input/_30__44'] shape=[ 512 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[23 as 'Func/StatefulPartitionedCall/input/_2__9'] shape=[ 64 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[24 as 'Func/StatefulPartitionedCall/input/_29__39'] shape=[ 512 4096 1 1 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[25 as 'Func/StatefulPartitionedCall/input/_28__10'] shape=[ 4096 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[26 as 'Func/StatefulPartitionedCall/input/_27__47'] shape=[ 4096 512 3 3 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[27 as 'Func/StatefulPartitionedCall/input/_26__43'] shape=[ 512 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[28 as 'Func/StatefulPartitionedCall/input/_25__37'] shape=[ 512 512 3 3 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[29 as 'Func/StatefulPartitionedCall/input/_24__46'] shape=[ 512 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[30 as 'Func/StatefulPartitionedCall/input/_23__40'] shape=[ 512 512 3 3 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[31 as 'Func/StatefulPartitionedCall/input/_22__38'] shape=[ 512 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[32 as 'Func/StatefulPartitionedCall/input/_21__20'] shape=[ 512 512 3 3 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[33 as 'Func/StatefulPartitionedCall/input/_20__15'] shape=[ 512 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[34 as 'Func/StatefulPartitionedCall/input/_1__7'] shape=[ 64 3 3 3 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[35 as 'Func/StatefulPartitionedCall/input/_19__36'] shape=[ 512 512 3 3 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[36 as 'Func/StatefulPartitionedCall/input/_18__8'] shape=[ 512 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[37 as 'Func/StatefulPartitionedCall/input/_17__24'] shape=[ 512 512 3 3 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[38 as 'Func/StatefulPartitionedCall/input/_16__45'] shape=[ 512 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[39 as 'Func/StatefulPartitionedCall/input/_15__42'] shape=[ 512 256 3 3 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[40 as 'Func/StatefulPartitionedCall/input/_14__29'] shape=[ 256 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[41 as 'Func/StatefulPartitionedCall/input/_13__19'] shape=[ 256 256 3 3 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[42 as 'Func/StatefulPartitionedCall/input/_12__14'] shape=[ 256 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[43 as 'Func/StatefulPartitionedCall/input/_11__35'] shape=[ 256 256 3 3 ] data_type=1
global onnx_importer.cpp:365 cv::dnn::dnn4_v20221220::dumpTensorProto DNN/ONNX: initializer[44 as 'Func/StatefulPartitionedCall/input/_10__13'] shape=[ 256 ] data_type=1
[DEBUG:0@0.328] global onnx_importer.cpp:867 cv::dnn::dnn4_v20221220::ONNXImporter::populateNet DNN/ONNX: input[0] dim[0] = <unk__188> (dynamic)
[DEBUG:0@0.328] global onnx_importer.cpp:882 cv::dnn::dnn4_v20221220::ONNXImporter::populateNet DNN/ONNX: input[0 as 'args_0:0'] shape=[ 0 224 224 3 ]
[DEBUG:0@0.328] global onnx_importer.cpp:340 cv::dnn::dnn4_v20221220::dumpValueInfoProto DNN/ONNX: output[0] dim[0] = <unk__189> (dynamic)
[DEBUG:0@0.328] global onnx_importer.cpp:349 cv::dnn::dnn4_v20221220::dumpValueInfoProto DNN/ONNX: output[0 as 'Identity:0'] shape=[ 0 224 224 1 ]
[ INFO:0@0.329] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Transpose]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv1a/BiasAdd__53) from domain='ai.onnx'
[ INFO:0@0.329] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv1a/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.329] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv1a/Relu) from domain='ai.onnx'
[ INFO:0@0.330] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv1b/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.330] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv1b/Relu) from domain='ai.onnx'
[ INFO:0@0.330] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [MaxPool]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/mpconv1/MaxPool) from domain='ai.onnx'
[ INFO:0@0.330] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv2a/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.330] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv2a/Relu) from domain='ai.onnx'
[ INFO:0@0.330] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv2b/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.330] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv2b/Relu) from domain='ai.onnx'
[ INFO:0@0.331] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [MaxPool]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/mpconv2/MaxPool) from domain='ai.onnx'
[ INFO:0@0.331] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv3a/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.331] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv3a/Relu) from domain='ai.onnx'
[ INFO:0@0.331] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv3b/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.331] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv3b/Relu) from domain='ai.onnx'
[ INFO:0@0.331] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv3c/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.331] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv3c/Relu) from domain='ai.onnx'
[ INFO:0@0.332] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [MaxPool]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/mpconv3/MaxPool) from domain='ai.onnx'
[ INFO:0@0.332] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv4a/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.332] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv4a/Relu) from domain='ai.onnx'
[ INFO:0@0.332] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv4b/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.332] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv4b/Relu) from domain='ai.onnx'
[ INFO:0@0.332] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv4c/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.333] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv4c/Relu) from domain='ai.onnx'
[ INFO:0@0.333] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [MaxPool]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/mpconv4/MaxPool) from domain='ai.onnx'
[ INFO:0@0.333] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv5a/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.333] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv5a/Relu) from domain='ai.onnx'
[ INFO:0@0.333] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv5b/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.333] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv5b/Relu) from domain='ai.onnx'
[ INFO:0@0.334] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv5c/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.334] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv5c/Relu) from domain='ai.onnx'
[ INFO:0@0.334] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [MaxPool]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/mpconv5/MaxPool) from domain='ai.onnx'
[ INFO:0@0.334] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv6/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.334] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv6/Relu) from domain='ai.onnx'
[ INFO:0@0.334] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/deconv6/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.334] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/deconv6/Relu) from domain='ai.onnx'
[ INFO:0@0.334] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Resize]:(onnx_node!Resize__137) from domain='ai.onnx'
[ INFO:0@0.335] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/deconv5/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.335] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/deconv5/Relu) from domain='ai.onnx'
[ INFO:0@0.335] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Resize]:(onnx_node!Resize__147) from domain='ai.onnx'
[ INFO:0@0.335] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/deconv4/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.335] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/deconv4/Relu) from domain='ai.onnx'
[ INFO:0@0.336] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Resize]:(onnx_node!Resize__157) from domain='ai.onnx'
[ INFO:0@0.336] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/deconv3/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.336] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/deconv3/Relu) from domain='ai.onnx'
[ INFO:0@0.336] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Resize]:(onnx_node!Resize__167) from domain='ai.onnx'
[ INFO:0@0.336] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/deconv2/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.337] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/deconv2/Relu) from domain='ai.onnx'
[ INFO:0@0.337] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Resize]:(onnx_node!Resize__177) from domain='ai.onnx'
[ INFO:0@0.337] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/deconv1/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.337] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Relu]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/deconv1/Relu) from domain='ai.onnx'
[ INFO:0@0.337] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 3 inputs and 1 outputs: [Conv]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/pred/BiasAdd) from domain='ai.onnx'
[ INFO:0@0.337] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 1 inputs and 1 outputs: [Sigmoid]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/pred/Sigmoid) from domain='ai.onnx'
[ INFO:0@0.337] global onnx_importer.cpp:1006 cv::dnn::dnn4_v20221220::ONNXImporter::handleNode DNN/ONNX: processing node with 2 inputs and 1 outputs: [Reshape]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/pred/BiasAdd__185) from domain='ai.onnx'
[DEBUG:0@0.337] global net_impl.cpp:447 cv::dnn::dnn4_v20221220::Net::Impl::registerOutput DNN: register output='Identity:0' id=55 defined as 54:0
[DEBUG:0@0.338] global onnx_importer.cpp:942 cv::dnn::dnn4_v20221220::ONNXImporter::populateNet DNN/ONNX: import completed!
[DEBUG:0@0.356] global system.cpp:2881 cv::details::restoreFPDenormalsState core: restore FP mxcsr flags = 0x00001fa0
[DEBUG:0@0.364] global system.cpp:2842 cv::details::setFPDenormalsIgnoreHint core: update FP mxcsr flags = 0x00009fe0
[DEBUG:0@0.364] global system.cpp:2881 cv::details::restoreFPDenormalsState core: restore FP mxcsr flags = 0x00001fa0
[DEBUG:0@0.365] global system.cpp:2842 cv::details::setFPDenormalsIgnoreHint core: update FP mxcsr flags = 0x00009fe0
OpenCV(4.7.0-dev) Error: Unspecified error (Number of input channels should be multiple of 3 but got 224) in cv::dnn::ConvolutionLayerImpl::getMemoryShapes, file C:\lib\opencv\modules\dnn\src\layers\convolution_layer.cpp, line 417
[ERROR:0@0.365] global net_impl.cpp:1169 cv::dnn::dnn4_v20221220::Net::Impl::getLayerShapesRecursively OPENCV/DNN: [Convolution]:(onnx_node!StatefulPartitionedCall/StatefulPartitionedCall/model/conv1a/BiasAdd): getMemoryShapes() throws exception. inputs=1 outputs=0/1 blobs=2
[ERROR:0@0.365] global net_impl.cpp:1172 cv::dnn::dnn4_v20221220::Net::Impl::getLayerShapesRecursively     input[0] = [ 1 224 3 224 ]
[ERROR:0@0.365] global net_impl.cpp:1180 cv::dnn::dnn4_v20221220::Net::Impl::getLayerShapesRecursively     blobs[0] = CV_32FC1 [ 64 3 3 3 ]
[ERROR:0@0.365] global net_impl.cpp:1180 cv::dnn::dnn4_v20221220::Net::Impl::getLayerShapesRecursively     blobs[1] = CV_32FC1 [ 64 1 ]
[ERROR:0@0.365] global net_impl.cpp:1182 cv::dnn::dnn4_v20221220::Net::Impl::getLayerShapesRecursively Exception message: OpenCV(4.7.0-dev) C:\lib\opencv\modules\dnn\src\layers\convolution_layer.cpp:417: error: (-2:Unspecified error) Number of input channels should be multiple of 3 but got 224 in function 'cv::dnn::ConvolutionLayerImpl::getMemoryShapes'

OpenCV: terminate handler is called! The last OpenCV error is:
OpenCV(4.7.0-dev) Error: Unspecified error (Number of input channels should be multiple of 3 but got 224) in cv::dnn::ConvolutionLayerImpl::getMemoryShapes, file C:\lib\opencv\modules\dnn\src\layers\convolution_layer.cpp, line 417

my code

    Mat img = imread(samples::findFile("building.jpg"));
    Mat my_inp;
    my_inp = dnn::blobFromImage(img, 1.0/256, Size(224, 224),
        (104.00698793, 116.66876762, 122.67891434),
        false, false);

in TF2 code to infer is

input_size=(224, 224)
img = cv.imread(cv.samples.findFile("building.jpg"))
img_net = img[0:input_size[1], 0:input_size[0], :]
img_net = (img_net.astype(np.float32))/256
img_net =  img_net.reshape(1,input_size[0],input_size[1],3)
imf_res = my_net(img_net).numpy()[0,:,:,0]

and
my_net.inputs[0].shape
TensorShape([None, 224, 224, 3])

Mat blob(4, sz, CV_32F, image.ptr(0))

1 Like

Finally I understand nothing…

    my_net = dnn::readNet("C:/tmp/model2b.onnx");
    int sz[] = { 1,224,224, 3 }; //orig dimension, batch extended
    Mat blob(4, sz,  CV_32F, img.ptr(0));
    my_net.setInput(blob);
    if (my_net.empty())
        cout << "Oops";
    Mat my_ouput1 = my_net.forward(), imgOut;
    cv::resize(my_ouput1.reshape(1, 224), imgOut, img.size()); // NO ERROR
    Mat my_inp = dnn::blobFromImage(img, 1.0 / 256, Size(224, 224),
        (104.00698793, 116.66876762, 122.67891434),
        false, false);
    my_net.setInput(my_inp);
    Mat my_ouput2 = my_net.forward(); // [ERROR:0@11.251] global net_impl.cpp:1182 

[ERROR:0@11.251] global net_impl.cpp:1182 cv::dnn::dnn4_v20221220::Net::Impl::getLayerShapesRecursively Exception message: OpenCV(4.7.0-dev) C:\lib\opencv\modules\dnn\src\layers\convolution_layer.cpp:417: error: (-2:Unspecified error) Number of input channels should be multiple of 3 but got 224 in function ‘cv::dnn::ConvolutionLayerImpl::getMemoryShapes’

you have to use blobFromImageWithParams and set datalayout

1 Like

Thanks for all the answers and attention, guys. Kinda strange, I looked at the documentation this function but I don’t have this in my OpenCV version. I’m using OpenCV-4.7-dev and it has only cv::dnn::blobfromImage, cv::dnn::blobfromImages, cv::dnn::imagesfromBlob, cv::dnn::readTorchBlob. By standard, a normal blob from cv::dnn::blobFromImage uses which datalayout? Unknown, NCHW or NHWC? It looks like NCHW because it always moves the channel to the second position of the array, right? Like [1 x 3 x 30 x 30], but someway before the model.forward() and after the cv::dnn::blobFromImage, in somewhere, it may change these dims to my input layer dimension from my model?! (that uses the channel in the last position (NHWC))

indeed, needs latest github master (4.7.0-dev)

again, please explain the “transpose” layer directly following your intended NHWC input :wink:

Hey Berak, sorry for the late answer. I don’t think the “transpose” layer was the problem or how it could be, the Input layer was wrong before passing by the transpose operation and the conv layer dimension was compatible with the expected in netron [128 x 3 x 1 x 1]. I rebuilded my OpenCV version with the latest resources as you suggested and changed the blob as @laurent.berger suggested. It works fine! Thank you so much!

cv::Mat blobPB = cv::dnn::blobFromImage(input, 1.0 / 255, cv::Size2i::Size_(30, 30), 0.0, false, false, CV_32F);

to

cv::dnn::Image2BlobParams params;

params.scalefactor = 1.0 / 255;
params.size = cv::Size2i::Size_(30, 30);
params.mean = 0.0;
params.ddepth = CV_32F;
params.datalayout = cv::dnn::DNN_LAYOUT_NHWC;
params.paddingmode = cv::dnn::DNN_PMODE_NULL;

cv::Mat blobPB;
cv::dnn::blobFromImageWithParams(input, blobPB, params);
2 Likes

Hey Berak, how could I install this version in my Anaconda environment? Is there any opencv-python-rolling for it?