Added morphological operations, fixes: #5197 (#5199)

* Added morphological operations, fixes: #5197

* Added dilation tests and type hints

* Added erosion tests and type hints

* fixes: TheAlgorithms#5197

* fixes: TheAlgorithms#5197

* Update erosion_operation.py

* made suggested changes in dilation

* made suggested changes in erosion

* made suggested changes in dilation

* removed extra spaces in the tests

* removed extra spaces in the tests
This commit is contained in:
Saurabh Suresh Powar 2021-10-16 20:02:40 +05:30 committed by GitHub
parent 37385883aa
commit 433b804f7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 148 additions and 0 deletions

View File

@ -0,0 +1,74 @@
import numpy as np
from PIL import Image
def rgb2gray(rgb: np.array) -> np.array:
"""
Return gray image from rgb image
>>> rgb2gray(np.array([[[127, 255, 0]]]))
array([[187.6453]])
>>> rgb2gray(np.array([[[0, 0, 0]]]))
array([[0.]])
>>> rgb2gray(np.array([[[2, 4, 1]]]))
array([[3.0598]])
>>> rgb2gray(np.array([[[26, 255, 14], [5, 147, 20], [1, 200, 0]]]))
array([[159.0524, 90.0635, 117.6989]])
"""
r, g, b = rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2]
return 0.2989 * r + 0.5870 * g + 0.1140 * b
def gray2binary(gray: np.array) -> np.array:
"""
Return binary image from gray image
>>> gray2binary(np.array([[127, 255, 0]]))
array([[False, True, False]])
>>> gray2binary(np.array([[0]]))
array([[False]])
>>> gray2binary(np.array([[26.2409, 4.9315, 1.4729]]))
array([[False, False, False]])
>>> gray2binary(np.array([[26, 255, 14], [5, 147, 20], [1, 200, 0]]))
array([[False, True, False],
[False, True, False],
[False, True, False]])
"""
return (127 < gray) & (gray <= 255)
def dilation(image: np.array, kernel: np.array) -> np.array:
"""
Return dilated image
>>> dilation(np.array([[True, False, True]]), np.array([[0, 1, 0]]))
array([[False, False, False]])
>>> dilation(np.array([[False, False, True]]), np.array([[1, 0, 1]]))
array([[False, False, False]])
"""
output = np.zeros_like(image)
image_padded = np.zeros(
(image.shape[0] + kernel.shape[0] - 1, image.shape[1] + kernel.shape[1] - 1)
)
# Copy image to padded image
image_padded[kernel.shape[0] - 2 : -1 :, kernel.shape[1] - 2 : -1 :] = image
# Iterate over image & apply kernel
for x in range(image.shape[1]):
for y in range(image.shape[0]):
summation = (
kernel * image_padded[y : y + kernel.shape[0], x : x + kernel.shape[1]]
).sum()
output[y, x] = int(summation > 0)
return output
# kernel to be applied
structuring_element = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])
if __name__ == "__main__":
# read original image
image = np.array(Image.open(r"..\image_data\lena.jpg"))
output = dilation(gray2binary(rgb2gray(image)), structuring_element)
# Save the output image
pil_img = Image.fromarray(output).convert("RGB")
pil_img.save("result_dilation.png")

View File

@ -0,0 +1,74 @@
import numpy as np
from PIL import Image
def rgb2gray(rgb: np.array) -> np.array:
"""
Return gray image from rgb image
>>> rgb2gray(np.array([[[127, 255, 0]]]))
array([[187.6453]])
>>> rgb2gray(np.array([[[0, 0, 0]]]))
array([[0.]])
>>> rgb2gray(np.array([[[2, 4, 1]]]))
array([[3.0598]])
>>> rgb2gray(np.array([[[26, 255, 14], [5, 147, 20], [1, 200, 0]]]))
array([[159.0524, 90.0635, 117.6989]])
"""
r, g, b = rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2]
return 0.2989 * r + 0.5870 * g + 0.1140 * b
def gray2binary(gray: np.array) -> np.array:
"""
Return binary image from gray image
>>> gray2binary(np.array([[127, 255, 0]]))
array([[False, True, False]])
>>> gray2binary(np.array([[0]]))
array([[False]])
>>> gray2binary(np.array([[26.2409, 4.9315, 1.4729]]))
array([[False, False, False]])
>>> gray2binary(np.array([[26, 255, 14], [5, 147, 20], [1, 200, 0]]))
array([[False, True, False],
[False, True, False],
[False, True, False]])
"""
return (127 < gray) & (gray <= 255)
def erosion(image: np.array, kernel: np.array) -> np.array:
"""
Return eroded image
>>> erosion(np.array([[True, True, False]]), np.array([[0, 1, 0]]))
array([[False, False, False]])
>>> erosion(np.array([[True, False, False]]), np.array([[1, 1, 0]]))
array([[False, False, False]])
"""
output = np.zeros_like(image)
image_padded = np.zeros(
(image.shape[0] + kernel.shape[0] - 1, image.shape[1] + kernel.shape[1] - 1)
)
# Copy image to padded image
image_padded[kernel.shape[0] - 2 : -1 :, kernel.shape[1] - 2 : -1 :] = image
# Iterate over image & apply kernel
for x in range(image.shape[1]):
for y in range(image.shape[0]):
summation = (
kernel * image_padded[y : y + kernel.shape[0], x : x + kernel.shape[1]]
).sum()
output[y, x] = int(summation == 5)
return output
# kernel to be applied
structuring_element = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])
if __name__ == "__main__":
# read original image
image = np.array(Image.open(r"..\image_data\lena.jpg"))
# Apply erosion operation to a binary image
output = erosion(gray2binary(rgb2gray(image)), structuring_element)
# Save the output image
pil_img = Image.fromarray(output).convert("RGB")
pil_img.save("result_erosion.png")