Based on this answer's algorithm I have written my code which is working as intended.
Here's a breakdown of the coding steps:
Otsu's thresholding is applied to the grayscale image1
using cv2.threshold()
with the cv2.THRESH_BINARY + cv2.THRESH_OTSU
flag to obtain image2
.
Erosion is performed on image2
using cv2.erode()
with a square kernel to obtain image3
.
The threshold distance K
is defined.
You then compare to 0 for pixels where image2
is larger than 0. So you can combine the result of the two full-image comparisons with the logical and(&)
operator, and use the result to index into the output image.
The final image
is displayed using cv2.imshow()
.
Note that a square region with side 2*K
is used instead of a circular mask in this implementation.
The choice between a circular or square area can be adjusted by modifying the mask variable in the code.
Feel free to adjust the threshold distance K
and experiment with different shapes and sizes of the neighborhood mask to suit your specific requirements.
import cv2
import numpy as np
# Load the image
image1 = cv2.imread('orange.jpg', cv2.IMREAD_GRAYSCALE)
# Otsu's thresholding
_, image2 = cv2.threshold(image1, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# Erosion
kernel = np.ones((5, 5), np.uint8)
image3 = cv2.erode(image2, kernel, iterations=1)
# Define the threshold distance K
K = 2
# Iterate over image1 pixels and generate the final image
final_image = np.copy(image1)
final_image[(cv2.blur(image3,[2*K+1, 2*K+1]) > 0) & (image2 > 0)] = 0
# Display the original and final image
cv2.imshow('Original image', image1)
cv2.imshow('Final Image', final_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
Output: