我正尝试规范化一个简单的numpy数组a
,如下所示:
a = np.ones((3,3))
cv2.normalize(a)
运行此命令时,OpenCV会引发错误,提示TypeError: Required argument 'dst' (pos 2) not found
。因此,我将documentation中也提到过的dst
参数作为参数。这是我的做法:
b = np.asarray([])
cv2.normalize(a, b)
此调用返回归一化的数组,但是b
的值仍为空。为什么会这样呢?
另一方面,如果我尝试以下操作:
b = np.copy(a)
cv2.normalize(a,b)
b
中的值现在已填充标准化值。我只是想了解OpenCV的这种行为。当空白为{/ {1}}时,为什么不填充b
?为什么OpenCV不会引发错误?
答案 0 :(得分:2)
在第一个示例中,您需要将cv2.normalize
的结果分配回一个变量。在the docs中,cv2.normalize()
的签名为:
dst = cv.normalize(src, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]])
您会注意到dst
既是函数的输入值也是返回值。这意味着您可以在函数中输入一个dst
数组,并且将对其进行原地修改或,您可以为此传递None
或空白数组参数,当调用函数时,将创建并返回一个新数组。
更具体地说,如果您对C ++不太熟悉:在C ++中,通常只返回基元(例如整数)或函数指针。它不像Python那样简单,在Python中,您可以只返回任意数量的所需对象。例如,您必须将它们填充到容器中并返回指向该容器的指针。因此,更常见的事情是您将对象直接传递给函数,而函数将只修改对象而不用担心返回和所有这些废话。此外,这意味着该函数不会在您不知道的场景后面创建对象。相反, you 控制对象的创建和实例化,然后将它们传递给函数。
在Python中将可变参数传递给函数并了解它们将被修改的情况要少得多(尽管仍然可能)。
由于OpenCV的绑定是从C ++库自动生成的,因此这些函数可以通过以下两种方式之一使用:您可以初始化一个大小/形状正确的数组,将其传递并进行突变(标准C ++方式),可以使用或传递None
或空白数组,而是返回输出数组(标准Python方式)。
这实际上在整个OpenCV库中非常普遍。如果您看到与输入之一相同的输入,并且不需要使用它来初始化函数,则基本上可以始终为该参数发送None
。
我不确定为什么的哲学原因,如果您在此处传递完全伪造的数组,OpenCV选择不抛出错误,尽管这种类型的问题实际上并不是一个很好的格式现场。另外,错误在OpenCV中不是很一致,在错误中对函数参数检查的断言非常严格,但是如果您尝试读取不存在的图像,则会很高兴返回空指针。无论如何,对于错误形状/类型的情况最终会发生的事情仅仅是忽略该参数。如果参数是正确的形状/类型,则仅对其进行更改。您可以想象发生这种情况的情况:
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组合时:
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]])