# Applying gaussian blur on RGBA images

I designed the code and it works quite well for images of lower res. However my program takes a lot of time and ram to display higher res images (occupies 2GB RAM for 4k images and takes 20 minutes). This program currently only processes files in .png format.

#------------------------------------
import matplotlib.pyplot as plt
import skimage
from skimage import color
import numpy as np
#------------------------------------
x=plt.imread("s2.png")    #the file name
#x=color.rgba2rgb(x)
y=x
n=int(input())     #"n" is the level of blurring(typical values=5,10,20,50)
le=y.shape[0]
bd=y.shape[1]
#------------------------------------
def frame(y):
y2=np.ones(shape=(le+(2*n),bd+(2*n)))
for i in range(0,le):
for j in range(0,bd):
y2[(i+n),(j+n)]=y[i,j]
return(y2)
#------------------------------------
#print((frame(y[:,:,0])).shape)

p=(2*n)+1
def kernel(p):

k=np.zeros(shape=(p,p))
for i in range(0,p):
for j in range(0,p):
k[i,j]=1.00005**(-(n-i)**2-(n-j)**2)
k=k/(np.sum(k))
return(k)
#print(kernel(p).shape)
#------------------------------------

def blur(arr,k,y2):
z=np.zeros(shape=(le,bd))
for i in range(0,le):
for j in range(0,bd):
z[i,j]=np.sum(k*(y2[i:(i+n+2+n-1),j:(j+n+2+n-1)]))

return(z)
#------------------------------------
r=blur(y[:,:,0],kernel(p),frame(y[:,:,0]))
g=blur(y[:,:,1],kernel(p),frame(y[:,:,1]))
b=blur(y[:,:,2],kernel(p),frame(y[:,:,2]))

x2=(np.array([r.transpose(),g.transpose(),b.transpose()])).transpose()
plt.imshow(x2)
plt.show()

• Python is slow. If you want to speed this up, try using Numba, or try rewriting in a compiled language. However, the better approach (if you’re not writing code to learn) is to use a pre-existing implementation of the convolution. Scikit has several (in sub-packages ndimage, signal, etc). Commented May 2, 2020 at 16:26

Before we get into deep performance concerns, let's do a quality pass:

## Global code

Lines like

x=plt.imread("s2.png")    #the file name
#x=color.rgba2rgb(x)
y=x
n=int(input())     #"n" is the level of blurring(typical values=5,10,20,50)
le=y.shape[0]
bd=y.shape[1]


should be in a function and not in global scope.

## Mystery input

Pass a prompt to input, such as Please enter the level of blurring.

## Extraneous parens

This:

y2=np.ones(shape=(le+(2*n),bd+(2*n)))
for i in range(0,le):
for j in range(0,bd):
y2[(i+n),(j+n)]=y[i,j]
return(y2)


can be

y2 = np.ones(shape=(le + 2*n, bd + 2*n))
for i in range(le):
for j in range(bd):
y2[i + n, j + n] = y[i, j]
return y2


Also note the default value for the start of range.

## In-place division

This:

k=k/(np.sum(k))
return(k)


can be

k /= np.sum(k)
return k


## Empty, not zero

Your blur method should definitely be vectorized, which I'll get to later, but for now, since it's clear that you're overwriting every entry: use empty rather than zeros.

## Add another dimension

This:

r=blur(y[:,:,0],kernel(p),frame(y[:,:,0]))
g=blur(y[:,:,1],kernel(p),frame(y[:,:,1]))
b=blur(y[:,:,2],kernel(p),frame(y[:,:,2]))


should not be three separate calls. Your data should have a dimension (y already does) of length 3, and y should be passed in its entirety.

## Variable names

le, bd and p mean nothing to me, and in three months they might not mean anything to you, either. Write these out with longer, more meaningful names. I promise that it will not slow the program down.

• Thank you for pointing out the flaws in quality. Would be great if you could give some tips for performance enhancement since the program is really slow. Commented May 1, 2020 at 4:02