Opencv:ValueError

时间:2016-06-02 06:30:01

标签: python python-2.7 opencv numpy opencv-contour

我检测到轮廓并将它们存储在cnts中,我将逐一访问它们,c_list是我感兴趣的轮廓列表。 我想检查我现在访问的轮廓是否已经使用此代码之前已经被访问过:

if not (np.all(cnts[c] in c_list)):
      while hierarchy[0][k][2] != -1:
        k = hierarchy[0][k][2]
        c_list.append(cnts[k])
        s = s+1

我仍然收到错误

  

ValueError:具有多个元素的数组的真值是不明确的。使用a.any()或a.all()

有人可以纠正我的错误吗?

1 个答案:

答案 0 :(得分:2)

您的问题与OpenCV无关,它来自numpy。

请考虑以下示例:

>>> import numpy as np
>>> [1,3] in [[1,3],[4,5]]
True

>>> np.array([1,3]) in [[1,3],[4,5]]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

你指定的评论(我们可以从OpenCV本身断言,但这个信息应该在你的问题中开始)你所比较的对象可能类似< / p>

c_list = [[[[291, 267]], [[288, 268]], [[289, 267]]]]
cnts = np.array([[[291, 267]], [[288, 268]], [[289, 267]]])
# test for cnts[0] in c_list

问题是numpy.ndarray的索引元素仍然是numpy.ndarray,但正如您在第一个示例中看到的那样,当您尝试使用通常的逻辑运算时,numpy数组的行为会有所不同在他们与本机列表配对。这是有道理的,因为在本机python 中,使用列表值操作数处理in的唯一明显方法是测试第二个列表是否具有等于第一个列表的列表值元素。有了numpy,你经常想对你的数组进行元素测试,这就是同一个表达式导致错误的原因。

现在,解决问题比预期的要复杂得多。目前还不完全清楚你想要实现的目标,并且可能有更合乎逻辑的方法。无论如何,请考虑这些修改过的例子:

>>> [1,3] in [[1,3],[4,5]]
True
>>> [1,3] in [[1,2],[4,5]]
False
>>> np.array([1,3]) in np.array([[1,3],[4,5]])
True
>>> np.array([1,3]) in np.array([[1,2],[4,5]])
True
>>> np.array([1,3]) in np.array([[0,2],[4,5]])
False

两个ndarrays 之间使用in时不会产生错误,但它会以令人惊讶的方式运行:如果有任何True 两个数组之间的共同元素!这显然不是你想要做的。

在我看来,你有两种选择。您可以将所有ndarray转换为列表。我的意思是:

>>> np.array([1,3]).tolist() in np.array([[1,3],[4,5]]).tolist()
True
>>> np.array([1,3]).tolist() in np.array([[1,2],[4,5]]).tolist()
False

这需要您调用c_list.append(cnts[k].tolist())并测试if not (cnts[c].tolist() in c_list):,但将numpy数组转换为本机python列表通常不是一个好主意,这主要是出于内存考虑。如果你的轮廓有很多元素(这取决于你是否将cv2.CHAIN_APPROX_SIMPLE传递给findContours()),这可能是一个很强的约束。

另一种选择是使用numpy完全完成。如果我正确理解您要检查数组np.array([[a,b]])是否在数组[np.array([[c,d]]), np.array([[f,g]]),...]列表中,那么您可以使用 elementwise 使用数组广播进行相等测试,并且使用np.all()np.any()来减少结果。例如:

>>> to_find = np.array([[1,3]])
>>> in_which = [np.array([[2,4]]),np.array([[1,3]]),np.array([[5,6]])]
>>> to_find in in_which
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>> np.all(to_find==in_which,axis=-1).any()
True

包含您的模板的列表相同:

>>> to_find = np.array([[1,3]])
>>> in_which = [np.array([[2,4]]),np.array([[1,2]]),np.array([[5,6]])]
>>> np.all(to_find==in_which,axis=-1).any()
False