예제 #1
0
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)
예제 #2
0
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
예제 #3
0
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)
예제 #4
0
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
예제 #5
0
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
예제 #6
0
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