Python Forum
Iterating kernel through image for filtering
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Iterating kernel through image for filtering
#1
I have two filters: (1) Median Filter and (2) Adaptive Median Filter

My median filter works. It takes an image, creates a padding the kernel convolves, replacing the center pixel with the median value found in each kernel window.

My adaptive median filter does not work. The difference between this one and the first one is that I want my adaptive median filter to iterate through the image block by block, instead of pixel by pixel, replacing the outliers in each kernel window with the median value. I think my logic is correct in my adaptive median, but I'm having trouble lining everything up in my output, especially with the dimensions of the image requiring the padding.

Also, is there a way to not include the padding when calculating the median near the edges?

import cv2
import numpy as np
from matplotlib import pyplot as plt
import math
import sys
from skimage.exposure import rescale_intensity

np.set_printoptions(threshold=sys.maxsize)

# PART 2: ADAPTIVE MEDIAN FILTER 

# load image
image = cv2.imread('2_noise.png',0)
image2 = cv2.imread('2_noise.png',0)

# convolve function
def medianFilter(image, kernel):

	# size of image and kernel
    (iH, iW) = image.shape[:2]
    (kH, kW) = kernel.shape[:2]
    print(iH, iW, kH, kW)
	
    # add padding to input image
    pad = (kW - 1) // 2
    image = cv2.copyMakeBorder(image, pad, pad, pad, pad,
        cv2.BORDER_REPLICATE)
		
    # allocate memory for the output image
    output = np.zeros((iH, iW), dtype="float32")
	
    # loop over the input image
    for y in np.arange(pad, iH + pad):
        for x in np.arange(pad, iW + pad):

            # extract the *center* region of the current (x, y)-coordinates dimensions
            roi = image[y - pad:y + pad + 1, x - pad:x + pad + 1]

			# convolution
            k = np.median(roi*kernel)

			# store the convolved value in the output(x,y)
            output[y - pad, x - pad] = k

	# rescale the output image
    output = rescale_intensity(output, in_range=(0, 255))
    output = (output * 255).astype("uint8")
 
	# return the output image
    return output

def iqr(a, outlierConstant):
    """
    a : numpy.ndarray (array from which outliers have to be removed.)
    outlierConstant : (scale factor around interquartile region.)                         
    """
    num = a.shape[0]

    upper_quartile = np.percentile(a, 75)
    lower_quartile = np.percentile(a, 25)
    IQR = (upper_quartile - lower_quartile) * outlierConstant
    quartileSet = (lower_quartile - IQR, upper_quartile + IQR)

    outlier_indx = []
    for i in range(num):
        if np.any(a[i] >= quartileSet[0]) and np.any(a[i] <= quartileSet[1]): pass
        else: outlier_indx += [i]            

    return outlier_indx  

def function(arrayMatrix, threshold=.5):
    zscore = (arrayMatrix - arrayMatrix.mean())/arrayMatrix.std()
    return np.where(np.abs(zscore) > threshold)

def adaptiveMedian(image, kernel):

	# size of image and kernel
    (iH, iW) = image.shape[:2]
    (kH, kW) = kernel.shape[:2]
    print('Image Size: ', iH, iW)
    print('Kernel Size: ', kH, kW)
	
    # add padding to input image
    pad = (kW - 1) // 2
    image = cv2.copyMakeBorder(image, pad, pad, pad, pad,
        cv2.BORDER_REPLICATE)
		
    # allocate memory for the output image
    output = np.zeros((iH+pad*2, iW+pad*2), dtype="float32")
    yRange = np.arange(pad, iH + pad)
    for xxx in yRange[::7]:
	    print(xxx)
    # loop over the input image
    for y in yRange[::7]:
        for x in yRange[::7]:
            #print(np.arange(pad, iH + pad))
            # extract the *center* region of the current (x, y)-coordinates dimensions
            roi = image[y - pad:y + pad + 1, x - pad:x + pad + 1]
            #print('roi: ', roi)
            # finding median
            median = np.median(roi)

			# finding outliers & reshaping
            outlier = function(roi)
            out = np.asarray(outlier,order=2)
            rowss = out.shape[0]
            colss = out.shape[1]
            xx = out[0]
            yy = out[1]
            data = np.array((xx,yy)).T
			
			# replacing outlier pixels with median value
            Range = len(data)
            for xx in range(0,Range):
                xCoord = data[xx][0]
                yCoord = data[xx][1]
                roi[xCoord][yCoord] = median
                #print('roi/median: ', roi)

                # convolution
                k = (roi*kernel)
                #print('k: ', k)
                # store refined mask into output image (removing salt & pepper)
                #print('y: ', y)
                #print('pad: ', pad)
                #print('x: ', x)
    output[y - pad:y + pad + 1, x - pad:x + pad + 1] = k
			
    # rescale the output image
    output = rescale_intensity(output, in_range=(0, 255))
    output = (output * 255).astype("uint8")

    # return the output image
    return output

# construct kernel mask
median = np.ones((7, 7), dtype="float")

# run the functions
adaptiveOutput = adaptiveMedian(image, median)
medianOutput = medianFilter(image2, median)

# plot both images
plt.figure(figsize=(11,6))
plt.subplot(131),plt.imshow(image, cmap = 'gray')
plt.title('Original Image w/ noise added'), plt.xticks([]), plt.yticks([])
plt.subplot(132),plt.imshow(medianOutput, cmap = 'gray')
plt.title('Median Filter'), plt.xticks([]), plt.yticks([])
plt.subplot(133),plt.imshow(adaptiveOutput, cmap = 'gray')
plt.title('Adaptive Median Filter'), plt.xticks([]), plt.yticks([])
plt.show()

Had to change the main for loop:

yRange = np.arange(pad, iH + pad)
    xRange = np.arange(pad, iW + pad)
    # loop over the input image
    for y in yRange[::6]:
        for x in xRange[::6]:
Also putting the output[...] = k line in the for xx loop, everything seems to work now:
            for xx in range(0,Range):
                xCoord = data[xx][0]
                yCoord = data[xx][1]
                roi[xCoord][yCoord] = median
                #print('roi/median: ', roi)

                # convolution
                k = (roi*kernel)
                #print('k: ', k)
                # store refined mask into output image (removing salt & pepper)
                #print('y: ', y)
                #print('pad: ', pad)
                #print('x: ', x)
                output[y - pad:y + pad + 1, x - pad:x + pad + 1] = k
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Setting up new Python kernel for JupyterLab Desktop on M1 Mac daler6 0 1,263 Jun-20-2022, 03:45 AM
Last Post: daler6
  Jupyter kernel restarts russellm10 0 1,490 Sep-14-2021, 04:24 AM
Last Post: russellm10
  Problem: Restart kernel onPydev console when trying to install a python package poppy2020 1 7,709 Nov-25-2020, 06:13 PM
Last Post: Larz60+
  Kernel needs to restart ErnestTBass 0 2,355 May-06-2020, 08:37 PM
Last Post: ErnestTBass
  Cannot install R kernel or R essentials ErnestTBass 4 4,462 May-01-2020, 12:28 AM
Last Post: Larz60+
  Seam Carving or Bilateral image filtering scott14 1 2,019 Dec-09-2018, 07:22 PM
Last Post: Larz60+
  Jupyter error - 'The kernel appears to have died, it will restart automatically' meganhollie 5 18,016 Jun-12-2018, 10:11 PM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020