Beispiel #1
0
def plot_pixel_mask(h, w, pixels, output_path=None):
    """
    Display a binary image that shows the given pixel mask.

    A black image with `w` x `h` pixels is created and the `pixels` are marked
    with white.

    Parameters
    ----------
    h : int
        The height of the image in pixels.
    w : int
        The width of the image in pixels.
    pixels : ndarray
        The 2D array of pixels that make up the mask. Each row is a coordinate
        pair (x, y), such that `coords` has size len(`pixels`) x 2.
    output_path : str, optional
        Path (including file type extension) under which the plot is saved (the
        default value is None which implies, that the plot is not saved).

    Notes
    -----
    The resulting image is displayed in a figure using
    `magni.imaging.visualisation.imshow`.

    Examples
    --------
    For example,

    >>> from magni.imaging.measurements import plot_pixel_mask
    >>> h = 3
    >>> w = 3
    >>> pixels = np.array([[0, 0], [1, 1], [2, 1]])
    >>> plot_pixel_mask(h, w, pixels)

    """

    _validate_plot_pixel_mask(h, w, pixels, output_path)

    mask = np.zeros((h, w))
    mask[pixels[:, 1], pixels[:, 0]] = 1

    fs = (np.abs([h, w])).min() / 10
    _plotting.setup_matplotlib({'figure': {'figsize': (h / fs, w / fs)}},
                               cmap='gray')

    fig, axes = plt.subplots(1, 1)
    _imshow(mask, ax=axes, show_axis='top')

    axes.set_xlabel('width [pixels]')
    axes.set_ylabel('height [pixels]')

    plt.tight_layout()

    if output_path is not None:
        plt.savefig(output_path)
Beispiel #2
0
def plot_pixel_mask(h, w, pixels, output_path=None):
    """
    Display a binary image that shows the given pixel mask.

    A black image with `w` x `h` pixels is created and the `pixels` are marked
    with white.

    Parameters
    ----------
    h : int
        The height of the image in pixels.
    w : int
        The width of the image in pixels.
    pixels : ndarray
        The 2D array of pixels that make up the mask. Each row is a coordinate
        pair (x, y), such that `coords` has size len(`pixels`) x 2.
    output_path : str, optional
        Path (including file type extension) under which the plot is saved (the
        default value is None which implies, that the plot is not saved).

    Notes
    -----
    The resulting image is displayed in a figure using
    `magni.imaging.visualisation.imshow`.

    Examples
    --------
    For example,

    >>> import numpy as np
    >>> from magni.imaging.measurements import plot_pixel_mask
    >>> h = 3
    >>> w = 3
    >>> pixels = np.array([[0, 0], [1, 1], [2, 1]])
    >>> plot_pixel_mask(h, w, pixels)

    """

    @_decorate_validation
    def validate_input():
        _numeric('h', 'integer', range_='[2;inf)')
        _numeric('w', 'integer', range_='[2;inf)')
        _numeric('pixels', 'integer', shape=(-1, 2))
        _numeric('pixels[:, 0]', 'integer', range_='[0;{}]'.format(w - 1),
                 shape=(-1,), var=pixels[:, 0])
        _numeric('pixels[:, 1]', 'integer', range_='[0;{}]'.format(h - 1),
                 shape=(-1,), var=pixels[:, 1])
        _generic('output_path', 'string', ignore_none=True)

    validate_input()

    mask = _util.construct_pixel_mask(h, w, pixels)

    figsize = plt.rcParams['figure.figsize']

    if w / h > figsize[0] / figsize[1]:
        figsize_local = [figsize[0], figsize[0] * h / w]
    else:
        figsize_local = [figsize[1] * w / h, figsize[1]]

    _plotting.setup_matplotlib({'figure': {'figsize': figsize_local}})

    fig, axes = plt.subplots(1, 1)
    _imshow(mask, ax=axes, show_axis='top')

    axes.set_xlabel('width [pixels]')
    axes.set_ylabel('height [pixels]')

    plt.tight_layout()

    if output_path is not None:
        plt.savefig(output_path)

    _plotting.setup_matplotlib({'figure': {'figsize': figsize}})
