我目前正在处理图像可视化,发现了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
以下是代码:
- 首先生成一个随机图像。
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 显示没有矩形被绘制
我非常好奇我的代码是否有问题?或者有什么隐藏的东西?
c = img[:, :, [2, 1, 0]].copy()
。 - api55img[:, :, [2, 1, 0]
只是创建到同一缓冲区的视图,并设置元数据,以便第三个轴以相反的顺序进行解释。不幸的是,无法为该缓冲区创建等效的cv::Mat标头。因此,尝试使用等效的Mat
调用函数失败了。但是,在Python包装器中有超载分辨率,因此它尝试从缓冲区创建一个UMat... - Dan Mašekresult = ret.get();
并可视化结果时,我看到那里有一个白色矩形。然而,原始输入(OP代码中的c
)不包含矩形,这表明在创建UMat对象时涉及复制(有点意料之中)。| 使用ndarray.copy()
进行数组的深度复制,就像您所做的那样,似乎会重新排列缓冲区,以便元数据再次“正常”(与cv :: Mat
兼容)。 - Dan MašekUMat
... 我需要留些时间来理解这一点。 - Dan Mašekimg[:,:,2::-1]
,您会得到这种行为,但是对于使用索引数组进行索引,它总是会复制。 - Eric