'How to extend mask region (True) by 1 or 2 pixels?
I have a numpy mask of True and False values, detecting black regions in an image.
I want to extend the True regions by 1 or 2 pixel.
For example, considering this mask:
[[False False False False False]
[False False TRUE False False]
[False TRUE TRUE TRUE False]
[False False TRUE False False]
[False False False False False]
I want to have:
[[False False TRUE False False]
[False TRUE TRUE TRUE False]
[TRUE TRUE TRUE TRUE TRUE ]
[False TRUE TRUE TRUE False]
[False False TRUE False False]
Actually I could have made a for loop, but in a big image it's to slow.
Any ideas ?
Thanks !
Solution 1:[1]
Dilation is the easiest way to extend the "True" regions.
Consider the array:
a = np.array([[False, False, False, False, False],
[False, False, True, False, False],
[False, True, True, True, False],
[False, False, True, False, False],
[False, False, False, False, False]])
Convert to integer data type
a = a.astype(np.uint8)
You get:
array([[0, 0, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 1, 1, 1, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, 0]], dtype=uint8)
Perform dilation using ellipse kernel of size 3x3:
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
dilate = cv2.dilate(a, kernel, iterations=1)
dilate:
array([[0, 0, 1, 0, 0],
[0, 1, 1, 1, 0],
[1, 1, 1, 1, 1],
[0, 1, 1, 1, 0],
[0, 0, 1, 0, 0]], dtype=uint8)
Convert the result to boolean data type:
d = np.array(dilate, dtype=bool)
Resulting array:
array([[False, False, True, False, False],
[False, True, True, True, False],
[ True, True, True, True, True],
[False, True, True, True, False],
[False, False, True, False, False]])
To extend the True regions further:
- increase the kernel size
- repeat dilation operation using
iteration
Note: Boolean array cannot be used as input with cv2.dilate(), or else it throws error: (-5:Bad argument). Hence we convert it to int data type, perform the opertion and convert it back to bool data type.
It seems
Solution 2:[2]
You can use the boolean sum:
new_mask = mask.copy()
new_mask[:,1:] = mask[:,1:]+mask[:,:-1]
new_mask[1:,:] = new_mask[1:,:]+mask[:-1,:]
new_mask now is:
array([[False, False, False, False, False],
[False, False, True, False, False],
[False, True, True, True, True],
[False, True, True, True, False],
[False, False, True, False, False]])
the sum between two boolean works as a logical or, so in the previous lines of code you are saying: new_mask[i,j] = (mask[i,j] or mask[i,j-1] or mask[i-1,j])
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