Beispiel #3
0
def show_transform_quantiles(img,
                             transform,
                             fraction=1.0,
                             area_mask=None,
                             ax=None):
    """
    Show a plot of the quantiles of the transform coefficients.

    The `fraction` of `transform` coefficients holding the most energy for the
    image `img` is considered. The four quantiles within this fraction of
    coefficients are illustrated in the `transform` domain by showing
    coefficients between the different quantiles in different colours. If an
    `area_mask` is specified, only this area in the plot is higlighted whereas
    the rest is darkened.

    Parameters
    ----------
    img : ndarray
        The image to show the transform quantiles for.
    transform : str
        The transform to use.
    fraction : float
        The fraction of coefficients used in the quantiles calculation (the
        default value is 1.0, which implies that all coefficients are used).
    area_mask : ndarray
        Bool array of the same shape as `img` which indicates the area of the
        image to highlight (the default value is None, which implies that no
        particular part of the image is highlighted).
    ax : matplotlib.axes.Axes
        The axes on which the image is displayed (the default is None, which
        implies that a separate figure is created).

    Returns
    -------
    coef_count : dict
        Different counts of coeffcients within the `area_mask` (only returned
        if `area_mask` is not None).

    Notes
    -----
    The ticks on the colorbar shown below the figure are the percentiles of the
    entire set of coefficients corresponding to the quantiles with fraction of
    coefficients. For instance, if fraction is 0.10, then the percentiles are
    92.5, 95.0, 97.5, 100.0, corresponding to the four quantiles within the 10
    percent coefficients holding the most energy.

    The `coef_count` dictionary holds the following keys:

    * C_total : Total number of considered coefficients.
    * Q_potential : Number of potential coefficients within `mask_area`.
    * P_fraction : The fraction of Q_potential to the pixel count in `img`.
    * Q_total : Total number of (considered) coefficients within `mask_area`.
    * Q_fraction : The fraction of Q_total to Q_potential
    * QC_fraction : The fraction of Q_total to C_total.
    * Q0-Q1 : Number of coefficients smaller than the first quantile.
    * Q1-Q2 : Number of coefficients between the first and second quantile.
    * Q2-Q3 : Number of coefficients between the second and third quantile.
    * Q3-Q4 : Number of coefficients between the third and fourth quantile.

    Each of the QX-QY holds a tuple containing two values:

    1. The number of coefficients.
    2. The fraction of the number of coefficients to Q_total.

    Examples
    --------
    For example, show quantiles for a fraction of 0.2 of the DCT coefficients:

    >>> import numpy as np
    >>> from magni.imaging.dictionaries import analysis as _a
    >>> img = np.arange(64).astype(np.float).reshape(8, 8)
    >>> transforms = 'DCT'
    >>> fraction = 0.2
    >>> _a.show_transform_quantiles(img, transform, fraction=fraction)

    """
    @_decorate_validation
    def validate_input():
        _numeric('img', ('integer', 'floating', 'complex'), shape=(-1, -1))
        _generic('transform', 'string', value_in=_utils.get_transform_names())
        _numeric('fraction', 'floating', range_='[0;1]')
        _numeric('area_mask', 'boolean', shape=img.shape, ignore_none=True)
        _generic('ax', mpl.axes.Axes, ignore_none=True)

    @_decorate_validation
    def validate_output():
        _generic('coef_counts',
                 'mapping',
                 has_keys=('Q_total', 'Q_potential', 'Q0_Q1', 'Q_fraction',
                           'Q3_Q4', 'Q2_Q3', 'Q1_Q2', 'C_total',
                           'QC_fraction'))

    validate_input()

    # Colorbrewer qualitative 5-class Set 1 as colormap
    colours = [(228, 26, 28), (55, 126, 184), (77, 175, 74), (152, 78, 163),
               (255, 127, 0)]
    norm_colours = [
        tuple([round(val / 255, 4) for val in colour])
        for colour in colours[::-1]
    ]
    norm_colours = [norm_colours[0]] * 2 + norm_colours
    quantile_cmap = mpl.colors.ListedColormap(norm_colours)

    # Transform
    transform_matrix = _utils.get_function_handle('matrix',
                                                  transform)(img.shape)
    all_coefficients = _vec2mat(transform_matrix.conj().T.dot(_mat2vec(img)),
                                img.shape)
    # Force very low values to zero to avoid false visualisations
    all_coefficients[all_coefficients < np.finfo(np.float).eps * 10] = 0

    # Masked coefficients
    sorted_coefficients = np.sort(np.abs(all_coefficients), axis=None)[::-1]
    mask = np.abs(all_coefficients) > sorted_coefficients[
        int(np.round(fraction * all_coefficients.size)) - 1]

    used_coefficients = np.zeros_like(all_coefficients, dtype=np.float)
    used_coefficients[mask] = np.abs(all_coefficients[mask])

    # Quantiles
    q_linspace = np.linspace((1 - fraction) * 100, 100, 5)
    q_percentiles = tuple(q_linspace[1:4])
    quantiles = np.percentile(used_coefficients, q_percentiles)
    disp_coefficients = np.zeros_like(used_coefficients)
    disp_coefficients[(0 < used_coefficients)
                      & (used_coefficients <= quantiles[0])] = 1
    disp_coefficients[(quantiles[0] < used_coefficients)
                      & (used_coefficients <= quantiles[1])] = 2
    disp_coefficients[(quantiles[1] < used_coefficients)
                      & (used_coefficients <= quantiles[2])] = 3
    disp_coefficients[quantiles[2] < used_coefficients] = 4

    # Quantile figure
    disp, axes_extent = _utils.get_function_handle('visualisation',
                                                   transform)(img.shape)
    if ax is None:
        fig, axes = plt.subplots(1, 1)
    else:
        fig = ax.get_figure()
        axes = ax
    im = _imshow(
        disp(_mat2vec(10**disp_coefficients)),
        ax=axes,  # anti-log10
        cmap=quantile_cmap,
        show_axis='top',
        interpolation='none',
        extent=axes_extent)
    divider = _make_axes_locatable(axes)
    c_bar_ax = divider.append_axes('bottom', '5%', pad='3%')
    cbar = fig.colorbar(im, c_bar_ax, orientation='horizontal')
    cbar.solids.set_edgecolor("face")
    cbar.set_ticks([0.85, 1.705, 2.278, 2.85, 3.419, 4.0])
    cbar.set_ticklabels(['Excluded'] + [str(q) for q in q_linspace])

    plt.tight_layout(rect=(0, 0, 1, 0.95))

    # Area mask
    if area_mask is not None:
        _imshow(np.ma.array(np.ones_like(disp_coefficients), mask=area_mask),
                ax=axes,
                cmap='gray',
                show_axis='top',
                interpolation='none',
                extent=axes_extent,
                alpha=0.15)

        # Count of coefficients
        Q_total = np.sum(disp(_mat2vec(10**disp_coefficients))[area_mask] != 0)
        Qs = [
            np.sum(disp(_mat2vec(10**disp_coefficients))[area_mask] == k)
            for k in [1, 2, 3, 4]
        ]
        coef_counts = {
            'Q' + str(k - 1) + '_Q' + str(k):
            (Qs[k - 1], round(Qs[k - 1] / Q_total, 2))
            for k in [1, 2, 3, 4]
        }
        coef_counts['Q_total'] = Q_total
        coef_counts['Q_potential'] = np.sum(area_mask)
        coef_counts['Q_fraction'] = round(Q_total / coef_counts['Q_potential'],
                                          2)
        coef_counts['C_total'] = np.sum(used_coefficients != 0)
        coef_counts['P_fraction'] = round(
            coef_counts['Q_potential'] / img.size, 2)
        coef_counts['QC_fraction'] = round(Q_total / coef_counts['C_total'], 2)

        validate_output()

        return coef_counts
