-
Notifications
You must be signed in to change notification settings - Fork 6
/
gaussian_filter_separate.py
65 lines (49 loc) · 1.84 KB
/
gaussian_filter_separate.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import cv2
import taichi as ti
import taichi.math as tm
ti.init(arch=ti.gpu)
img_blurred = ti.Vector.field(3, dtype=ti.u8, shape=(1024, 1024))
weights = ti.field(dtype=ti.f32, shape=1024, offset=-512)
img2d = ti.types.ndarray(element_dim=1)
@ti.func
def compute_weights(radius, sigma):
total = 0.0
# Not much computation here - serialize the for loop to save two more GPU kernel launch costs
ti.loop_config(serialize=True)
for i in range(-radius, radius + 1):
# Drop the normal distribution constant coefficients since we need to normalize later anyway
val = ti.exp(-0.5 * (i / sigma)**2)
weights[i] = val
total += val
ti.loop_config(serialize=True)
for i in range(-radius, radius + 1):
weights[i] /= total
@ti.kernel
def gaussian_blur(img: img2d, sigma: ti.f32):
img_blurred.fill(0)
n, m = img.shape[0], img.shape[1]
blur_radius = ti.ceil(sigma * 3, int)
compute_weights(blur_radius, sigma)
for i, j in ti.ndrange(n, m):
l_begin, l_end = ti.max(0, i - blur_radius), ti.min(n, i + blur_radius + 1)
total_rgb = tm.vec3(0.0)
total_weight = 0.0
for l in range(l_begin, l_end):
w = weights[i - l]
total_rgb += img[l, j] * w
total_weight += w
img_blurred[i, j] = (total_rgb / total_weight).cast(ti.u8)
for i, j in ti.ndrange(n, m):
l_begin, l_end = ti.max(0, j - blur_radius), ti.min(m, j + blur_radius + 1)
total_rgb = tm.vec3(0.0)
total_weight = 0.0
for l in range(l_begin, l_end):
w = weights[j - l]
total_rgb += img_blurred[i, l] * w
total_weight += w
img[i, j] = (total_rgb / total_weight).cast(ti.u8)
img = cv2.imread('images/mountain.jpg')
cv2.imshow('input', img)
gaussian_blur(img, 10)
cv2.imshow('blurred', img)
cv2.waitKey()