|
| 1 | +import numpy as np |
| 2 | +from PIL import Image |
| 3 | + |
| 4 | + |
| 5 | +def rgb2gray(rgb: np.array) -> np.array: |
| 6 | + """ |
| 7 | + Return gray image from rgb image |
| 8 | + >>> rgb2gray(np.array([[[127, 255, 0]]])) |
| 9 | + array([[187.6453]]) |
| 10 | + >>> rgb2gray(np.array([[[0, 0, 0]]])) |
| 11 | + array([[0.]]) |
| 12 | + >>> rgb2gray(np.array([[[2, 4, 1]]])) |
| 13 | + array([[3.0598]]) |
| 14 | + >>> rgb2gray(np.array([[[26, 255, 14], [5, 147, 20], [1, 200, 0]]])) |
| 15 | + array([[159.0524, 90.0635, 117.6989]]) |
| 16 | + """ |
| 17 | + r, g, b = rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2] |
| 18 | + return 0.2989 * r + 0.5870 * g + 0.1140 * b |
| 19 | + |
| 20 | + |
| 21 | +def gray2binary(gray: np.array) -> np.array: |
| 22 | + """ |
| 23 | + Return binary image from gray image |
| 24 | + >>> gray2binary(np.array([[127, 255, 0]])) |
| 25 | + array([[False, True, False]]) |
| 26 | + >>> gray2binary(np.array([[0]])) |
| 27 | + array([[False]]) |
| 28 | + >>> gray2binary(np.array([[26.2409, 4.9315, 1.4729]])) |
| 29 | + array([[False, False, False]]) |
| 30 | + >>> gray2binary(np.array([[26, 255, 14], [5, 147, 20], [1, 200, 0]])) |
| 31 | + array([[False, True, False], |
| 32 | + [False, True, False], |
| 33 | + [False, True, False]]) |
| 34 | + """ |
| 35 | + return (127 < gray) & (gray <= 255) |
| 36 | + |
| 37 | + |
| 38 | +def erosion(image: np.array, kernel: np.array) -> np.array: |
| 39 | + """ |
| 40 | + Return eroded image |
| 41 | + >>> erosion(np.array([[True, True, False]]), np.array([[0, 1, 0]])) |
| 42 | + array([[False, False, False]]) |
| 43 | + >>> erosion(np.array([[True, False, False]]), np.array([[1, 1, 0]])) |
| 44 | + array([[False, False, False]]) |
| 45 | + """ |
| 46 | + output = np.zeros_like(image) |
| 47 | + image_padded = np.zeros( |
| 48 | + (image.shape[0] + kernel.shape[0] - 1, image.shape[1] + kernel.shape[1] - 1) |
| 49 | + ) |
| 50 | + |
| 51 | + # Copy image to padded image |
| 52 | + image_padded[kernel.shape[0] - 2 : -1 :, kernel.shape[1] - 2 : -1 :] = image |
| 53 | + |
| 54 | + # Iterate over image & apply kernel |
| 55 | + for x in range(image.shape[1]): |
| 56 | + for y in range(image.shape[0]): |
| 57 | + summation = ( |
| 58 | + kernel * image_padded[y : y + kernel.shape[0], x : x + kernel.shape[1]] |
| 59 | + ).sum() |
| 60 | + output[y, x] = int(summation == 5) |
| 61 | + return output |
| 62 | + |
| 63 | + |
| 64 | +# kernel to be applied |
| 65 | +structuring_element = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]]) |
| 66 | + |
| 67 | +if __name__ == "__main__": |
| 68 | + # read original image |
| 69 | + image = np.array(Image.open(r"..\image_data\lena.jpg")) |
| 70 | + # Apply erosion operation to a binary image |
| 71 | + output = erosion(gray2binary(rgb2gray(image)), structuring_element) |
| 72 | + # Save the output image |
| 73 | + pil_img = Image.fromarray(output).convert("RGB") |
| 74 | + pil_img.save("result_erosion.png") |
0 commit comments