Reputation: 31
Writing CNN to classify pictures. I encountered a problem with garbage pixels. image The resulting network gives ~90% quality, it seems that it can be improved by averaging these pixels. Is there a ready algorithm in numpy, opencv, etc. that allows to do this? Not normally smoothing, but specifically for these pixels. Or do I have to do it manually?
Upvotes: 2
Views: 3767
Reputation: 5815
I agree that if you are using a CNN for some kind of classification you should train the network to handle this kind of noisy images. Maybe augment your dataset with some salt and pepper noise. Anyway, here's a possible solution for filtering out the outliers. It builds on the idea proposed by fmw42. These are the steps:
5
) to create a mask for the outliers close to 0
.250
) to create a mask for the outliers close to 255
.Let's see the code:
# 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)
The median filtering with a kernel size of 11
looks like this:
The outliers are practically gone. Now, let's put this aside for the moment and compute a pair of binary masks for both outliers:
# 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)
The outliers mask is this:
Now, you really don't provide your original data. You provide an image most likely plotted using matplotlib
. That's a problem, because the image you posted is processed and compressed. This results in some sharp edges around the outliers on the original image. One straightforward solution is to dilate the outliers mask a little bit to cover this compression artifacts:
# 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)
The outliers mask now looks like this:
Ok, let's adaptive-filter the original input using the median blurred image and the outliers mask. Just make sure to reshape all the numpy
arrays to their proper size for broadcasting:
# 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)
For the first image, this is the result:
More results:
Upvotes: 4