转置numpy矩阵会导致cv的绘制函数抛出错误

时间:2014-10-05 00:30:05

标签: python opencv numpy

当我转换它们时,我一直遇到一些使用cv显示numpy矩阵图像的问题。

请考虑以下代码。

import cv2, numpy as np
...
ones = np.ones((100,100))
onesT = np.copy(ones.T)
onesCT = np.copy(ones.T, order='C')
cv2.circle(ones, (50,50), 3, (0), thickness=-1)
cv2.circle(onesCT, (50,50), 3, (0), thickness=-1)
cv2.circle(onesT, (50,50), 3, (0), thickness=-1)

前两个“cv2.circle”调用有效,但第三个调用给出了以下错误:

    102         cv2.circle(ones, (50,50), 3, (0), thickness=-1)
    103         cv2.circle(onesCT, (50,50), 3, (0), thickness=-1)
--> 104         cv2.circle(onesT, (50,50), 3, (0), thickness=-1)

TypeError: Layout of the output array img is incompatible with cv::Mat (step[ndims-1] != elemsize or step[1] != elemsize*nchannels)

为什么在转置矩阵时会发生这种情况,但如果我更改内存复制的顺序则不会发生这种情况?对我来说,所有这些矩阵都是完全相同的。

1 个答案:

答案 0 :(得分:1)

在一个抽象层次上,所有这些矩阵都是相同的。但是在较低级别,其中两个使用C约定(row-major order)存储数据,而另一个(onesT)使用Fortran约定(列主要顺序)。显然cv2.circle需要一个C连续的数组。

您可以使用flags属性检查订单。请注意F_CONTIGUOUS的{​​{1}}标志为True:

onesT

检查订单信息的简明方法是np.isfortran

In [24]: ones.flags
Out[24]: 
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False

In [25]: onesT.flags
Out[25]: 
  C_CONTIGUOUS : False
  F_CONTIGUOUS : True
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False

In [26]: onesCT.flags
Out[26]: 
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False

In [27]: np.isfortran(onesT) Out[27]: True 使用Fortran命令,因为2-d数组的转置是通过简单地交换每个维度的“strides”而实现的,而不是实际复制内存中的值数组。

例如,

onesT

(这使转置操作非常有效。)

您复制了转置数组以创建In [28]: x = np.array([[1, 2, 3], [4, 5, 6]]) In [29]: np.isfortran(x) Out[29]: False In [30]: np.isfortran(x.T) Out[30]: True ,但如果您查看np.copy的文档字符串,您会看到onesT参数的默认值为{{1 },这意味着“尽可能地匹配a的布局。”特别是,在这种情况下,它保留了Fortran订单。另一方面,order是一个C连续数组,因为您明确告诉'K'使用C约定对副本进行排序。