【问题标题】:python opencv TypeError: Layout of the output array incompatible with cv::Matpython opencv TypeError:输出数组的布局与 cv::Mat 不兼容
【发布时间】:2014-07-12 21:29:20
【问题描述】:

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

一旦我从上面链接中的“选择性搜索算法”中从 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

错误是:

    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)

怎么了? 我在另一段没有错误的代码中做了非常相似的事情。这是没有错误的代码:

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

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

【问题讨论】:

    标签: python arrays matlab opencv numpy


    【解决方案1】:

    解决办法是先将found转换成一个numpy数组,然后再恢复成一个列表:

    found = np.array(found)
    boxes = cv2.groupRectangles(found.tolist(), 1, 2)
    

    【讨论】:

      【解决方案2】:

      我自己的解决方案是简单地询问原始数组的副本......(上帝和加里布拉德斯基知道为什么......)

      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)  
      

      【讨论】:

      • 简单地复制数组对我来说也适用于类似的错误。
      • 也可以确认一下,好像没有明显区别。
      • 此解决方案适用于 cv2.ellipse() 函数产生的类似错误
      • 我遇到了同样的问题,我注意到如果我只使用astype(np.uint8) 它也可以工作。但后来我读到astype 会自动复制数组。
      • Deniz Beker 的解决方案 (ascontiguousarray) 解释了原因。
      【解决方案3】:

      Opencv 似乎无法绘制数据类型为 np.int64 的 numpy 数组,这是 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)
      

      解决方法是先将数组转换为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)
      

      【讨论】:

        【解决方案4】:

        另一个原因可能是数组不连续。使其连续也可以解决问题

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

        【讨论】:

        • 有效。谁能解释一下为什么 cv2.rectangle() 函数需要这样做?
        • @Nic 也为我工作。我也想知道为什么这也是必要的。
        • 错误消息或多或少地描述了它,但是是的,它使用了一些专门的术语。如果你想多挖,这里是cv2代码:github.com/opencv/opencv/blob/3.4.0/modules/python/src2/…基本上cv::Mat只能表达某种类型的stride(或“step”),而且需要一个可写的view,所以不能复制(as这完全违背了输出 arg 的目的),因此快速失败。更多详情:docs.opencv.org/3.4.0/d3/d63/classcv_1_1Mat.html#details
        • 和这个评论区的其他人一样,我也因为cv2.rectange()的问题来到这里。我的问题是颜色类型,我的颜色是np.ndarray,将其转换为tuple 解决了我的问题。
        【解决方案5】:

        为了完整起见,我们中的许多人似乎都使用了上面 Etienne Perot 的解决方案,减去 .copy()。将数组类型转换为 int 就足够了。例如,使用霍夫变换时:

            # Define the Hough transform parameters
            rho,theta,threshold,min,max = 1, np.pi/180, 30, 40, 60  
        
            image = ima.astype(np.uint8) # assuming that ima is an image.
        
            # Run Hough on edge detected image
            lines = cv2.HoughLinesP(sob, rho, theta, threshold, np.array([]), min, max)
        
            # Iterate over the output "lines" and draw lines on the blank 
            line_image = np.array([[0 for col in range(x)] for row in range(y)]).astype(np.uint8)
        
            for line in lines: # lines are series of (x,y) coordinates
                for x1,y1,x2,y2 in line:
                    cv2.line(line_image, (x1,y1), (x2,y2), (255,0,0), 10)
        

        只有这样才能使用plt.imshow()绘制数据

        【讨论】:

          猜你喜欢
          • 2019-05-23
          • 1970-01-01
          • 1970-01-01
          • 2019-08-03
          • 2012-12-04
          • 1970-01-01
          • 2012-06-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多