Wavelet transform in openCV

拜拜、爱过 提交于 2019-12-02 17:37:40

Here is direct and inverse Haar Wavelet transform (used for filtering):

#include "opencv2/opencv.hpp"
#include <iostream>
#include <vector>
#include <stdio.h>

using namespace cv;
using namespace std;

// Filter type
#define NONE 0  // no filter
#define HARD 1  // hard shrinkage
#define SOFT 2  // soft shrinkage
#define GARROT 3  // garrot filter
//--------------------------------
// signum
//--------------------------------
float sgn(float x)
{
    float res=0;
    if(x==0)
    {
        res=0;
    }
    if(x>0)
    {
        res=1;
    }
    if(x<0)
    {
        res=-1;
    }
    return res;
}
//--------------------------------
// Soft shrinkage
//--------------------------------
float soft_shrink(float d,float T)
{
    float res;
    if(fabs(d)>T)
    {
        res=sgn(d)*(fabs(d)-T);
    }
    else
    {
        res=0;
    }

    return res;
}
//--------------------------------
// Hard shrinkage
//--------------------------------
float hard_shrink(float d,float T)
{
    float res;
    if(fabs(d)>T)
    {
        res=d;
    }
    else
    {
        res=0;
    }

    return res;
}
//--------------------------------
// Garrot shrinkage
//--------------------------------
float Garrot_shrink(float d,float T)
{
    float res;
    if(fabs(d)>T)
    {
        res=d-((T*T)/d);
    }
    else
    {
        res=0;
    }

    return res;
}
//--------------------------------
// Wavelet transform
//--------------------------------
static void cvHaarWavelet(Mat &src,Mat &dst,int NIter)
{
    float c,dh,dv,dd;
    assert( src.type() == CV_32FC1 );
    assert( dst.type() == CV_32FC1 );
    int width = src.cols;
    int height = src.rows;
    for (int k=0;k<NIter;k++) 
    {
        for (int y=0;y<(height>>(k+1));y++)
        {
            for (int x=0; x<(width>>(k+1));x++)
            {
                c=(src.at<float>(2*y,2*x)+src.at<float>(2*y,2*x+1)+src.at<float>(2*y+1,2*x)+src.at<float>(2*y+1,2*x+1))*0.5;
                dst.at<float>(y,x)=c;

                dh=(src.at<float>(2*y,2*x)+src.at<float>(2*y+1,2*x)-src.at<float>(2*y,2*x+1)-src.at<float>(2*y+1,2*x+1))*0.5;
                dst.at<float>(y,x+(width>>(k+1)))=dh;

                dv=(src.at<float>(2*y,2*x)+src.at<float>(2*y,2*x+1)-src.at<float>(2*y+1,2*x)-src.at<float>(2*y+1,2*x+1))*0.5;
                dst.at<float>(y+(height>>(k+1)),x)=dv;

                dd=(src.at<float>(2*y,2*x)-src.at<float>(2*y,2*x+1)-src.at<float>(2*y+1,2*x)+src.at<float>(2*y+1,2*x+1))*0.5;
                dst.at<float>(y+(height>>(k+1)),x+(width>>(k+1)))=dd;
            }
        }
        dst.copyTo(src);
    }   
}
//--------------------------------
//Inverse wavelet transform
//--------------------------------
static void cvInvHaarWavelet(Mat &src,Mat &dst,int NIter, int SHRINKAGE_TYPE=0, float SHRINKAGE_T=50)
{
    float c,dh,dv,dd;
    assert( src.type() == CV_32FC1 );
    assert( dst.type() == CV_32FC1 );
    int width = src.cols;
    int height = src.rows;
    //--------------------------------
    // NIter - number of iterations 
    //--------------------------------
    for (int k=NIter;k>0;k--) 
    {
        for (int y=0;y<(height>>k);y++)
        {
            for (int x=0; x<(width>>k);x++)
            {
                c=src.at<float>(y,x);
                dh=src.at<float>(y,x+(width>>k));
                dv=src.at<float>(y+(height>>k),x);
                dd=src.at<float>(y+(height>>k),x+(width>>k));

               // (shrinkage)
                switch(SHRINKAGE_TYPE)
                {
                case HARD:
                    dh=hard_shrink(dh,SHRINKAGE_T);
                    dv=hard_shrink(dv,SHRINKAGE_T);
                    dd=hard_shrink(dd,SHRINKAGE_T);
                    break;
                case SOFT:
                    dh=soft_shrink(dh,SHRINKAGE_T);
                    dv=soft_shrink(dv,SHRINKAGE_T);
                    dd=soft_shrink(dd,SHRINKAGE_T);
                    break;
                case GARROT:
                    dh=Garrot_shrink(dh,SHRINKAGE_T);
                    dv=Garrot_shrink(dv,SHRINKAGE_T);
                    dd=Garrot_shrink(dd,SHRINKAGE_T);
                    break;
                }

                //-------------------
                dst.at<float>(y*2,x*2)=0.5*(c+dh+dv+dd);
                dst.at<float>(y*2,x*2+1)=0.5*(c-dh+dv-dd);
                dst.at<float>(y*2+1,x*2)=0.5*(c+dh-dv-dd);
                dst.at<float>(y*2+1,x*2+1)=0.5*(c-dh-dv+dd);            
            }
        }
        Mat C=src(Rect(0,0,width>>(k-1),height>>(k-1)));
        Mat D=dst(Rect(0,0,width>>(k-1),height>>(k-1)));
        D.copyTo(C);
    }   
}
//--------------------------------
//
//--------------------------------
int process(VideoCapture& capture)
{
    int n = 0;
    const int NIter=4;
    char filename[200];
    string window_name = "video | q or esc to quit";
    cout << "press space to save a picture. q or esc to quit" << endl;
    namedWindow(window_name, CV_WINDOW_KEEPRATIO); //resizable window;
    Mat frame;
    capture >> frame;

    Mat GrayFrame=Mat(frame.rows, frame.cols, CV_8UC1);
    Mat Src=Mat(frame.rows, frame.cols, CV_32FC1);
    Mat Dst=Mat(frame.rows, frame.cols, CV_32FC1);
    Mat Temp=Mat(frame.rows, frame.cols, CV_32FC1);
    Mat Filtered=Mat(frame.rows, frame.cols, CV_32FC1);
    for (;;) 
    {
        Dst=0;
        capture >> frame;
        if (frame.empty()) continue;
        cvtColor(frame, GrayFrame, CV_BGR2GRAY);
        GrayFrame.convertTo(Src,CV_32FC1);
        cvHaarWavelet(Src,Dst,NIter);

        Dst.copyTo(Temp);

        cvInvHaarWavelet(Temp,Filtered,NIter,GARROT,30);

        imshow(window_name, frame);

        double M=0,m=0;
        //----------------------------------------------------
        // Normalization to 0-1 range (for visualization)
        //----------------------------------------------------
        minMaxLoc(Dst,&m,&M);
        if((M-m)>0) {Dst=Dst*(1.0/(M-m))-m/(M-m);}
        imshow("Coeff", Dst);

        minMaxLoc(Filtered,&m,&M);
        if((M-m)>0) {Filtered=Filtered*(1.0/(M-m))-m/(M-m);}        
        imshow("Filtered", Filtered);

        char key = (char)waitKey(5);
        switch (key) 
        {
        case 'q':
        case 'Q':
        case 27: //escape key
            return 0;
        case ' ': //Save an image
            sprintf(filename,"filename%.3d.jpg",n++);
            imwrite(filename,frame);
            cout << "Saved " << filename << endl;
            break;
        default:
            break;
        }
    }
    return 0;
}

