/
mvd_algorithms.py
166 lines (150 loc) · 5.51 KB
/
mvd_algorithms.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import numpy as np
from scipy.ndimage.filters import convolve, correlate, gaussian_filter
from scipy.ndimage.measurements import maximum_position
from scipy.fftpack import fft2, ifft2
def pad_and_center_psf(psf, s):
ss = psf.shape
psf = np.pad(psf, ((0, s[0]-ss[0]), (0, s[1]-ss[1])),
mode='constant', constant_values=(0.0, 0.0))
mp = maximum_position(psf)
psf = np.roll(np.roll(psf, -mp[0], axis=0), -mp[1], axis=1)
return psf
def mvd_wiener(initImg, imgList, psfList, iterNum, mu, positiveOnly=True):
if positiveOnly:
initImg[initImg < 0.0] = 0.0
viewNum = len(imgList)
fftFactor = np.sqrt(initImg.shape[0]*initImg.shape[1])
mu = mu * fftFactor
I = np.sum(np.abs(initImg))
e = fft2(initImg)
e_img_old = initImg
e_img = initImg
if iterNum == 0:
return e_img
# pre-compute spectra
ijList = [fft2(img) for img in imgList]
pjList = [fft2(pad_and_center_psf(psf, initImg.shape)) for psf in psfList]
for i in xrange(iterNum):
c_all = np.zeros(e.shape, dtype=float)
for j in xrange(viewNum):
ij = ijList[j]
pj = pjList[j]
sj = e * pj
cj = (np.conj(pj) * (ij - sj))/(np.square(np.abs(pj)) + mu**2)
c_all = c_all + cj / float(viewNum)
e = e + c_all
e_img = np.real(ifft2(e))
if positiveOnly:
e_img[e_img < 0.0] = 0.0
e_img = e_img / np.sum(np.abs(e_img)) * I
e = fft2(e_img)
print 'iter #%d, total change: %f.' %\
(i+1, np.sum(np.abs(e_img_old-e_img))/I)
e_img_old = e_img
return e_img
def mvd_lr(initImg, imgList, psfList, iterNum):
EPS = np.finfo(float).eps
viewNum = len(imgList)
initImg = initImg - np.amin(initImg)
initImg = initImg / np.sum(np.abs(initImg))
reconImg = initImg
for i in xrange(iterNum):
updateAll = np.ones(initImg.shape, dtype=float)
for j in xrange(viewNum):
img = imgList[j]
psf = psfList[j]
psf_prime = np.flipud(np.fliplr(psf))
update = convolve(img/(convolve(reconImg, psf)+EPS), psf_prime)
updateAll = updateAll * update
# display progress
progress = float(i*viewNum+j+1)/(viewNum*iterNum)
timeElapsed = time.time() - startTime
timeRemaining = timeElapsed/progress*(1-progress)
sys.stdout.write('\r%.2f%%, %.2f s elapsed, %.2f s remaining' %
(progress*100.0, timeElapsed, timeRemaining))
sys.stdout.flush()
reconImg = reconImg * updateAll
reconImg = np.abs(reconImg)
reconImg = reconImg / np.sum(reconImg)
sys.stdout.write('\n')
return reconImg
def inner_product(x, y=None):
if y is None:
y = x
return np.sum(x*y)
def index_min(vals):
return min(xrange(len(vals)), key=vals.__getitem__)
def mapgg_step_size(x, d, u, v, w, gamma, t, t_xx):
t_dd = np.square(d)
t_xd = x * d
u_gamma = lambda x: (convolve(x, u) + gamma*x)
ug_dd = u_gamma(t_dd)
ug_xd = u_gamma(t_xd)
q4 = inner_product(t_dd, ug_dd)
q3 = 4*inner_product(t_dd, ug_xd)
q2 = 4*inner_product(t_xd, ug_xd) + 2*inner_product(t_dd, t)
q1 = 4*inner_product(t_xd, t)
q0 = inner_product(t_xx, t-v) + w
if q4 <= 0.0:
print 'warning: negative q4'
# find local extrema
alphas = np.roots((4*q4, 3*q3, 2*q2, q1)).real
vals = np.polyval((q4, q3, q2, q1, q0), alphas)
return alphas[index_min(vals)]
def phi_eval(t_xx, t, v, w):
return inner_product(t_xx, t-v) + w
def mvd_map_tikhonov(initImg, imgList, psfList, iterNum,
gamma, weights='even', sigma=None):
viewNum = len(imgList)
assert len(psfList) == viewNum
if isinstance(weights, (list, tuple)):
assert len(weights) == viewNum
c2 = weights ** 2
elif weights == 'even':
c2 = [1.0] * viewNum
## initialization ##
print 'initializing...'
# pre-blur inputs
if sigma is not None:
imgList = [gaussian_filter(img, sigma) for img in imgList]
psfList = [gaussian_filter(psf, sigma) for psf in psfList]
# check and process init. guess
if iterNum == 0:
return initImg
initImg[initImg < 0.0] = 0.0
x = np.sqrt(initImg)
# initializing u, v, w
u = np.zeros(psfList[0].shape)
v = np.zeros(imgList[0].shape)
w = 0.0
for idx in xrange(viewNum):
u = u + c2[idx] * correlate(psfList[idx], psfList[idx])
v = v + c2[idx] * correlate(imgList[idx], psfList[idx])
w = w + c2[idx] * inner_product(imgList[idx])
# initializing previous gradient power
p_rp = 1.0
# initializing init. search direction
d = np.zeros(imgList[0].shape)
## start iteration ##
print 'start iteration...'
for k in xrange(iterNum):
# temp. t_xx
t_xx = np.square(x)
# temp. t
t = convolve(t_xx, u) + gamma*t_xx - v
# gradient r
r = 4*x*t
# search direction
p_r = inner_product(r)
d = (p_r/p_rp)*d - r
# step size
alpha = mapgg_step_size(x, d, u, v, w, gamma, t, t_xx)
# save previous power of r
p_rp = p_r
# update
update = alpha*d
x = x + update
print 'iter #%d, residue: %f.' %\
(k+1, phi_eval(t_xx, t, v, w)/w)
## return result ##
return np.square(x)