# Dilation, Erosion, Opening and Closing of Binary Images in Python

# Binarizing the Image

A binary image is a 1-bit image in which each pixel, instead of being a value from 1 to 255 or an array of numbers [r, g, b], is either 0 or 1 — 0 being completely black and 1 being completely white. This may be reversed according to your image decoder.

Using Python’s PIL package we can write an algorithm that binarizes RGB images based on a *threshold*. If the mean of red, green and blue values is higher than the threshold, we go with either 0 or 1, or vice versa.

```
def binarize_image(threshold, inimage, outimage):
for i in range(inimage.size[0]):
for j in range(inimage.size[1]):
if np.mean(inimage.getpixel((i, j))) > threshold:
outimage.putpixel((i, j), 1)
else:
outimage.putpixel((i, j), 0)
```

So if we open this image:

And create a blank image:

```
im = Image.open("/content/screws.jpeg")
out = Image.new('1', im.size, 0xffffff)
```

After thresholding it with a value of 125 we get:

We’re going to use this image for 4 widely used operations on binary images: erosion, dilation, opening, closing.

# Erosion

Erosion is basically retracting of the black pixels. Imagine a Matrix A and a 3x3 matrix B:

```
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 0 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
```

If for each pixel, we superimpose the origin of B, if B is completely contained by A the pixels are retained, else, turned to the white pixel.

```
0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 1 1 1 0 0 0 1 1 1 1 0
0 1 1 1 1 0 0 0 1 1 1 1 0
0 1 1 1 1 1 1 1 1 1 1 1 0
0 1 1 1 1 1 1 1 1 1 1 1 0
0 1 1 1 1 1 1 1 1 1 1 1 0
0 1 1 1 1 1 1 1 1 1 1 1 0
0 1 1 1 1 1 1 1 1 1 1 1 0
0 1 1 1 1 1 1 1 1 1 1 1 0
0 1 1 1 1 1 1 1 1 1 1 1 0
0 1 1 1 1 1 1 1 1 1 1 1 0
0 1 1 1 1 1 1 1 1 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0
```

The code for this in Python is:

```
def erosion(imin):
imout = imin.copy()
for i in range(1, imin.size[0] - 1):
for j in range(2, imin.size[1] - 1):
if imin.getpixel((i, j)) == 1:
for m in [0, 1, -1]:
for n in [0, 1, -1]:
imout.putpixel((i + m, j + n), 1)
else:
continue
return imout
```

The result is:

# Dilation

Dilation is the exact opposite of erosion, it *expands* the black pixels. The code for it is:

```
def dilation(imin):
imout = imin.copy()
for i in range(1, imin.size[0] - 1):
for j in range(2, imin.size[1] - 1):
if imin.getpixel((i, j)) == 0:
for m in [0, 1, -1]:
for n in [0, 1, -1]:
imout.putpixel((i + m, j + n), 0)
else:
continue
return imout
```

The result is:

# Mathematical Notation for Erosion and Dilation and their Duality

There’s a *duality* between dilation and erosion. if A is the image and B is the 3x3 mask we saw above:

# Closing and Opening

Closing and opening are summarily defined as:

The codes for them are:

```
def opening(imgin):
imgout = imgin.copy()
for i in range(2, imgin.size[0] - 2):
for j in range(2, imgin.size[1] - 2):
if imgin.getpixel((i, j)) == 1:
for m in [0, 2, -2]:
for n in [0, 2, -2]:
if imgin.getpixel((i + m, j + n)) == 0:
imgout.putpixel((i + abs(m) - 1, j + abs(n) - 1), 1)
return imgout
def closing(imgin):
imgout = imgin.copy()
for i in range(2, imgin.size[0] - 2):
for j in range(2, imgin.size[1] - 2):
if imgin.getpixel((i, j)) == 0:
for m in [0, 2, -2]:
for n in [0, 2, -2]:
if imgin.getpixel((i + m, j + n)) == 1:
imgout.putpixel((i + abs(m) - 1, j + abs(n) - 1), 0)
return imgout
```

The results are:

For opening and for closing:

Hope you enjoyed this!