文章目录
- 前言
- 一、工具介绍及下载(Visual C++ 6.0/MATLAB)
-
- 1. Visual C++ 6.0
- 2. MATLAB
- 二、一维小波变换C语言代码
-
- 1. 基于循环卷积的一维小波变换程序(Visual C++ 6.0)
- 2. 代码效果验证程序(MATLAB)
- 三、代码效果验证展示
-
- 1. 近似系数对比
- 2. 细节系数对比
- 3. 重构后与原始数据对比
- 总结
- 参考
前言 最近对循环卷积、小波变换比较感兴趣,阅读了一些文章,也有了一些收获。在学习的过程中,无意间看到了一篇名为《一维小波变换,可多次分解》的博客-https://blog.csdn.net/lichengyu/article/details/5829785。该博客分享了代码,并进行了小波变换多次分解分析,但遗憾的是,没有介绍实现平台、博客图片看不到,且有读者反映代码实现有一定问题,影响学习和体验。
出于上述原因,本文基于原代码进行适当修改并在Visual C++ 6.0上编译实现;为验证代码效果,将运算结果与MATLAB中dwt函数获得的结果进行比较分析;结果显示,所写代码能较好实现对原始信号的分解。
一、工具介绍及下载(Visual C++ 6.0/MATLAB) 1. Visual C++ 6.0 Visual C++是Microsoft公司推出的功能最强大、也是最复杂的程序设计工具之一。它最常用的版本为Visual C++ 6.0。
Visual C++ 6.0集程序的代码编辑、编译、连接、调试等功能于一体,为编程人员提供了一个既完整又方便的开发环境。
[下载链接]:
https://pan.baidu.com/s/1qDKJQHXf29XqxBe8hfhQaQ
[提取码]: 6bxk
2. MATLAB MATLAB是美国 MathWorks 公司出品的商业数学软件 ,用于数据分析 、无线通信 、深度学习 、图像处理与计算机视觉 、信号处理 、量化金融与风险管理、机器人, 控制系统等领域。MATLAB是matrix&laboratory两个词的组合,意为矩阵工厂(矩阵实验室),软件主要面对科学计算、可视化以及交互式程序设计的高科技计算环境。
[下载链接]:
https://pan.baidu.com/s/1jnp9OeXZRnwScGU68K03CQ
[提取码]: 1234
二、一维小波变换C语言代码 1. 基于循环卷积的一维小波变换程序(Visual C++ 6.0) 代码如下:
#include
#include
#include #defineLENGTH4320// 信号长度,本例中原始信号为4320个数据点(matlab中leleccum信号)
/*****************************************************************
* 函数: 一维卷积函数
*
* 说明: 循环卷积,卷积结果的长度与输入信号的长度相同
*
* 输入参数: data[],输入信号;
*h[],Daubechies 3 小波基低通滤波器系数;
*g[],Daubechies 3 小波基高通滤波器系数;
*cov[],卷积结果;
*n,输入信号长度;
*m,卷积核长度.
*****************************************************************/
void Covlution(double data[], double h[], double g[], double cov[], int n, int m)
{
int i = 0;
int j = 0;
int k = 0;
// 将cov[]清零
for(i = 0;
i < n;
i++)
{
cov[i] = 0;
} // ****************************************************
// 奇数行用h[]进行卷积
// **************************************************** // 前m/2+1行
i = 0;
for(j = 0;
j < m/2;
j+=2, i+=2)
{
for(k = m/2-j;
k < m;
k++ )
{
cov[i] += data[k-(m/2-j)] * h[k];
// k针对core[k]
}for(k = n-m/2+j;
k < n;
k++ )
{
cov[i] += data[k] * h[k-(n-m/2+j)];
// k针对data[k]
}
} // 中间的n-m行
for( ;
i <= (n-m)+m/2;
i+=2)
{
for( j = 0;
j < m;
j++)
{
cov[i] += data[i-m/2+j] * h[j];
}
} // 最后m/2-1行
// i = ( (n - m) + m/2 + 1 )/2*2;
for(j = 1;
j <= m/2;
j+=2, i+=2)
{
for(k = 0;
k < j;
k++)
{
cov[i] += data[k] * h[m-j-k];
// k针对data[k]
}for(k = 0;
k < m-j;
k++)
{
cov[i] += h[k] * data[n-(m-j)+k];
// k针对core[k]
}
} // ****************************************************
// 偶数行用g[]进行卷积
// **************************************************** // 前m/2+1行
i = 1;
for(j = 0;
j < m/2;
j+=2, i+=2)
{
for(k = m/2-j;
k < m;
k++ )
{
cov[i] += data[k-(m/2-j)] * g[k];
// k针对core[k]
}for(k = n-m/2+j;
k < n;
k++ )
{
cov[i] += data[k] * g[k-(n-m/2+j)];
// k针对data[k]
}
} //中间的n-m行
for( ;
i <= (n-m)+m/2;
i+=2)
{
for( j = 0;
j < m;
j++)
{
cov[i] += data[i-m/2+j] * g[j];
}
} // 最后m/2-1行
// i = ( (n - m) + m/2 + 1 );
for(j = 1;
j <= m/2;
j+=2, i+=2)
{
for(k = 0;
k < j;
k++)
{
cov[i] += data[k] * g[m-j-k];
// k针对data[k]
}for(k = 0;
k < m-j;
k++)
{
cov[i] += g[k] * data[n-(m-j)+k];
// k针对core[k]
}
}
}/*****************************************************************
* 函数: 排序函数
*
* 说明: 将卷积后的结果data[]进行排序,使尺度系数和小波系数分开
*****************************************************************/
void Sort(double data[], double sort[], int n)
{
int i;
for(i = 0;
i < n;
i+=2) // 上采样
{
sort[i/2] = data[i];
} for(i = 1;
i < n;
i+=2) // 下采样
{
sort[n/2+i/2] = data[i];
}}/*****************************************************************
* 函数: 一维小波变换函数
*
* 说明: 一维小波变换,可进行多次分解
*
* 输入参数: input[],输入信号;
*output[],小波变换结果,包括尺度系数和小波系数两部分;
*temp[],存放中间结果;
*h[],Daubechies 3 小波基低通滤波器系数;
*g[],Daubechies 3 小波基高通滤波器系数;
*n,输入信号长度;
*m,Daubechies 3 小波基紧支集长度;
*nStep,小波变换分解次数
*****************************************************************/
void DWT1D(double input[], double output[], double temp[], double h[], double g[], int n, int m, int nStep)
{
int i = 0;
for(i = 0;
i < n;
i++)
{
output[i] = input[i];
} for(i = 0;
i < nStep;
i++)
{
Covlution(output, h, g, temp, n, m);
Sort(temp, output, n);
n = n/2;
}
}void main()
{ double data[LENGTH];
// 输入信号
double temp[LENGTH];
// 中间结果
double data_output[LENGTH];
// 一维小波变换后的结果 int i = 0;
int n = 0;
// 输入信号长度
int m = 6;
// Daubechies 3 正交小波基长度
int nStep = 1;
// 分解级数 static double h[] = {.332670552950,
.806891509311,
.459877502118,
-.135011020010,
-.085441273882,
.035226291882};
static double g[] = {.035226291882,
.085441273882,
-.135011020010,
-.459877502118,
.806891509311,
-.332670552950};
char data1[LENGTH];
// 缓冲区, 从txt文件中读取一行数据
FILE *fp;
// 文件指针
int len;
// 行字符个数
if((fp = fopen("D:\\data.txt","r")) == NULL)
{
perror("fail to read");
exit (1) ;
}while(fgets(data1,LENGTH,fp) != NULL)
{
data[n] = atof(data1);
n++;
len = strlen(data1);
data1[len-1] = '\0';
// 去掉换行符
printf("%s %d \n",data1, n);
// 打印文件中每行字符串及文件中总字符串个数
}// 打印从文件中读取的数值
/*for(i = 0;
i < LENGTH;
i++)
{
printf("%.12f\n",data[i]);
}*/ // 一维小波变换
DWT1D(data, data_output, temp, h, g, n, m, nStep);
// 一维小波变换后的结果写入txt文件
fp=fopen("D:\\data_output.txt","a");
// 打印并写入一维小波变换后的结果
for(i = 0;
i < n/pow(2,nStep-1);
i++)
{
printf("%f\n", data_output[i]);
fprintf(fp,"%f\n", data_output[i]);
} // 关闭文件
fclose(fp);
}
2. 代码效果验证程序(MATLAB) 代码如下:
%% 2022.04.30晚
%目的:将Visual C++ 6.0 代码中运算得到的数据
%与matlab自带的小波分解和重构函数得到的数据做对比分析;
%% 导入原始信号并利用matlab自带分解函数得到近似及细节系数
load leleccum;
s = leleccum(1:4320);
% 采用matlab自带函数
[cA1,cD1] = dwt(s,'db3');
%% Visual C++ 6.0 代码中运算得到的数据(近似及细节系数)
Data_Output = load('D:\data_output.txt');
Num = length(Data_Output);
data_output_L = Data_Output(1:Num/2);
% 近似系数(低频)
data_output_H = Data_Output(Num/2+1:4320);
% 细节系数(高频)%% 两种方法获得的近似及细节系数对比分析
figure(1);
% 近似系数对比
plot(data_output_L,'black');
hold on
plot(cA1,'r');
legend('data_output_L','cA1');
% 添加线段标签figure(2);
% 细节系数对比
plot(data_output_H,'black');
hold on
plot(cD1,'r');
legend('data_output_H','cD1');
% 添加线段标签%% 将Visual C++ 6.0 代码中运算得到的数据(近似及细节系数)重构后与原始数据作对比
A1 = upcoef('a',data_output_L,'db3',1);
D1 = upcoef('d',data_output_H,'db3',1);
figure(3);
% 重构后与原始数据作对比
plot(A1+D1,'black');
hold on
plot(s,'r');
legend('A1+D1','s');
% 添加线段标签
三、代码效果验证展示 1. 近似系数对比
文章图片
2. 细节系数对比
文章图片
3. 重构后与原始数据对比
文章图片
总结 1) 介绍了代码实现和验证工具并提供了下载渠道;
2) 基于原代码进行适当修改并在Visual C++ 6.0上编译实现;
3) 为验证代码效果,在MATLAB中与dwt函数获得的结果进行比较分析;
4) 结果显示,所写代码能较好实现对原始信号的分解。
参考 【小波变换|基于循环卷积的一维小波变换程序验证(C语言)】https://blog.csdn.net/lichengyu/article/details/5829785
https://blog.csdn.net/Archar_Saber/article/details/50043507
baike.baidu.com/item/MATLAB/263035
https://blog.csdn.net/GGY1102/article/details/121733746
https://blog.csdn.net/chengxiao_ling/article/details/88993680
推荐阅读
- python|机器学习之朴素贝叶斯算法+应用实例
- 数据分析与机器学习|大厂面试机器学习算法(5)推荐系统算法
- MATLAB正弦波图
- MATLAB在矩阵上的运算
- MATLAB变量
- MATLAB Trapz
- MATLAB控制语句
- MATLAB程序设计环境
- MATLAB辛普森法则