Exemplo n.º 1
0
    def __init__(self, biort=DEFAULT_BIORT, qshift=DEFAULT_QSHIFT):
        try:
            self.biort = _biort(biort)
        except TypeError:
            self.biort = biort

        # Load quarter sample shift wavelets
        try:
            self.qshift = _qshift(qshift)
        except TypeError:
            self.qshift = qshift
Exemplo n.º 2
0
    def __init__(self, biort=DEFAULT_BIORT, qshift=DEFAULT_QSHIFT):
        # Load bi-orthogonal wavelets
        try:
            self.biort = _biort(biort)
        except TypeError:
            self.biort = biort

        # Load quarter sample shift wavelets
        try:
            self.qshift = _qshift(qshift)
        except TypeError:
            self.qshift = qshift
Exemplo n.º 3
0
    def __init__(self, biort=DEFAULT_BIORT, qshift=DEFAULT_QSHIFT, ext_mode=4):
        # Load bi-orthogonal wavelets
        try:
            self.biort = _biort(biort)
        except TypeError:
            self.biort = biort

        # Load quarter sample shift wavelets
        try:
            self.qshift = _qshift(qshift)
        except TypeError:
            self.qshift = qshift

        self.ext_mode = ext_mode
Exemplo n.º 4
0
    def __init__(self, biort=DEFAULT_BIORT, qshift=DEFAULT_QSHIFT, ext_mode=4, discard_level_1=False):
        """
        Constructor for the 3D DT-CWT transform class (NumPy).
        :param biort: Level 1 wavelets to use. See :py:func:`dtcwt.coeffs.biort`.
        :param qshift: Level >= 2 wavelets to use. See :py:func:`dtcwt.coeffs.qshift`.
        :param discard_level_1: True if level 1 high-pass bands are to be discarded.
        """
        # Load bi-orthogonal wavelets
        try:
            self.biort = _biort(biort)
        except TypeError:
            self.biort = biort

        # Load quarter sample shift wavelets
        try:
            self.qshift = _qshift(qshift)
        except TypeError:
            self.qshift = qshift

        self.ext_mode = ext_mode
        self.discard_level_1 = discard_level_1
Exemplo n.º 5
0
    def forward(self, X, nlevels=3, include_scale=False):
        """Perform a *n*-level DTCWT decompostion on a 1D column vector *X* (or on
        the columns of a matrix *X*).

        :param X: 1D real array or 2D real array whose columns are to be transformed
        :param nlevels: Number of levels of wavelet decomposition

        :returns: A :py:class:`DTCWT.Pyramid`-like object representing the transform result.

        If *biort* or *qshift* are strings, they are used as an argument to the
        :py:func:`biort` or :py:func:`qshift` functions. Otherwise, they are
        interpreted as tuples of vectors giving filter coefficients. In the *biort*
        case, this should be (h0o, g0o, h1o, g1o). In the *qshift* case, this should
        be (h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b).

        .. codeauthor:: Rich Wareham <*****@*****.**>, Aug 2013
        .. codeauthor:: Nick Kingsbury, Cambridge University, May 2002
        .. codeauthor:: Cian Shaffrey, Cambridge University, May 2002

        """
        # Which wavelets are to be used?
        biort = self.biort
        qshift = self.qshift

        # Need this because colfilter and friends assumes input is 2d
        X = asfarray(X)
        if len(X.shape) == 1:
            X = np.atleast_2d(X).T

        # Try to load coefficients if biort is a string parameter
        try:
            h0o, g0o, h1o, g1o = _biort(biort)
        except TypeError:
            h0o, g0o, h1o, g1o = biort

        # Try to load coefficients if qshift is a string parameter
        try:
            h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b = _qshift(qshift)
        except TypeError:
            h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b = qshift

        L = np.asanyarray(X.shape)

        # ensure that X is an even length, thus enabling it to be extended if needs be.
        if X.shape[0] % 2 != 0:
            raise ValueError('Size of input X must be a multiple of 2')

        if nlevels == 0:
            if include_scale:
                return Pyramid(X, (), ())
            else:
                return Pyramid(X, ())

        # initialise
        Yh = [
            None,
        ] * nlevels
        if include_scale:
            # This is only required if the user specifies scales are to be outputted
            Yscale = [
                None,
            ] * nlevels

        # Level 1.
        Hi = colfilter(X, h1o)
        Lo = colfilter(X, h0o)
        Yh[0] = Hi[::2, :] + 1j * Hi[1::2, :]  # Convert Hi to complex form.
        if include_scale:
            Yscale[0] = Lo

        # Levels 2 and above.
        for level in xrange(1, nlevels):
            # Check to see if height of Lo is divisable by 4, if not extend.
            if Lo.shape[0] % 4 != 0:
                Lo = np.vstack((Lo[0, :], Lo, Lo[-1, :]))

            Hi = coldfilt(Lo, h1b, h1a)
            Lo = coldfilt(Lo, h0b, h0a)

            Yh[level] = Hi[::2, :] + 1j * Hi[
                1::2, :]  # Convert Hi to complex form.
            if include_scale:
                Yscale[level] = Lo

        Yl = Lo

        if include_scale:
            return Pyramid(Yl, Yh, Yscale)
        else:
            return Pyramid(Yl, Yh)
