I recently stumbled upon a bothering fact when using the pywavelet library in Python. When we use the default "symmetric" padding, the inverse wavelet transform is not the adjoint of the wavelet transform (and it's not the mathematical inverse of the wavelet transform, "only in one direction").

However, if you use the "zero" padding the adjoint property is verified (not the inverse property). And if you use the "periodization" padding then all the properties are verified.

I wanted to know if there was a theoretical reason behind why the padding has such a big influence on these properties or if it was down to implementation.

You can find a code below highlighting the said issue:

import numpy as np
import pywt

wavelet_type = "db4"
level = 4
mode = "symmetric"

coeffs_tpl = pywt.wavedecn(data=np.zeros((512, 512)), wavelet=wavelet_type, mode=mode, level=level)
coeffs_1d, coeff_slices, coeff_shapes = pywt.ravel_coeffs(coeffs_tpl)
coeffs_tpl_rec = pywt.unravel_coeffs(coeffs_1d, coeff_slices, coeff_shapes)
_ = pywt.waverecn(coeffs_tpl_rec, wavelet=wavelet_type, mode=mode)

def py_W(im):
    alpha = pywt.wavedecn(data=im, wavelet=wavelet_type, mode=mode, level=level)
    alpha, _, _ = pywt.ravel_coeffs(alpha)
    return alpha

def py_Ws(alpha):
    coeffs = pywt.unravel_coeffs(alpha, coeff_slices, coeff_shapes)
    im = pywt.waverecn(coeffs, wavelet=wavelet_type, mode=mode)
    return im

x_example = np.random.rand(*coeffs_1d.shape)
y_example = np.random.rand(512, 512)
x_Tadj_y = np.dot(x_example, np.conjugate(py_W(y_example)))
T_x_y = np.dot(py_Ws(x_example).flatten(), np.conjugate(y_example.flatten()))
print(np.allclose(x_Tadj_y, T_x_y))
print("\n Inverse from image to image:")
print(np.allclose(py_Ws(py_W(y_example)), y_example))
print("\n Inverse from coefficients to coefficients:")
print(np.allclose(py_W(py_Ws(x_example)), x_example))

EDIT: When reading the documentation about the different paddings, I could see that the problematic paddings compute a redundant representation of the original image (for example you have more coefficients than pixels in your original image). Therefore, it's normal that the inverse property is not verified from coefficients to coefficients (if taken at random without structure). However, this doesn't explain why the adjoint property is not verified.

Also I don't know whether this redundance is theoretical to ensure perfect reconstruction or is an implementation choice.


Actually the redundancy perfectly explains why the adjoint property is not verified. The reconstruction operator is not orthogonal anymore and therefore the inverse is not necessarily its adjoint.

You can compute the adjoint efficiently according to https://arxiv.org/pdf/1707.02018.pdf.

Regarding the necessity of redundance, according to this person it is theoretically needed, although he couldn't provided a resource or a proof of that. But since it's a separate issue, I am going to ask another question (you can check it here).

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.