为什么cv2.rectangle有时返回np.ndarray,而有时cv2.UMat

时间:2019-08-21 07:21:34

标签: python python-3.x numpy opencv

我目前正在对某些图像进行可视化处理,并发现了opencv的cv2.rectangle的这种奇怪行为:

  • 当输入图像是np.ndarray时,例如arr,cv2.rectangle()返回np.ndarray,并且用矩形绘制arr。

  • 当输入图像是arr的某种变体时,例如arr [:, ::,[2,0,1]],cv2.rectangle()返回cv2.UMat,并且未绘制矩形。

我当前的环境是:

  • Python 3.7
  • Opencv 4.1

以下是代码:

  1. 首先生成随机图像。
import numpy as np
import cv2
import copy

img = np.random.randint(0, 255, (100, 120, 3)).astype("uint8")
  1. 现在添加一个矩形
a = copy.deepcopy(img)
ret = cv2.rectangle(a, (0, 0), (10, 10), color=(255, 255, 255), thickness=2)
  1. 您会发现:

    • ret是一个np.ndarray
    • ret的可视化和显示一个矩形的显示
  2. 尝试另一种方式:

b = copy.deepcopy(img)
c = b[:, :, [2, 1, 0]]
ret = cv2.rectangle(c, (0, 0), (10, 10), color=(255, 255, 255), thickness=2)
  1. 您会发现:

    • ret是cv2.UMat
    • ret或c的可视化显示未绘制矩形

我真的很好奇我的代码有什么问题吗?还是背后隐藏着什么?

1 个答案:

答案 0 :(得分:1)

由于我偶然发现了这个问题,我会努力回答这个问题,并且在评论中我看到了很多正确的东西!

OpenCV只能处理连续数组,这意味着必须以某种方式在内存中对它们进行布局。切片np.array时,numpy仅更改读取顺序以提高速度(而不是耗时的复制),并因此使其不连续(找到{{3} }。

@Das Masek和@Eric的陈述都是正确的。使用索引数组对np.array进行切片会创建{strong>总是,如记录的here所示。但是,不幸的是,numpy复制了数组,但不会将其更改回连续的数组(在我看来,这是不良行为)。

解决方案将是以下之一:

  1. copy() np.array;通过显式复制,numpy将布局更改回连续的状态,这与使用index-array-slicing一样。您可以使用flags检查数组的a.flags,依此类推。如果您要自动执行某些操作,这无疑是最昂贵的,因为您每次都按字面意思进行复制。
  2. 对我来说,更优雅的版本是使用np.ascontiguousarray()。仅当数组已经不连续且不会copy时,此函数才会更改数组的布局。

另一个需要注意的是:根据here,所有OpenCV绘图函数实际上都是一个None返回值,因为它们是就位函数。因此,我建议这样使用它们。