Source code for pyrtools.pyramids.GaussianPyramid

from .pyramid import Pyramid
from .filters import parse_filter
from .c.wrapper import corrDn


[docs] class GaussianPyramid(Pyramid): """Gaussian pyramid Parameters ---------- image : `array_like` 1d or 2d image upon which to construct to the pyramid. height : 'auto' or `int`. The height of the pyramid. If 'auto', will automatically determine based on the size of `image`. filter_name : {'binomN', 'haar', 'qmf8', 'qmf12', 'qmf16', 'daub2', 'daub3', 'daub4', 'qmf5', 'qmf9', 'qmf13'} name of filter to use when constructing pyramid. All scaled so L-2 norm is 1.0 * `'binomN'` - binomial coefficient filter of order N-1 * `'haar'` - Haar wavelet * `'qmf8'`, `'qmf12'`, `'qmf16'` - Symmetric Quadrature Mirror Filters [1]_ * `'daub2'`, `'daub3'`, `'daub4'` - Daubechies wavelet [2]_ * `'qmf5'`, `'qmf9'`, `'qmf13'` - Symmetric Quadrature Mirror Filters [3]_, [4]_ edge_type : {'circular', 'reflect1', 'reflect2', 'repeat', 'zero', 'extend', 'dont-compute'} Specifies how to handle edges. Options are: * `'circular'` - circular convolution * `'reflect1'` - reflect about the edge pixels * `'reflect2'` - reflect, doubling the edge pixels * `'repeat'` - repeat the edge pixels * `'zero'` - assume values of zero outside image boundary * `'extend'` - reflect and invert * `'dont-compute'` - zero output when filter overhangs imput boundaries. Attributes ---------- image : `array_like` The input image used to construct the pyramid. image_size : `tuple` The size of the input image. pyr_type : `str` or `None` Human-readable string specifying the type of pyramid. For base class, is None. edge_type : `str` Specifies how edges were handled. pyr_coeffs : `dict` Dictionary containing the coefficients of the pyramid. Keys are `(level, band)` tuples and values are 1d or 2d numpy arrays (same number of dimensions as the input image) pyr_size : `dict` Dictionary containing the sizes of the pyramid coefficients. Keys are `(level, band)` tuples and values are tuples. is_complex : `bool` Whether the coefficients are complex- or real-valued. Only `SteerablePyramidFreq` can have a value of True, all others must be False. References ---------- .. [1] J D Johnston, "A filter family designed for use in quadrature mirror filter banks", Proc. ICASSP, pp 291-294, 1980. .. [2] I Daubechies, "Orthonormal bases of compactly supported wavelets", Commun. Pure Appl. Math, vol. 42, pp 909-996, 1988. .. [3] E P Simoncelli, "Orthogonal sub-band image transforms", PhD Thesis, MIT Dept. of Elec. Eng. and Comp. Sci. May 1988. Also available as: MIT Media Laboratory Vision and Modeling Technical Report #100. .. [4] E P Simoncelli and E H Adelson, "Subband image coding", Subband Transforms, chapter 4, ed. John W Woods, Kluwer Academic Publishers, Norwell, MA, 1990, pp 143--192. """ def __init__(self, image, height='auto', filter_name='binom5', edge_type='reflect1', **kwargs): super().__init__(image=image, edge_type=edge_type) if self.pyr_type is None: self.pyr_type = 'Gaussian' self.num_orientations = 1 self.filters = {'downsample_filter': parse_filter(filter_name, normalize=False)} upsamp_filt = kwargs.pop('upsample_filter_name', None) if upsamp_filt is not None: if self.pyr_type != 'Laplacian': raise Exception("upsample_filter should only be set for Laplacian pyramid!") self.filters['upsample_filter'] = parse_filter(upsamp_filt, normalize=False) self._set_num_scales('downsample_filter', height, 1) self._build_pyr() def _build_next(self, image): """build the next level of the pyramid This should not be called directly by users, it's a helper function for constructing the pyramid """ if image.shape[0] == 1: res = corrDn(image=image, filt=self.filters['downsample_filter'].T, edge_type=self.edge_type, step=(1, 2)) elif image.shape[1] == 1: res = corrDn(image=image, filt=self.filters['downsample_filter'], edge_type=self.edge_type, step=(2, 1)) else: tmp = corrDn(image=image, filt=self.filters['downsample_filter'].T, edge_type=self.edge_type, step=(1, 2)) res = corrDn(image=tmp, filt=self.filters['downsample_filter'], edge_type=self.edge_type, step=(2, 1)) return res def _build_pyr(self): """build the pyramid This should not be called directly by users, it's a helper function for constructing the pyramid we do this in a separate method for a bit of class wizardry: by over-writing this method in the LaplacianPyramid class, which inherits the GaussianPyramid class, we can still correctly construct the LaplacianPyramid with a single call to the GaussianPyramid constructor """ im = self.image self.pyr_coeffs[(0, 0)] = self.image.copy() self.pyr_size[(0, 0)] = self.image_size for lev in range(1, self.num_scales): im = self._build_next(im) self.pyr_coeffs[(lev, 0)] = im.copy() self.pyr_size[(lev, 0)] = im.shape
[docs] def recon_pyr(self, *args): """Reconstruct the pyramid -- NOT NECESSARY FOR GAUSSIANS """ raise Exception('Not necessary for Gaussian Pyramids')