int main(int ac, char** av) 
{
    VideoCapture capture(0);
    if (!capture.isOpened()) 
    {
        return 1;
    }
    return process(capture);
}

Here is another implementation of Wavelet transform in OpenCV from Mahavir:

            #include <opencv2\highgui\highgui.hpp>
            #include <opencv2\core\core.hpp>
            #include <opencv2\core\mat.hpp>
            #include <opencv2\imgproc\imgproc.hpp>
            #include<iostream>
            #include<math.h>
            #include<conio.h>
            using namespace std;
            using namespace cv;

            class image
            {
            public:
                Mat im,im1,im2,im3,im4,im5,im6,temp,im11,im12,im13,im14,imi,imd,imr;
                float a,b,c,d;
                int getim();
            };

            int image::getim()
            {
                im=imread("lena.jpg",0); //Load image in Gray Scale
                imi=Mat::zeros(im.rows,im.cols,CV_8U);
                im.copyTo(imi);

                im.convertTo(im,CV_32F,1.0,0.0);
                im1=Mat::zeros(im.rows/2,im.cols,CV_32F);
                im2=Mat::zeros(im.rows/2,im.cols,CV_32F);
                im3=Mat::zeros(im.rows/2,im.cols/2,CV_32F);
                im4=Mat::zeros(im.rows/2,im.cols/2,CV_32F);
                im5=Mat::zeros(im.rows/2,im.cols/2,CV_32F);
                im6=Mat::zeros(im.rows/2,im.cols/2,CV_32F);

                //--------------Decomposition-------------------

                for(int rcnt=0;rcnt<im.rows;rcnt+=2)
                {
                    for(int ccnt=0;ccnt<im.cols;ccnt++)
                    {

                        a=im.at<float>(rcnt,ccnt);
                        b=im.at<float>(rcnt+1,ccnt);
                        c=(a+b)*0.707;
                        d=(a-b)*0.707;
                        int _rcnt=rcnt/2;
                        im1.at<float>(_rcnt,ccnt)=c;
                        im2.at<float>(_rcnt,ccnt)=d;
                    }
                }

                for(int rcnt=0;rcnt<im.rows/2;rcnt++)
                {
                    for(int ccnt=0;ccnt<im.cols;ccnt+=2)
                    {

                        a=im1.at<float>(rcnt,ccnt);
                        b=im1.at<float>(rcnt,ccnt+1);
                        c=(a+b)*0.707;
                        d=(a-b)*0.707;
                        int _ccnt=ccnt/2;
                        im3.at<float>(rcnt,_ccnt)=c;
                        im4.at<float>(rcnt,_ccnt)=d;
                    }
                }

                for(int rcnt=0;rcnt<im.rows/2;rcnt++)
                {
                    for(int ccnt=0;ccnt<im.cols;ccnt+=2)
                    {

                        a=im2.at<float>(rcnt,ccnt);
                        b=im2.at<float>(rcnt,ccnt+1);
                        c=(a+b)*0.707;
                        d=(a-b)*0.707;
                        int _ccnt=ccnt/2;
                        im5.at<float>(rcnt,_ccnt)=c;
                        im6.at<float>(rcnt,_ccnt)=d;
                    }
                }

                imr=Mat::zeros(256,256,CV_32F);
                imd=Mat::zeros(256,256,CV_32F);
                im3.copyTo(imd(Rect(0,0,128,128)));
                im4.copyTo(imd(Rect(0,127,128,128)));
                im5.copyTo(imd(Rect(127,0,128,128)));
                im6.copyTo(imd(Rect(127,127,128,128)));


                //---------------------------------Reconstruction-------------------------------------

                im11=Mat::zeros(im.rows/2,im.cols,CV_32F);
                im12=Mat::zeros(im.rows/2,im.cols,CV_32F);
                im13=Mat::zeros(im.rows/2,im.cols,CV_32F);
                im14=Mat::zeros(im.rows/2,im.cols,CV_32F);

                for(int rcnt=0;rcnt<im.rows/2;rcnt++)
                {
                    for(int ccnt=0;ccnt<im.cols/2;ccnt++)
                    {
                        int _ccnt=ccnt*2;
                        im11.at<float>(rcnt,_ccnt)=im3.at<float>(rcnt,ccnt);     //Upsampling of stage I
                        im12.at<float>(rcnt,_ccnt)=im4.at<float>(rcnt,ccnt);
                        im13.at<float>(rcnt,_ccnt)=im5.at<float>(rcnt,ccnt);
                        im14.at<float>(rcnt,_ccnt)=im6.at<float>(rcnt,ccnt);
                    }
                }


                for(int rcnt=0;rcnt<im.rows/2;rcnt++)
                {
                    for(int ccnt=0;ccnt<im.cols;ccnt+=2)
                    {

                        a=im11.at<float>(rcnt,ccnt);
                        b=im12.at<float>(rcnt,ccnt);
                        c=(a+b)*0.707;
                        im11.at<float>(rcnt,ccnt)=c;
                        d=(a-b)*0.707;                           //Filtering at Stage I
                        im11.at<float>(rcnt,ccnt+1)=d;
                        a=im13.at<float>(rcnt,ccnt);
                        b=im14.at<float>(rcnt,ccnt);
                        c=(a+b)*0.707;
                        im13.at<float>(rcnt,ccnt)=c;
                        d=(a-b)*0.707;
                        im13.at<float>(rcnt,ccnt+1)=d;
                    }
                }

                temp=Mat::zeros(im.rows,im.cols,CV_32F);

                for(int rcnt=0;rcnt<im.rows/2;rcnt++)
                {
                    for(int ccnt=0;ccnt<im.cols;ccnt++)
                    {

                        int _rcnt=rcnt*2;
                        imr.at<float>(_rcnt,ccnt)=im11.at<float>(rcnt,ccnt);     //Upsampling at stage II
                        temp.at<float>(_rcnt,ccnt)=im13.at<float>(rcnt,ccnt); 
                    }
                }

                for(int rcnt=0;rcnt<im.rows;rcnt+=2)
                {
                    for(int ccnt=0;ccnt<im.cols;ccnt++)
                    {

                        a=imr.at<float>(rcnt,ccnt);
                        b=temp.at<float>(rcnt,ccnt);
                        c=(a+b)*0.707;
                        imr.at<float>(rcnt,ccnt)=c;                                      //Filtering at Stage II
                        d=(a-b)*0.707;
                        imr.at<float>(rcnt+1,ccnt)=d;
                    }
                }

                imd.convertTo(imd,CV_8U);
                namedWindow("Input Image",1);
                imshow("Input Image",imi);
                namedWindow("Wavelet Decomposition",1);
                imshow("Wavelet Decomposition",imd);
                imr.convertTo(imr,CV_8U);
                namedWindow("Wavelet Reconstruction",1);
                imshow("Wavelet Reconstruction",imr);
                waitKey(0);
                return 0;
            }

            int main()
            {
                image my;
                my.getim();
                return 0;
            }

