Пример #1
0
    def test_PSNR(self):
        k = len(self.flat_array)
        x_zero = np.zeros(k)
        x_flat = np.arange(k)
        x_1d = np.arange(k).reshape(*self.d1_array.shape)
        x_2d = np.arange(k).reshape(*self.d2_array.shape)

        p = 1.42
        psnr_const = 10 * np.log10(p**2 / np.mean(self.flat_const_offset ** 2))
        psnr_noise = 10 * np.log10(p**2 / np.mean(self.flat_noise ** 2))

        # Integrity check of test setup
        self.assertGreater(psnr_const, 1e-3)
        self.assertGreater(psnr_noise, 1e-3)
        self.assertNotAlmostEqual(psnr_const, psnr_noise)

        # Identical arrays
        self.assertEqual(calculate_psnr(x_zero, x_zero, p), np.inf)
        self.assertEqual(calculate_psnr(x_2d, x_2d, p), np.inf)

        # Additve offset
        self.assertAlmostEqual(
            calculate_psnr(x_flat, x_flat + self.flat_const_offset, p),
            psnr_const)
        self.assertAlmostEqual(
            calculate_psnr(x_1d, x_1d - self.d1_const_offset, p), psnr_const)
        self.assertAlmostEqual(
            calculate_psnr(x_2d, x_2d + self.d2_const_offset, p), psnr_const)

        # Additive noise
        self.assertAlmostEqual(
            calculate_psnr(x_flat, x_flat - self.flat_noise, p), psnr_noise)
        self.assertAlmostEqual(
            calculate_psnr(x_1d, x_1d + self.d1_noise, p), psnr_noise)
        self.assertAlmostEqual(
            calculate_psnr(x_2d, x_2d - self.d2_noise, p), psnr_noise)

        # Fails
        self.assertNotAlmostEqual(
            calculate_psnr(x_flat, x_flat + self.flat_noise, p), psnr_const)
        self.assertNotAlmostEqual(
            calculate_psnr(x_flat, x_flat - self.flat_const_offset, p),
            psnr_noise)
        self.assertNotAlmostEqual(
            calculate_psnr(x_flat, x_flat + self.flat_noise, 25), psnr_noise)
        self.assertNotAlmostEqual(
            calculate_psnr(x_flat, x_flat + self.flat_noise, p*1.01),
            psnr_noise)
Пример #2
0
def analyse(x, Phi, Psi, **kwargs):
    """
    Sample an image, reconstruct it, and analyse the reconstructed image.

    Parameters
    ----------
    x : numpy.ndarray
        The original image vector.
    Phi : magni.utils.matrices.Matrix or numpy.matrix
        The measurement matrix.
    Psi : magni.utils.matrices.Matrix or numpy.matrix
        The dictionary.

    Returns
    -------
    x : numpy.ndarray
        The reconstructed image vector.

    See Also
    --------
    magni.afm.config : Configuration options.
    magni.imaging.evaluation : Image reconstruction quality evaluation.

    Notes
    -----
    Additional \*\*kwargs are passed on to the reconstruction algorithm.

    Examples
    --------
    Prior to the actual example, data is loaded and a measurement matrix and a
    dictionary are defined. First, the example MI file provided with the
    package is loaded:

    >>> import os, numpy as np, magni
    >>> from magni.afm.reconstruction import analyse
    >>> path = magni.utils.split_path(magni.__path__[0])[0]
    >>> path = path + 'examples' + os.sep + 'example.mi'
    >>> if os.path.isfile(path):
    ...     mi_file = magni.afm.io.read_mi_file(path)
    ...     mi_buffer = mi_file.get_buffer('Topography')[0]
    ...     mi_data = mi_buffer.data
    ...     x = magni.imaging.mat2vec(mi_data)

    Next, a measurement matrix is defined. This matrix is equal to the matrix
    generated by running `np.eye(len(x))[::2, :]` but for speed, the matrix is
    instead defined with fast operations:

    >>> def Phi_A(x):
    ...     y = x[::2]
    ...     return y
    >>> def Phi_T(y):
    ...     x = np.zeros((2 * len(y), 1))
    ...     x[::2] = y
    ...     return x
    >>> if os.path.isfile(path):
    ...     Phi = magni.utils.matrices.Matrix(Phi_A, Phi_T, (),
    ...                                       (int(len(x) / 2), len(x)))

    Next, a dictionary is defined. This dictionary is the DCT basis likewise
    defined with fast operations:

    >>> if os.path.isfile(path):
    ...     Psi = magni.imaging.dictionaries.get_DCT(mi_data.shape)

    Finally, the actual example:

    >>> if os.path.isfile(path):
    ...     print('MSE: {:.2f}, PSNR: {:.2f}'.format(*analyse(x, Phi, Psi)))
    ... else:
    ...     print('MSE: 0.24, PSNR: 6.22')
    MSE: 0.24, PSNR: 6.22

    """

    @_decorate_validation
    def validate_input():
        _numeric('x', ('integer', 'floating', 'complex'), shape=(-1, 1))
        _numeric('Phi', ('integer', 'floating', 'complex'),
                 shape=(-1, x.shape[0]))
        _numeric('Psi', ('integer', 'floating', 'complex'),
                 shape=(x.shape[0], -1))

    validate_input()

    y = Phi.dot(x)
    x_hat = reconstruct(y, Phi, Psi, **kwargs)

    x_scaled = _visualisation.stretch_image(x, 1.0)
    x_hat_scaled = _visualisation.stretch_image(x_hat, 1.0)

    mse = _eval.calculate_mse(x_scaled, x_hat_scaled)
    psnr = _eval.calculate_psnr(x_scaled, x_hat_scaled, 1.0)

    return (mse, psnr)
Пример #3
0
    def test_PSNR(self):
        k = len(self.flat_array)
        x_zero = np.zeros(k)
        x_flat = np.arange(k)
        x_1d = np.arange(k).reshape(*self.d1_array.shape)
        x_2d = np.arange(k).reshape(*self.d2_array.shape)

        p = 1.42
        psnr_const = 10 * np.log10(p**2 / np.mean(self.flat_const_offset ** 2))
        psnr_noise = 10 * np.log10(p**2 / np.mean(self.flat_noise ** 2))

        # Integrity check of test setup
        self.assertGreater(psnr_const, 1e-3)
        self.assertGreater(psnr_noise, 1e-3)
        self.assertNotAlmostEqual(psnr_const, psnr_noise)

        # Identical arrays
        self.assertEqual(calculate_psnr(x_zero, x_zero, p), np.inf)
        self.assertEqual(calculate_psnr(x_2d, x_2d, p), np.inf)

        # Additve offset
        self.assertAlmostEqual(
            calculate_psnr(x_flat, x_flat + self.flat_const_offset, p),
            psnr_const)
        self.assertAlmostEqual(
            calculate_psnr(x_1d, x_1d - self.d1_const_offset, p), psnr_const)
        self.assertAlmostEqual(
            calculate_psnr(x_2d, x_2d + self.d2_const_offset, p), psnr_const)

        # Additive noise
        self.assertAlmostEqual(
            calculate_psnr(x_flat, x_flat - self.flat_noise, p), psnr_noise)
        self.assertAlmostEqual(
            calculate_psnr(x_1d, x_1d + self.d1_noise, p), psnr_noise)
        self.assertAlmostEqual(
            calculate_psnr(x_2d, x_2d - self.d2_noise, p), psnr_noise)

        # Fails
        self.assertNotAlmostEqual(
            calculate_psnr(x_flat, x_flat + self.flat_noise, p), psnr_const)
        self.assertNotAlmostEqual(
            calculate_psnr(x_flat, x_flat - self.flat_const_offset, p),
            psnr_noise)
        self.assertNotAlmostEqual(
            calculate_psnr(x_flat, x_flat + self.flat_noise, 25), psnr_noise)
        self.assertNotAlmostEqual(
            calculate_psnr(x_flat, x_flat + self.flat_noise, p*1.01),
            psnr_noise)