Exemplo n.º 6
0
    def inverse_hu(self, pyramid, gain_mask=None):
        """Perform an *n*-level dual-tree complex wavelet (DTCWT) 1D
        reconstruction.

        :param pyramid: A :py:class:`DTCWT.Pyramid`-like object containing the transformed signal.
        :param gain_mask: Gain to be applied to each subband.

        :returns: Reconstructed real array.

        The *l*-th element of *gain_mask* is gain for wavelet subband at level l.
        If gain_mask[l] == 0, no computation is performed for band *l*. Default
        *gain_mask* is all ones. Note that *l* is 0-indexed.

        .. codeauthor:: Rich Wareham <*****@*****.**>, Aug 2013
        .. codeauthor:: Nick Kingsbury, Cambridge University, May 2002
        .. codeauthor:: Cian Shaffrey, Cambridge University, May 2002

        """
        # Which wavelets are to be used?
        biort = self.biort
        qshift = self.qshift

        Yl = pyramid.lowpass
        Yh = pyramid.highpasses

        a = len(Yh)  # No of levels.

        if gain_mask is None:
            gain_mask = np.ones(a)  # Default gain_mask.

        # Try to load coefficients if biort is a string parameter
        try:
            h0o, g0o, h1o, g1o = _biort(biort)
        except TypeError:
            h0o, g0o, h1o, g1o = biort

        # Try to load coefficients if qshift is a string parameter
        try:
            h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b = _qshift(qshift)
        except TypeError:
            h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b = qshift

        level = a - 1  # No of levels = no of rows in L.
        if level < 0:
            # if there are no levels in the input, just return the Yl value
            return Yl
        """ 此处可以将 hi Lo 拆开 逐层恢复,考虑到卷积是可拆分的 (x1 + x2) * k = x1 * k + x2 * k """
        low_band_signal = np.copy(Yl)
        high_band_signals = [c2q1d(np.copy(item)) for item in Yh[::-1]]

        for i in range(level):
            low_band_signal = colifilt(low_band_signal, g0b, g0a)
            high_band_signals[i] = colifilt(high_band_signals[i], g1b, g1a)

            if low_band_signal.shape[0] != high_band_signals[i + 1].shape[0]:
                low_band_signal = low_band_signal[1:-1, ...]

            if high_band_signals[i].shape[0] != high_band_signals[i +
                                                                  1].shape[0]:
                high_band_signals[i] = high_band_signals[i][1:-1, ...]

            for j in range(i):
                high_band_signals[j] = colifilt(high_band_signals[j], g0b, g0a)
                if high_band_signals[j].shape[0] != high_band_signals[
                        i + 1].shape[0]:
                    high_band_signals[j] = high_band_signals[j][1:-1, ...]

        low_band_signal = colfilter(low_band_signal, g0o)
        high_band_signals[-1] = colfilter(high_band_signals[-1], g1o)
        for i in range(level):
            high_band_signals[i] = colfilter(high_band_signals[i], g0o)

        return low_band_signal, high_band_signals
Exemplo n.º 7
0
    def _inverse_ops(self, Yl, Yh, gain_mask=None):
        """Perform an *n*-level dual-tree complex wavelet (DTCWT) 1D
        reconstruction.

        :param Yl: The lowpass output from a forward transform. Should be a
            tensorflow variable.
        :param Yh: The tuple of highpass outputs from a forward transform.
            Should be tensorflow variables.
        :param gain_mask: Gain to be applied to each subband.

        :returns: A tf.Variable holding the output

        The *l*-th element of *gain_mask* is gain for wavelet subband at level
        l.  If gain_mask[l] == 0, no computation is performed for band *l*.
        Default *gain_mask* is all ones. Note that *l* is 0-indexed.

        .. codeauthor:: Fergal Cotter <*****@*****.**>, Sep 2017
        .. codeauthor:: Rich Wareham <*****@*****.**>, Aug 2013
        .. codeauthor:: Nick Kingsbury, Cambridge University, May 2002
        .. codeauthor:: Cian Shaffrey, Cambridge University, May 2002

        """
        # Which wavelets are to be used?
        biort = self.biort
        qshift = self.qshift
        a = len(Yh)  # No of levels.

        if gain_mask is None:
            gain_mask = np.ones(a)  # Default gain_mask.
        gain_mask = np.array(gain_mask)

        # Try to load coefficients if biort is a string parameter
        try:
            h0o, g0o, h1o, g1o = _biort(biort)
        except TypeError:
            h0o, g0o, h1o, g1o = biort

        # Try to load coefficients if qshift is a string parameter
        try:
            h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b = _qshift(qshift)
        except TypeError:
            h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b = qshift

        level = a-1   # No of levels = no of rows in L.
        if level < 0:
            # if there are no levels in the input, just return the Yl value
            return Yl

        # Reconstruct levels 2 and above in reverse order.
        Lo = Yl
        while level >= 1:
            Hi = c2q1d(Yh[level]*gain_mask[level])
            Lo = colifilt(Lo, g0b, g0a) + colifilt(Hi, g1b, g1a)

            # If Lo is not the same length as the next Therefore we have to clip
            # Lo so it is the same height as the next Yh. Yh => t1 was extended.
            Lo_shape = Lo.get_shape().as_list()
            next_shape = Yh[level-1].get_shape().as_list()
            if Lo_shape[1] != 2 * next_shape[1]:
                Lo = Lo[:,1:-1]
                Lo_shape = Lo.get_shape().as_list()

            # Check the row shapes across the entire matrix
            if (np.any(np.asanyarray(Lo_shape[1:]) !=
                       np.asanyarray(next_shape[1:] * np.array((2,1))))):
                raise ValueError('Yh sizes are not valid for DTWAVEIFM')

            level -= 1

        # Reconstruct level 1.
        if level == 0:
            Hi = c2q1d(Yh[level]*gain_mask[level])
            Z = colfilter(Lo,g0o) + colfilter(Hi,g1o)

        return Z
Exemplo n.º 8
0
    def _forward_ops(self, X, nlevels=3):
        """ Perform a *n*-level DTCWT-2D decompostion on a 2D matrix *X*.

        For column inputs, we still need the input shape to be 3D, but with 1 as
        the last dimension.

        :param X: 3D real array of size [batch, h, w]
        :param nlevels: Number of levels of wavelet decomposition
        :param extended: True if a singleton dimension was added at the
            beginning of the input. Signal to remove afterwards.

        :returns: A tuple of Yl, Yh, Yscale
        """
        biort = self.biort
        qshift = self.qshift

        # Try to load coefficients if biort is a string parameter
        try:
            h0o, g0o, h1o, g1o = _biort(biort)
        except TypeError:
            h0o, g0o, h1o, g1o = biort

        # Try to load coefficients if qshift is a string parameter
        try:
            h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b = _qshift(qshift)
        except TypeError:
            h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b = qshift

        # Check the shape and form of the input
        if X.dtype not in tf_dtypes:
            raise ValueError('X needs to be a tf variable or placeholder')

        original_size = X.get_shape().as_list()[1:]

        # ############################ Resize #################################
        # The next few lines of code check to see if the image is odd in size,
        # if so an extra ... row/column will be added to the bottom/right of the
        # image
        #  initial_row_extend = 0
        #  initial_col_extend = 0
        # If the row count of X is not divisible by 2 then we need to
        # extend X by adding a row at the bottom
        if original_size[0] % 2 != 0:
            #  X = tf.pad(X, [[0, 0], [0, 1], [0, 0]], 'SYMMETRIC')
            raise ValueError('Size of input X must be a multiple of 2')

        #  extended_size = X.get_shape().as_list()[1:]

        if nlevels == 0:
            return X, (), ()

        # ########################### Initialise ###############################
        Yh = [None, ] * nlevels
        # This is only required if the user specifies a third output
        # component.
        Yscale = [None, ] * nlevels

        # ############################ Level 1 #################################
        # Uses the biorthogonal filters
        if nlevels >= 1:
            # Do odd top-level filters on cols.
            Hi = colfilter(X, h1o)
            Lo = colfilter(X, h0o)

            # Convert Hi to complex form by taking alternate rows
            Yh[0] = tf.cast(Hi[:,::2,:], tf.complex64) + \
                1j*tf.cast(Hi[:,1::2,:], tf.complex64)
            Yscale[0] = Lo

        # ############################ Level 2+ ################################
        # Uses the qshift filters
        for level in xrange(1, nlevels):
            # If the row count of Lo is not divisible by 4 (it will be
            # divisible by 2), add 2 extra rows to make it so
            if Lo.get_shape().as_list()[1] % 4 != 0:
                Lo = tf.pad(Lo, [[0, 0], [1, 1], [0, 0]], 'SYMMETRIC')

            # Do even Qshift filters on cols.
            Hi = coldfilt(Lo, h1b, h1a)
            Lo = coldfilt(Lo, h0b, h0a)

            # Convert Hi to complex form by taking alternate rows
            Yh[level] = tf.cast(Hi[:,::2,:], tf.complex64) + \
                1j * tf.cast(Hi[:,1::2,:], tf.complex64)
            Yscale[level] = Lo

        Yl = Lo

        return Yl, tuple(Yh), tuple(Yscale)
