我目前正在对某些图像进行可视化处理,并发现了opencv的cv2.rectangle的这种奇怪行为:
当输入图像是np.ndarray时,例如arr,cv2.rectangle()返回np.ndarray,并且用矩形绘制arr。
当输入图像是arr的某种变体时,例如arr [:, ::,[2,0,1]],cv2.rectangle()返回cv2.UMat,并且未绘制矩形。
我当前的环境是:
以下是代码:
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)
您会发现:
尝试另一种方式:
b = copy.deepcopy(img)
c = b[:, :, [2, 1, 0]]
ret = cv2.rectangle(c, (0, 0), (10, 10), color=(255, 255, 255), thickness=2)
您会发现:
我真的很好奇我的代码有什么问题吗?还是背后隐藏着什么?
答案 0 :(得分:1)
由于我偶然发现了这个问题,我会努力回答这个问题,并且在评论中我看到了很多正确的东西!
OpenCV只能处理连续数组,这意味着必须以某种方式在内存中对它们进行布局。切片np.array
时,numpy
仅更改读取顺序以提高速度(而不是耗时的复制),并因此使其不连续(找到{{3} }。
@Das Masek和@Eric的陈述都是正确的。使用索引数组对np.array
进行切片会创建{strong>总是,如记录的here所示。但是,不幸的是,numpy
复制了数组,但不会将其更改回连续的数组(在我看来,这是不良行为)。
解决方案将是以下之一:
copy()
np.array
;通过显式复制,numpy
将布局更改回连续的状态,这与使用index-array-slicing一样。您可以使用flags
检查数组的a.flags
,依此类推。如果您要自动执行某些操作,这无疑是最昂贵的,因为您每次都按字面意思进行复制。np.ascontiguousarray()
。仅当数组已经不连续且不会copy
时,此函数才会更改数组的布局。另一个需要注意的是:根据here,所有OpenCV绘图函数实际上都是一个None
返回值,因为它们是就位函数。因此,我建议这样使用它们。