Hope someone finds it useful!

I see that there's very few code examples for wavelet in java, especially if you're using openCV. I had to use wavelet in java with openCV and I used the C code from @la luvia and converted to java.

There was a lot of trouble while translating the code, because it had a lot of diferences in the openCV methods and ways of using it. This book helped me a lot in the process too.

I hope this code and the book give some perspective of how to use the lib and few diferences between the C and Java.

Here's the code:

import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

public class Wavelet {

    //Imperative in java
    static{
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    String pathname = "C:/Users/user/img096";


    public static void main(String[] args) {
        Wavelet wavelet = new Wavelet();
        wavelet.applyHaarFoward();
        wavelet.applyHaarReverse();

        Imgcodecs.imwrite(wavelet.pathname+"imi.jpg", wavelet.imi);
        Imgcodecs.imwrite(wavelet.pathname+"imd.jpg", wavelet.imd);
        Imgcodecs.imwrite(wavelet.pathname+"imr.jpg", wavelet.imr);
    }

    Mat im,im1,im2,im3,im4,im5,im6,temp,im11,im12,im13,im14,imi,imd,imr;
    float a,b,c,d;

    private void applyHaarFoward(){
        try{
            im = Imgcodecs.imread(pathname+".jpg", 0);
            imi = new Mat(im.rows(), im.cols(), CvType.CV_8U);
            im.copyTo(imi);

            //in CvType. If the number of channels is omitted, it evaluates to 1. 
            im.convertTo(im, CvType.CV_32F, 1.0, 0.0);
            im1 = new Mat(im.rows()/2, im.cols(), CvType.CV_32F);
            im2 = new Mat(im.rows()/2, im.cols(), CvType.CV_32F);

            im3 = new Mat(im.rows()/2, im.cols()/2, CvType.CV_32F);
            im4 = new Mat(im.rows()/2, im.cols()/2, CvType.CV_32F);

            im5 = new Mat(im.rows()/2, im.cols()/2, CvType.CV_32F);
            im6 = new Mat(im.rows()/2, im.cols()/2, CvType.CV_32F);


            // ------------------- Decomposition ------------------- 

            for (int rcnt = 0; rcnt < im.rows(); rcnt+=2) {
                for (int ccnt = 0; ccnt < im.cols(); ccnt++) {
                    //even though the CvType is float with only one channel
                    //the method Mat.get() return a double array 
                    //with only one position, [0].
                    a = (float) im.get(rcnt, ccnt)[0];
                    b = (float) im.get(rcnt+1, ccnt)[0];
                    c = (float) ((a+b)*0.707);
                    d = (float) ((a-b)*0.707);
                    int _rcnt= rcnt/2;
                    im1.put(_rcnt, ccnt, c);
                    im2.put(_rcnt, ccnt, d);

                }
            }

            for (int rcnt = 0; rcnt < im.rows()/2; rcnt++) {
                for (int ccnt = 0; ccnt < im.cols() - 2; ccnt+=2) {
                    a = (float) im1.get(rcnt, ccnt)[0];
                    b = (float) im1.get(rcnt, ccnt+1)[0];
                    c = (float) ((a+b)*0.707);
                    d = (float) ((a-b)*0.707);
                    int _ccnt = ccnt/2;
                    im3.put(rcnt, _ccnt, c);
                    im4.put(rcnt, _ccnt, d);
                }
            }

            for (int rcnt = 0; rcnt < im.rows()/2; rcnt++) {
                for (int ccnt = 0; ccnt < im.cols() - 2; ccnt+=2) {
                    a = (float) im2.get(rcnt, ccnt)[0];
                    b = (float) im2.get(rcnt, ccnt+1)[0];
                    c = (float) ((a+b)*0.707);
                    d = (float) ((a-b)*0.707);
                    int _ccnt = ccnt/2;
                    im5.put(rcnt, _ccnt, c);
                    im6.put(rcnt, _ccnt, d);
                }
            }

            imr = Mat.zeros(im.rows(), im.cols(), CvType.CV_32F);//imr = Mat.zeros(512, 512, CvType.CV_32F);
            imd = Mat.zeros(512, 512, CvType.CV_32F);
            im3.copyTo(imd.adjustROI(0, 0, 256, 256));
            im4.copyTo(imd.adjustROI(0, 255, 256, 256));
            im5.copyTo(imd.adjustROI(255, 0, 256, 256));
            im6.copyTo(imd.adjustROI(255, 255, 256, 256));





        }catch(Exception ex){
            System.err.println(ex.getLocalizedMessage());
            ex.printStackTrace();
        }
    }

    private void applyHaarReverse(){
        // ------------------- Reconstruction ------------------- 
                im11 = Mat.zeros(im.rows()/2, im.cols(), CvType.CV_32F);
                im12 = Mat.zeros(im.rows()/2, im.cols(), CvType.CV_32F);
                im13 = Mat.zeros(im.rows()/2, im.cols(), CvType.CV_32F);
                im14 = Mat.zeros(im.rows()/2, im.cols(), CvType.CV_32F);

                for (int rcnt = 0; rcnt < im.rows()/2; rcnt++) {
                    for (int ccnt = 0; ccnt < im.cols()/2; ccnt++) {
                        int _ccnt  = ccnt*2;
                        im11.put(rcnt, _ccnt, im3.get(rcnt, ccnt));
                        im12.put(rcnt, _ccnt, im4.get(rcnt, ccnt));
                        im13.put(rcnt, _ccnt, im5.get(rcnt, ccnt));
                        im14.put(rcnt, _ccnt, im6.get(rcnt, ccnt));
                    }
                }

                for (int rcnt = 0; rcnt < im.rows()/2; rcnt++) {
                    for (int ccnt = 0; ccnt < im.cols() - 2; ccnt+=2) {
                        a = (float) im11.get(rcnt, ccnt)[0];
                        b = (float) im12.get(rcnt, ccnt)[0];
                        c = (float) ((a+b)*0.707);
                        im11.put(rcnt, ccnt, c);
                        d = (float) ((a-b)*0.707);
                        im11.put(rcnt, ccnt+1, d);

                        a = (float) im13.get(rcnt, ccnt)[0];
                        b = (float) im14.get(rcnt, ccnt)[0];
                        c = (float) ((a+b)*0.707);
                        im13.put(rcnt, ccnt, c);
                        d = (float) ((a-b)*0.707);
                        im13.put(rcnt, ccnt+1, d);
                    }
                }

                temp = Mat.zeros(im.rows(), im.cols(), CvType.CV_32F);

                for (int rcnt = 0; rcnt < im.rows()/2; rcnt++) {
                    for (int ccnt = 0; ccnt < im.cols(); ccnt++) {
                        int _rcnt = rcnt*2;
                        imr.put(_rcnt, ccnt, im11.get(rcnt, ccnt));
                        temp.put(_rcnt, ccnt, im13.get(rcnt, ccnt));
                    }
                }


                for (int rcnt = 0; rcnt < im.rows()-2; rcnt+=2) {
                    for (int ccnt = 0; ccnt < im.cols(); ccnt++) {
                        a = (float) imr.get(rcnt, ccnt)[0];
                        b = (float) temp.get(rcnt, ccnt)[0];
                        c = (float) ((a+b)*0.707);
                        imr.put(rcnt, ccnt, c);
                        d = (float) ((a-b)*0.707);
                        imr.put(rcnt+1, ccnt, d);
                    }
                }

    }
}

Hope it's useful.

Suggestion: I don't suggest you to implement dwt from scratch, it is very hard to meet your demands. If you really need it's cpp version in your job, I recommend you try PyWavelets, whose basic functions of dwt are implementd in C, so you can migrate it to your program easily. Otherwise, you can also verify your thoughts with python first rather than take a risk of paying useless efforts.


Here is one of my implementation of dwt which support many kinds of wavelet filter, it works but dosen't work well. With the increasing of level, the reconstrusion being more and more blurred.

If you want to change the wavelet filter, you can use matlab (wfilters(wname)) or pick from PyWavelets's source code, and it also gives the rule to get totall 4 filter from these coefficients.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!