-
Notifications
You must be signed in to change notification settings - Fork 7
/
GuidedFilter.py
116 lines (84 loc) · 6.64 KB
/
GuidedFilter.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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# -*- coding: utf-8 -*-
import numpy as np
import cv2
class GuidedFilter:
def __init__(self, I, radius=5, epsilon=0.4):
self._radius = 2 * radius + 1
self._epsilon = epsilon
self._I = self._toFloatImg(I)
self._initFilter()
def _toFloatImg(self, img):
if img.dtype == np.float32:
return img
return ( 1.0 / 255.0 ) * np.float32(img)
def _initFilter(self):
I = self._I
r = self._radius
eps = self._epsilon
Ir, Ig, Ib = I[:, :, 0], I[:, :, 1], I[:, :, 2]
self._Ir_mean = cv2.blur(Ir, (r, r))
self._Ig_mean = cv2.blur(Ig, (r, r))
self._Ib_mean = cv2.blur(Ib, (r, r))
Irr_var = cv2.blur(Ir ** 2, (r, r)) - self._Ir_mean ** 2 + eps
Irg_var = cv2.blur(Ir * Ig, (r, r)) - self._Ir_mean * self._Ig_mean
Irb_var = cv2.blur(Ir * Ib, (r, r)) - self._Ir_mean * self._Ib_mean
Igg_var = cv2.blur(Ig * Ig, (r, r)) - self._Ig_mean * self._Ig_mean + eps
Igb_var = cv2.blur(Ig * Ib, (r, r)) - self._Ig_mean * self._Ib_mean
Ibb_var = cv2.blur(Ib * Ib, (r, r)) - self._Ib_mean * self._Ib_mean + eps
self._Ir_mean = cv2.blur(Ir, (r, r))
self._Ig_mean = cv2.blur(Ig, (r, r))
self._Ib_mean = cv2.blur(Ib, (r, r))
Irr_var = cv2.blur(Ir ** 2, (r, r)) - self._Ir_mean ** 2 + eps
Irg_var = cv2.blur(Ir * Ig, (r, r)) - self._Ir_mean * self._Ig_mean
Irb_var = cv2.blur(Ir * Ib, (r, r)) - self._Ir_mean * self._Ib_mean
Igg_var = cv2.blur(Ig * Ig, (r, r)) - self._Ig_mean * self._Ig_mean + eps
Igb_var = cv2.blur(Ig * Ib, (r, r)) - self._Ig_mean * self._Ib_mean
Ibb_var = cv2.blur(Ib * Ib, (r, r)) - self._Ib_mean * self._Ib_mean + eps
Irr_inv = Igg_var * Ibb_var - Igb_var * Igb_var
Irg_inv = Igb_var * Irb_var - Irg_var * Ibb_var
Irb_inv = Irg_var * Igb_var - Igg_var * Irb_var
Igg_inv = Irr_var * Ibb_var - Irb_var * Irb_var
Igb_inv = Irb_var * Irg_var - Irr_var * Igb_var
Ibb_inv = Irr_var * Igg_var - Irg_var * Irg_var
I_cov = Irr_inv * Irr_var + Irg_inv * Irg_var + Irb_inv * Irb_var
Irr_inv /= I_cov
Irg_inv /= I_cov
Irb_inv /= I_cov
Igg_inv /= I_cov
Igb_inv /= I_cov
Ibb_inv /= I_cov
self._Irr_inv = Irr_inv
self._Irg_inv = Irg_inv
self._Irb_inv = Irb_inv
self._Igg_inv = Igg_inv
self._Igb_inv = Igb_inv
self._Ibb_inv = Ibb_inv
def _computeCoefficients(self, p):
r = self._radius
I = self._I
Ir, Ig, Ib = I[:, :, 0], I[:, :, 1], I[:, :, 2]
p_mean = cv2.blur(p, (r, r))
Ipr_mean = cv2.blur(Ir * p, (r, r))
Ipg_mean = cv2.blur(Ig * p, (r, r))
Ipb_mean = cv2.blur(Ib * p, (r, r))
Ipr_cov = Ipr_mean - self._Ir_mean * p_mean
Ipg_cov = Ipg_mean - self._Ig_mean * p_mean
Ipb_cov = Ipb_mean - self._Ib_mean * p_mean
ar = self._Irr_inv * Ipr_cov + self._Irg_inv * Ipg_cov + self._Irb_inv * Ipb_cov
ag = self._Irg_inv * Ipr_cov + self._Igg_inv * Ipg_cov + self._Igb_inv * Ipb_cov
ab = self._Irb_inv * Ipr_cov + self._Igb_inv * Ipg_cov + self._Ibb_inv * Ipb_cov
b = p_mean - ar * self._Ir_mean - ag * self._Ig_mean - ab * self._Ib_mean
ar_mean = cv2.blur(ar, (r, r))
ag_mean = cv2.blur(ag, (r, r))
ab_mean = cv2.blur(ab, (r, r))
b_mean = cv2.blur(b, (r, r))
return ar_mean, ag_mean, ab_mean, b_mean
def _computeOutput(self, ab, I):
ar_mean, ag_mean, ab_mean, b_mean = ab
Ir, Ig, Ib = I[:, :, 0], I[:, :, 1], I[:, :, 2]
q = ar_mean * Ir + ag_mean * Ig + ab_mean * Ib + b_mean
return q
def filter(self, p):
p_32F = _toFloatImg(p)
ab = self._computeCoefficients(p)
return self._computeOutput(ab, self._I)