首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Opencv: ValueError

Opencv: ValueError
EN

Stack Overflow用户
提问于 2016-06-02 06:30:00
回答 1查看 1.2K关注 0票数 0

我已经检测到轮廓并将它们存储在碳纳米管中,我正在逐一访问它们,c_list是我感兴趣的轮廓的列表。我想通过使用以下代码来检查我现在访问的轮廓是否已经被访问:

代码语言:javascript
运行
复制
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()

有人能纠正我做错了什么吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-06-07 11:57:52

您的问题实际上与OpenCV无关,它来自于numpy。

考虑以下例子:

代码语言:javascript
运行
复制
>>> 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本身断言,但这些信息应该在您的问题中首先提出),您正在比较的对象可能如下所示

代码语言:javascript
运行
复制
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,您通常希望对数组进行元素级的测试,这就是为什么相同的表达式会导致错误。

现在,解决你的问题比人们想象的要复杂得多。还不完全清楚你想要实现什么,而且可能有一个更合理的方法来实现它。无论如何,请考虑以下修改的示例:

代码语言:javascript
运行
复制
>>> [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

虽然在两个ndarray之间使用in不会产生错误,但它以一种令人惊讶的方式运行:如果两个数组之间有任何公共元素,则返回True!这显然不是你想做的。

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

代码语言:javascript
运行
复制
>>> 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]]),...]列表中,那么可以使用元素等式测试来使用数组广播,并使用np.all()np.any()来减少结果。示例:

代码语言:javascript
运行
复制
>>> 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

对于不包含模板的列表也是如此:

代码语言:javascript
运行
复制
>>> 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
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37584260

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档