如何使用opencv-python消除图像噪点?

时间:2018-10-10 20:25:20

标签: python opencv image-processing computer-vision

我正在处理皮肤图像,以识别皮肤上的瑕疵,并且由于存在噪声(主要是由于存在毛发),这项工作变得更加复杂。

我有一个图像示例,其中我尝试仅突出显示皮肤斑点,但是由于头发过多,该算法无效。有了这个,我希望您能帮助我开发一种去除或减少头发数量的算法,以便我只能突出显示我感兴趣的区域(ROI)。

用于突出皮肤瑕疵的算法:

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()

使用的示例图像: enter image description here

如何处理这些噪音,以改善我的关注区域?

1 个答案:

答案 0 :(得分:5)

这是一个非常困难的任务,因为头发超过了ROI(摩尔)。我不知道如何帮助将其从痣中移除,但是我可以帮助移除背景,如照片中没有毛发。对于从痣中去除毛发,我建议您搜索“从图像中去除水印”和“深度神经网络”,以训练模型去除毛发(请注意,此任务将非常困难)。

话虽如此,为了消除背景,您可以尝试使用已经准备好进行检测的相同代码而不会出现毛发。您将获得像这样的二进制图像:

enter image description here

现在您的区域充满了白色线条(头发),这些线条越过您的轮廓即ROI,cv2.findContours()也将它们选中,因为它们已连接。但是,如果您查看图片,会发现白线很细,可以通过在图像上执行打开(cv2.morphologyEx)将其从图像中删除。开口是侵蚀,然后是膨胀,因此当您以足够大的内核尺寸侵蚀图像时,白线会消失:

enter image description here

现在您的白点周围有一些杂讯,您可以通过执行另一次扩张(cv2.dilate())将其连接起来:

enter image description here

要使ROI更加平滑,可以使图像cv2.blur()模糊:

enter image description here

在那之后,您可以进行其他加工并搜索最大轮廓。最终结果:

enter image description here

希望它会有所帮助。干杯!

示例代码:

import numpy as np
import cv2

# Read the image and perfrom an OTSU threshold
img = cv2.imread('hair.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

# Remove hair with opening
kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(thresh,cv2.MORPH_OPEN,kernel, iterations = 2)

# Combine surrounding noise with ROI
kernel = np.ones((6,6),np.uint8)
dilate = cv2.dilate(opening,kernel,iterations=3)

# Blur the image for smoother ROI
blur = cv2.blur(dilate,(15,15))

# Perform another OTSU threshold and search for biggest contour
ret, thresh = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
_, 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.imshow('img', res)
cv2.waitKey(0)
cv2.destroyAllWindows()