Skip to content

Commit c1a4cc9

Browse files
praveennadimintiitsvinayakcclauss
authored
Add bilateral filter (TheAlgorithms#1786)
* Added Bilateral filter * Added Bilateral filter * changed types of varS and varI * formatted with black * added type hints * changed variable names * Update bilateral_filter.py * Drop transitory variables, add parse_args() Co-authored-by: vinayak <[email protected]> Co-authored-by: Christian Clauss <[email protected]>
1 parent 5543d14 commit c1a4cc9

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
"""
2+
Implementation of Bilateral filter
3+
4+
Inputs:
5+
img: A 2d image with values in between 0 and 1
6+
varS: variance in space dimension.
7+
varI: variance in Intensity.
8+
N: Kernel size(Must be an odd number)
9+
Output:
10+
img:A 2d zero padded image with values in between 0 and 1
11+
"""
12+
13+
import cv2
14+
import numpy as np
15+
import math
16+
import sys
17+
18+
19+
def vec_gaussian(img: np.ndarray, variance: float) -> np.ndarray:
20+
# For applying gaussian function for each element in matrix.
21+
sigma = math.sqrt(variance)
22+
cons = 1 / (sigma * math.sqrt(2 * math.pi))
23+
return cons * np.exp(-((img / sigma) ** 2) * 0.5)
24+
25+
26+
def get_slice(img: np.ndarray, x: int, y: int, kernel_size: int) -> np.ndarray:
27+
half = kernel_size // 2
28+
return img[x - half : x + half + 1, y - half : y + half + 1]
29+
30+
31+
def get_gauss_kernel(kernel_size: int, spatial_variance: float) -> np.ndarray:
32+
# Creates a gaussian kernel of given dimension.
33+
arr = np.zeros((kernel_size, kernel_size))
34+
for i in range(0, kernel_size):
35+
for j in range(0, kernel_size):
36+
arr[i, j] = math.sqrt(
37+
abs(i - kernel_size // 2) ** 2 + abs(j - kernel_size // 2) ** 2
38+
)
39+
return vec_gaussian(arr, spatial_variance)
40+
41+
42+
def bilateral_filter(
43+
img: np.ndarray,
44+
spatial_variance: float,
45+
intensity_variance: float,
46+
kernel_size: int,
47+
) -> np.ndarray:
48+
img2 = np.zeros(img.shape)
49+
gaussKer = get_gauss_kernel(kernel_size, spatial_variance)
50+
sizeX, sizeY = img.shape
51+
for i in range(kernel_size // 2, sizeX - kernel_size // 2):
52+
for j in range(kernel_size // 2, sizeY - kernel_size // 2):
53+
54+
imgS = get_slice(img, i, j, kernel_size)
55+
imgI = imgS - imgS[kernel_size // 2, kernel_size // 2]
56+
imgIG = vec_gaussian(imgI, intensity_variance)
57+
weights = np.multiply(gaussKer, imgIG)
58+
vals = np.multiply(imgS, weights)
59+
val = np.sum(vals) / np.sum(weights)
60+
img2[i, j] = val
61+
return img2
62+
63+
64+
def parse_args(args: list) -> tuple:
65+
filename = args[1] if args[1:] else "../image_data/lena.jpg"
66+
spatial_variance = float(args[2]) if args[2:] else 1.0
67+
intensity_variance = float(args[3]) if args[3:] else 1.0
68+
if args[4:]:
69+
kernel_size = int(args[4])
70+
kernel_size = kernel_size + abs(kernel_size % 2 - 1)
71+
else:
72+
kernel_size = 5
73+
return filename, spatial_variance, intensity_variance, kernel_size
74+
75+
76+
if __name__ == "__main__":
77+
filename, spatial_variance, intensity_variance, kernel_size = parse_args(sys.argv)
78+
img = cv2.imread(filename, 0)
79+
cv2.imshow("input image", img)
80+
81+
out = img / 255
82+
out = out.astype("float32")
83+
out = bilateral_filter(out, spatial_variance, intensity_variance, kernel_size)
84+
out = out * 255
85+
out = np.uint8(out)
86+
cv2.imshow("output image", out)
87+
cv2.waitKey(0)
88+
cv2.destroyAllWindows()

0 commit comments

Comments
 (0)