Exemplo n.º 1
0
def PSNR(f, g, max_val=None):
    """
    ~ Calculates peak signal-to-noise ratio of an array and its noisy approximation
    
    ========input=========
    
    f : Input noise-free array
    g : Input noisy approximation array
    max_val : Maximum pixel value
    
    ========output========
    
    psnr : PSNR
    
    """

    f = tl.array(f)
    g = tl.array(g)

    if (tl.shape(f) != tl.shape(g)):
        raise TypeError('f and g must be arrays of equal shape')

    if (max_val == None): max_val = tl.maxx([f, g])

    if ((f == g).all()):
        psnr = tl.inf
    else:
        mse = tl.mean(tl.abss(f - g)**2)
        psnr = 10 * tl.log10(max_val**2 / mse)

    return psnr
Exemplo n.º 2
0
    def profile(self, z, f, dx=1.):
        """
        Beam's complex amplitude at an axial distance z from waist.
        Plane lies perpendicular to z axis and has the same shape as f.
        
        ========Input=========
    
        z : Axial distance from waist
        f : 2D Array defining the output array shape
        dx : Pixel pitch (default value is unit of measurement)
        
        ========Raises========
        
        TypeError: If f isn't a 2D array
        
        ========Output========
    
        g : 2D complex array (complex amplitude at an axial distance z from waist centered at z axis)
        
        """

        if (len(tl.shape(f)) != 2):
            raise TypeError('f must be a 2D array')

        n, m = tl.shape(f)
        x = tl.arange(-m * dx / 2, m * dx / 2, dx)
        y = tl.arange(-n * dx / 2, n * dx / 2, dx)
        X, Y = tl.meshgrid(x, y)
        R = tl.sqrt(X**2 + Y**2)
        g = self.value(R, z)

        return g
Exemplo n.º 3
0
    def profile(self, z, f, dx=1.):
        """
        Beam's complex amplitude at an axial distance z from waist.
        Plane lies perpendicular to z axis and has the same shape as f.
        
        ========Input=========
    
        z : Axial distance from waist
        f : 2D Array defining the output array shape
        dx : Pixel pitch (default value is unit of measurement)
        
        ========Raises========
    
        ========Output========
    
        g : 2D complex array (complex amplitude at an axial distance z from waist centered at z axis)
        
        """

        n, m = tl.shape(f)
        x = tl.arange(-m * dx / 2, m * dx / 2, dx)
        y = tl.arange(-n * dx / 2, n * dx / 2, dx)
        X, Y = tl.meshgrid(x, y)
        g = self.value(X, Y, z)
        return g
Exemplo n.º 4
0
def GetRBW(f, dx=1., dy=None, p=0.98):
    """
    ~ Approximately calculates full radial bandwidth
    ~ This is not a verified numerical method just something I made up
    
    ========Input=========
    
    f :         Input 2D array
    p :         Effectiveness parameter
    dx :        Horizontal sampling interval (Default value is unit of measurement)
    dy :        Vertical sampling interval (Default for square sampling)

    ========output========
    
    RBW :       Full radial bandwidth.
    
    """

    if (dy == None):
        dy = dx

    n, m = tl.shape(f)
    M = max([n, m])

    F = FFT2(f)
    P = Power(F)  # Total power
    fr = tl.arange(1, M + 1)  # Radial frequency in pixels
    Pr = [Power(F * Ellipse(fri, fri, (n, m), use_pxc=True)) for fri in fr
          ]  # Power as function of radial distance in the Fourier domain
    RBW = 2 * max(fr[Pr <= p * P]) * max([1. / dx, 1. / dy])

    return RBW
Exemplo n.º 5
0
def HighPassF(f, px=0.5, py=0.5, mask='rect'):
    """
    ~ High pass filter
    
    ========Input=========
    
    f :     Input 2D array
    px :    Characteristic horizontal length of filter function
    py :    Characteristic vertical length of filter function
    mask :  Filter function

    ========output========
    
    g : Filtered signal
    
    """

    shape = tl.shape(f)

    filters = {
        'rect': Rect(px, py, shape),
        'ellipse': Ellipse(px, py, shape),
        'gauss': Gauss(px, py, shape)
    }

    F = FFT2(f)
    F *= (1. - filters.get(mask))
    g = IFFT2(F)

    return g
