Home > Back-end >  How to extend mask region (True) by 1 or 2 pixels?
How to extend mask region (True) by 1 or 2 pixels?

Time:05-13

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 !

CodePudding user response:

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

CodePudding user response:

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])

  • Related