Пример #4
0
def analyse(x, Phi, Psi):
    """
    Sample an image, reconstruct it, and analyse the reconstructed image.

    Parameters
    ----------
    x : numpy.ndarray
        The original image vector.
    Phi : magni.utils.matrices.Matrix or numpy.matrix
        The measurement matrix.
    Psi : magni.utils.matrices.Matrix or numpy.matrix
        The dictionary.

    Returns
    -------
    x : numpy.ndarray
        The reconstructed image vector.

    See Also
    --------
    magni.afm.config : Configuration options.
    magni.imaging.evaluation : Image reconstruction quality evaluation.

    Examples
    --------
    Prior to the actual example, data is loaded and a measurement matrix and a
    dictionary are defined. First, the example MI file provided with the
    package is loaded:

    >>> import os, numpy as np, magni
    >>> from magni.afm.reconstruction import analyse
    >>> path = magni.utils.split_path(magni.__path__[0])[0]
    >>> path = path + 'examples' + os.sep + 'example.mi'
    >>> if os.path.isfile(path):
    ...     mi_file = magni.afm.io.read_mi_file(path)
    ...     mi_buffer = mi_file.get_buffer('Topography')[0]
    ...     mi_data = mi_buffer.get_data()
    ...     x = magni.imaging.mat2vec(mi_data)

    Next, a measurement matrix is defined. This matrix is equal to the matrix
    generated by running `np.eye(len(x))[::2, :]` but for speed, the matrix is
    instead defined with fast operations:

    >>> def Phi_A(x):
    ...     y = x[::2]
    ...     return y
    >>> def Phi_T(y):
    ...     x = np.zeros((2 * len(y), 1))
    ...     x[::2] = y
    ...     return x
    >>> if os.path.isfile(path):
    ...     Phi = magni.utils.matrices.Matrix(Phi_A, Phi_T, (),
    ...                                       (int(len(x) / 2), len(x)))

    Next, a dictionary is defined. This dictionary is the DCT basis likewise
    defined with fast operations:

    >>> if os.path.isfile(path):
    ...     Psi = magni.imaging.dictionaries.get_DCT(mi_data.shape)

    Finally, the actual example:

    >>> if os.path.isfile(path):
    ...     print('MSE: {:.2f}, PSNR: {:.2f}'.format(*analyse(x, Phi, Psi)))
    ... else:
    ...     print('MSE: 0.24, PSNR: 6.22')
    MSE: 0.24, PSNR: 6.22

    """

    @_decorate_validation
    def validate_input():
        _numeric('x', ('integer', 'floating', 'complex'), shape=(-1, 1))
        _numeric('Phi', ('integer', 'floating', 'complex'),
                 shape=(-1, x.shape[0]))
        _numeric('Psi', ('integer', 'floating', 'complex'),
                 shape=(x.shape[0], -1))

    validate_input()

    y = Phi.dot(x)
    x_hat = reconstruct(y, Phi, Psi)

    x_scaled = _visualisation.stretch_image(x, 1.0)
    x_hat_scaled = _visualisation.stretch_image(x_hat, 1.0)

    mse = _eval.calculate_mse(x_scaled, x_hat_scaled)
    psnr = _eval.calculate_psnr(x_scaled, x_hat_scaled, 1.0)

    return (mse, psnr)
Пример #5
0
def analyse(x, Phi, Psi):
    """
    Sample an image, reconstruct it, and analyse the reconstructed image.

    Parameters
    ----------
    x : numpy.ndarray
        The original image vector.
    Phi : magni.utils.matrices.Matrix or numpy.matrix
        The measurement matrix.
    Psi : magni.utils.matrices.Matrix or numpy.matrix
        The dictionary.

    Returns
    -------
    x : numpy.ndarray
        The reconstructed image vector.

    See Also
    --------
    magni.afm.config : Configuration options.
    magni.imaging.evaluation : Image reconstruction quality evaluation.

    Examples
    --------
    Prior to the actual example, data is loaded and a measurement matrix and a
    dictionary are defined. First, the example MI file provided with the
    package is loaded:

    >>> from magni.afm.reconstruction import analyse
    >>> path = magni.utils.split_path(magni.__path__[0])[0]
    >>> path = path + 'examples' + os.sep + 'example.mi'
    >>> mi_file = magni.afm.io.read_mi_file(path)
    >>> mi_buffer = mi_file.get_buffer('Topography')[0]
    >>> mi_data = mi_buffer.get_data()
    >>> x = magni.imaging.mat2vec(mi_data)

    Next, a measurement matrix is defined. This matrix is equal to the matrix
    generated by running `np.eye(len(x))[::2, :]` but for speed, the matrix is
    instead defined with fast operations:

    >>> def Phi_A(x):
    ...     y = x[::2]
    ...     return y
    >>> def Phi_T(y):
    ...     x = np.zeros((2 * len(y), 1))
    ...     x[::2] = y
    ...     return x
    >>> Phi = magni.utils.matrices.Matrix(Phi_A, Phi_T, (),
    ...                                   (int(len(x) / 2), len(x)))

    Next, a dictionary is defined. This dictionary is the DCT basis likewise
    defined with fast operations:

    >>> Psi = magni.imaging.dictionaries.get_DCT(mi_data.shape)

    Finally, the actual example:

    >>> print('MSE: {:.2f}, PSNR: {:.2f}'.format(*analyse(x, Phi, Psi)))
    MSE: 0.23, PSNR: 5.92

    """

    _validate_analyse(x, Phi, Psi)

    y = Phi.dot(x)
    x_hat = reconstruct(y, Phi, Psi)

    mse = _eval.calculate_mse(x, x_hat)
    psnr = _eval.calculate_psnr(x, x_hat, float(np.abs(x).max()))

    return (mse, psnr)