Exemplo n.º 6
0
def Entropy(f, nbits=0):
    """
    ~ Calculates entropy of array histogram
    
    ========input=========
    
    f : Input array
    nbits : Calculate for a given number of bits
    
    ========output========
    
    S : Shannon Entropy
    
    """

    f = tl.reshape(f, (1, tl.prod(tl.shape(f))))[0]

    if (nbits != 0):
        f = LinearNormal(f)
        MAX = 2.**nbits - 1
        f = tl.floor(f * MAX)

    pdf = tl.Series(f).value_counts().values

    pdf = pdf / tl.summ(pdf * 1.)

    S = -tl.summ(pdf * tl.log2(pdf))

    return S
Exemplo n.º 7
0
def LinearNormal(f, new_min=0., new_max=1.):
    """
    ~ Linearly normalizes f to interval [new_min,new_max]
    ~ If the input array is complex, only affects its norm
    
    ========Input=========
    
    f : Input array
    new_min : Minimum value in normalization interval (default 0)
    new_max : Maximum value in normalization interval (default 1)
    
    ========Output========
    
    g : Normalized input array
    
    """

    if tl.iscomplex(f).any():
        fnorm = tl.abss(f)
        if ((fnorm == tl.mean(fnorm)).all()):
            g = 1.
        else:
            g = (fnorm - tl.minn(fnorm)) / (tl.maxx(fnorm) - tl.minn(fnorm)
                                            ) * (new_max - new_min) + new_min
        g *= tl.exp(1j * tl.angle(f))

    else:
        if ((f == tl.mean(f)).all()):
            g = tl.ones(tl.shape(f))
        else:
            g = (f - tl.minn(f)) / (tl.maxx(f) -
                                    tl.minn(f)) * (new_max - new_min) + new_min

    return g
Exemplo n.º 8
0
def FresnelIR(f, z, wl, dx):
    """
    ~ Propagates f in free space sampling the Impulse Response
    Voelz D. Computational Fourier Optics: A MATLAB Tutorial. 2011.
    
    ========Input=========
    
    f :     Input complex amplitude profile (2D complex array)
    z :     Propagation distance
    wl :    Central wavelenght of the field
    dx :    Sampling interval (default value is unit of measurement)
    
    ========Output========
    
    h :     Propagated complex amplitude profile (2D complex array)
    
    """

    n, m = tl.shape(f)
    Lx = dx * n
    Ly = dx * m
    F = FFT2(f)
    x = tl.arange(-Lx / 2, Lx / 2, dx)
    y = tl.arange(-Ly / 2, Ly / 2, dx)
    X, Y = tl.meshgrid(x, y)
    g = tl.exp(1j * tl.pi / (wl * z) * (X**2 + Y**2)) / (1j * wl * z)
    G = FFT2(g) * dx * dx
    h = IFFT2(F * G)

    return h
Exemplo n.º 9
0
def FresnelTF(f, z, wl, dx):
    """
    ~ Propagates f in free space sampling the Transfer Function
    Voelz D. Computational Fourier Optics: A MATLAB Tutorial. 2011.
    
    ========Input=========
    
    f :     Input complex amplitude profile (2D complex array)
    z :     Propagation distance
    wl :    Central wavelenght of the field
    dx :    Sampling interval (default value is unit of measurement)
    SBC :   Use the source bandwidth criterion for large propagation regime
    
    ========Output========
    
    h :     Propagated complex amplitude profile (2D complex array)
    """

    n, m = tl.shape(f)
    Lx = dx * n
    Ly = dx * m
    F = FFT2(f)
    fx = tl.arange(-1 / (2 * dx), 1 / (2 * dx), 1 / Lx)
    fy = tl.arange(-1 / (2 * dx), 1 / (2 * dx), 1 / Ly)
    FX, FY = tl.meshgrid(fx, fy)
    G = tl.exp((-1j * wl * tl.pi * z) * (FX**2 + FY**2))
    h = IFFT2(F * G)

    return h
Exemplo n.º 10
0
def Fraunhofer(f, z, wl, dx=1.):
    """
    ~ Propagates input 2D array in free space using the Fraunhofer propagator
    Voelz D. Computational Fourier Optics: A MATLAB Tutorial. 2011.
    
    ========Input=========
    
    f :     Input complex amplitude profile (2D complex array)
    z :     Propagation distance
    wl :    Central wavelenght of the field
    dx :    Sampling interval (default value is unit of measurement)
    
    ========Output========
    
    g  :    Propagated complex amplitude profile (2D complex array)
    oL :    Observation plane side lenght
    
    """

    n, m = tl.shape(f)
    oL = wl * z / dx  # Observation plane side lenght
    odx = oL / m
    ody = oL / n  # Observation plane sample interval
    x = tl.arange(-oL / 2, oL / 2, odx)
    y = tl.arange(-oL / 2, oL / 2, ody)
    X, Y = tl.meshgrid(x, y)

    g = -1j / (wl * z) * tl.exp(1j * tl.pi / (wl * z) * (X**2 + Y**2))
    g = g * FFT2(f) * dx * dx

    return g, oL
