From 5c908c72a0b743a1ad31bb7e8530039755f972f7 Mon Sep 17 00:00:00 2001 From: Saurabh Suresh Powar <66636289+Spnetic-5@users.noreply.github.com> Date: Sun, 10 Oct 2021 17:35:52 +0530 Subject: [PATCH 01/11] Added morphological operations, fixes: #5197 --- .../dilation_operation.py | 59 +++++++++++++++++++ .../erosion_operation.py | 58 ++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 digital_image_processing/morphological_operations/dilation_operation.py create mode 100644 digital_image_processing/morphological_operations/erosion_operation.py diff --git a/digital_image_processing/morphological_operations/dilation_operation.py b/digital_image_processing/morphological_operations/dilation_operation.py new file mode 100644 index 000000000000..90fce023b581 --- /dev/null +++ b/digital_image_processing/morphological_operations/dilation_operation.py @@ -0,0 +1,59 @@ +import numpy as np +from PIL import Image + + +def rgb2gray(rgb): + """ + Return gray image from rgb image + """ + r, g, b = rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2] + gray = 0.2989 * r + 0.5870 * g + 0.1140 * b + return gray + + +def gray2binary(gray): + """ + Return binary image from gray image + """ + return (127 < gray) & (gray <= 255) + + +def dilation(image, kernel): + """ + Return dilated image + """ + 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() + if summation > 0: + output[y, x] = 1 + else: + output[y, x] = 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")) + # convert it into binary image + binary = gray2binary(rgb2gray(image)) + # Apply dilation operation + output = dilation(binary, structuring_element) + # Save the output image + pil_img = Image.fromarray(output).convert("RGB") + pil_img.save("result_dilation.png") diff --git a/digital_image_processing/morphological_operations/erosion_operation.py b/digital_image_processing/morphological_operations/erosion_operation.py new file mode 100644 index 000000000000..a40ac5d9e7bc --- /dev/null +++ b/digital_image_processing/morphological_operations/erosion_operation.py @@ -0,0 +1,58 @@ +import numpy as np +from PIL import Image + + +def rgb2gray(rgb): + """ + Return gray image from rgb image + """ + r, g, b = rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2] + gray = 0.2989 * r + 0.5870 * g + 0.1140 * b + return gray + + +def gray2binary(gray): + """ + Return binary image from gray image + """ + return (127 < gray) & (gray <= 255) + + +def erosion(image, kernel): + """ + Return eroded image + """ + 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() + if summation == 5: + output[y, x] = 1 + else: + output[y, x] = 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")) + # convert it into binary image + binary = gray2binary(rgb2gray(image)) + # Apply erosion operation + output = erosion(binary, structuring_element) + # Save the output image + pil_img = Image.fromarray(output).convert("RGB") + pil_img.save("result_erosion.png") From e195500e68bbf122e0e16097e1e032390de7b93f Mon Sep 17 00:00:00 2001 From: Saurabh Suresh Powar <66636289+Spnetic-5@users.noreply.github.com> Date: Mon, 11 Oct 2021 01:44:12 +0530 Subject: [PATCH 02/11] Added dilation tests and type hints --- .../dilation_operation.py | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/digital_image_processing/morphological_operations/dilation_operation.py b/digital_image_processing/morphological_operations/dilation_operation.py index 90fce023b581..215311422ba8 100644 --- a/digital_image_processing/morphological_operations/dilation_operation.py +++ b/digital_image_processing/morphological_operations/dilation_operation.py @@ -2,25 +2,47 @@ from PIL import Image -def rgb2gray(rgb): +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] gray = 0.2989 * r + 0.5870 * g + 0.1140 * b return gray -def gray2binary(gray): +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, kernel): +def dilation(image: np.array, kernel: np.array) -> np.array: """ Return dilated image + >>> dilation(np.array([[True, False, True]]), np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])) + array([[ True, True, True]]) + >>> dilation(np.array([[True, False, False]]), np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])) + array([[ True, True, False]]) """ output = np.zeros_like(image) image_padded = np.zeros( From e625df39875991cc1c3746eb64299f959588dafd Mon Sep 17 00:00:00 2001 From: Saurabh Suresh Powar <66636289+Spnetic-5@users.noreply.github.com> Date: Mon, 11 Oct 2021 01:45:30 +0530 Subject: [PATCH 03/11] Added erosion tests and type hints --- .../erosion_operation.py | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/digital_image_processing/morphological_operations/erosion_operation.py b/digital_image_processing/morphological_operations/erosion_operation.py index a40ac5d9e7bc..5bff87952c82 100644 --- a/digital_image_processing/morphological_operations/erosion_operation.py +++ b/digital_image_processing/morphological_operations/erosion_operation.py @@ -2,25 +2,47 @@ from PIL import Image -def rgb2gray(rgb): +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] gray = 0.2989 * r + 0.5870 * g + 0.1140 * b return gray -def gray2binary(gray): +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, kernel): +def erosion(image: np.array, kernel: np.array) -> np.array: """ Return eroded image + >>> erosion(np.array([[True, True, False]]), np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])) + array([[False, False, False]]) + >>> erosion(np.array([[True, False, False]]), np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])) + array([[False, False, False]]) """ output = np.zeros_like(image) image_padded = np.zeros( From f07017ccf109ec0fe47dd11e61a227701c71252c Mon Sep 17 00:00:00 2001 From: Saurabh Suresh Powar <66636289+Spnetic-5@users.noreply.github.com> Date: Mon, 11 Oct 2021 13:10:56 +0530 Subject: [PATCH 04/11] fixes: TheAlgorithms#5197 --- .../morphological_operations/dilation_operation.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/digital_image_processing/morphological_operations/dilation_operation.py b/digital_image_processing/morphological_operations/dilation_operation.py index 215311422ba8..b8cb34bc6822 100644 --- a/digital_image_processing/morphological_operations/dilation_operation.py +++ b/digital_image_processing/morphological_operations/dilation_operation.py @@ -39,10 +39,10 @@ def gray2binary(gray: np.array) -> np.array: def dilation(image: np.array, kernel: np.array) -> np.array: """ Return dilated image - >>> dilation(np.array([[True, False, True]]), np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])) - array([[ True, True, True]]) - >>> dilation(np.array([[True, False, False]]), np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])) - array([[ True, True, False]]) + >>> 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( From 555cc5f576e57aa2d7a8174b5d67ede37c4d25d0 Mon Sep 17 00:00:00 2001 From: Saurabh Suresh Powar <66636289+Spnetic-5@users.noreply.github.com> Date: Mon, 11 Oct 2021 13:11:25 +0530 Subject: [PATCH 05/11] fixes: TheAlgorithms#5197 --- .../morphological_operations/erosion_operation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/digital_image_processing/morphological_operations/erosion_operation.py b/digital_image_processing/morphological_operations/erosion_operation.py index 5bff87952c82..6de9cd3f5a4a 100644 --- a/digital_image_processing/morphological_operations/erosion_operation.py +++ b/digital_image_processing/morphological_operations/erosion_operation.py @@ -37,11 +37,11 @@ def gray2binary(gray: np.array) -> np.array: def erosion(image: np.array, kernel: np.array) -> np.array: - """ + """ Return eroded image - >>> erosion(np.array([[True, True, False]]), np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])) + >>> erosion(np.array([[True, True, False]]), np.array([[0, 1, 0]])) array([[False, False, False]]) - >>> erosion(np.array([[True, False, False]]), np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])) + >>> erosion(np.array([[True, False, False]]), np.array([[1, 1, 0]])) array([[False, False, False]]) """ output = np.zeros_like(image) From 0913eb21fdff475685ce03a66428c1f04783af19 Mon Sep 17 00:00:00 2001 From: Saurabh Suresh Powar <66636289+Spnetic-5@users.noreply.github.com> Date: Mon, 11 Oct 2021 13:12:09 +0530 Subject: [PATCH 06/11] Update erosion_operation.py --- .../morphological_operations/erosion_operation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/digital_image_processing/morphological_operations/erosion_operation.py b/digital_image_processing/morphological_operations/erosion_operation.py index 6de9cd3f5a4a..5950e217f25c 100644 --- a/digital_image_processing/morphological_operations/erosion_operation.py +++ b/digital_image_processing/morphological_operations/erosion_operation.py @@ -37,7 +37,7 @@ def gray2binary(gray: np.array) -> np.array: 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]]) From eb0b4f561547b1c1a12fe48dde577acd789fd1fa Mon Sep 17 00:00:00 2001 From: Saurabh Suresh Powar <66636289+Spnetic-5@users.noreply.github.com> Date: Sat, 16 Oct 2021 19:15:43 +0530 Subject: [PATCH 07/11] made suggested changes in dilation --- .../morphological_operations/dilation_operation.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/digital_image_processing/morphological_operations/dilation_operation.py b/digital_image_processing/morphological_operations/dilation_operation.py index b8cb34bc6822..c05fbb3cfeb0 100644 --- a/digital_image_processing/morphological_operations/dilation_operation.py +++ b/digital_image_processing/morphological_operations/dilation_operation.py @@ -15,8 +15,7 @@ def rgb2gray(rgb: np.array) -> np.array: array([[159.0524, 90.0635, 117.6989]]) """ r, g, b = rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2] - gray = 0.2989 * r + 0.5870 * g + 0.1140 * b - return gray + return 0.2989 * r + 0.5870 * g + 0.1140 * b def gray2binary(gray: np.array) -> np.array: @@ -58,10 +57,7 @@ def dilation(image: np.array, kernel: np.array) -> np.array: summation = ( kernel * image_padded[y : y + kernel.shape[0], x : x + kernel.shape[1]] ).sum() - if summation > 0: - output[y, x] = 1 - else: - output[y, x] = 0 + output[y, x] = int(summation > 0) return output From d2146b8779dd27166e9660963688a45f79b3b8d5 Mon Sep 17 00:00:00 2001 From: Saurabh Suresh Powar <66636289+Spnetic-5@users.noreply.github.com> Date: Sat, 16 Oct 2021 19:18:53 +0530 Subject: [PATCH 08/11] made suggested changes in erosion --- .../morphological_operations/erosion_operation.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/digital_image_processing/morphological_operations/erosion_operation.py b/digital_image_processing/morphological_operations/erosion_operation.py index 5950e217f25c..e8fe375079a9 100644 --- a/digital_image_processing/morphological_operations/erosion_operation.py +++ b/digital_image_processing/morphological_operations/erosion_operation.py @@ -15,8 +15,7 @@ def rgb2gray(rgb: np.array) -> np.array: array([[159.0524, 90.0635, 117.6989]]) """ r, g, b = rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2] - gray = 0.2989 * r + 0.5870 * g + 0.1140 * b - return gray + return 0.2989 * r + 0.5870 * g + 0.1140 * b def gray2binary(gray: np.array) -> np.array: @@ -58,10 +57,7 @@ def erosion(image: np.array, kernel: np.array) -> np.array: summation = ( kernel * image_padded[y : y + kernel.shape[0], x : x + kernel.shape[1]] ).sum() - if summation == 5: - output[y, x] = 1 - else: - output[y, x] = 0 + output[y, x] = int(summation == 5) return output @@ -71,10 +67,8 @@ def erosion(image: np.array, kernel: np.array) -> np.array: if __name__ == "__main__": # read original image image = np.array(Image.open(r"..\image_data\lena.jpg")) - # convert it into binary image - binary = gray2binary(rgb2gray(image)) - # Apply erosion operation - output = erosion(binary, structuring_element) + # 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") From dffb122261b27d1c019cd19c78d9300210b8a21e Mon Sep 17 00:00:00 2001 From: Saurabh Suresh Powar <66636289+Spnetic-5@users.noreply.github.com> Date: Sat, 16 Oct 2021 19:19:48 +0530 Subject: [PATCH 09/11] made suggested changes in dilation --- .../morphological_operations/dilation_operation.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/digital_image_processing/morphological_operations/dilation_operation.py b/digital_image_processing/morphological_operations/dilation_operation.py index c05fbb3cfeb0..1ed3d6f14c98 100644 --- a/digital_image_processing/morphological_operations/dilation_operation.py +++ b/digital_image_processing/morphological_operations/dilation_operation.py @@ -68,10 +68,7 @@ def dilation(image: np.array, kernel: np.array) -> np.array: if __name__ == "__main__": # read original image image = np.array(Image.open(r"..\image_data\lena.jpg")) - # convert it into binary image - binary = gray2binary(rgb2gray(image)) - # Apply dilation operation - output = dilation(binary, structuring_element) + output = dilation(gray2binary(rgb2gray(image)), structuring_element) # Save the output image pil_img = Image.fromarray(output).convert("RGB") pil_img.save("result_dilation.png") From 5c4c622c2074072f101d50ddf6d1ce4f98c70795 Mon Sep 17 00:00:00 2001 From: Saurabh Suresh Powar <66636289+Spnetic-5@users.noreply.github.com> Date: Sat, 16 Oct 2021 19:31:50 +0530 Subject: [PATCH 10/11] removed extra spaces in the tests --- .../morphological_operations/dilation_operation.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/digital_image_processing/morphological_operations/dilation_operation.py b/digital_image_processing/morphological_operations/dilation_operation.py index 1ed3d6f14c98..274880b0a50a 100644 --- a/digital_image_processing/morphological_operations/dilation_operation.py +++ b/digital_image_processing/morphological_operations/dilation_operation.py @@ -9,9 +9,9 @@ def rgb2gray(rgb: np.array) -> np.array: array([[187.6453]]) >>> rgb2gray(np.array([[[0, 0, 0]]])) array([[0.]]) - >>> rgb2gray(np.array([[[2, 4, 1]]])) + >>> rgb2gray(np.array([[[2, 4, 1]]])) array([[3.0598]]) - >>> rgb2gray(np.array([[[26, 255, 14], [ 5, 147, 20], [ 1, 200, 0]]])) + >>> 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] @@ -25,9 +25,9 @@ def gray2binary(gray: np.array) -> np.array: array([[False, True, False]]) >>> gray2binary(np.array([[0]])) array([[False]]) - >>> gray2binary(np.array([[26.2409, 4.9315, 1.4729]])) + >>> 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]])) + >>> gray2binary(np.array([[26, 255, 14], [5, 147, 20], [1, 200, 0]])) array([[False, True, False], [False, True, False], [False, True, False]]) From 09a845e693fbd018dd39d95079215d06b40f3897 Mon Sep 17 00:00:00 2001 From: Saurabh Suresh Powar <66636289+Spnetic-5@users.noreply.github.com> Date: Sat, 16 Oct 2021 19:32:51 +0530 Subject: [PATCH 11/11] removed extra spaces in the tests --- .../morphological_operations/erosion_operation.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/digital_image_processing/morphological_operations/erosion_operation.py b/digital_image_processing/morphological_operations/erosion_operation.py index e8fe375079a9..4b0a5eee8c03 100644 --- a/digital_image_processing/morphological_operations/erosion_operation.py +++ b/digital_image_processing/morphological_operations/erosion_operation.py @@ -9,9 +9,9 @@ def rgb2gray(rgb: np.array) -> np.array: array([[187.6453]]) >>> rgb2gray(np.array([[[0, 0, 0]]])) array([[0.]]) - >>> rgb2gray(np.array([[[2, 4, 1]]])) + >>> rgb2gray(np.array([[[2, 4, 1]]])) array([[3.0598]]) - >>> rgb2gray(np.array([[[26, 255, 14], [ 5, 147, 20], [ 1, 200, 0]]])) + >>> 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] @@ -25,9 +25,9 @@ def gray2binary(gray: np.array) -> np.array: array([[False, True, False]]) >>> gray2binary(np.array([[0]])) array([[False]]) - >>> gray2binary(np.array([[26.2409, 4.9315, 1.4729]])) + >>> 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]])) + >>> gray2binary(np.array([[26, 255, 14], [5, 147, 20], [1, 200, 0]])) array([[False, True, False], [False, True, False], [False, True, False]])