小波变换笔记

作者: kuizhu | 来源:发表于2018-07-18 19:14 被阅读2次

    实现haar小波

    参考文章中讲解了haar小波的原理,比较易懂,实现了多级haar小波分解,本文参照它进行了练习,同时添加了小波重建。

    # include<iostream>
    # include<opencv2/opencv.hpp>
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
        Mat src = imread("F:\\testdata\\pic\\16.jpg");
        Mat HSV;
        cvtColor(src, HSV, CV_BGR2HSV);
        vector<Mat> channels;
        split(HSV, channels);
    
        Mat img = channels.at(1);
            //上述是获取HSV中的饱和度图像,按需修改
        namedWindow("img", 0);
        imshow("img", img);
        int height = img.rows;
        int width = img.cols;
        int depth = 2;
        int depthcount = 1;
    
        Mat tmp = Mat::ones(Size(width, height), CV_32FC1);
        Mat wavelet = Mat::ones(Size(width, height), CV_32FC1);
        Mat imgtmp = img.clone();
    
        imgtmp.convertTo(imgtmp, CV_32FC1);
    
        //---------------------------------------小波分解-----------------------------//
        while (depthcount <= depth)
        {
            height = img.rows / pow(2,depthcount-1);
            width = img.cols / pow(2,depthcount-1);
    
            //水平方向变换
            for (int i = 0; i < height; ++i)
            {
                for (int j = 0; j < width / 2; ++j)
                {
                    tmp.at<float>(i, j) = (imgtmp.at<float>(i, 2 * j) + imgtmp.at<float>(i, 2 * j + 1)) / 2;
                    tmp.at<float>(i, j+width/2) = (imgtmp.at<float>(i, 2 * j) - imgtmp.at<float>(i, 2 * j + 1)) / 2;
                }
            }
            
            //垂直方向变换
            for (int i = 0; i < height / 2; ++i)
            {
                for (int j = 0; j < width; ++j)
                {
                    wavelet.at<float>(i, j) = (tmp.at<float>(2 * i, j) + tmp.at<float>(2 * i + 1, j)) / 2;
                    wavelet.at<float>(i+height/2, j) = (tmp.at<float>(2 * i, j) - tmp.at<float>(2 * i + 1, j)) / 2;
                }
            }
            /*
            //低通滤波,选用高斯低通滤波器
            Mat ROI = wavelet(Rect(0, 0, width, height));
            GaussianBlur(ROI, ROI, Size(7, 7), 0.5);
            Mat dst(wavelet, Rect(0, 0, width, height));
            ROI.copyTo(dst);
            */
            imgtmp = wavelet;
            depthcount++;
    
    
        }
    
        
        //------------------------------------------小波重建--------------------------------------//
        while (depth > 0)
        {
            height = img.rows / pow(2, depth - 1);
            width = img.cols / pow(2, depth - 1);
            //列逆变换
            for (int i = 0; i < height/2; ++i)
            {
                for (int j = 0; j < width; ++j)
                {
                    float value1 = imgtmp.at<float>(i, j);
                    float value2 = imgtmp.at<float>(i+height/2, j);
                    tmp.at<float>(2 * i, j) = value1 + value2;
                    tmp.at<float>(2 * i+1, j) = value1 - value2;
                }
            }
            
            //行逆变换
            for (int i = 0; i < height; ++i)
            {
                for (int j = 0; j < width / 2; ++j)
                {
                    float value1 = tmp.at<float>(i, j);
                    float value2 = tmp.at<float>(i , j+width/2);
                    wavelet.at<float>(i, 2*j) = value1 + value2;
                    wavelet.at<float>(i , 2*j+1) = value1 - value2;
                }
            }
    
            Mat ROI=wavelet(Rect(0, 0, width, height));
            Mat dst(imgtmp, Rect(0, 0, width, height));
            ROI.copyTo(dst);
            depth--;
        }
    
    
    
        namedWindow("res", 0);
        imgtmp.convertTo(imgtmp, CV_8UC1);
        imshow("res", imgtmp);
        waitKey(0);
        return 0;
    }
    

    开源代码实现多种小波函数的小波变换

    • C++ wavelet library
    • 可以选择按照其文档中的配置方法,调用动态链接库,但是我的尝试不成功,出现了内存异常,所以本文直接将其源码放入自己的项目中,和自己的项目一起编译,可以实现同样的功能。需要注意的是,需要配置好FFTW这个依赖,方法见VS2015配置FFTW
    • 函数说明
    • 利用这个库中的函数可以得到小波分解的近似系数细节系数

    使用示例

    重要的只有如下两行函数调用

    dwt_2d(data, depth, name, output, flag, length);
    
    idwt_2d(output, flag, name, res, length);
    
    #include <iostream>
    #include <fstream>
    #include "wavelet2d.h"
    #include <vector>
    #include <string>
    #include <cmath>
    #include<opencv2\opencv.hpp>
    using namespace std;
    using namespace cv;
    
    int main() {
      //读入图片,获取饱和度
      Mat src = imread("F:\\testdata\\poreImgV3\\10.jpg");
      resize(src, src, Size(450, 450));
      Mat HSV;
      cvtColor(src, HSV, CV_BGR2HSV);
      vector<Mat> channels;
      channels.resize(3);
      split(HSV, channels);
      Mat saturation = channels.at(1);
      namedWindow("s", 0);
      imshow("s", saturation);
      waitKey(0);
      //将饱和度图像数据存入vector<vector<double>>中,一行一行放置
      int row = saturation.rows;
      int col = saturation.cols;
      //分配大小
      vector<vector<double>> data;
      data.resize(row);
      for (int i = 0; i < data.size(); ++i)
      {
          data[i].resize(col);
      }
      //放入数据
      for (int i = 0; i < row; ++i)
      {
          for (int j = 0; j < col; ++j)
          {
              data[i][j] = saturation.at<uchar>(i, j);
          }
      }
    
      int depth = 2;
      string name = "haar";
      vector<double> output;
      //output.resize(row*col);
      vector<double> flag;
      vector<int> length; 
      //小波分解
      dwt_2d(data, depth, name, output, flag, length);
    
      vector<vector<double>> res;
      res.resize(row);
      for (int i = 0; i < res.size(); ++i)
      {
          res[i].resize(col);
      }
      //----------------------------------------------------------------------------------
    
      //小波重建
      idwt_2d(output, flag, name, res, length);
      //写回原图像中
      Mat recovery(src.size(), CV_8UC1);
      for (int i = 0; i < row; ++i)
      {
          for (int j = 0; j < col; ++j)
          {
              recovery.at<uchar>(i, j) = (uchar)res[i][j];
          }
      }
      imshow("res", recovery);
      waitKey(0);
      system("pause");
      return 0;
    }
    
    

    相关文章

      网友评论

        本文标题:小波变换笔记

        本文链接:https://www.haomeiwen.com/subject/pdsapftx.html