Beispiel #4
0
def show_transform_coefficients(img,
                                transforms,
                                output_path=None,
                                fig_ext='pdf'):
    """
    Show the transform coefficients.

    The transform coefficient of `img` are shown for the `transforms`. If
    `output_path` is not None, the resulting figure and data used in the figure
    are saved.

    Parameters
    ----------
    img : ndarray
        The image to show the transform coefficients for.
    transforms : list or tuple
        The names as strings of the transforms to use.
    output_path : str
        The output path (see notes below) to save the figure and data to (the
        default is None, which implies that the figure and data are not saved).
    fig_ext : str
        The figure extension determining the format of the saved figure (the
        default is 'pdf' which implies that the figure is saved as a PDF).

    Notes
    -----
    The `output_path` is specified as a path to a folder + an optional prefix
    to the file name. The remaining file name is fixed. If e.g, the fixed part
    of the file name was 'plot', then:

    * output_path = '/home/user/' would save the figure under /home/user/ with
      the name plot.pdf.
    * output_path = '/home/user/best' would save the figure under /home/user
      with the name best_plot.pdf.

    In addition to the saved figures, an annotated and chased HDF database with
    the data used to create the figures are also saved. The name of the HDF
    database is the same as for the figure with the exception that the file
    extension is '.hdf5'.

    Examples
    --------
    Save a figure showing the coefficients for the DCT and DFT transforms:

    >>> import os, numpy as np
    >>> from magni.imaging.dictionaries import analysis as _a
    >>> img = np.arange(64).astype(np.float).reshape(8, 8)
    >>> transforms = ('DCT', 'DFT')
    >>> o_p = './coefficient_test'
    >>> _a.show_transform_coefficients(img, transforms, output_path=o_p)
    >>> current_dir = os.listdir('./')
    >>> for file in sorted(current_dir):
    ...     if 'coefficient_test' in file:
    ...         print(file)
    coefficient_test_transform_coefficients.hdf5
    coefficient_test_transform_coefficients.pdf

    """
    @_decorate_validation
    def validate_input():
        _numeric('img', ('integer', 'floating', 'complex'), shape=(-1, -1))
        _levels(
            'transforms',
            (_generic(None, 'explicit collection'),
             _generic(None, 'string', value_in=_utils.get_transform_names())))
        _generic('output_path', 'string', ignore_none=True)
        _generic('fig_ext', 'string')

    validate_input()

    if len(transforms) == 1:
        fig, axes = plt.subplots(1, 1, squeeze=False)
    else:
        rows = int(np.ceil(len(transforms) / 2))
        fig, axes = plt.subplots(rows, 2, squeeze=False)

    axes = axes.flatten()

    datasets = dict()
    for k, transform in enumerate(transforms):
        matrix_handle = _utils.get_function_handle('matrix', transform)
        visual_handle = _utils.get_function_handle('visualisation', transform)

        coefficients = matrix_handle(img.shape).conj().T.dot(_mat2vec(img))
        disp, axes_extent = visual_handle(img.shape)

        scaled_coefficients = _visualisation.stretch_image(
            np.abs(coefficients), 1.0) + 1e-6
        _imshow(disp(scaled_coefficients),
                ax=axes[k],
                show_axis='top',
                extent=axes_extent)
        axes[k].set_title(transform, y=1.05)

        datasets[transform] = {'coefficients': coefficients}

    # Save figures
    if output_path is not None:
        _save_output(output_path, 'transform_coefficients', fig, fig_ext,
                     datasets)
