Opencv:值错误
Opencv: ValueError
我已经检测到轮廓并将它们存储在 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: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
有人可以纠正我做错了什么吗?
您的问题与 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 本身断言,但此信息应该在您的问题中开始)您正在比较的对象 可能 类似
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
,但正如您在我的第一个示例中看到的那样,当您尝试使用通常的它们的逻辑操作与本机列表配对。这是有道理的,因为在本机 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
不会产生错误,但它的行为方式令人惊讶:它 returns True
如果两个数组之间有 any 个公共元素!这显然不是你想要做的。
在我看来,您有两个选择。您可以将所有 ndarrays 转换为列表。我的意思是:
>>> 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
我已经检测到轮廓并将它们存储在 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: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
有人可以纠正我做错了什么吗?
您的问题与 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 本身断言,但此信息应该在您的问题中开始)您正在比较的对象 可能 类似
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
,但正如您在我的第一个示例中看到的那样,当您尝试使用通常的它们的逻辑操作与本机列表配对。这是有道理的,因为在本机 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
不会产生错误,但它的行为方式令人惊讶:它 returns True
如果两个数组之间有 any 个公共元素!这显然不是你想要做的。
在我看来,您有两个选择。您可以将所有 ndarrays 转换为列表。我的意思是:
>>> 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