'When applying Gaussian filter the image becomes dark

When I run the following code the output result is blurred but the image gets darker as I increase the value of sigma.
Imports

import numpy as np
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
import math
import copy

Gaussian filter code

e = 2.71828182845904
pi = 3.1415926535897

def gaus(mat_l,sigma):
    Matrix = [[0.0 for x in range(mat_l)] for y in range(mat_l)] 
    for x in range(-(int(mat_l/2)),(int(mat_l/2))+1):
        for y in range(-(int(mat_l/2)),(int(mat_l/2))+1):
            ee = pow(e,(-(((pow(x,2)+pow(y,2))/(2*(pow(sigma,2)))))))
            aa = (1/(2*pi*pow(sigma,2)))
            result = ee*aa
            Matrix[x+int(mat_l/2)][y+int(mat_l/2)] = round(result,6)
    return Matrix

Convolution code

def matrix_convolve(image,kernel,a,b,mul=1):
    print(kernel)
    img_x, img_y = image.shape
    kernl_x, kernl_y = kernel.shape

    result = copy.deepcopy(image)
    for i in range(img_x-int(len(kernel)/2)):
        for j in range(img_y-int(len(kernel)/2)):
            result[i][j] = 0
            summ = 0
            for s in range(-a,a+1):
                for t in range(-b,b+1):
                    summ += kernel[s,t] * image[i+s,j+t]
            result[i][j] = math.ceil(mul*summ)
    return result

Driver

image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

kernal = gaus(5,5)
kernal = np.array([kernal[0],kernal[1],kernal[2],kernal[3],kernal[4]])

result3 = matrix_convolve(image,kernal,2,2)
plt.imshow(result3.astype(np.uint8),cmap='gray')
plt.show()

When sigma is 5, the output image is output_with_sigma_5

when sigma is 2, the output image is output_with_sigma_2

result3=cv2.GaussianBlur(image,(5,5),5)
plt.imshow(result3.astype(np.uint8),cmap='gray')
plt.show()

When blurred using OpenCV the following is the output for sigma 5 opencv



Solution 1:[1]

The problem is that you sample only a 5x5 grid of the Gaussian kernel. The larger the sigma, the more of the kernel you cut off, and the more power you lose.

A blurring kernel should always sum up to 1. If it adds up to 0.5, for example, the average intensity of the output image will be half of that of the input.

The solution is twofold:

  1. Sample a larger fraction of your kernel. At least 1+2*ceil(2*sigma), but preferably 3 times instead of 2.

  2. Normalize your kernel. Even if you sample up to 3*sigma out from the center, you still lose a bit of power in the sampling, especially for small sigma. Normalizing the kernel is as simple as adding up all the kernel values and then dividing each kernel value by that sum.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1