为什么 cv2.rectangle 有时返回 np.ndarray,而有时返回 cv2.UMat [英] Why cv2.rectangle sometimes return np.ndarray, while sometimes cv2.UMat

查看:120
本文介绍了为什么 cv2.rectangle 有时返回 np.ndarray,而有时返回 cv2.UMat的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm currently working on visualizing some images and found this weired behaviour of opencv's cv2.rectangle:

  • 当输入图像是 np.ndarray 时,比如说 arr,cv2.rectangle() 返回一个 np.ndarray,而 arr 是用矩形绘制的.

  • when input image is an np.ndarray, say arr, cv2.rectangle() returns an np.ndarray, and arr is drawn with a rectangle.

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

when input image is some variant of arr, like arr[:, :, [2, 0, 1]], cv2.rectangle() returns a cv2.UMat, and no rectangle is drawn.

我目前的环境是:

  • 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. 你会发现:

  1. You'll find:

  • ret 是一个 np.ndarray
  • ret 的可视化并显示绘制了一个矩形

尝试另一种方式:

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

  1. 你会发现:

  1. You'll find:

  • ret 是一个 cv2.UMat
  • ret 或 c 的可视化显示没有绘制矩形

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

I'm really curious that is there anything wrong with my code? Or there is something hidden behind it?

推荐答案

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

I'll make the effor to answer this since I stumbled upon this problem a lot and in the comments I see a lot of correct stuff!

OpenCV 只能处理连续数组,这意味着它们必须以某种方式在内存中排列.在切片 np.array 时,numpy 只是改变读取顺序以提高速度(而不是耗时的复制)并使其非连续strong>(在此处找到).

OpenCV can only deal with contiguous arrays, meaning they have to be laid out in a certain way in memory. When slicing an np.array, numpy just changes the read order to increase the speed (instead of time consuming copying) and makes it therefore non-contiguous (found here).

@Das Masek 和@Eric 的陈述都是正确的.使用索引数组对 np.array 进行切片创建 总是 文档中的副本 此处.但是,不幸的是 numpy 复制了数组,但不会将其改回连续数组(在我看来,这似乎是不好的行为).

Both @Das Masek and @Eric are correct with their statements. Using index-array to slice an np.array creates always a copy as documented here. However, unfortunately numpy copies the array but won't change it back to a contiguous array (which to me seems like bad behavior).

解决方案是以下之一:

  1. copy() np.array;通过显式复制,numpy 将布局改回连续,这与索引数组切片不同.您可以使用 a.flags 等检查数组的 flags.如果您想自动化某些东西,这显然是最昂贵的,因为您实际上每次都在复制.
  2. 对我来说更优雅的版本是使用 np.ascontiguousarray().仅当数组已经不连续时,此函数才会更改数组的布局,并且不会复制它.
  1. copy() the np.array; by explicitely copying, numpy changes the layout back to contiguous, as not done with index-array-slicing. You can check the flags of your array with a.flags and so forth. This is obiously the most expensive if you want to automate something because you are literally copying every single time.
  2. the more elegant version for me would be to use np.ascontiguousarray(). This function changes the layout of the array only if it is already non-contiguous, and does not copy it.


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


On a different note: according the documentation, all OpenCV drawing function actually have a None return value, since they are inplace functions. Therefore I would recommend using them as such.

这篇关于为什么 cv2.rectangle 有时返回 np.ndarray,而有时返回 cv2.UMat的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