【问题标题】:Python OpenCV drawing errors after manipulating array with numpy使用 numpy 操作数组后 Python OpenCV 绘图错误
【发布时间】:2015-07-26 18:16:18
【问题描述】:

我正在使用 OpenCV 读取图像,并尝试在 numpy 中对其进行处理(旋转 90 度)。使用 matplotlib 中的imshow 查看结果,一切似乎都运行良好 - 图像已旋转。但是,我不能在新图像上使用来自 OpenCV 的绘图方法。在以下代码中(我在 sagemath 云工作表中运行它):

%python
import cv2
import matplotlib.pyplot as plt
import numpy as np
import os, sys
image = np.array( cv2.imread('imagename.png') )
plt.imshow(image,cmap='gray')
image = np.array(np.rot90(image,3) ) # put it right side up
plt.imshow(image,cmap='gray')
cv2.rectangle(image,(0,0),(100,100),(255,0,0),2)
plt.imshow(image,cmap='gray')

cv2.rectangle() 命令出现以下错误:

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

如果我改用 np.array(np.rot90(image,4) )(即旋转 360 度),错误就会消失。所以看起来尺寸的变化把它搞砸了。 OpenCV 是否将尺寸存储在我需要更新的内部某处?

编辑:rot90() 之后添加image = image.copy() 解决了这个问题。请参阅下面 rayryeng 的回答。

【问题讨论】:

    标签: python image opencv image-processing numpy


    【解决方案1】:

    这显然是 Python OpenCV 包装器中的一个错误。如果您在此处查看此问题:np.rot90() corrupts an opencv image,显然进行不会导致返回原始尺寸的旋转会损坏图像,并且该帖子中的 OP 会遇到您遇到的相同错误。 FWIW,我也遇到了同样的错误....不知道为什么。

    解决此问题的方法是在旋转后制作图像的副本,然后显示该图像。这我无法真正解释,但它似乎有效。此外,请确保在代码末尾调用 plt.show()显示图像:

    import cv2
    import matplotlib.pyplot as plt
    import numpy as np
    import os, sys
    image = np.array( cv2.imread('imagename.png') )
    plt.imshow(image,cmap='gray')
    image = np.array(np.rot90(image,3) ) # put it right side up
    
    image = image.copy() # Change
    
    plt.imshow(image,cmap='gray')
    cv2.rectangle(image,(0,0),(100,100),(255,0,0),2)
    plt.imshow(image,cmap='gray')
    
    plt.show() # Show image
    

    【讨论】:

    • 这很有趣cv2.imread() 只是返回一个 ndarray。 ndarray 独立于 OpenCV,并且没有以我能看到的任何方式损坏。对我来说唯一有意义的是 OpenCV 单独跟踪“图像”(ndarray)的尺寸或其他东西。虽然那样复制解决方法的工作原理没有意义。
    • 老实说,我也不知道它为什么会起作用。我正在考虑提交一个错误请求,以找出为什么需要这样做才能使轮换工作......而且我也看不到操作之间的任何损坏。如果您制作副本,它就可以简单地工作!
    • 我猜这与 python 存储数组的方式有关。 numpy.rotate() 实际上并没有改变数据,它只是将视图更改为它。如果您在复制之前和之后(旋转之后)执行“打印 image.flags”,我认为发生的事情是有道理的。由于 OpenCV 都是 C,因此 C 例程无法正确处理 numpy 数组中的新视图。所以基本上,这是 OpenCV python 包装器如何将信息传递给 c 例程的一个错误。不确定是否真的有解决方案,但如果数据格式是“不连续”或无法正常工作,它至少会引发错误。
    【解决方案2】:

    我在使用 numpy 1.11.2 和 opencv 3.3.0 时遇到了同样的问题。不知道为什么,但这对我有用。 在使用 cv2.rectangle 之前,添加以下行:

    image1 = image1.transpose((1,0)).astype(np.uint8).copy()
    

    Reference

    【讨论】:

    • 这与接受的答案相同,只是您将旋转实现为转置操作,然后进行复制。
    【解决方案3】:

    转换数据类型适用于我的问题。 图像在转换之前是 np.int64 类型。

    image = image.astype(np.int32) # convert data type
    

    【讨论】:

    • 请详细说明 - 您在轮换之前或之后执行此操作,等等?如果是之后,那么这与上一个答案相同,因为转换它会导致 numpy 创建一个新数组。
    • 我在 cv2.putText 之前执行此操作。 cv2.putText 是在我的问题中引发 TypeError 的行。 'image.copy()' 对我不起作用。我猜 Layout 表示 numpy 数组中的内存或数据布局,它在 np.float64 和 float32 之间存在差异
    猜你喜欢
    • 2023-01-13
    • 2019-08-11
    • 1970-01-01
    • 2018-11-30
    • 1970-01-01
    • 2017-04-25
    • 2020-05-18
    • 1970-01-01
    相关资源
    最近更新 更多