Konium
Konium

Reputation: 31

How to remove scratches from metallographic images using Python

I have the following image to analyze and extract the porosity out of it (black dots).

metallographic image of porous alloy

My issue is that my code might be picking up on the scratches (defects from polishing the cross-sections). I am looking for a way to remove the scratches.

I tried Inpainting (https://github.com/Chandrika372/Image-Restoration-by-Inpainting-Algorithm/blob/main/Inpainting.py) but the scratches are too small for detection. I also found few examples running on C and with Matlab, but if I use my image as an input, the output is still the same; the scratches seem too fine for the algos.

Any help would be appreciated.

Upvotes: 2

Views: 836

Answers (1)

nathancy
nathancy

Reputation: 46650

A simple Otsu's threshold should do it. The idea is to Gaussian blur to remove noise then cv2.bitwise_and to extract the dots.

Binary image

enter image description here

Result

enter image description here

You can also optionally filter out large/small dots using contour area filtering with a threshold value

import cv2

# Load image, grayscale, Gaussian blur, Otsu's threshold
image = cv2.imread("1.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5,5), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# OPTIONAL to filter out small/large dots using contour area filtering
# Adjust the area to only keep larger dots
'''
DOT_AREA = 10
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area < DOT_AREA:
        cv2.drawContours(thresh, [c], -1, 0, -1)
'''

# Bitwise_and to extract dots
result = cv2.bitwise_and(image, image, mask=thresh)
result[thresh==0] = 255

cv2.imshow("thresh", thresh)
cv2.imshow("result", result)
cv2.waitKey()

Upvotes: 2

Related Questions