Skip to content
Advertisement

shrink and enlarge contour image with Python OpenCV

I have an image with an object like below:

enter image description here

I can detect the contour and get a mask with only ball region, but my ROI is the edge region, that means I need a bigger and a smaller mask which combine to get this:

enter image description here

so my question is: how can I shrink/enlarge the mask of contour around contour’s center?

Advertisement

Answer

Here is one way to do that in Python/OpenCV.

 - Read the input
 - Convert to grayscale
 - Threshold
 - Use morphology close and open to clean up noise and small regions to form a mask
 - Dilate the mask
 - Erode the mask
 - Merge the input and dilated mask
 - Merge the eroded mask with the previous result
 - Save the result

Input:

enter image description here

import cv2
import numpy as np

# read image
img = cv2.imread("basketball.png")

# convert img to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# make anything not white into black
mask = gray.copy()
mask[mask!=255] = 0

# invert mask so center is white and outside is black
mask = 255 - mask

# close open mask to clean up small regions and make 3 channels
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)

# erode mask
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (51,51))
erode = cv2.morphologyEx(mask, cv2.MORPH_ERODE, kernel)

# dilate mask and make 3 channels
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (51,51))
dilate = cv2.morphologyEx(mask, cv2.MORPH_DILATE, kernel)

# merge image onto dilated mask using mask
result = np.where(mask==(255,255,255), img, dilate)

# merge inverted erode onto result using erode
result = np.where(erode==(255,255,255), (255-erode), result)

# write result to disk
cv2.imwrite("basketball_mask.png", mask)
cv2.imwrite("basketball_eroded_mask.png", erode)
cv2.imwrite("basketball_dilate_mask.png", dilate)
cv2.imwrite("basketball_dilate_mask.png", dilate)
cv2.imwrite("basketball_result.png", result)

# display it
cv2.imshow("image", img)
cv2.imshow("mask", mask)
cv2.imshow("erode", erode)
cv2.imshow("dilate", dilate)
cv2.imshow("result", result)
cv2.waitKey(0)

Mask:

enter image description here

Erode mask:

enter image description here

Dilate mask:

enter image description here

Result:

enter image description here

Note: If you dilate too much, you reach the edges of the image and then the shape changes. To avoid that, pad the input with background color enough to contain the dilated size.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement