python opencv TypeError: Layout of the output array incompatible with cv::Mat

39,919

Solution 1

The solution was to convert found first to a numpy array, and then to recovert it into a list:

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

Solution 2

My own solution was simply to ask a copy of original array...(god & gary bradski knows why...)

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)  

Solution 3

Another reason may be that the array is not contiguous. Making it contiguous would also solve the issue

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

Solution 4

Opencv appears to have issues drawing to numpy arrays that have the data type np.int64, which is the default data type returned by methods such as np.array and np.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)

The solution is to convert the array to np.int32 first:

>>> 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)
Share:
39,919
user961627
Author by

user961627

Updated on May 13, 2020

Comments

  • user961627
    user961627 almost 4 years

    I'm using the selective search here: http://koen.me/research/selectivesearch/ This gives possible regions of interest where an object might be. I want to do some processing and retain only some of the regions, and then remove duplicate bounding boxes to have a final neat collection of bounding boxes. To discard unwanted/duplicated bounding boxes regions, I'm using the grouprectangles function of opencv for pruning.

    Once I get the interesting regions from Matlab from the "selective search algorithm" in the link above, I save the results in a .mat file and then retrieve them in a python program, like this:

     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
    

    The error is:

        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)
    

    What's wrong? I did something very similar in another piece of code which gave no errors. This was the error-free code:

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

    The only difference I can see is that boxes was a numpy array which I then converted to a list. But in my problematic code, found is already a list.

  • nair.ashvin
    nair.ashvin over 8 years
    simply copying the array worked for me for a similar error as well.
  • Pwnna
    Pwnna over 8 years
    Can confirm this as well, there seems to be no visible difference, tho.
  • DanGoodrick
    DanGoodrick almost 8 years
    This solution worked for a similar error produced by the cv2.ellipse() function
  • DarkCygnus
    DarkCygnus over 6 years
    Same with cv2.line ... although it seems that the issue was solved by changing it to a np array rather than "just" making a copy of it (that is, it should be a np array copy of your list)
  • CMCDragonkai
    CMCDragonkai about 6 years
    I had the same problem, and I noticed if I just use astype(np.uint8) it also just works. But then I read that astype automatically copies the array.
  • Nic
    Nic almost 6 years
    Works. Can anyone explain why this is necessary for the cv2.rectangle() function?
  • TimZaman
    TimZaman over 5 years
  • user3731622
    user3731622 over 5 years
    @Nic worked for me too. I'd like to hear why this is necessary too.
  • plhn
    plhn over 5 years
    Deniz Beker’s solution(ascontiguousarray) explains why.
  • Gabriel123
    Gabriel123 almost 4 years
    thanks! I had identical problem with cv2.HoughLinesP AND cv2.line methods, and a conversion to int through .astype(np.uint8) solved both issues and saved my hair!
  • Eric Cousineau
    Eric Cousineau over 3 years
    The error message more-or-less describes it, but yeah, it uses some specialized terms. If you want to dig more, here's the cv2 code: github.com/opencv/opencv/blob/3.4.0/modules/python/src2/… Basically, cv::Mat can only express a certain type of stride (or "step"), and you need a writeable view, so you can't copy (as that defeats the purpose of an output arg entirely), hence the fail-fast. For more details: docs.opencv.org/3.4.0/d3/d63/classcv_1_1Mat.html#details
  • Can H. Tartanoglu
    Can H. Tartanoglu over 2 years
    Like some other people in this comment area, I also got here because of issues with cv2.rectange(). My problem was with the color type, my color was np.ndarray, converting it to tuple solved my problem.