Source code for magni.imaging.dictionaries._matrices

"""
..
    Copyright (c) 2014-2017, Magni developers.
    All rights reserved.
    See LICENSE.rst for further information.

Module providing fast linear operations wrapped in matrix emulators.

Routine listings
----------------
get_DCT(shape, overcomplete_shape=None)
    Get the DCT fast operation dictionary for the given image shape.
get_DFT(shape, overcomplete_shape=None)
    Get the DFT fast operation dictionary for the given image shape.

See Also
--------
magni.imaging.dictionaries._fastops : Fast linear operations.
magni.utils.matrices : Matrix emulators.

"""


from __future__ import division

from pkg_resources import parse_version as _parse_version
from scipy import __version__ as _scipy_version

from magni.imaging.dictionaries import _fastops
from magni.utils.matrices import Matrix as _Matrix
from magni.utils.validation import decorate_validation as _decorate_validation
from magni.utils.validation import validate_generic as _generic
from magni.utils.validation import validate_levels as _levels
from magni.utils.validation import validate_numeric as _numeric


[docs]def get_DCT(shape, overcomplete_shape=None): """ Get the DCT fast operation dictionary for the given image shape. Parameters ---------- shape : list or tuple The shape of the image for which the dictionary is the DCT dictionary. overcomplete_shape : list or tuple, optional The shape of the (overcomplete) frequency domain for the DCT dictionary. The entries must be greater than or equal to the corresponding entries in `shape`. Returns ------- matrix : magni.utils.matrices.Matrix The specified DCT dictionary. See Also -------- magni.utils.matrices.Matrix : The matrix emulator class. Examples -------- Create a dummy image: >>> import numpy as np, magni >>> img = np.random.randn(64, 64) >>> vec = magni.imaging.mat2vec(img) Perform DCT in the ordinary way: >>> dct_normal = magni.imaging.dictionaries._fastops.dct2(vec, img.shape) Perform DCT using the present function: >>> from magni.imaging.dictionaries import get_DCT >>> matrix = get_DCT(img.shape) >>> dct_matrix = matrix.T.dot(vec) Check that the two ways produce the same result: >>> np.allclose(dct_matrix, dct_normal) True Compute the overcomplete transform (and back again) and check that the resulting image is identical to the original. Notice how this example first ensures that the necessary version of SciPy is available: >>> from pkg_resources import parse_version >>> from scipy import __version__ as _scipy_version >>> if parse_version(_scipy_version) >= parse_version('0.16.0'): ... matrix = get_DCT(img.shape, img.shape) ... dct_matrix = matrix.T.dot(vec) ... vec_roundtrip = matrix.dot(dct_matrix) ... np.allclose(vec, vec_roundtrip) ... else: ... True True """ @_decorate_validation def validate_input(): _levels('shape', ( _generic(None, 'explicit collection', len_=2), _numeric(None, 'integer', range_='[1;inf)'))) if overcomplete_shape is not None: _generic('overcomplete_shape', 'explicit collection', len_=2), _numeric(('overcomplete_shape', 0), 'integer', range_='[{};inf)'.format(shape[0])) _numeric(('overcomplete_shape', 1), 'integer', range_='[{};inf)'.format(shape[1])) validate_input() entries = shape[0] * shape[1] if overcomplete_shape is None: args = (shape,) shape = (entries, entries) else: if _parse_version(_scipy_version) < _parse_version('0.16.0'): raise NotImplementedError( 'Over-complete DCT requires SciPy >= 0.16.0') args = (shape, overcomplete_shape) shape = (entries, overcomplete_shape[0] * overcomplete_shape[1]) return _Matrix(_fastops.idct2, _fastops.dct2, args, shape)
[docs]def get_DFT(shape, overcomplete_shape=None): """ Get the DFT fast operation dictionary for the given image shape. Parameters ---------- shape : list or tuple The shape of the image for which the dictionary is the DFT dictionary. overcomplete_shape : list or tuple, optional The shape of the (overcomplete) frequency domain for the DFT dictionary. The entries must be greater than or equal to the corresponding entries in `shape`. Returns ------- matrix : magni.utils.matrices.Matrix The specified DFT dictionary. See Also -------- magni.utils.matrices.Matrix : The matrix emulator class. Examples -------- Create a dummy image: >>> import numpy as np, magni >>> img = np.random.randn(64, 64) >>> vec = magni.imaging.mat2vec(img) Perform DFT in the ordinary way: >>> dft_normal = magni.imaging.dictionaries._fastops.dft2(vec, img.shape) Perform DFT using the present function: >>> from magni.imaging.dictionaries import get_DFT >>> matrix = get_DFT(img.shape) >>> dft_matrix = matrix.conj().T.dot(vec) Check that the two ways produce the same result: >>> np.allclose(dft_matrix, dft_normal) True Compute the overcomplete transform (and back again): >>> matrix = get_DFT(img.shape, img.shape) >>> dft_matrix = matrix.conj().T.dot(vec) >>> vec_roundtrip = matrix.dot(dft_matrix) Check that the twice transformed image is identical to the original: >>> np.allclose(vec, vec_roundtrip) True """ @_decorate_validation def validate_input(): _levels('shape', ( _generic(None, 'explicit collection', len_=2), _numeric(None, 'integer', range_='[1;inf)'))) if overcomplete_shape is not None: _generic('overcomplete_shape', 'explicit collection', len_=2), _numeric(('overcomplete_shape', 0), 'integer', range_='[{};inf)'.format(shape[0])) _numeric(('overcomplete_shape', 1), 'integer', range_='[{};inf)'.format(shape[1])) validate_input() entries = shape[0] * shape[1] if overcomplete_shape is None: args = (shape,) shape = (entries, entries) else: args = (shape, overcomplete_shape) shape = (entries, overcomplete_shape[0] * overcomplete_shape[1]) return _Matrix(_fastops.idft2, _fastops.dft2, args, shape, is_complex=True)