在将 'dst' 的值保持为空数组的同时进行标准化 [英] Normalizing while keeping the value of 'dst' as an empty array

查看:50
本文介绍了在将 'dst' 的值保持为空数组的同时进行标准化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图规范化一个简单的 numpy 数组 a 如下:

I was trying to normalize a simple numpy array a as follows:

a = np.ones((3,3))

cv2.normalize(a)

在运行时,OpenCV 会抛出一个错误,指出 TypeError: Required argument 'dst' (pos 2) not found.所以我把 dst 参数也放在 文档.我是这样做的:

On running this, OpenCV throws an error saying TypeError: Required argument 'dst' (pos 2) not found. So I put the dst argument as also mentioned in the documentation. Here is how I did:

b = np.asarray([])
cv2.normalize(a, b)

此调用返回规范化数组,但 b 的值仍为空.为什么会这样?

This call returns the normalized array but the value of b is still empty. Why is it so?

另一方面,如果我尝试以下操作:

On the other hand, if I try the following:

b = np.copy(a)

cv2.normalize(a,b)

b 中的值现在填充了规范化的值.我只是想了解 OpenCV 的这种行为.b 为空/形状与a 不一样时,为什么不填充?为什么 OpenCV 不抛出错误?

The values in b are now filled with normalized values. I just wanted to understand this behaviour of OpenCV. Why does it not fill b when it is empty / shape is not the same as a? Why doesn't OpenCV throw an error?

推荐答案

在第一个示例中,您需要将 cv2.normalize 的结果分配回变量.来自 文档cv2 的签名.normalize() 是:

You would need to assign the result of cv2.normalize back to a variable, in the first example. From the docs, the signature for cv2.normalize() is:

dst = cv.normalize(src, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]])

您会注意到 dst 既是函数的输入值,又是函数的返回值.这意味着你可以在函数中输入一个 dst 数组,它会被就地修改,或者,你可以通过 None或调用函数时该参数的空白数组,将创建并返回一个新数组.

You'll notice that dst is both an input and return value from the function. This means that you can either input a dst array into the function, and it will be modified in-place, or, you can pass None or a blank array for that argument when calling the function, and a new array will be created and returned.

更具体地说,如果您对 C++ 不是很熟悉:在 C++ 中,您通常只从函数返回原语(例如整数)或指针.它不像 Python 那样简单,你可以只返回任意数量的任何你想要的对象;例如,您必须将它们塞入容器并返回指向该容器的指针.所以,更常见的是你直接将对象传递给函数,函数只会修改对象,而不用担心返回和所有这些废话.此外,这意味着该函数不会在幕后创建您不知道的对象.相反,控制对象的创建和实例化,并将它们传递给函数.

To be a little more specific, if you're not very familiar with C++: in C++, you generally only return primitives (e.g. integers) or pointers from functions. It's not as easy like Python where you can just return any number of whatever objects you want; you have to stuff them into a container and return a pointer to that container, for example. So, the more common thing is for you to pass the object to the function directly, and the function will just modify the object instead of worrying about returns and all this nonsense. Furthermore, this means that the function isn't creating objects behind the scenes that you don't know about. Instead you control object creation and instantiation, and you pass them into the function.

在 Python 中将可变参数传递给函数并理解它们将被修改的情况要少得多(尽管仍然可能).

It is much less common (though still possible) in Python to pass mutable arguments into functions with the understanding that they will be modified.

由于 OpenCV 的绑定是从 C++ 库自动生成的,因此这些函数可以以任何一种方式使用;您可以初始化一个大小/形状正确的数组,将其传入,然后对其进行变异(标准 C++ 方式),您可以传入 None 或一个空白数组,它会返回输出数组(标准 Python 方式).

Since the bindings for OpenCV are automatically generated from the C++ libraries, the functions have the ability to be used in either of these ways; you can initialize an array of the right size/shape, pass it in, and have it be mutated (the standard C++ way), or you can pass in None or a blank array, and it will instead return the output array (the standard Python way).

这实际上在整个 OpenCV 库中都很常见.如果您看到与输出之一相同的输入并且不需要使用它来初始化函数,则基本上可以始终为该参数发送 None.

This is actually very common all throughout the OpenCV library. If you see the same input as one of the outputs and you don't need to use it to initialize the function, you can basically always send None for that argument.

我不确定 为什么 OpenCV 选择不抛出错误的哲学原因,如果你在那里传入完全虚假的数组,尽管这种类型的问题并不是一个很好的格式地点.此外,OpenCV 中的错误不是很一致,它们对函数参数检查的断言非常严格,但如果您尝试读取不存在的图像,则会很乐意返回空指针.无论如何,对于错误形状/类型的情况,最终会发生的事情只是参数被忽略.只有当它是正确的形状/类型时,参数才会发生变化.你可以想象类似这样的事情正在发生:

I'm not sure the philosophical reason of why OpenCV chooses to not throw an error if you pass in totally bogus arrays there, though that type of question isn't really a good format for this site. Additionally, errors are not very consistent in OpenCV, where they are extremely strict on assertions for function argument checking, but will happily return a null pointer if you try and read an image that doesn't exist. Anyways, what ends up happening for the cases of the wrong shape/type is simply that the argument is ignored. The argument is only mutated if it's the correct shape/type. You can imagine the equivalent of something like this happening:

In [29]: a = np.eye(3, dtype=np.float64)

In [30]: b = np.eye(3, dtype=np.uint8)  # different dtype

In [31]: c = np.eye(2)  # different shape

In [32]: d = 'asdf'  # not even an array

In [33]: cv2.normalize(a, b)
Out[33]:
array([[0.57735027, 0.        , 0.        ],
       [0.        , 0.57735027, 0.        ],
       [0.        , 0.        , 0.57735027]])

In [34]: b  # not modified because different dtype
Out[34]:
array([[1, 0, 0],
       [0, 1, 0],
       [0, 0, 1]], dtype=uint8)

In [35]: cv2.normalize(a, c)
Out[35]:
array([[0.57735027, 0.        , 0.        ],
       [0.        , 0.57735027, 0.        ],
       [0.        , 0.        , 0.57735027]])

In [36]: c  # not modified because different shape
Out[36]:
array([[1., 0.],
       [0., 1.]])

In [37]: cv2.normalize(a, d)  # error because it's not convertible to a `cv::UMat`
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-37-642f9bb78a6b> in <module>
----> 1 cv2.normalize(a, d)

TypeError: Expected cv::UMat for argument 'dst'

但是当我们拥有正确的 shape 和 dtype 组合时:

But when we have the right combination of shape and dtype:

In [38]: e = np.empty_like(a)   # same dtype/shape as a

In [39]: cv2.normalize(a, e)
Out[39]:
array([[0.57735027, 0.        , 0.        ],
       [0.        , 0.57735027, 0.        ],
       [0.        , 0.        , 0.57735027]])

In [40]: e  # mutated
Out[40]:
array([[0.57735027, 0.        , 0.        ],
       [0.        , 0.57735027, 0.        ],
       [0.        , 0.        , 0.57735027]])

这篇关于在将 'dst' 的值保持为空数组的同时进行标准化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