python - 为什么 cv2.rectangle 有时会返回 np.ndarray,而有时会返回 cv2.UMat
问题描述
我目前正在对一些图像进行可视化,并发现了 opencv 的 cv2.rectangle 的这种奇怪行为:
当输入图像是 np.ndarray 时,比如说 arr,cv2.rectangle() 返回一个 np.ndarray,并且 arr 用矩形绘制。
当输入图像是 arr 的某个变体时,例如 arr[:, :, [2, 0, 1]],cv2.rectangle() 返回一个 cv2.UMat,并且不绘制矩形。
我目前的环境是:
- 蟒蛇 3.7
- 开放式简历 4.1
以下是代码:
- 首先生成一个随机图像。
import numpy as np
import cv2
import copy
img = np.random.randint(0, 255, (100, 120, 3)).astype("uint8")
- 现在添加一个矩形
a = copy.deepcopy(img)
ret = cv2.rectangle(a, (0, 0), (10, 10), color=(255, 255, 255), thickness=2)
你会找到:
- 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)
你会找到:
- ret 是一个 cv2.UMat
- ret 或 c 的可视化显示没有绘制矩形
我真的很好奇我的代码有什么问题吗?还是背后隐藏着什么?
解决方案
我会努力回答这个问题,因为我经常偶然发现这个问题,并且在评论中我看到了很多正确的东西!
OpenCV 只能处理连续数组,这意味着它们必须以某种方式在内存中布局。切片时np.array
,numpy
只需更改读取顺序以提高速度(而不是耗时的复制)并因此使其不连续(在此处找到)。
@Das Masek 和@Eric 的陈述都是正确的。使用 index-array 对 an 进行切片始终np.array
会创建一个副本,如此处所述。但是,不幸的是,复制了数组,但不会将其更改回连续数组(对我来说这似乎是不好的行为)。numpy
解决方案将是以下之一:
copy()
np.array
; _ 通过显式复制,numpy
将布局更改回连续,而不是使用索引数组切片。你可以检查flags
你的阵列a.flags
等等。如果你想自动化某些东西,这显然是最昂贵的,因为你每次都在复制。- 对我来说更优雅的版本是使用
np.ascontiguousarray()
. 只有当数组已经不连续时,此函数才会更改数组的布局,并且不会copy
。
另一方面:根据文档,所有 OpenCV 绘图函数实际上都有一个None
返回值,因为它们是就地函数。因此,我建议这样使用它们。
推荐阅读
- java - JpaTransactionManager 不回滚事务
- ios - 如何在代码中使用自动布局
- visual-studio-code - 创建扩展 - 发布者显示名称
- python - Python Tkinter 更改矩形列表的所有颜色
- node.js - 在 Angular 5 中使用电子生成器构建电子应用程序
- php - 用户在docusign中签署文档后如何在webhook URL上获得响应
- matlab - 将类转换为结构体并存储在 .mat 文件中 - MATLAB
- sql - 仅当更新的列具有不同的值时触发
- javascript - 使用 Javascript/JQuery 动态更新 Selectize 字段
- c# - 如何在 Ms 单元测试中使用 Moq 覆盖异常块