Exemplo n.º 11
0
def Embed(f, g, x=0., y=0.):
    """
    ~ Embeds g onto f centered at (x,y)
    ~ (x,y) coordinates are given in a centered cartesian frame

    ========Input=========
    
    f : 2D input array
    g : 2D array to be embedded
    x : x cartesian coordinate of the embedding center measured from input array's center
    y : y cartesian coordinate of the embedding center measured from input array's center
    
    ========Raises========

    ValueError : If either f or g isn't a 2D array    
    ValueError : If g is bigger than f
    
    ========Output========
    
    h : 2D input array f with g embedded at (x,y)

    """

    if ((tl.ndim(f), tl.ndim(g)) != (2, 2)):
        raise ValueError('Input and embedding arrays must be 2D')

    (m, n) = tl.shape(f)

    (mm, nn) = tl.shape(g)

    if (mm > m or nn > n):
        raise ValueError('Embedding array must be smaller than input array')

    h = f.copy()
    h[tl.int32(tl.floor((m - mm) * 0.5) +
               y):tl.int32(tl.floor((m + mm) * 0.5) + y),
      tl.int32(tl.floor((n - nn) * 0.5) +
               x):tl.int32(tl.floor((n + nn) * 0.5) + x)] = g

    return h
Exemplo n.º 12
0
def Fresnel2S(f, z, wl, L1, L2):
    """
    ~ Propagates input 2D array in free space using the two-step Fresnel propagator
    Voelz D. Computational Fourier Optics: A MATLAB Tutorial. 2011.
    
    ========Input=========
    
    f :     Input complex amplitude profile (2D complex array)
    z :     Propagation distance
    wl :    Central wavelenght of the field
    L1 :    Input sample plane side lenght
    L2 :    Output sample plane side lenght
    
    ========Output========
    
    h :     Propagated complex amplitude profile (2D complex array)
    
    """

    if (tl.ndim(f) != 2):
        raise TypeError("Input array must be a 2D square array")

    m, n = tl.shape(f)

    if (m != n):
        raise ValueError("Input array must be a 2D square array")

    k = 2 * tl.pi / wl

    # Source plane
    dx1 = L1 / m
    x1 = tl.arange(-L1 / 2., L1 / 2., dx1)
    X, Y = tl.meshgrid(x1, x1)
    F = f * tl.exp(1j * k / (2. * z * L1) * (L1 - L2) * (X**2 + Y**2))
    F = tl.fft.fft2(tl.fft.fftshift(F))

    # Dummy plane
    fx1 = tl.arange(-1. / (2 * dx1), 1. / (2 * dx1), 1. / L1)
    fx1 = tl.fft.fftshift(fx1)
    FX1, FY1 = tl.meshgrid(fx1, fx1)
    G = F * tl.exp(-1j * tl.pi * wl * z * L1 / L2 * (FX1**2 + FY1**2))
    g = tl.fft.ifftshift(tl.fft.ifft2(G))

    # Observation plane
    dx2 = L2 / m
    x2 = tl.arange(-L2 / 2., L2 / 2., dx2)
    X, Y = tl.meshgrid(x2, x2)
    g = (L2 / L1) * g * tl.exp(-1j * k / (2. * z * L2) * (L1 - L2) *
                               (X**2 + Y**2))
    g = g * (dx1 / dx2)**2

    return g