Пример #6
0
def show_psnr_energy_rolloff(img,
                             reconstructions,
                             fractions,
                             return_vals=False,
                             output_path=None,
                             fig_ext='pdf'):
    """
    Show the PSNR and energy rolloff for the reconstructions.

    A plot of the Peak Signal to Noise Ratio (PSNR) and retained energy in the
    `recontructions` versus the `fractions` of coefficients used in the
    reconstructions is shown. If return_vals is True, the data used in the plot
    is returned. If `output_path` is not None, the resulting figure and data
    used in the figure are saved.

    Parameters
    ----------
    img : ndarray
        The image which the reconstructions are based on.
    reconstructions : list or tuple
        The reconstructions (each an ndarray) to show rolloff for.
    fractions : list or tuple
        The fractions of coefficents used in the reconstructions.
    return_vals : bool
        The flag indicating wheter or not to return the PSNR and energy values
        (the default is False, which indicate that the values are not
        returned).
    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).

    Returns
    -------
    psnrs : ndarray
       The PSNR values shown in the figure (only returned if return_vals=True).
    energy : ndarray
       The retained energy values shown in the figure (only returned if
       return_vals=True).

    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 PSNR and energy rolloff plot for reconstructions bases on the DCT:

    >>> import os, numpy as np
    >>> from magni.imaging.dictionaries import analysis as _a
    >>> img = np.arange(64).astype(np.float).reshape(8, 8)
    >>> transform = 'DCT'
    >>> fractions = (0.2, 0.4)
    >>> coefs, recons = _a.get_reconstructions(img, transform, fractions)
    >>> o_p = './rolloff_test'
    >>> _a.show_psnr_energy_rolloff(img, recons, fractions, output_path=o_p)
    >>> current_dir = os.listdir('./')
    >>> for file in sorted(current_dir):
    ...     if 'rolloff_test' in file:
    ...         print(file)
    rolloff_test_psnr_energy_rolloff.hdf5
    rolloff_test_psnr_energy_rolloff.pdf

    """
    @_decorate_validation
    def validate_input():
        _numeric('img', ('integer', 'floating', 'complex'), shape=(-1, -1))
        _levels('reconstructions',
                (_generic(None, 'explicit collection'),
                 _numeric(None, ('integer', 'floating', 'complex'),
                          shape=img.shape)))
        _levels('fractions', (_generic(None, 'explicit collection'),
                              _numeric(None, 'floating', range_='[0;1]')))
        _numeric('return_vals', 'boolean')
        _generic('output_path', 'string', ignore_none=True)
        _generic('fig_ext', 'string')

    validate_input()

    psnrs = np.zeros_like(fractions)
    energy = np.zeros_like(fractions)

    for k, reconstruction in enumerate(reconstructions):
        psnrs[k] = _evaluation.calculate_psnr(img, reconstruction,
                                              float(img.max()))
        energy[k] = _evaluation.calculate_retained_energy(img, reconstruction)

    fig, axes = plt.subplots(1, 2)
    axes[0].plot(fractions, psnrs)
    axes[0].set_xlabel('Fraction of coefficients')
    axes[0].set_ylabel('PSNR [dB]')
    axes[1].plot(fractions, energy)
    axes[1].set_xlabel('Fraction of coefficients')
    axes[1].set_ylabel('Retained energy [%]')
    fig.suptitle(('PSNR/Energy vs. fraction of coefficients used in ' +
                  'reconstruction'),
                 fontsize=14)
    plt.tight_layout(rect=(0, 0, 1, 0.95))

    # Save figures and data
    if output_path is not None:
        datasets = {
            'psnrs': {
                'fractions': fractions,
                'values': psnrs
            },
            'energy': {
                'fractions': fractions,
                'values': energy
            }
        }
        _save_output(output_path, 'psnr_energy_rolloff', fig, fig_ext,
                     datasets)

    # Return values
    if return_vals:
        return psnrs, energy