How to resize a contour in opencv 2.4.11 python? (Goal: Object extraction)
Asked Answered
M

1

8

I'm super new to opencv, so pardon my ignorance...

Basically: I have an object of interest in my image. I would like to extract it.

My problems arise from downscaling the original image in order to facilitate processing. I have found a contour of the object on the smaller image. What I would really like to do is use the information about that contour to extract the object from the original full size image.

I can really only think of two ways to do this, but I have no idea which of these actually make sense in opencv:

  1. Resize the contour. Then draw it on the original image.
  2. (The one I'm using, without success...) Use the contour to create a mask. Resize the mask. Then add the mask to the original image.

I'm using No. 2, but I think there is a problem with the mask. Resized, it no longer contains the contour.

Here are the important parts of my current code:

image = cv2.imread(path)
orig = image.copy()
...

#resize the image
image = cv2.resize(image, dim, interpolation = cv2.INTER_AREA)
....

#convert to gray scale
...

#get contour
(cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
...
screenCnt = cv2.approxPolyDP(c, 0.01 * peri, True) #<--the contour
...

#create the mask
mask = np.ones(image.shape,np.uint8)*255
cv2.drawContours(mask,[screenCnt],0,(0,0,0),-1)
cv2.imshow("Small mask",mask) #<--- looks good
print(mask.shape) #<---returns a 3 element tuple
cv2.waitKey(0)

#now resize the mask
mask_big = cv2.resize(mask,(0,0),fx=ratio,fy=300)
cv2.imshow("Big mask",mask_big) #<--- ends up big, but all white (no contour)
cv2.waitKey(0)

I've been scouring the internet without luck, but I think I'm missing something fundamental here. Thanks a million to all answerers!

Mcalpin answered 27/7, 2015 at 4:16 Comment(4)
I would suggest trying the "resize the contour" route. I've done similar operations in the past and it has worked out fairly well.Fletcherfletcherism
@Mcalpin Isn't is possible to take all the contour points from your downsampled image and multiply them by your downsampling factor? I.e. if you downsampled by 128x, then multiplying all your contour points by 128 and drawing on the original image should work, no?Italy
@Italy - thanks for your answer! so yes, absolutely. but I don't understand what the contour object actually is. how are its points defined and how do I extract them? (i'm finding the documentation online unhelpful in this)Mcalpin
@Mcalpin The contour object is a list, containing numpy arrays with the X,Y coordinates of each contour. I.e. if findContours found n contours, the contour list is of length n. Each element in the list contains the coordinates of the contour. The simple way to see if this works is to iterate through each element of the contour object (from the downsampled image), multiplying each by the downsampling factor, appending these upsampled values to a new list, and then passing the upsampled contour object to drawContours to overlay on your original imageItaly
A
7

As I see it is quite old question. However, I had the same one and was't able to find quick answer with sample of code. Here is the example (for opencv 3.4)

_, contours, _ = cv2.findContours(mask.astype(np.uint8), cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

coef_y = img_orig.shape[0] / img_resized.shape[0]
coef_x = img_orig.shape[1] / img_resized.shape[1]

for contour in contours:
    contour[:, :, 0] = contour[:, :, 0] * coef_x
    contour[:, :, 1] = contour[:, :,  1] * coef_y

    cv2.drawContours(img_orig, contour, -1, (0, 255, 0), 2)
Adriell answered 17/3, 2019 at 20:9 Comment(1)
Good solution! Just be careful that what you name img_orig and img_resized matches the order of the division elements as presented in this question and answer. In my case I had to swap the elements in the division, but otherwise all's fine :)Suziesuzuki

© 2022 - 2024 — McMap. All rights reserved.