Copy and paste region of image in opencv?

2020-07-10 07:15发布

问题:

I'm stuck at this tutorial where a ROI is pasted over another region of same image. Python trows a value error when I try something similar:

img = cv2.imread(path, -1)
eye = img[349:307, 410:383]
img[30:180, 91:256] = eye

Exeption:

Traceback (most recent call last):
  File "test.py", line 13, in <module>
    img[30:180, 91:256] = eye
ValueError: could not broadcast input array from shape (0,0,3) into shape (150,165,3)

This might be very newb question, but I couldn't come up with an answer by searching on google. Are there other numpy methods for doing this?

EDIT: Also in the tutorial its not specified how the coordinates should be entered. Ex: I can enter coords of the region I want something like: eye = img[x1:y1, x2:y2] or img[x1:x2, y1:y2]. This is what confusing to me. Actually I tried to get these coords from a mouse callback method which printed the position of the mouse click. So, the coordinates are surely from the inside of image.

回答1:

I would guess that there's something off with your image. Let's look at the error returned

ValueError: could not broadcast input array from shape (0,0,3) into shape (150,165,3)

So eye appears to have the dimension (0,0,3) and img has the dimension (150,165,3). The 3 corresponds to RGB which is the 3 different color channels. So your original image is 150x165. But you tried to select a region at img[349:307, 410:383]. I suspect since the region you specified is outside the image it is not selecting anything hence the dimensions (0,0,3).

Try import pdb; pdb.set_trace() after the second line where you initialize eye. This will pop you into an interactive python terminal where you can see what's going on. Try to see what the dimensions of img are and if it's really what you want. Maybe the image you downloaded is smaller than the example causing the error.

Check out the first answer to a similar question. Your method for getting roi looks correct so try just adjusting the coordinates to a smaller region that fits.



回答2:

Your slice [349:307, 410:383] returns an empty array eye, which could not be assigned to an array view of different shape.

E.g.:

In [8]: import cv2
   ...: fn=r'D:\Documents\Desktop\1.jpg'
   ...: img=cv2.imread(fn, -1)
   ...: roi=img[200:400, 200:300]

In [9]: roi.shape
Out[9]: (200, 100, 3)

In [10]: img2=img.copy()

In [11]: img2[:roi.shape[0], :roi.shape[1]]=roi

In [12]: cv2.imshow('img', img)
    ...: cv2.imshow('roi', roi)
    ...: cv2.imshow('img2', img2)
    ...: cv2.waitKey(0)
    ...: cv2.destroyAllWindows()

result:

img & roi:

img2:

NOTE that even if roi is not an empty array, assignment with mismatching shapes will raise errors:

In [13]: img2[:100, :100]=roi
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-13-85de95cf3ded> in <module>()
----> 1 img2[:100, :100]=roi

ValueError: could not broadcast input array from shape (200,100,3) into shape (100,100,3)


回答3:

img[349:307, 410:383]

is asking for the interpreter to find all the x values above 349 AND below 307, which is impossible, and will return a slice size 0. Turn your numbers around.

img[307,349, 383:413]

Also your dimensions are wrong. How can you put a slice of width 42 into a slice of width 150?