I have an image with an object like below:
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:
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.
JavaScript
x
10
10
1
- Read the input
2
- Convert to grayscale
3
- Threshold
4
- Use morphology close and open to clean up noise and small regions to form a mask
5
- Dilate the mask
6
- Erode the mask
7
- Merge the input and dilated mask
8
- Merge the eroded mask with the previous result
9
- Save the result
10
Input:
JavaScript
1
51
51
1
import cv2
2
import numpy as np
3
4
# read image
5
img = cv2.imread("basketball.png")
6
7
# convert img to grayscale
8
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
9
10
# make anything not white into black
11
mask = gray.copy()
12
mask[mask!=255] = 0
13
14
# invert mask so center is white and outside is black
15
mask = 255 - mask
16
17
# close open mask to clean up small regions and make 3 channels
18
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
19
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
20
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
21
mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
22
23
# erode mask
24
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (51,51))
25
erode = cv2.morphologyEx(mask, cv2.MORPH_ERODE, kernel)
26
27
# dilate mask and make 3 channels
28
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (51,51))
29
dilate = cv2.morphologyEx(mask, cv2.MORPH_DILATE, kernel)
30
31
# merge image onto dilated mask using mask
32
result = np.where(mask==(255,255,255), img, dilate)
33
34
# merge inverted erode onto result using erode
35
result = np.where(erode==(255,255,255), (255-erode), result)
36
37
# write result to disk
38
cv2.imwrite("basketball_mask.png", mask)
39
cv2.imwrite("basketball_eroded_mask.png", erode)
40
cv2.imwrite("basketball_dilate_mask.png", dilate)
41
cv2.imwrite("basketball_dilate_mask.png", dilate)
42
cv2.imwrite("basketball_result.png", result)
43
44
# display it
45
cv2.imshow("image", img)
46
cv2.imshow("mask", mask)
47
cv2.imshow("erode", erode)
48
cv2.imshow("dilate", dilate)
49
cv2.imshow("result", result)
50
cv2.waitKey(0)
51
Mask:
Erode mask:
Dilate mask:
Result:
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.