Skip to content

Wavelet1d

C++ 1D/2D DWT Implementation for Win32 and Linux

Wavelet2d / Wavelet2s Libraries

  • 1D DWT and IDWT Implementation (Two Modes)
  • 2D DWT and IDWT Implementation (Two Modes)
  • 1D SWT and ISWT Implementation ( Stationary Wavelet Transform)
  • 2D SWT Implementation
  • Implemented using FFTW3 Library
  • Shared(.so) and static(.a) libraries for Linux
  • Shared(.dll) and static(.a) libraries for Win32 GCC (MinGW).
  • Shared(.dll) libraries for Microsoft VC++

This implementation uses C++ vector objects to accept input, store and output data. This is done to overcome certain programming limitations associated with using arrays. Dynamic arrays were also an option but they require a lot of house-cleaning without having any advantages over vector objects. To learn more about vectors, please refer to excellent tutorial at CPLUSPLUS. Vectors and Arrays can be converted back and forth so even if you are more comfortable with arrays, using vectors should not really be a problem.

Documentation

Wavelet Filters

int filtcoef(string , vector<double>&, vector<double>&, vector<double>&, vector<double>&)
웨이블릿 필터를 획득한다. 첫 번째 인자(nm)에 웨이블릿 이름을 입력하면 vector<double>&를 통하여 필터를 획득할 수 있다.

아래는 필터의 종류이다.

  • Daubechies: DB1, DB2, ...,, DB15
  • Biorthogonal: bior1.1, bior1.3, bior1.5, bior2.2, bior2.4, bior2.6, bior2.8, bior3.1, bior3.3, bior3.5, bior3.7, bior3.9, bior4.4, bior5.5, bior6.8
  • Coiflets: coif1, coif2, coif3, coif4, coif5
  • Symmlets: SYM1, sym2, ........, sym10

2D DWT/IDWT Functions

As in 1D case, both periodic and symmetric extension methods for Decimated DWT take exactly same input arguments.The difference is that Output vector in periodic extension has usually the same size (~NXN) as the input vector(NXN) while output vector in symmetric extension case has redundancies with length/breadth depending on size of filter used.

주기적 확장 (Periodic Extension)

void* dwt_2d(vector<vector<double>> &origsig, int J, string nm, vector<double>&dwt_output,vector<double>&flag, vector<int>&length)
첫 번째 인자(origsig)는 Image/Matrix 입력 값이다. J는 웨이블릿 분해 계수이고 nm은 웨이블릿 이름이다.

Additional dwt_2d_sym Functions

void* dispDWT(vector<double>&,vector<vector<double>> &, vector<int>&, vector<int>&, int )
void* dwt_output_dim_sym(vector<int>&,vector<int>&, int )
2D DWT의 결과는 1차원 Vector이며 출력에 부적합한 형식이다. 따라서 전통적인 방식(정사각형 이미지를 반복적으로 4등분 하는 이미지)으로 출력에 적합하게 변환한다.

dwt_output_dim_sym()

dwt_output_dim_sym()함수의 두 번째 인자(length2)에 출력을 위한 서브 이미지의 크기를 반환한다. 이 인자의 마지막 두 개의 값은 DWT의 크기를 나타낸다.

dwt_output_dim_sym(length, length2, J);
// ...
int siz = length2.size();
int rows_n = length2[siz - 2];
int cols_n = length2[siz - 1];
Vector2d dwtdisp(rows_n, Vector1d(cols_n));

참고로 이미지 출력 방식은 아래와 같다.
Three_Level_Wavelet_Image_Decomposition.png

그리고 dwt_output_dim_sym()함수의 구현은 아래와 같다.

void* dwt_output_dim_sym(vector<int> &length, vector<int> &length2, int J)
{
    unsigned int sz = length.size();
    int rows = length[sz - 2];
    int cols = length[sz - 1];
    for (int i = 0; i < J; i++) {
        rows = (int) ceil((double) rows / 2.0);
        cols = (int) ceil((double) cols / 2.0);
    }
    for (int i = 0; i < J + 1; i++) {
        length2.push_back(rows);
        length2.push_back(cols);
        rows = rows * 2;
        cols = cols * 2;
    }
    return 0;
}

Wavelet2d DWT Example

2D DWT결과를 OpenCV IplImage로 출력하는 방법은 아래와 같다.

// 3.5 Image Approximation Demo
// http://wavelet2d.sourceforge.net/
IplImage * createDWTImage(IplImage * original)
{
    using namespace std;
    using namespace cv;

    int height = original->height;
    int width = original->width;
    // int channels = original->nChannels;
    // int depth = original->depth;

    Mat matrix_original(original);
    Vector2d vector_original(height, Vector1d(width));

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            const int k = 1; // what is k ?
            uchar * image_cursor = (uchar*) matrix_original.data + y * matrix_original.step;
            uchar pixel = image_cursor[x * matrix_original.elemSize() + k];
            vector_original[y][x] = (double) pixel;
        }
    }

    std::string nm = "db2"; // Daubechies : db1,db2,.., ,db15

    Vector1d l1, h1, l2, h2;
    filtcoef(nm, l1, h1, l2, h2);

    // unsigned int lf=l1.size();
    // int rows_n =(int) (rows+ J*(lf-1));
    // int cols_n =(int) (cols + J * ( lf -1));

    // Finding 2D DWT Transform of the image using symetric extension algorithm
    // Extension is set to 0 (eg., int e = 0)
    Vector1i length;
    Vector1d output, flag;

    int J = 1; // depth of dwt.
    dwt_2d(vector_original, J, nm, output, flag, length);

    double max;
    Vector1i length2;

    // This algorithm computes DWT of image of any given size. Together with convolution and
    // subsampling operations it is clear that subsampled images are of different length than
    // dyadic length images. In order to compute the "effective" size of DWT we do additional
    // calculations.
    dwt_output_dim_sym(length, length2, J);

    // length2 is gives the integer vector that contains the size of subimages that will
    // combine to form the displayed output image. The last two entries of length2 gives the
    // size of DWT ( rows_n by cols_n)
    int siz = length2.size();
    int rows_n = length2[siz - 2];
    int cols_n = length2[siz - 1];
    Vector2d dwtdisp(rows_n, Vector1d(cols_n));

    dispDWT(output, dwtdisp, length, length2, J);

    // dispDWT returns the 2D object dwtdisp which will be displayed using OPENCV’s image
    // handling functions
    Vector2d dwt_output = dwtdisp;

    // Storing the DWT coefficients in two different vectors that will be used to approximate
    // Image with two different sets of chosen coefficients.
    Vector1d dwt_coef1;
    Vector1d dwt_coef2;
    dwt_coef1 = output;
    dwt_coef2 = output;

    maxval(dwt_output, max); // max value is needed to take care of overflow which happens because
    // of convolution operations performed on unsigned 8 bit images

    //Displaying Scaled Image
    // Creating Image in OPENCV
    IplImage * cvImg; // image used for output
    CvSize imgSize; // size of output image
    imgSize.width = cols_n;
    imgSize.height = rows_n;
    cvImg = cvCreateImage(imgSize, 8, 1);

    // dwt_hold is created to hold the dwt output as further operations need to be
    // carried out on dwt_output in order to display scaled images.
    Vector2d dwt_hold(rows_n, Vector1d(cols_n));
    dwt_hold = dwt_output;

    // Setting coefficients of created image to the scaled DWT output values
    for (int i = 0; i < imgSize.height; i++) {
        for (int j = 0; j < imgSize.width; j++) {
            if (dwt_output[i][j] <= 0.0) {
                dwt_output[i][j] = 0.0;
            }
            if (i <= (length2[0]) && j <= (length2[1])) {
                ((uchar*) (cvImg->imageData + cvImg->widthStep * i))[j] =
                        (char) ((dwt_output[i][j] / max) * 255.0);
            } else {
                ((uchar*) (cvImg->imageData + cvImg->widthStep * i))[j] =
                        (char) (dwt_output[i][j]);
            }
        }
    }

    // cvNamedWindow("DWT Image", 1); // creation of a visualisation window
    // cvShowImage("DWT Image", cvImg); // image visualisation
    // cvWaitKey();

    return cvImg;
}

See also

Favorite site