# How to remove the hotspots from given image by using Python and opencv?

In the picture below there are some regions which are very bright (i.e. more white). Some bright regions are wide and some are narrow or thin. The red box covers one such wide bright spot, and blue box covers one thin bright spot. Thin bright spots are called edges and wide bright spots are called hot-spots.

I want to remove all the hot-spots from the image (i.e. make them black), but no edge should be removed.

My question is how to write Python code using OpenCV to remove all hot-spots but no edge?

Based on this answer's algorithm I have written my code which is working as intended.

Here's a breakdown of the coding steps:

1. Otsu's thresholding is applied to the grayscale image1 using cv2.threshold() with the cv2.THRESH_BINARY + cv2.THRESH_OTSU flag to obtain image2.

2. Erosion is performed on image2 using cv2.erode() with a square kernel to obtain image3.

3. The threshold distance K is defined.

4. 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.

5. 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

# 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:

• Nice. Can you also add the image result? That way it will be easy for people to see whether this could be applicable also to their situation? Commented Jun 3, 2023 at 18:06
• Is it me or mask is not used in the algorithm? Commented Jun 5, 2023 at 14:35
• @SébastienVincent see my updated answer which is very concise. Commented Jun 6, 2023 at 6:59

Can you try the following approach using OpenCV

The logic behind this is:

1. Convert the image to grayscale.

2. Apply a Gaussian blur to the image to smooth out the edges.

3. Threshold the image to create a binary image where the hot-spots are white and the rest of the image is black.

4. Dilate the binary image to fill in any small holes in the hot-spots.

5. Find the contours in the dilated image.

6. Iterate over the contours and remove any that are not large enough.

7. Fill in all of the remaining contours with black.

  import cv2

def remove_hotspots(image):
# Convert the image to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Apply a Gaussian blur to the image to smooth out the edges
blur = cv2.GaussianBlur(gray, (5, 5), 0)

# Threshold the image to create a binary image where the hot-spots are white and the rest of the image is black
threshold = cv2.threshold(blur, 128, 255, cv2.THRESH_BINARY)[1]

# Dilate the binary image to fill in any small holes in the hot-spots
dilated = cv2.dilate(threshold, None, iterations=2)

# Find the contours in the dilated image
contours, hierarchy = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Iterate over the contours and remove any that are not large enough
for i in range(len(contours)):
if cv2.contourArea(contours[i]) < 100:
continue

# Fill in the contour with black
cv2.drawContours(image, contours, i, 0, -1)

return image

if __name__ == "__main__":