首页 > 解决方案 > 为什么 cv2.rectangle 有时会返回 np.ndarray,而有时会返回 cv2.UMat

问题描述

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

我目前的环境是:

以下是代码:

  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 的可视化显示没有绘制矩形

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

标签: pythonpython-3.xnumpyopencv

解决方案


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

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

@Das Masek 和@Eric 的陈述都是正确的。使用 index-array 对 an 进行切片始终np.array会创建一个副本,如此所述。但是,不幸的是,复制了数组,但不会将其更改回连续数组(对我来说这似乎是不好的行为)。numpy

解决方案将是以下之一:

  1. copy()np.array; _ 通过显式复制,numpy将布局更改回连续,而不是使用索引数组切片。你可以检查flags你的阵列a.flags等等。如果你想自动化某些东西,这显然是最昂贵的,因为你每次都在复制
  2. 对我来说更优雅的版本是使用np.ascontiguousarray(). 只有当数组已经不连续时,此函数才会更改数组的布局,并且不会copy

另一方面:根据文档,所有 OpenCV 绘图函数实际上都有一个None返回值,因为它们是就地函数。因此,我建议这样使用它们。


推荐阅读