c++ - 通过软阈值 (C++) 使用 2d Haar 小波变换进行图像去噪

标签 c++ c wavelet haar-wavelet wavelet-transform

我正在尝试通过 Haar 变换实现基本的 2D 小波变换之一。

我将其应用于图像去噪问题。

我的恢复结果有一些黑色 block 和一些白色 block 。

我想我在没有归一化的情况下停留在软阈值部分。

这是我的代码:

   #include "StdAfx.h"
   #include "WaveletDenoising.h"
   #include <cmath>


   WaveletDenoising::WaveletDenoising(void)
   {
   }

   WaveletDenoising::~WaveletDenoising(void)
   {
   }

   /* Forward Haar wavelet transform: */
   void WaveletDenoising::ForwardHaar1D(double* data, int length)
   {
    const float inv_sqrt2 = 1/sqrt((double)2.0);

    float norm = 1.0f/sqrt((double)length);

    for(int i=0; i < length; i++) {
        data[i] *= norm;
    }

    float *tmp = new float[length];

    while(length > 1) {
        length /= 2;

        for(int i=0; i < length; i++) {
            tmp[i] = (data[2*i] + data[2*i+1]) * inv_sqrt2;
            tmp[length + i] = (data[2*i] - data[2*i+1]) * inv_sqrt2;
        }

        memcpy(data, tmp, length*2*sizeof(float));
    }

    delete [] tmp;
   }

   /* Transpose matrix: */   
   void WaveletDenoising::Transpose(double *data, int width, int height)
   {
    double *B = new double[width*height];

    for(int y=0; y < height; y++) {
        for(int x=0; x < width; x++) {
            B[x*height + y] = data[y*width + x];
        }
    }

    memcpy(data, B, sizeof(double)*width*height);

    delete [] B;
   }

   /* Forward 2d Haar wavelet transform: */
   void WaveletDenoising::ForwardHaar2D(double* data, int width, int height)
   {
    for(int i=0; i < height; i++) 
        ForwardHaar1D(&data[i*width], width);

    Transpose(data, width, height);

    for(int i=0; i < width; i++) 
        ForwardHaar1D(&data[i*height], height);

    Transpose(data, height, width);
   }

   /* Inverse 1d Haar transform */
   void WaveletDenoising::InverseHaar1D(double* data, int length)
   {
    const float inv_sqrt2 = 1/sqrt((double)2.0);
    float inv_norm = sqrt((double)length);

    float *tmp = new float[length];
    int k = 1;

    while(k < length)  {
        for(int i=0; i < k; i++) {
            tmp[2*i] = (data[i] + data[k+i]) * inv_sqrt2;
            tmp[2*i+1] = (data[i] - data[k+i]) * inv_sqrt2;
        }

        memcpy(data, tmp, sizeof(double)*(k*2));

        k *= 2;
    }

    for(int i=0; i < length; i++) {
        data[i] *= inv_norm;
    }

    delete [] tmp;
   }

   /* Inverse 2d Haar wavelet transform */
   void WaveletDenoising::InverseHaar2D(double* data, int width, int height)
   {
    for(int i=0; i < width; i++) {
        InverseHaar1D(&data[i*height], height);
    }

    Transpose(data, height, width);

    for(int i=0; i < height; i++) {
        InverseHaar1D(&data[i*width], width);
    }

    Transpose(data, width, height);
   }

   /* Image denoising by soft-thresholding */
   void WaveletDenoising::WaveletThresholdDenoising(int width, int height, double* src,    double* des, double threshold)
   {
    int i, j, x, y;

    this->ForwardHaar2D(src, width, height);

    double mi = src[0*width+0]; /* find min value */
    double ma = src[0*width+0]; /* find max value */

    for (y=0; y<height; y++)
    {
        for (x=0; x<width; x++)
        {
            if (mi > src[y*width+x])
                mi = src[y*width+x];
            if (ma < src[y*width+x])
                ma = src[y*width+x];
        }
    }

    /* soft-thresholding */
    for (y=0; y<height; y++)
    {
        for (x=0; x<width; x++)
        {
            if (src[y*width+x] < threshold) 
                src[y*width+x] = 0;
            else if (src[y*width+x] > threshold)
                src[y*width+x] = src[y*width+x] - threshold;
            else if (src[y*width+x] < -threshold)
                src[y*width+x] = src[y*width+x] + threshold;


        }
    }

    this->InverseHaar2D(src, width, height);

    for (y=0; y<height; y++)
    {
        for (x=0; x<width; x++)
        {
            // for normalized:
            src[y*width+x] = ((src[y*width+x] - mi) / (ma - mi))*255;

            double temp =  src[y*width+x];
            if (temp < 0) temp = 0;
            else if (temp >255) temp = 255;
            else temp = temp;
            des[y*width+x] = (BYTE) src[y*width+x];
        }
    }
   }

我该怎么做?

最佳答案

在这段代码上花了几个小时后,我终于找到了我的代码的问题。首先,我必须更改 InverseHaar1D 函数中 temp 变量的 double 类型,而不是 float。其次,根据噪声级别调整调用函数中的threshold 值。第三,去掉一些多余的线,如下图明确的功能。您可以通过此链接查看结果:https://www.mediafire.com/?v80rslisl7fff6n

   /* Image denoising by soft-thresholding */
   void WaveletDenoising::WaveletThresholdDenoising(int width, int height, double* src, double* des, double threshold)
   {
    int x, y;

    /* Forward 2d Haar transform */
    this->ForwardHaar2D(src, width, height);

    /* soft-thresholding */
    for(y=0; y < height; y++) 
    {
        for(x=0; x < width; x++) 
        {
            if (src[y*width+x] > threshold)
                src[y*width+x] = src[y*width+x] - threshold;
            else if (src[y*width+x] < -threshold)
                src[y*width+x] = src[y*width+x] + threshold;
            else
                src[y*width+x] = 0;
        }
    }

    /* Inverse 2D Haar transform */
    this->InverseHaar2D(src, width, height);

    for (y=0; y<height; y++)
    {
        for (x=0; x<width; x++)
        {
            double temp =  src[y*width+x];
            if (temp < 0) temp = 0;
            else if (temp >255) temp = 255;
            else 
               des[y*width+x] = (BYTE) temp;
        }
    }
   }

关于c++ - 通过软阈值 (C++) 使用 2d Haar 小波变换进行图像去噪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22651148/

相关文章:

c++ - 使用 sscaf_s 从 obj 读取顶点线不起作用

c - 搜索字符串并将其与字符串数组进行比较

c - Erlang ei ei_decode_version等函数未定义引用

matlab - 关于理解信号中包含的幅度

image-processing - 如何计算图像的逆平稳小波变换?

c++ - 列出 boost io_service 中的事件处理程序

C++ 释放结构使用的所有内存

c++ - 为什么打印单向链表时有一个虚拟节点?

c - 如何在 qt creator 中为 gcc 添加选项?

c++ - 在多个查询的子数组中查找不同(唯一)值的数量