Exemplo n.º 9
0
    def forward(self, X, nlevels=3, include_scale=False):
        """Perform a *n*-level DTCWT decompostion on a 1D column vector *X* (or on
        the columns of a matrix *X*).

        :param X: 1D real array or 2D real array whose columns are to be transformed
        :param nlevels: Number of levels of wavelet decomposition

        :returns: A :py:class:`dtcwt.Pyramid`-like object representing the transform result.

        If *biort* or *qshift* are strings, they are used as an argument to the
        :py:func:`biort` or :py:func:`qshift` functions. Otherwise, they are
        interpreted as tuples of vectors giving filter coefficients. In the *biort*
        case, this should be (h0o, g0o, h1o, g1o). In the *qshift* case, this should
        be (h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b).

        .. codeauthor:: Rich Wareham <*****@*****.**>, Aug 2013
        .. codeauthor:: Nick Kingsbury, Cambridge University, May 2002
        .. codeauthor:: Cian Shaffrey, Cambridge University, May 2002

        """
        # Which wavelets are to be used?
        biort = self.biort
        qshift = self.qshift

        # Need this because colfilter and friends assumes input is 2d
        X = asfarray(X)
        if len(X.shape) == 1:
            X = np.atleast_2d(X).T

        # Try to load coefficients if biort is a string parameter
        try:
            h0o, g0o, h1o, g1o = _biort(biort)
        except TypeError:
            h0o, g0o, h1o, g1o = biort

        # Try to load coefficients if qshift is a string parameter
        try:
            h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b = _qshift(qshift)
        except TypeError:
            h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b = qshift

        L = np.asanyarray(X.shape)

        # ensure that X is an even length, thus enabling it to be extended if needs be.
        if X.shape[0] % 2 != 0:
            raise ValueError("Size of input X must be a multiple of 2")

        if nlevels == 0:
            if include_scale:
                return Pyramid(X, (), ())
            else:
                return Pyramid(X, ())

        # initialise
        Yh = [None] * nlevels
        if include_scale:
            # This is only required if the user specifies scales are to be outputted
            Yscale = [None] * nlevels

        # Level 1.
        Hi = colfilter(X, h1o)
        Lo = colfilter(X, h0o)
        Yh[0] = Hi[::2, :] + 1j * Hi[1::2, :]  # Convert Hi to complex form.
        if include_scale:
            Yscale[0] = Lo

        # Levels 2 and above.
        for level in xrange(1, nlevels):
            # Check to see if height of Lo is divisable by 4, if not extend.
            if Lo.shape[0] % 4 != 0:
                Lo = np.vstack((Lo[0, :], Lo, Lo[-1, :]))

            Hi = coldfilt(Lo, h1b, h1a)
            Lo = coldfilt(Lo, h0b, h0a)

            Yh[level] = Hi[::2, :] + 1j * Hi[1::2, :]  # Convert Hi to complex form.
            if include_scale:
                Yscale[level] = Lo

        Yl = Lo

        if include_scale:
            return Pyramid(Yl, Yh, Yscale)
        else:
            return Pyramid(Yl, Yh)
Exemplo n.º 10
0
    def inverse(self, pyramid, gain_mask=None):
        """Perform an *n*-level dual-tree complex wavelet (DTCWT) 1D
        reconstruction.

        :param pyramid: A :py:class:`dtcwt.Pyramid`-like object containing the transformed signal.
        :param gain_mask: Gain to be applied to each subband.

        :returns: Reconstructed real array.

        The *l*-th element of *gain_mask* is gain for wavelet subband at level l.
        If gain_mask[l] == 0, no computation is performed for band *l*. Default
        *gain_mask* is all ones. Note that *l* is 0-indexed.

        .. codeauthor:: Rich Wareham <*****@*****.**>, Aug 2013
        .. codeauthor:: Nick Kingsbury, Cambridge University, May 2002
        .. codeauthor:: Cian Shaffrey, Cambridge University, May 2002

        """
        # Which wavelets are to be used?
        biort = self.biort
        qshift = self.qshift

        Yl = pyramid.lowpass
        Yh = pyramid.highpasses

        a = len(Yh)  # No of levels.

        if gain_mask is None:
            gain_mask = np.ones(a)  # Default gain_mask.

        # Try to load coefficients if biort is a string parameter
        try:
            h0o, g0o, h1o, g1o = _biort(biort)
        except TypeError:
            h0o, g0o, h1o, g1o = biort

        # Try to load coefficients if qshift is a string parameter
        try:
            h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b = _qshift(qshift)
        except TypeError:
            h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b = qshift

        level = a - 1  # No of levels = no of rows in L.
        if level < 0:
            # if there are no levels in the input, just return the Yl value
            return Yl

        Lo = Yl
        while level >= 1:  # Reconstruct levels 2 and above in reverse order.
            Hi = c2q1d(Yh[level] * gain_mask[level])
            Lo = colifilt(Lo, g0b, g0a) + colifilt(Hi, g1b, g1a)

            if (
                Lo.shape[0] != 2 * Yh[level - 1].shape[0]
            ):  # If Lo is not the same length as the next Yh => t1 was extended.
                Lo = Lo[1:-1, ...]  # Therefore we have to clip Lo so it is the same height as the next Yh.

            if np.any(np.asanyarray(Lo.shape) != np.asanyarray(Yh[level - 1].shape * np.array((2, 1)))):
                raise ValueError("Yh sizes are not valid for DTWAVEIFM")

            level -= 1

        if level == 0:  # Reconstruct level 1.
            Hi = c2q1d(Yh[level] * gain_mask[level])
            Z = colfilter(Lo, g0o) + colfilter(Hi, g1o)

        # Return a 1d vector or a column vector
        if Z.shape[1] == 1:
            return Z.flatten()
        else:
            return Z