Beispiel #5
0
def plot_pixel_mask(h, w, pixels, output_path=None):
    """
    Display a binary image that shows the given pixel mask.

    A black image with `w` x `h` pixels is created and the `pixels` are marked
    with white.

    Parameters
    ----------
    h : int
        The height of the image in pixels.
    w : int
        The width of the image in pixels.
    pixels : ndarray
        The 2D array of pixels that make up the mask. Each row is a coordinate
        pair (x, y), such that `coords` has size len(`pixels`) x 2.
    output_path : str, optional
        Path (including file type extension) under which the plot is saved (the
        default value is None which implies, that the plot is not saved).

    Notes
    -----
    The resulting image is displayed in a figure using
    `magni.imaging.visualisation.imshow`.

    Examples
    --------
    For example,

    >>> import numpy as np
    >>> from magni.imaging.measurements import plot_pixel_mask
    >>> h = 3
    >>> w = 3
    >>> pixels = np.array([[0, 0], [1, 1], [2, 1]])
    >>> plot_pixel_mask(h, w, pixels)

    """

    @_decorate_validation
    def validate_input():
        _numeric('h', 'integer', range_='[2;inf)')
        _numeric('w', 'integer', range_='[2;inf)')
        _numeric('pixels', 'integer', shape=(-1, 2))
        _numeric('pixels[:, 0]', 'integer', range_='[0;{}]'.format(w - 1),
                 shape=(-1,), var=pixels[:, 0])
        _numeric('pixels[:, 1]', 'integer', range_='[0;{}]'.format(h - 1),
                 shape=(-1,), var=pixels[:, 1])
        _generic('output_path', 'string', ignore_none=True)

    validate_input()

    mask = np.zeros((h, w))
    mask[pixels[:, 1], pixels[:, 0]] = 1

    figsize = plt.rcParams['figure.figsize']

    if w / h > figsize[0] / figsize[1]:
        figsize_local = [figsize[0], figsize[0] * h / w]
    else:
        figsize_local = [figsize[1] * w / h, figsize[1]]

    _plotting.setup_matplotlib({'figure': {'figsize': figsize_local}})

    fig, axes = plt.subplots(1, 1)
    _imshow(mask, ax=axes, show_axis='top')

    axes.set_xlabel('width [pixels]')
    axes.set_ylabel('height [pixels]')

    plt.tight_layout()

    if output_path is not None:
        plt.savefig(output_path)

    _plotting.setup_matplotlib({'figure': {'figsize': figsize}})