python opencv TypeError:输出数组的布局与cv :: Mat不兼容

use*_*627 10 python arrays matlab opencv numpy

我在这里使用选择性搜索:http://koen.me/research/selectivesearch/ 这给出了一个对象可能存在的感兴趣区域.我想进行一些处理并仅保留一些区域,然后删除重复的边界框以获得最终整齐的边界框集合.为了丢弃不需要/重复的边界框区域,我使用grouprectanglesopencv 的功能进行修剪.

一旦我从上面链接中的"选择性搜索算法"中获取Matlab中的有趣区域,我将结果保存在一个.mat文件中,然后在python程序中检索它们,如下所示:

 import scipy.io as sio
 inboxes = sio.loadmat('C:\\PATH_TO_MATFILE.mat')
 candidates = np.array(inboxes['boxes'])
 # candidates is 4 x N array with each row describing a bounding box like this: 
 # [rowBegin colBegin rowEnd colEnd]
 # Now I will process the candidates and retain only those regions that are interesting
 found = [] # This is the list in which I will retain what's interesting
 for win in candidates: 
     # doing some processing here, and if some condition is met, then retain it:
     found.append(win)

# Now I want to store only the interesting regions, stored in 'found', 
# and prune unnecessary bounding boxes

boxes = cv2.groupRectangles(found, 1, 2) # But I get an error here
Run Code Online (Sandbox Code Playgroud)

错误是:

    boxes = cv2.groupRectangles(found, 1, 2)
TypeError: Layout of the output array rectList is incompatible with cv::Mat (step[ndims-1] != elemsize or step[1] != elemsize*nchannels)
Run Code Online (Sandbox Code Playgroud)

怎么了?我在另一段代码中做了非常相似的事情,没有给出任何错误.这是无错误的代码:

inboxes = sio.loadmat('C:\\PATH_TO_MY_FILE\\boxes.mat')
boxes = np.array(inboxes['boxes'])
pruned_boxes = cv2.groupRectangles(boxes.tolist(), 100, 300)
Run Code Online (Sandbox Code Playgroud)

我能看到的唯一区别是,这boxes是一个numpy数组,然后我转换为列表.但在我有问题的代码中,found已经是一个列表.

小智 49

我自己的解决方案只是问一个原始阵列的副本......(上帝和加里布拉兹基知道为什么......)

im = dbimg[i]
bb = boxes[i]  
m = im.transpose((1, 2, 0)).astype(np.uint8).copy() 
pt1 = (bb[0],bb[1])
pt2 = (bb[0]+bb[2],bb[1]+bb[3])  
cv2.rectangle(m,pt1,pt2,(0,255,0),2)  
Run Code Online (Sandbox Code Playgroud)

  • 简单地复制数组对我来说也是一个类似的错误. (4认同)
  • 我遇到了同样的问题,我注意到如果我只使用 `astype(np.uint8)` 它也可以正常工作。但是后来我读到 `astype` 会自动复制数组。 (2认同)
  • Deniz Beker 的解决方案(`ascontiguousarray`) 解释了原因。 (2认同)

Den*_*ker 16

另一个原因可能是阵列不连续.使其连续也将解决问题

image = np.ascontiguousarray(image, dtype=np.uint8)

  • 作品.任何人都可以解释为什么这对cv2.rectangle()函数是必要的? (2认同)

vvo*_*ejn 7

这里提出了很多解决方案,但根本原因是数组的内存布局。由于某种原因(编辑:请参阅下面的评论),OpenCV 要求其输入采用 C 顺序(行优先)而不是 F 顺序(列优先),请参阅此处了解详细信息。

这里提出的所有解决方案都隐式地将数组更改为 C 顺序:

  • usingarray.copy()这样做是因为有一个默认参数order='C'
  • 转换为列表并返回 NumPy,因为 C 顺序是默认值
  • array.astype() 可能会这样做(似乎取决于原始布局和数据类型)
  • np.ascontiguousarray()转换为 C 阶。

在本例中,这是一个重现该问题的小示例cv2.line

import cv2
import numpy as np

img = np.zeros((200, 200, 3), dtype=np.uint8)

# Breaks
img = np.require(img, requirements=["F_CONTIGUOUS"])

# img = np.require(img, requirements=["C_CONTIGUOUS"])  # Fixes it
# img = img.copy()  # Also fixes it

cv2.line(img, (10, 10), (100, 100), (255,0,0), 5)
Run Code Online (Sandbox Code Playgroud)


use*_*627 5

解决方案是先转换found为 numpy 数组,然后将其恢复为列表:

found = np.array(found)
boxes = cv2.groupRectangles(found.tolist(), 1, 2)
Run Code Online (Sandbox Code Playgroud)


Mat*_*eck 5

Opencv 似乎在绘制具有数据类型 的 numpy 数组时出现问题,这是和 等np.int64方法返回的默认数据类型:np.arraynp.full

>>> canvas = np.full((256, 256, 3), 255)
>>> canvas
array([[255, 255, 255],
       [255, 255, 255],
       [255, 255, 255]])
>>> canvas.dtype
dtype('int64')
>>> cv2.rectangle(canvas, (0, 0), (2, 2), (0, 0, 0))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Layout of the output array img is incompatible with cv::Mat (step[ndims-1] != elemsize or step[1] != elemsize*nchannels)
Run Code Online (Sandbox Code Playgroud)

解决方案是将数组转换为np.int32第一个:

>>> cv2.rectangle(canvas.astype(np.int32), (0, 0), (2, 2), (0, 0, 0))
array([[  0,   0,   0],
       [  0, 255,   0],
       [  0,   0,   0]], dtype=int32)
Run Code Online (Sandbox Code Playgroud)