Exemplo n.º 11
0
    def inverse(self, pyramid, gain_mask=None):
        """Perform an *n*-level dual-tree complex wavelet (DTCWT) 1D
        reconstruction.

        :param pyramid: A :py:class:`dtcwt.Pyramid`-like object containing the transformed signal.
        :param gain_mask: Gain to be applied to each subband.

        :returns: Reconstructed real array.

        The *l*-th element of *gain_mask* is gain for wavelet subband at level l.
        If gain_mask[l] == 0, no computation is performed for band *l*. Default
        *gain_mask* is all ones. Note that *l* is 0-indexed.

        .. codeauthor:: Rich Wareham <*****@*****.**>, Aug 2013
        .. codeauthor:: Nick Kingsbury, Cambridge University, May 2002
        .. codeauthor:: Cian Shaffrey, Cambridge University, May 2002

        """
        # Which wavelets are to be used?
        biort = self.biort
        qshift = self.qshift

        Yl = pyramid.lowpass
        Yh = pyramid.highpasses

        a = len(Yh)  # No of levels.

        if gain_mask is None:
            gain_mask = np.ones(a)  # Default gain_mask.

        # Try to load coefficients if biort is a string parameter
        try:
            h0o, g0o, h1o, g1o = _biort(biort)
        except TypeError:
            h0o, g0o, h1o, g1o = biort

        # Try to load coefficients if qshift is a string parameter
        try:
            h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b = _qshift(qshift)
        except TypeError:
            h0a, h0b, g0a, g0b, h1a, h1b, g1a, g1b = qshift

        level = a - 1  # No of levels = no of rows in L.
        if level < 0:
            # if there are no levels in the input, just return the Yl value
            return Yl

        Lo = Yl
        while level >= 1:  # Reconstruct levels 2 and above in reverse order.
            Hi = c2q1d(Yh[level] * gain_mask[level])
            Lo = colifilt(Lo, g0b, g0a) + colifilt(Hi, g1b, g1a)

            if Lo.shape[0] != 2 * Yh[level - 1].shape[
                    0]:  # If Lo is not the same length as the next Yh => t1 was extended.
                Lo = Lo[
                    1:-1,
                    ...]  # Therefore we have to clip Lo so it is the same height as the next Yh.

            if np.any(
                    np.asanyarray(Lo.shape) != np.asanyarray(
                        Yh[level - 1].shape * np.array((2, 1)))):
                raise ValueError('Yh sizes are not valid for DTWAVEIFM')

            level -= 1

        if level == 0:  # Reconstruct level 1.
            Hi = c2q1d(Yh[level] * gain_mask[level])
            Z = colfilter(Lo, g0o) + colfilter(Hi, g1o)

        # Return a 1d vector or a column vector
        if Z.shape[1] == 1:
            return Z.flatten()
        else:
            return Z