Exemplo n.º 13
0
def ErrDiffBin(f,
               T=0.5,
               b=[[1 / 16., 5 / 16., 3 / 16.], [7 / 16., 0., 0.], [0., 0.,
                                                                   0.]]):
    """
    ~ Binarizes input 2D array using the Error-Diffusion algorithm.
    Barnard E. Optimal error diffusion for computer-generated holograms. J Opt Soc Am A 1988;5:1803-17.
    
    ========Input=========
    
    f : Real input 2D array 
    T : Binarization threshold (default value for input array with [0,1] dynamic range)
    b : 3x3 2D real array with the diffusion coefficients (default given by paper; see paper for details)
    
    ========Raises========
    
    TypeError : If b isn't a 3x3 2D real array
    ValueError : If b doesn't meet the convergence conditions (see paper for details)
    
    ========Output========
    
    h[1:-1,1:-1] : Binarized input array

    """

    b = tl.array(b)

    if (tl.shape(b) != (3, 3) or tl.isreal(b).all() == False):
        raise TypeError('b has to be a 3x3 2D array')

    if (tl.summ(abs(b)) > 1):
        raise ValueError(
            'The diffusion coefficients don\'t meet the convergence conditions'
        )

    n, m = f.shape
    g = tl.zeros((n + 2, m + 2))
    h = tl.zeros((n + 2, m + 2))
    s = tl.zeros((n + 2, m + 2))

    g[1:-1, 1:-1] = f

    for i in range(1, n - 1):
        for j in range(1, m - 1):

            g[i, j] += tl.summ(b * s[i - 1:i + 2, j - 1:j + 2])
            h[i, j] = (g[i, j] > T) * 1.
            s[i, j] = g[i, j] - h[i, j]

    return h[1:-1, 1:-1]
Exemplo n.º 14
0
def FresnelCS(f, z, wl, dx=1., SBC=False):
    """
    ~ Propagates input 2D array in free space using the critical sampling criterion
    ~ Samples either the Impulse Response or the Transfer Function given the critic sampling criterion
    Voelz D. Computational Fourier Optics: A MATLAB Tutorial. 2011.
    
    ========Input=========
    
    f :     Input complex amplitude profile (2D complex array)
    z :     Propagation distance
    wl :    Central wavelenght of the field
    dx :    Sampling interval (default value is unit of measurement)
    SBC :   Use the source bandwidth criterion for large propagation regime
    
    ========Output========
    
    h :     Propagated complex amplitude profile (2D complex array)
    
    """

    n, m = tl.shape(f)  # Array dimensions
    Lx = dx * m
    Ly = dx * n  # Source plane side lenghts
    zc = dx * Lx / wl  # Critic sampling propagation distance
    F = FFT2(f)

    if (SBC):  # Check the source bandwidth criterion
        B = GetRBW(f, dx)
        SBC = B <= min([Lx, Ly]) / (wl * z)

    if (abs(z) > zc and not SBC):  # Propagating using Impulse Response
        x = tl.arange(-Lx / 2., Lx / 2., dx)
        y = tl.arange(-Ly / 2., Ly / 2., dx)
        X, Y = tl.meshgrid(x, y)
        g = tl.exp(1j * tl.pi / (wl * z) * (X**2 + Y**2)) / (1j * wl * z)
        G = FFT2(g) * dx * dx

    if (abs(z) <= zc):  # Propagating using Transfer Function
        F = 0.5 / dx  # Nyquist frequency
        fx = tl.arange(-F, F, 1. / Lx)
        fy = tl.arange(-F, F, 1. / Ly)
        FX, FY = tl.meshgrid(fx, fy)
        G = tl.exp((-1j * wl * tl.pi * z) * (FX**2 + FY**2))

    h = IFFT2(F * G)

    return h
Exemplo n.º 15
0
def Trim(f, shape, x=0., y=0.):
    """
    ~ Trims an array from f centered at (x,y) with shape shape
    ~ (x,y) coordinates are given in a centered cartesian frame

    ========Input=========
    
    f :         2D input array from which the trim is taken
    shape :     Trimming shape
    x :         x cartesian coordinate of the trimming center measured from input array's center
    y :         y cartesian coordinate of the trimming center measured from input array's center
    
    ========Raises========
    
    TypeError :     If input array isn't 2D
    TypeError :     If trimming shape isn't 2D
    ValueError :    If trimming shape is bigger than input array's shape

    ========Output========
    
    h : Trimmed 2D array

    """

    if (tl.ndim(f) != 2):
        raise TypeError('Input array must be 2D')

    if (len(shape) != 2):
        raise TypeError('Trimming shape must be 2D')

    (m, n) = tl.shape(f)
    (mm, nn) = shape

    if (mm > m or nn > n):
        raise ValueError('Trimming array must be smaller than input array')

    h = f[tl.int32(tl.floor((m - mm) * 0.5) +
                   y):tl.int32(tl.floor((m + mm) * 0.5) + y),
          tl.int32(tl.floor((n - nn) * 0.5) +
                   x):tl.int32(tl.floor((n + nn) * 0.5) + x)]

    return h