How to remove image noise using opencv - python?

4

I am working with skin images, in recognition of skin blemishes, and due to the presence of noises, mainly by the presence of hairs, this work becomes more complicated.

I have an image example in which I work in an attempt to highlight only the skin spot, but due to the large number of hairs, the algorithm is not effective. With this, I would like you to help me develop an algorithm to remove or reduce the number of hairs so that I can only highlight my area of interest (ROI), which are the spots.

Algorithm used to highlight skin blemishes:

import numpy as np
import cv2

#Read the image and perform threshold
img = cv2.imread('IMD006.bmp')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.medianBlur(gray,5)
_,thresh = cv2.threshold(blur,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

#Search for contours and select the biggest one
contours, hierarchy =     cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)

#Create a new mask for the result image
h, w = img.shape[:2]
mask = np.zeros((h, w), np.uint8)

#Draw the contour on the new mask and perform the bitwise operation
cv2.drawContours(mask, [cnt],-1, 255, -1)
res = cv2.bitwise_and(img, img, mask=mask)

#Display the result
cv2.imwrite('IMD006.png', res)
#cv2.imshow('img', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

Image example used:

Output:

Thealgorithmbehavesasexpectedforhairlessimages,asseenbelow:

How to deal with these noises to the point of improving my region of interest?

    
asked by anonymous 10.10.2018 / 22:20

1 answer

2

Solution

  • Creating the mask with:
    • morphologyEx with cv2.MORPH_CLOSE
    • cv2.blur to delete the image
    • Binarization with flag cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU
    • Floodfill to remove the corners of the mask
  • Cut from the original image the one found by the mask, with AND logic
  • Canny Edges to find hair strands and then dilation
  • Remove from the cropped image the one found by Canny Edges, with OR logic
  • Use the Inpaint interpolation of Alexandru Telea to fill in the blanks, predicting what should be in that empty place.

Example Code

import numpy as np
import cv2
import urllib.request


# Abrir a imagem do link ou img = cv2.imread(diretorio_da_imagem//nome_do_arquivo)
resp = urllib.request.urlopen("https://i.stack.imgur.com/pgW91.png")
img = np.asarray(bytearray(resp.read()), dtype="uint8")
img = cv2.imdecode(img, cv2.IMREAD_COLOR)

kernel = np.ones((3,3),np.uint8)

# Utilização do morphologyEx e blur
closing = cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel, iterations = 2)
blur = cv2.blur(closing,(15,15))

# Binarização
gray = cv2.cvtColor(blur,cv2.COLOR_BGR2GRAY)
_, mask = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
cv2.imshow('Binarização',mask)
cv2.waitKey(0)

#Preenche os quatro cantos da imagem binária
w, h = mask.shape[::-1]
cv2.floodFill(mask, None, (0, 0), 0)
cv2.floodFill(mask, None, (w-1, 0), 0)
cv2.floodFill(mask, None, (0, h-1), 0)
cv2.floodFill(mask, None, (w-1, h-1), 0)
cv2.imshow('mask',mask)
cv2.waitKey(0)

#Lógica AND para obter da imagem original a encontrada pela criação do mask
img = cv2.bitwise_and(img, img, mask=mask )
cv2.imshow('AND',img)
cv2.waitKey(0)

#Canny Edges
edges = cv2.Canny(img, 100,200)
dilate = cv2.dilate(edges,kernel,iterations=1)
dilate = cv2.bitwise_not(dilate)
cv2.imshow('Canny',dilate)
cv2.waitKey(0)

#Lógica OR para retirar da imagem original os pêlos encontrados
img = cv2.bitwise_or(img, img, mask=dilate )
cv2.imshow('Edges',img)
cv2.waitKey(0)

#Interpolação da imagem para preencher os vazios
dilate = cv2.bitwise_not(dilate)
inpaint = cv2.inpaint(img, dilate, 3,cv2.INPAINT_TELEA)
cv2.imshow('InPaint', inpaint)
cv2.waitKey(0)

cv2.destroyAllWindows()

Results

Binarization

Floodfill

ANDLogic

CannyEdges

ORlogic

Inpaintinterpolation

    
12.11.2018 / 20:18