Discrete Wavelet Transform (DWT)

_images/dwt2d1.png

Discrete Wavelet Transform Block Diagram

Image decomposition (i.e. analysis or forward transformation) is performed by decompose().

#include <wtcv/dwt2d.hpp>
using namespace wtcv;

cv::Mat image = ...;
DWT2D dwt(Wavelet::create("db2"));
DWT2D::Coeffs coeffs = dwt.decompose(image);

Alternatively, DWT2D objects are functors.

DWT2D::Coeffs coeffs = dwt(image);

A third option is the functional interface.

DWT2D::Coeffs coeffs = dwt2d(image, "db2");

Image reconstruction (i.e. synthesis or inverse transformation) is accomplished with reconstruct()

cv::Mat reconstructed_image = dwt.reconstruct(coeffs);

or DWT2D::Coeffs::reconstruct().

cv::Mat reconstructed_image = coeffs.reconstruct();

Coefficients

This DWT2D::Coeffs is a view onto a cv::Mat containing the DWT coefficients. The coefficients at each decomposition level are comprised of three submatrices: the horizontal detail subband, the vertical detail subband, and the diagonal detail subband. There is a single submatrix of approximation coefficients stored alongside the coarsest details. Smaller level indices correspond to smaller scales (i.e. higher resolutions). The submatrices are layed out as (a 4-level decomposition is shown for illustration):

A
H0
H1
H2
H3
V0
V1
V2
V3
D0
D1
D2
D3

The regions labeled H0, V0, and D0 are the level 0 (i.e. finest) horizontal, vertical, and diagonal detail subbands, respectively. Likewise, H1, V1, and D1 are the level 1 coefficients, H2, V2, and D2 are the level 2 coefficients, and H3, V3, and D3 are the level 3 (i.e. coarsest) coefficients. The approximation coefficients are labeled A.

Constructing DWT2D::Coeffs Objects

DWT2D::Coeffs objects are created by one of the following methods:

The third method is less common and is only used when the coefficients are generated algorithmically (as opposed to transforming an image).

The only caveat is that default constructed DWT2D::Coeffs can be used as DWT2D::decompose() or dwt2d() output parameters.

cv::Mat image = ...;
DWT2D::Coeffs coeffs;
// Coefficients are passed as an output parameter.
dwt2d(image, coeffs);

But, this can be accompished with

cv::Mat image = ...;
// Coefficients are returned.
DWT2D::Coeffs coeffs = dwt2d(image);

The performance should be comparable because DWT2D::Coeffs are moveable. The difference is a matter of style. The first method is more idiomatic of OpenCV code while the second is a bit more succinct.

Interoperability With OpenCV

Converting Between cv::Mat And DWT2D::Coeffs

DWT2D::Coeffs objects are implicitly converted to cv::Mat.

DWT2D::Coeffs coeffs = ...;

// DWT2D::Coeffs can be assigned to a cv::Mat.
cv::Mat matrix = coeffs;

// Functions that accept a cv::Mat also accept a DWT2D::Coeffs.
void foo(const cv::Mat& matrix) {...}
foo(coeffs);

Warning

Converting a DWT2D::Coeffs to a cv::Mat discards the metadata that defines the subband submatrices and the associated DWT2D.

// The matrix has the same numerical data but can no longer be used as
// a DWT2D::Coeffs because the metadata has been lost.
cv::Mat matrix = coeffs;

Warning

Converting a DWT2D::Coeffs to a cv::Mat returns the private cv::Mat member. Since cv::Mat objects share the underlying data, any modification of the matrix is a modification of the coefficients.

// Be careful, matrix and coeffs share the same data.
// This sets all matrix elements and coefficients to zero.
cv::Mat matrix = coeffs;
matrix = 0.0;

Converting a cv::Mat to a DWT2D::Coeffs is done in one of two ways - in each case an existing DWT2D::Coeffs object is required to provide the necessary metadata.

  1. Use clone_and_assign() on the existing coefficients

auto new_coeffs = coeffs.clone_and_assign(matrix);
  1. Assignment to the existing coefficients

coeffs = matrix;

Calling OpenCV Functions

DWT2D::Coeffs objects are implicitly converted to cv::InputArray, cv::OutputArray, and cv::InputOutputArray. In each case the array is initialized with the private cv::Mat member. Since cv::Mat objects share the underlying data, any modification of the array’s matrix is a modification of the coefficients. This means that DWT2D::Coeffs can be passed to any OpenCV function and acted on like a normal cv::Mat.

Output Arguments

Many OpenCV functions return their result via an output argument. Consider the taking the log:

cv::Mat log_coeffs;
cv::log(coeffs, log_coeffs);

This does correctly compute log_coeffs, but it loses the DWT2D::Coeffs metadata.

To make log_coeffs a DWT2D::Coeffs, and not just a cv::Mat, initialize it with empty_clone().

DWT2D::Coeffs log_coeffs = coeffs.empty_clone();
cv::log(coeffs, log_coeffs);

API Reference

DWT API