Python 滤除图像中的离群值

Python filter to remove outliers in image

写CNN对图片进行分类。我遇到垃圾像素问题。 image 生成的网络给出了 ~90% 的质量,似乎可以通过对这些像素进行平均来改进它。 numpy、opencv 等中是否有允许执行此操作的现成算法?通常不是平滑,而是专门针对这些像素。还是我必须手动完成?

我同意,如果你使用 CNN 进行某种分类,你应该训练网络来处理这种嘈杂的图像。也许用一些椒盐噪声来扩充你的数据集。无论如何,这是过滤掉异常值的可能解决方案。它建立在 fmw42 提出的想法之上。这些是步骤:

  1. 使用大内核
  2. 应用中值模糊
  3. 将原始(未处理的)图像转换为灰度
  4. (Invert) Threshold 具有低阈值(例如,5)的灰度图像,为接近 0 的异常值创建掩码.
  5. 阈值 具有高低阈值(例如250)的灰度图像,为接近255的异常值创建掩码。
  6. 合并 两个掩码以创建异常值掩码
  7. 使用离群掩码 adaptive-filter 原始输入图像,必要时替换中值。

让我们看看代码:

# Imports:
import cv2
import numpy as np

# image path
path = "D://opencvImages//noisyNumbers//"
fileName = "noisy01.png"

# Reading an image in default mode:
inputImage = cv2.imread(path + fileName)

# Apply median filter:
filteredImage = cv2.medianBlur(inputImage, ksize=11)

# Convert input image to grayscale:
grayscaleImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)

内核大小为 11 的中值滤波如下所示:

异常值几乎消失了。现在,让我们暂时搁置这一点,为两个异常值计算一对二进制掩码:

# Get low mask:
_, lowMask = cv2.threshold(grayscaleImage, 5, 255, cv2.THRESH_BINARY_INV)

# Get high mask:
_, highMask = cv2.threshold(grayscaleImage, 250, 255, cv2.THRESH_BINARY)

# Create outliers mask:
outliersMask = cv2.add(lowMask, highMask)

离群掩码是这样的:

现在,你真的不提供你的原始数据。您提供最有可能使用 matplotlib 绘制的图像。这是个问题,因为您发布的图片经过处理和压缩。这会导致原始图像上的异常值周围出现一些锐利的边缘。一种直接的解决方案是稍微扩大异常值掩码以覆盖此压缩伪像:

# Set kernel (structuring element) size:
kernelSize = 3
# Set operation iterations:
opIterations = 1
# Get the structuring element:
maxKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernelSize, kernelSize))

# Apply dilation:
outliersMask = cv2.dilate(outliersMask, maxKernel)

异常值掩码现在看起来像这样:

好的,让我们 adaptive-filter 使用中值模糊图像和异常值掩码的原始输入。只需确保将所有 numpy 数组重塑为适合广播的大小:

# Re-shape the binary mask to a 3-channeled image:
augmentedBinary = cv2.merge([outliersMask, outliersMask, outliersMask])
# Apply the adaptive filter:
cleanedImage = np.where(augmentedBinary == (255, 255, 255), filteredImage, inputImage)

# Show the result
cv2.imshow("Adaptive Filtering", cleanedImage)
cv2.waitKey(0)

对于第一张图片,这是结果:

更多结果: