jinsom
jinsom

Reputation: 125

How to remove border edge noise from an image using python?

I am trying to preprocess a photo of the eye vessels by removing the black border and extraneous non-eye features in the image (Ex. see below for text and "clip") by replacing the black areas with the average pixel values from 3 random squares.

crop1 = randomCrop(image2, 50, 50) #Function that finds random 50x50 area
crop2 = randomCrop(image2, 50, 50)
crop3 = randomCrop(image2, 50, 50)

mean1 = RGB_Mean(crop1)
mean2 = RGB_Mean(crop2)
mean3 = RGB_Mean(crop3)

#RGB Mean
result = [statistics.mean(k) for k in zip(mean1, mean2, mean3)]

for i in range(len(image2[:,0, 0])):
    for j in range(len(image2[0,:,0])):
        thru_pixel = image2[i, j]
        if (thru_pixel[0] < 50 and thru_pixel[1] < 50 and thru_pixel[2] < 50):
            image2[i,j, :] = result
        if (thru_pixel[0] > 190 and thru_pixel[1] > 190 and thru_pixel[2] > 190):
            image2[i,j, :] = result

However, there is leftover noise around the border of the image, as well as leftover text and a clip at the bottom left.

Here's an example image.

Original :

enter image description here

and Post-Processing

enter image description here

You can see there's still left over black-gray border noise as well as text at the bottom right and a "clip" at the bottom left. Is there anything I could try to get rid of any of these artifacts while maintaining the integrity of the eye blood vessels?

Thank you for your time and help!

Upvotes: 3

Views: 2546

Answers (1)

nathancy
nathancy

Reputation: 46680

Assuming you want to isolate the eye blood vessels, here's an approach which can be broken down into two stages, one to remove the artifacts and another to isolate blood vessels

  • Convert image to grayscale
  • Otsu's threshold to obtain binary image
  • Perform morphological operations to remove artifacts
  • Adaptive threshold to isolate blood vessels
  • Find contours and filter using maximum threshold area
  • Bitwise-and to get final result

Beginning from your original image, we convert to grayscale and Otsu's threshold to obtain a binary image

enter image description here

Now we perform morph open to remove the artifacts (left). We inverse this mask to obtain the white border and then do a series of bitwise operations to get the removed artifacts image (right)

enter image description here enter image description here

From here we adaptive threshold to get the veins

enter image description here

Note there is the unwanted border so we find contours and filter using a maximum threshold area. If a contour passes the filter, we draw it onto a blank mask

enter image description here

Finally we perform bitwise-and on the original image to get our result

enter image description here

Note we could have performed additional morph open after the adaptive threshold to remove the small particles of noise but the tradeoff is that it will remove vein details. I'll leave this optional step up to you

import cv2
import numpy as np

# Grayscale, Otsu's threshold, opening
image = cv2.imread('1.png')
blank_mask = np.zeros(image.shape, dtype=np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15,15))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=3)

inverse = 255 - opening
inverse = cv2.merge([inverse,inverse,inverse])
removed_artifacts = cv2.bitwise_and(image,image,mask=opening)
removed_artifacts = cv2.bitwise_or(removed_artifacts, inverse)

# Isolate blood vessels
veins_gray = cv2.cvtColor(removed_artifacts, cv2.COLOR_BGR2GRAY)
adaptive = cv2.adaptiveThreshold(veins_gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,11,3)

cnts = cv2.findContours(adaptive, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

for c in cnts:
    area = cv2.contourArea(c)
    if area < 5000:
        cv2.drawContours(blank_mask, [c], -1, (255,255,255), 1)

blank_mask = cv2.cvtColor(blank_mask, cv2.COLOR_BGR2GRAY)
final = cv2.bitwise_and(image, image, mask=blank_mask)
# final[blank_mask==0] = (255,255,255) # White version

cv2.imshow('thresh', thresh)
cv2.imshow('opening', opening)
cv2.imshow('removed_artifacts', removed_artifacts)
cv2.imshow('adaptive', adaptive)
cv2.imshow('blank_mask', blank_mask)
cv2.imshow('final', final)
cv2.waitKey()

Upvotes: 3

Related Questions