【问题标题】:NumPy array loses dimension upon assignment/copy, why?NumPy 数组在分配/复制时丢失维度,为什么?
【发布时间】:2019-11-30 17:26:23
【问题描述】:

我有以下代码:

print(type(a1), a1.shape)
a2 = a1                  #.reshape(-1,1,2) this solves my problem
print(type(a2), a2.shape)

输出是:

<class 'numpy.ndarray'> (8, 1, 2)
<class 'numpy.ndarray'> (8, 2)

我知道(已注释掉的)重塑解决了我的问题,但是,我想了解为什么简单的赋值会导致数组的中心维度丢失。

有人知道发生了什么吗?为什么用另一个名字引用数组会改变它的尺寸?

【问题讨论】:

  • 我无法想象赋值 a2 = a1 会改变底层 NumPy 数组对象。请您发布完整的代码以重现您所看到的问题以及您正在使用的任何库的版本吗? (我已经看到您在 Ajit 的答案下方留下的 opencv 链接,但我无法准确推断出这段代码与这个问题中的问题有何关系。)
  • 请注意代码中第 61 行的重塑:github.com/opencv/opencv/blob/master/samples/python/…。如果没有这种重塑,p0 将不会具有与good_new 相同的维度,即它将失去“中心”维度。
  • 是的,我注意到了 reshape,但代码中的内容远不止简单的赋值或复制。 NumPy 数组不会由于分配或通过其copy() 方法而丢失维度,仅由于特定的索引操作、显式整形、轴上的缩减等。在您的链接中,good_new 被分配给索引@的结果987654329@ 是cv.calcOpticalFlowPyrLK(..., p0, ...) 的输出,所以如果good_new 必须重新整形以引入额外的维度,我并不感到惊讶。我不认为你的问题的前提是正确的,所以我不确定如何回答。
  • good_new 具有中心尺寸,只需打印即可。如果您删除分配上的reshape 语句,p0 将丢失它。我也对此感到惊讶,但是,它正在发生。干杯,
  • 好吧,我想我明白了:当我运行脚本时,good_new 的形状为 (17, 2)。这看起来是因为 p0p1 都具有形状 (17, 1, 2)st 具有形状 (17, 1) 并且脚本设置了 good_new = p1[st==1](第 43 行)。由于布尔索引(即p1[st==1]),中心维度从p1 中删除,然后将此二维数组分配给good_new 变量。这就是为什么good_new 必须在重新分配回名称p0(必须是3D)之前重新整形。所以维度是由于索引而不是分配/复制而丢失的。

标签: arrays python-3.x numpy dimensions


【解决方案1】:

查看 cmets 中提到的openCV script,需要将其重塑为三个维度,因为通过布尔索引而不是仅通过分配会丢失一个维度。

该脚本中引发问题的数组名称是p0good_new

以下是该脚本中操作的细分:

  1. p0 是一个 3D 数组,形状为 (17, 1, 2)

  2. 行:

    p1, st, err = cv.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
    

    创建新数组,数组p1 的形状为(17, 1, 2),数组st 的形状为(17, 1)

  3. 赋值good_new = p1[st==1] 通过对p1 的布尔索引操作创建一个新的数组对象。这是一个二维数组,形状为(17, 2)。索引操作丢失了一个维度。

  4. 名称p0 需要分配回good_new 中包含的数组数据,但p0 也需要是3D 的。为此,脚本使用p0 = good_new.reshape(-1, 1, 2)


为了完整起见,值得总结一下为什么步骤 (3) 中的布尔索引操作会导致维度消失。

布尔数组st == 1 的形状为(17, 1),与p1(17, 1, 2) 的初始尺寸相匹配。

这意味着选择发生在p1 的第二维中:索引器数组st == 1 正在确定哪些形状为(2,) 的数组应该在结果数组中。最终数组的形状为(n, 2),其中n 是布尔数组中True 值的数量。

NumPy 文档here 中详细介绍了此行为。

【讨论】:

    【解决方案2】:

    我不确定你为什么会得到这个。但它不应该像这样返回。你能分享一下你的 a1 是如何创建的吗?

    我尝试如下但无法重新创建它

    a1=np.ones((8,1,2),dtype=np.uint8)
    print(type(a1), a1.shape)
    
    <class 'numpy.ndarray'> (8, 1, 2)
    
    a2=a1
    
    print(type(a2), a2.shape)
    
    <class 'numpy.ndarray'> (8, 1, 2)`
    

    【讨论】:

    猜你喜欢
    • 2015-07-29
    • 2015-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-11
    • 1970-01-01
    相关资源
    最近更新 更多