def deconv_wiener(ys, hs, gamma=1.0e-6, n_threads=6, y_is_fft=False, h_is_fft=False, fft_is_unitary=True): """ wiener deconv y is/are the recorded image(s) h is/are the (already fftshifted) kernel(s) both can be equal sized tuples, in which case a joint deconvolution is performed if the data or the kernels are already fourier transformed then set y_is_fft/h_is_fft to True """ if not isinstance(ys, (list, tuple)): ys = [ys] if not isinstance(hs, (list, tuple)): hs = [hs] if len(ys) != len(hs): raise ValueError("len(y) != len(h) %d != %d" % (len(ys), len(hs))) if not np.all([_y.shape == _h.shape for _y, _h in zip(ys, hs)]): raise ValueError("y and h have non compatible shapes...") if not y_is_fft: dshape = ys[0].shape else: dshape = ys[0].shape[:-1] + (2 * (ys[0].shape[-1] - 1),) FFTW = MyFFTW(dshape, unitary=fft_is_unitary, n_threads=n_threads) if not h_is_fft: Hs = [FFTW.rfftn(h) for h in hs] else: Hs = hs if not y_is_fft: Ys = [FFTW.rfftn(y) for y in ys] else: Ys = ys U = reduce(np.add, [_H.conjugate() * _Y for _H, _Y in zip(Hs, Ys)]) U /= 1.0 * gamma + reduce(np.add, [np.abs(_H) ** 2 for _H in Hs]) return FFTW.irfftn(U)
def deconv_rl(ys, hs, Niter=10, gamma = 1.e-5, n_threads = 6, h_is_fft = False, log_iter = False, mult_mode = "root", fft_is_unitary=False): """ richardson lucy deconvolution y is/are the recorded image(s) h is/are the kernel(s) both can be equal sized tuples, in which case a joint deconvolution is performed if the data or the kernels are already fourier transformed then set y_is_fft/h_is_fft to True increase gamma if something explodes.... mult_mode = "root", "max", "min" definies how each lr channel is multiplied "root" and "min" should be preferred """ if not isinstance(ys,(list,tuple)): ys = [ys] if not isinstance(hs,(list,tuple)): hs = [hs] if len(ys) != len(hs): raise ValueError("len(y) != len(h) %d != %d"%(len(ys),len(hs))) if not h_is_fft and not np.all([_y.shape == _h.shape for _y, _h in zip(ys,hs)]): raise ValueError("y and h have non compatible shapes...") dshape = ys[0].shape if log_iter: print "creating FFTW object" FFTW = MyFFTW(dshape,n_threads = n_threads, unitary=fft_is_unitary) if not h_is_fft: if ys[0].ndim==1: hs_flip = [h[::-1] for h in hs] elif ys[0].ndim==2: hs_flip = [h[::-1,::-1] for h in hs] elif ys[0].ndim==3: hs_flip = [h[::-1,::-1,::-1] for h in hs] else: raise NotImplementedError("data dimension %s not supported"%ys[0].ndim) else: if ys[0].ndim==1: hs_flip = h elif ys[0].ndim==2: hs_flip = [h[::-1,:] for h in hs] elif ys[0].ndim==3: hs_flip = [h[::-1,::-1,:] for h in hs] else: raise NotImplementedError("data dimension %s not supported"%ys[0].ndim) if log_iter: print "setting up ffts" if not h_is_fft: Hs = [FFTW.rfftn(h) for h in hs] Hs_flip = [FFTW.rfftn(h) for h in hs_flip] else: Hs = hs Hs_flip = hs_flip def _single_lucy_multiplier(d,u_f,h_f,h_flip_f): tmp = np.abs(FFTW.irfftn(u_f*h_f)) tmp2 = FFTW.rfftn(d/(tmp+gamma)) tmp3 = np.abs(FFTW.irfftn(tmp2*h_flip_f)) return tmp3 u = np.mean([np.mean(_y) for _y in ys])*np.ones_like(ys[0]) um = [] for i in range(Niter): if log_iter: print "deconv_rl step %s/%s"%(i+1,Niter) U = FFTW.rfftn(u) us = np.stack([_single_lucy_multiplier(y,U,H,H_flip) for y,H,H_flip in zip(ys,Hs,Hs_flip)]) if mult_mode=="root": u *= reduce(np.multiply,us**(1./len(ys))) elif mult_mode =="max": u *= np.amax(us,axis=0) elif mult_mode =="min": u *= np.amin(us,axis=0) else: raise KeyError(multmode) um.append(us) #return u,us[0] return u
def deconv_wiener2(ys, hs, gamma=1.0e-6, n_threads=6, y_is_fft=False, h_is_fft=False): """ wiener deconv y is/are the recorded image(s) h is/are the (already fftshifted) kernel(s) both can be equal sized tuples, in which case a joint deconvolution is performed if the data or the kernels are already fourier transformed then set y_is_fft/h_is_fft to True noise level is estimated gamma is the thikoniv regularizer """ if not isinstance(ys, (list, tuple)): ys = [ys] if not isinstance(hs, (list, tuple)): hs = [hs] if len(ys) != len(hs): raise ValueError("len(y) != len(h) %d != %d" % (len(ys), len(hs))) if not np.all([_y.shape == _h.shape for _y, _h in zip(ys, hs)]): raise ValueError("y and h have non compatible shapes...") if not y_is_fft: dshape = ys[0].shape else: dshape = ys[0].shape[:-1] + (2 * (ys[0].shape[-1] - 1),) FFTW = MyFFTW(dshape, unitary=True, n_threads=n_threads) if not h_is_fft: Hs = [FFTW.rfftn(h) for h in hs] else: Hs = hs if not y_is_fft: Ys = [FFTW.rfftn(y) for y in ys] else: Ys = ys # estimate noise power spectrum hs_cut = [np.abs(h_f[0, 0]) * 1.0e-6 for h_f in Hs] # inds_noise = [2./(1.+np.exp((np.abs(h_f)-h_cut)/h_cut)) for h_cut, h_f in zip(hs_cut,Hs)] # inds_noise = [1.0 * (np.abs(h_f) < h_cut) for h_cut, h_f in zip(hs_cut, Hs)] inds_signal = [1.0 - ind_noise for ind_noise in inds_noise] # the different power spectra ps_y = [np.abs(y_f) ** 2 for y_f in Ys] ps_signal = [ind * p for ind, p in zip(inds_signal, ps_y)] mean_ps_noise = [np.mean(ind * p) for ind, p in zip(inds_noise, ps_y)] ps_noise = [ ind_n * p + ind_s * mean_p for ind_n, ind_s, p, mean_p in zip(inds_noise, inds_signal, ps_y, mean_ps_noise) ] filters = [p_signal / (1.0 * p_signal + p_noise) for p_signal, p_noise in zip(ps_signal, ps_noise)] U = reduce(np.add, [_H.conjugate() * _Y * _F for _H, _Y, _F in zip(Hs, Ys, filters)]) U /= 1.0 * gamma + reduce(np.add, [np.abs(_H) ** 2 for _H in Hs]) return FFTW.irfftn(U)
def deconv_tv_al(ys, hs, mu = 1000., rho = 2., Niter = 10, n_threads = 6, tv_norm = "isotropic", y_is_fft = False, h_is_fft = False): """ total variation deconv y is/are the recorded image(s) h is/are the kernel(s) both can be equal sized tuples, in which case a joint deconvolution is performed if the data or the kernels are already fourier transformed then set y_is_fft/h_is_fft to True tv_norm = "isotropic","anisotropic" """ if not isinstance(ys,(list,tuple)): ys = [ys] if not isinstance(hs,(list,tuple)): hs = [hs] if len(ys) != len(hs): raise ValueError("len(y) != len(h) %d != %d"%(len(ys),len(hs))) if not np.all([_y.shape == _h.shape for _y, _h in zip(ys,hs)]): raise ValueError("y and h have non compatible shapes...") if not y_is_fft: dshape = ys[0].shape else: dshape = ys[0].shape[:-1]+(2*(ys[0].shape[-1]-1),) FFTW = MyFFTW(dshape,n_threads = n_threads) if not h_is_fft: Hs = [FFTW.rfftn(h) for h in hs] else: Hs = hs if not y_is_fft: Ys = [FFTW.rfftn(y) for y in ys] else: Ys = ys lap = -dft_lap(dshape, use_rfft = True) if not y_is_fft: f = 1.*ys[0] else: f = np.real(FFTW.irfftn(ys[0])) #u = np.array(np.gradient(f)) u = grad(f) y = np.zeros((ys[0].ndim,)+dshape) rnorm = 0. for i in range(Niter): # print i, _fun(f,mu), rho # f subproblem f_f = 1.*mu/rho*reduce(np.add,[_H.conjugate()*_Y for _H,_Y in zip(Hs,Ys)]) f_f -= FFTW.rfftn(divergence(u-1./rho*y)) f_f /= 1.*mu/rho*reduce(np.add,[np.abs(_H)**2 for _H in Hs]) + lap f = np.real(FFTW.irfftn(f_f)) # u subproblem #df = np.array(np.gradient(f)) df = grad(f) if tv_norm == "isotropic": # isotropic case v = df + 1./rho*y mv = np.sqrt(np.sum(v**2,axis=0)) mv[mv==0] = 1. tv = np.maximum(0,mv-1./rho)/mv u = tv*v else: # anisotropic case u = soft_thresh(df + 1./rho*y,1./rho) y -= rho*(u-df) print rho rnorm_new = np.sqrt(np.mean((u-df)**2)) if rnorm_new > .7*rnorm: rho *= 2. rnorm = rnorm_new return f
def deconv_hyperlap(y, h, lam = 1000., outeriter= 6, inneriter = 1, reg0=0., alpha = None, n_threads = 6, logged = False): """ hyper laplacian regularized deconvolution Krishnan et al see http://people.ee.duke.edu/~lcarin/NIPS2009_0341.pdf y is/are the recorded image(s) h is/are the (already fftshifted) kernel(s) of same shape both can be equal sized tuples, in which case a joint deconvolution is performed if the data or the kernels are already fourier transformed then set y_is_fft/h_is_fft to True """ # see the paper for definition of the following hyperparameter beta = 1. beta_inc = 2.8 if alpha is not None: look = get_lookup(alpha) else: alpha = 1. #make everything scale invariant y_mean = np.mean(y) y = y/y_mean dshape = y.shape FFTW = MyFFTW(dshape,unitary = False, n_threads = n_threads) H = FFTW.rfftn(h) Y = FFTW.rfftn(y) fs = finite_deriv_dft_forward(dshape, use_rfft=True) x = 1.*y den1 = reduce(np.add,[f.conjugate()*f for f in fs]) den2 = H.conjugate()*H nom1 = H.conjugate()*Y res = [] def objective(x): dxs = np.gradient(x) X = FFTW.rfftn(x) x_b = FFTW.irfftn(X*H) ener = .5*lam*np.sum((x_b-y)**2) grad = np.sum([abs(dx)**alpha for dx in dxs]) return ener +grad for i in xrange(outeriter): print "iteration: %d / %d"%(i+1,outeriter) for _ in xrange(inneriter): # w subproblem #dx1, dx2 = np.gradient(x) #dxs = [.5*(np.roll(x,-1,i)-np.roll(x,1,i)) for i in range(y.ndim)] dxs = np.gradient(x) if alpha == 1.: ws = [soft_thresh(dx,1./beta) for dx in dxs] else: ws = [look(dx,beta) for dx in dxs] res.append(x) # x subproblem w_fs = [FFTW.rfftn(w) for w in ws] nom2 = reduce(np.add,[f.conjugate()*w_f for f, w_f in zip(fs,w_fs)]) x = FFTW.irfftn((nom1+1.*lam/beta*nom2)/(reg0*lam/beta+den1+1.*lam/beta*den2)) # nom = f1.conjugate()*w1_f + f2.conjugate()*w2_f + 1.*lam/beta*H.conjugate()*Y # den = reg + f1.conjugate()*f1 + f2.conjugate()*f2 + 1.*lam/beta*H.conjugate()*H # x = FFTW.irfftn(nom/den) if logged: print "objective f = %s"%objective(x) # return H.conjugate()*Y beta *= beta_inc x *= y_mean return x, res
def deconv_hyperlap_breg(y, h, lam = 1000., gamma = 5., niter = 10, n_threads = 6, logged = False): """ hyper laplacian regularized deconvolution via split bregman Krishnan et al see http://people.ee.duke.edu/~lcarin/NIPS2009_0341.pdf y is/are the recorded image(s) h is/are the (already fftshifted) kernel(s) of same shape both can be equal sized tuples, in which case a joint deconvolution is performed if the data or the kernels are already fourier transformed then set y_is_fft/h_is_fft to True params: lam - the higher, the bigger the data term gamma - the smaller, the more TV enforced """ alpha = 1. #make everything scale invariant y_mean = np.mean(y) y = y/y_mean dshape = y.shape FFTW = MyFFTW(dshape,unitary = False, n_threads = n_threads) H = FFTW.rfftn(h) Y = FFTW.rfftn(y) dft_stencil = dft_lap(dshape, use_rfft=True) x = 1.*y def objective(x): dxs = np.gradient(x) X = FFTW.rfftn(x) x_b = FFTW.irfftn(X*H) ener = .5*lam*np.sum((x_b-y)**2) grad = np.sum([abs(dx)**alpha for dx in dxs]) return ener + grad d = np.zeros((x.ndim,)+x.shape) b = np.zeros((x.ndim,)+x.shape) grad_x = np.stack(np.gradient(x)) for i in xrange(niter): print "iteration: %d / %d"%(i+1,niter) # d subproblem d = soft_thresh(grad_x+b,1./gamma) # x subproblem nom1 = H.conjugate()*Y nom2 = FFTW.rfftn(divergence(d-b)) den1 = H.conjugate()*H den2 = dft_stencil x = FFTW.irfftn((1.*lam/gamma*nom1 - nom2)/(1.*lam/gamma*den1 - den2)) grad_x = np.stack(np.gradient(x)) # enforcing constraint b += grad_x - d x *= y_mean return x