np.rot90()破坏了opencv图像

时间:2013-12-30 16:32:29

标签: python opencv

尝试将横向图像旋转为纵向时,应用旋转后,我无法在图像上绘制。

img1 = cv2.imread('a.jpg')
cv2.circle(img1, tuple([10,10]),radius = 3, color = (255,0,0))

工作正常。

然后我尝试:

img2 = np.rot90(img1,3)
cv2.circle(img2, tuple([10,10]),radius = 3, color = (255,0,0))

我收到错误:

TypeError: Layout of the output array img is incompatible with cv::Mat (step[ndims-1] != elemsize or step[1] != elemsize*nchannels)

查看type(img2)img2.dtype,它似乎与img1相同。 尺寸看起来也很好(前两个尺寸翻转,第三个尺寸保持“3”)

顺便说一下:这似乎有效。 (为什么?):

img2 = np.rot90(img1,3)
img3 = img2.copy()
cv2.circle(img3, tuple([10,10]),radius = 3, color = (255,0,0))

2 个答案:

答案 0 :(得分:3)

我有同样的问题,从来没有深究过它。我使用的解决方法是使用OpenCV进行图像旋转/翻转,例如:

# flip image vertically
img = cv2.flip(img, 0)

# flip image horizontally
img = cv2.flip(img, 1)

# transpose image
img = cv2.transpose(img)

请注意,旋转相当于进行转置和翻转。

答案 1 :(得分:0)

np.rot90 本身并没有完全破坏图像。这背后的原因是因为 OpenCV 无法处理 numpy 数组的“视图”。 np.rot90 以及其他几个 numpy 操作实际上并不修改底层数组,而是将修改后的“视图”返回给数组。这通常会在 OpenCV 操作中引发以下错误:

Layout of the output array img is incompatible with cv::Mat (step[ndims-1] != elemsize or step[1] != elemsize*nchannels)
Expected Ptr<cv::UMat> for argument 'img'

np.rot90(img1)np.fliplr(img1)np.flipud(img1)np.transpose(img1, (1, 0, 2)) 等操作都只是返回视图,并且都会抛出上述相同的错误。

添加 .copy() 可以解决错误的原因是,当在视图上调用 .copy() 时,它会作为与原始数组不同的新数组存储在内存中。您实际上可以非常简单地验证这一点:

import numpy as np

img = np.random.choice(256, (50, 100, 3)).astype(np.uint8)
img_r = np.rot90(img)

print(img_r == img)
# False

print(np.shares_memory(img, img_r))
# True

img_r = img_r.copy()
print(np.shares_memory(img, img_r))
# False

如您所见,即使 img_r == img 显示 False,它们仍然共享相同的内存——因为 img_rimg 的视图。但是在调用 .copy() 之后,视图 img_r 变成了它自己的数组,不再与原来的 img 共享内存。