예제 #1
0
def iabel_basex_transform(Q0):
    # basex requires a whole image
    IM = put_image_quadrants((Q0, Q0, Q0, Q0), odd_size=True)
    print ("basex uses whole image reconstructed from Q0 shape ",IM.shape)
    rows, cols = IM.shape
    center = (rows//2+rows%2, cols//2+cols%2)
    AIM = BASEX (IM, center, n=rows, verbose=True)
    return get_image_quadrants(AIM)[0]  # only return Q0
예제 #2
0
def iabel_basex_transform(Q0):
    # basex requires a whole image
    IM = put_image_quadrants((Q0, Q0, Q0, Q0), odd_size=True)
    print("basex uses whole image reconstructed from Q0 shape ", IM.shape)
    rows, cols = IM.shape
    center = (rows // 2 + rows % 2, cols // 2 + cols % 2)
    AIM = BASEX(IM, center, n=rows, verbose=True)
    return get_image_quadrants(AIM)[0]  # only return Q0
예제 #3
0
def rbasex_transform(IM,
                     origin='center',
                     rmax='MIN',
                     order=2,
                     odd=False,
                     weights=None,
                     direction='inverse',
                     reg=None,
                     out='same',
                     basis_dir=None,
                     verbose=False):
    r"""
    This function takes the input image and outputs its forward or inverse Abel
    transform as an image and its radial distributions.

    The **origin**, **rmax**, **order**, **odd** and **weights** parameters are
    passed to :class:`abel.tools.vmi.Distributions`, so see its documentation
    for their detailed descriptions.

    Parameters
    ----------
    IM : m × n numpy array
        the image to be transformed
    origin : tuple of int or str
        image origin, explicit in the (row, column) format, or as a location
        string (by default, the image center)
    rmax : int or string
        largest radius to include in the transform (by default, the largest
        radius with at least one full quadrant of data)
    order : int
        highest angular order present in the data, ≥ 0 (by default, 2)
    odd : bool
        include odd angular orders (by default is `False`, but is enabled
        automatically if **order** is odd)
    weights : m × n numpy array, optional
        weighting factors for each pixel. The array shape must match the image
        shape. Parts of the image can be excluded from analysis by assigning
        zero weights to their pixels. By default is `None`, which applies equal
        weight to all pixels.
    direction : str: ``'forward'`` or ``'inverse'``
        type of Abel transform to be performed (by default, inverse)
    reg : None or str or tuple (str, float), optional
        regularization to use for inverse Abel transform. ``None`` (default)
        means no regularization, a string selects a non-parameterized
        regularization method, and parameterized methods are selected by a
        tuple (`method`, `strength`). Available methods are:

        ``('L2', strength)``:
            Tikhonov :math:`L_2` regularization with `strength` as the square
            of the Tikhonov factor. This is the same as “Tikhonov
            regularization” used in BASEX, with almost identical effects on the
            radial distributions.
        ``('diff', strength)``:
            Tikhonov regularization with the difference operator (approximation
            of the derivative) multiplied by the square root of `strength` as
            the Tikhonov matrix. This tends to produce less blurring, but more
            negative overshoots than ``'L2'``.
        ``('SVD', strength)``:
            truncated SVD (singular value decomposition) with
            N = `strength` × **rmax** largest singular values removed for each
            angular order. This mimics the approach proposed (but in fact not
            used) in pBasex. `Not recommended` due to generally poor results.
        ``'pos'``:
            non-parameterized method, finds the best (in the least-squares
            sense) solution with non-negative :math:`\cos^n\theta \sin^m\theta`
            terms (see :meth:`~abel.tools.vmi.Distributions.Results.cossin`).
            For **order** = 0, 1, and 2 (with **odd** = `False`) this is
            equivalent to :math:`I(r, \theta) \geqslant 0`; for higher orders
            this assumption is stronger than :math:`I \geqslant 0` and
            corresponds to no interference between different multiphoton
            channels. Not implemented for odd orders > 1.

            Notice that this method is nonlinear, which also means that it is
            considerably slower than the linear methods and the transform
            operator cannot be cached.

        In all cases, `strength` = 0 provides no regularization. For the
        Tikhonov methods, `strength` ~ 100 is a reasonable value for megapixel
        images. For truncated SVD, `strength` must be < 1; `strength` ~ 0.1 is
        a reasonable value; `strength` ~ 0.5 can produce noticeable ringing
        artifacts. See the :ref:`full description <rBasexmathreg>` and examples
        there.
    out : str or None
        shape of the output image:

        ``'same'`` (default):
            same shape and origin as the input
        ``'fold'`` (fastest):
            Q0 (upper right) quadrant (for ``odd=False``) or right half (for
            ``odd=True``) up to **rmax**, but limited to the largest
            input-image quadrant (or half)
        ``'unfold'``:
            like ``'fold'``, but symmetrically “unfolded” to all 4 quadrants
        ``'full'``:
            all pixels with radii up to **rmax**
        ``'full-unique'``:
            the unique part of ``'full'``: Q0 (upper right) quadrant for
            ``odd=False``, right half for ``odd=True``
        ``None``:
            no image (**recon** will be ``None``). Can be useful to avoid
            unnecessary calculations when only the transformed radial
            distributions (**distr**) are needed.
    basis_dir : str, optional
        path to the directory for saving / loading the basis set (useful only
        for the inverse transform without regularization; time savings in other
        cases are small and might be negated by the disk-access overhead).
        If ``None`` (default), the basis set will not be loaded from or saved
        to disk.
    verbose : bool
        print information about processing (for debugging), disabled by default

    Returns
    -------
    recon : 2D numpy array or None
        the transformed image. Is centered and might have different dimensions
        than the input image.
    distr : Distributions.Results object
        the object from which various distributions for the transformed image
        can be retrieved, see :class:`abel.tools.vmi.Distributions.Results`
    """
    if order == 0:
        odd = False  # (to eliminate additional checks)
    elif order % 2:
        odd = True  # enable automatically for odd orders

    # extract radial profiles from input image
    p = _profiles(IM, origin, rmax, order, odd, weights, verbose)
    # (caches Distributions as _dst)

    Rmax = _dst.rmax

    # get appropriate transform matrices
    A = get_bs_cached(Rmax, order, odd, direction, reg, _dst.valid, basis_dir,
                      verbose)

    # transform radial profiles
    if reg == 'pos':
        if verbose:
            print('Solving NNLS equations...')
        N = len(p)
        p = np.hstack(p)
        cs = nnls(A, p)[0]
        cs = np.split(cs, N)
        if odd:
            # (1 ± cos) / 2 → cos^0, cos^1
            c = [cs[0] + cs[1], cs[0] - cs[1]]
        else:
            # cossin → cos transform
            C = np.flip(invpascal(N, 'upper'))
            c = C.dot(cs)
    else:
        if verbose:
            print('Applying radial transforms...')
        c = [An.dot(pn) for An, pn in zip(A, p)]

    # construct output (transformed) distributions
    distr = Distributions.Results(np.arange(Rmax + 1), np.array(c), order, odd,
                                  _dst.valid)

    if out is None:
        return None, distr

    # output size
    if out == 'same':
        height = _dst.shape[0] if odd else _dst.VER + 1
        width = _dst.HOR + 1
        row = _dst.row if odd else 0
    elif out in ['fold', 'unfold']:
        height = _dst.Qheight
        width = _dst.Qwidth
        row = _dst.row if odd else 0
    elif out in ['full', 'full-unique']:
        height = 2 * Rmax + 1 if odd else Rmax + 1
        width = Rmax + 1
        row = Rmax if odd else 0
    else:
        raise ValueError('Wrong output shape "{}"'.format(out))
    # construct output image from transformed radial profiles
    if verbose:
        print('Constructing output image...')
    # bottom right quadrant or right half
    recon = _image(height, width, row, c, verbose)
    if odd:
        if out not in ['fold', 'full-unique']:
            # combine with left half (mirrored without central column)
            recon = np.hstack((recon[:, :0:-1], recon))
    else:  # even only
        recon = recon[::-1]  # flip to Q0
        if out not in ['fold', 'full-unique']:
            # assemble full image
            recon = put_image_quadrants((recon, recon, recon, recon),
                                        (2 * height - 1, 2 * width - 1))
    if out == 'same':
        # crop as needed
        row = 0 if odd else _dst.VER - _dst.row
        col = _dst.HOR - _dst.col
        H, W = IM.shape
        recon = recon[row:row + H, col:col + W]

    return recon, distr
예제 #4
0
    plt.plot (radial, speed, label=method)

# reassemble image, each quadrant a different method

# for < 4 images pad using a blank quadrant
blank = np.zeros(IAQ0.shape)  
for q in range(ntrans, 4):
    iabelQ.append(blank)

# more than 4, split quadrant
if ntrans == 5:
    # split last quadrant into 2 = upper and lower triangles
    tmp_img = np.tril(np.flipud(iabelQ[-2])) +\
              np.triu(np.flipud(iabelQ[-1]))
    iabelQ[3] = np.flipud(tmp_img)
# Fix me when > 5 images
 

im = put_image_quadrants ((iabelQ[0],iabelQ[1],iabelQ[2],iabelQ[3]), 
                           odd_size=True)

plt.subplot(121)
plt.imshow(im,vmin=0,vmax=0.8)

plt.subplot(122)
plt.axis(ymin=-0.05,ymax=1.1,xmin=50,xmax=450)
plt.legend(loc=0,labelspacing=0.1)
plt.tight_layout()
plt.savefig('example_all_O2.png',dpi=100)
plt.show()
예제 #5
0
    plt.subplot(122)
    plt.plot(radial, speed, label=method)

# reassemble image, each quadrant a different method

# for < 4 images pad using a blank quadrant
blank = np.zeros(IAQ0.shape)
for q in range(ntrans, 4):
    iabelQ.append(blank)

# more than 4, split quadrant
if ntrans == 5:
    # split last quadrant into 2 = upper and lower triangles
    tmp_img = np.tril(np.flipud(iabelQ[-2])) +\
              np.triu(np.flipud(iabelQ[-1]))
    iabelQ[3] = np.flipud(tmp_img)
# Fix me when > 5 images

im = put_image_quadrants((iabelQ[0], iabelQ[1], iabelQ[2], iabelQ[3]),
                         odd_size=True)

plt.subplot(121)
plt.imshow(im, vmin=0, vmax=0.8)

plt.subplot(122)
plt.axis(ymin=-0.05, ymax=1.1, xmin=50, xmax=450)
plt.legend(loc=0, labelspacing=0.1)
plt.tight_layout()
plt.savefig('example_all_O2.png', dpi=100)
plt.show()