Image2BlobParams C++ and python

My code in python :

paramTF2cedn = cv.dnn.Image2BlobParams()
paramTF2cedn.datalayout = cv.dnn.DNN_LAYOUT_NHWC;
paramTF2cedn.ddepth = cv.CV_32F;
paramTF2cedn.mean = (128, 128, 128)
paramTF2cedn.scalefactor = 1 / 128.
paramTF2cedn.size = (224, 224)
paramTF2cedn.swapRB = False;
paramTF2cedn.paddingmode = cv.dnn.DNN_PMODE_NULL
print("paramTF2cedn.scalefactor = ", paramTF2cedn.scalefactor)

result is
paramTF2cedn.scalefactor = (0.0078125, 1.0, 1.0, 1.0)

in C++

    Image2BlobParams paramTF2cedn;
    paramTF2cedn.datalayout = DNN_LAYOUT_NHWC;
    paramTF2cedn.ddepth = CV_32F;
    paramTF2cedn.mean = (128, 128, 128);
    paramTF2cedn.scalefactor = 1 / 128.;
    paramTF2cedn.size = Size(224, 224);
    paramTF2cedn.swapRB = false;
    paramTF2cedn.paddingmode = DNN_PMODE_NULL;
    cout << "paramTF2cedn.scalefactor = " << paramTF2cedn.scalefactor << endl;

result is

paramTF2cedn.scalefactor = [0.0078125, 0, 0, 0]

Is it really what it is expected?
@dkurt

in c++, 1/128 will indeed only init the 1st Scalar component
(known, very old discussion …)

we should use :

paramTF2cedn.scalefactor = Scalar::all(1 / 128.);

in docs / samples

Why not?
but in python why a scalar x becomes (x, 1, 1, 1)? Inference is wrong after.

blob.shape
(1, 224, 224, 3)
blob[0,:,:,0].max()
0.890625
blob[0,:,:,1].max()
119.0
blob[0,:,:,2].max()
120.0

I undestand C++ result but in python why add extra 1 ? it should be 0

z = complex(1,2)
z=(1+2j)
z=complex(1)
z=(1+0j) and not (1+1j)

Hi laurent,

why a scalar x becomes (x, 1, 1, 1)?

This should be a bug. If you set the paramTF2cedn.scalefactor = 1 / 128.; The correct should be [1/128, 0, 0, 0];

I just double check of it, and I suspect that the Python bing convert Scalar(1/128) to Scaral(1/128, 1.0, 1.0, 1.0) to C++. Maybe this is a mismatch in Python-C++ Binding.

Hi Guys,
I think I got it.
Image2BlobParams has defaul constructor.
Image2BlobParams::Image2BlobParams():scalefactor(Scalar::all(1.0)), size(Size()), mean(Scalar()), swapRB(false), ddepth(CV_32F),
datalayout(DNN_LAYOUT_NCHW), paddingmode(DNN_PMODE_NULL)
https://github1s.com/opencv/opencv/blob/HEAD/modules/dnn/src/dnn_utils.cpp#L14-L15
It will set the default scalefactor as [1.0, 1.0, 1.0, 1.0].
For Python, theparamTF2cedn.scalefactor = 1 / 128. will only repleace the first 1.0 to 1 / 128.
Do something like paramTF2cedn.scalefactor[0] = 1 / 128.
For C++, it will do the paramTF2cedn.scalefactor = Scalar(1/128).
For Python.

1 Like

May be you should try with your python version :

p = cv.dnn.Image2BlobParams()
p.mean = 12
p.scalefactor = 11
p.mean
(12.0, 0.0, 0.0, 0.0)
p.scalefactor
(11.0, 1.0, 1.0, 1.0)

I cannot found python online with a 4.7 version
May be my python binding is bugged

Your can use opencv-rolling,
pip install opencv-python-rolling==4.7.0.20230603

May be you should try with your python version :slight_smile:

Yes, this issue does exist.

You are right difference is here

p = cv.dnn.Image2BlobParams(1/128.0)
p.scalefactor
(0.0078125, 0.0, 0.0, 0.0)

I just test it with the following python code:

param = cv.dnn.Image2BlobParams()
param.mean = np.array([0.2, 0.3, 0.4]) # [0.2, 0.3, 0.4, 0.0]
# then redefine it.
param.mean = 1.0 # it is [1.0, 0.3, 0.4, 0.0]  <<--
1 Like

Hi laurent.berger

I have create issue for it, and look forward any reply,

1 Like