C 如何获得与Matlab使用FFTW时相同的希尔伯特变换结果?
我需要计算希尔伯特变换,从我的信号中得到它的绝对数。 我安装了FFTW并进行了跟踪,两者都运行良好 然而,我像视频一样实现了希尔伯特变换,我没有得到与Matlab计算的值相同的值 我读过一些人,他们仅仅通过FFT和其他计算来解决这个问题,但他们没有给出足够清晰的答案。 谁能给我提供几行基于FFTW的代码,让结果与Matlab计算结果一致 下面是我在视频中看到的希尔伯特变换代码:C 如何获得与Matlab使用FFTW时相同的希尔伯特变换结果?,c,signal-processing,fft,absolute,fftw,C,Signal Processing,Fft,Absolute,Fftw,我需要计算希尔伯特变换,从我的信号中得到它的绝对数。 我安装了FFTW并进行了跟踪,两者都运行良好 然而,我像视频一样实现了希尔伯特变换,我没有得到与Matlab计算的值相同的值 我读过一些人,他们仅仅通过FFT和其他计算来解决这个问题,但他们没有给出足够清晰的答案。 谁能给我提供几行基于FFTW的代码,让结果与Matlab计算结果一致 下面是我在视频中看到的希尔伯特变换代码: void hilbert(const double* in, fftw_complex* out) { //
void hilbert(const double* in, fftw_complex* out)
{
// copy the data to the complex array
for (int i = 0; i < N; ++i) {
out[i][REAL] = in[i];
out[i][IMAG] = 0;
}
// creat a DFT plan and execute it
fftw_plan plan = fftw_plan_dft_1d(N, out, out, FFTW_FORWARD, FFTW_ESTIMATE);
fftw_execute(plan);
// destroy a plan to prevent memory leak
fftw_destroy_plan(plan);
int hN = N >> 1; // half of the length (N/2)
int numRem = hN; // the number of remaining elements
// multiply the appropriate value by 2
//(those should multiplied by 1 are left intact because they wouldn't change)
for (int i = 1; i < hN; ++i) {
out[i][REAL] *= 2;
out[i][IMAG] *= 2;
}
// if the length is even, the number of the remaining elements decrease by 1
if (N % 2 == 0)
numRem--;
else if (N > 1) {
out[hN][REAL] *= 2;
out[hN][IMAG] *= 2;
}
// set the remaining value to 0
// (multiplying by 0 gives 0, so we don't care about the multiplicands)
memset(&out[hN + 1][REAL], 0, numRem * sizeof(fftw_complex));
// creat a IDFT plan and execute it
plan = fftw_plan_dft_1d(N, out, out, FFTW_BACKWARD, FFTW_ESTIMATE);
fftw_execute(plan);
// do some cleaning
fftw_destroy_plan(plan);
fftw_cleanup();
// scale the IDFT output
for (int i = 0; i < N; ++i) {
out[i][REAL] /= N;
out[i][IMAG] /= N;
}
}
void hilbert(常数双*in,fftw\u复数*out)
{
//将数据复制到复杂数组中
对于(int i=0;i>1;//长度的一半(N/2)
int numRem=hN;//剩余元素的数量
//将适当的值乘以2
//(那些应该乘以1的值保持不变,因为它们不会改变)
对于(int i=1;i1){
out[hN][REAL]*=2;
out[hN][IMAG]*=2;
}
//将剩余值设置为0
//(乘以0等于0,所以我们不关心被乘数)
memset(&out[hN+1][REAL],0,numRem*sizeof(fftw_复合体));
//创建IDFT计划并执行
plan=fftw\U plan\U dft\U 1d(N,out,out,fftw\U向后,fftw\U估算);
fftw_执行(计划);
//打扫
fftw销毁计划(计划);
fftw_cleanup();
//缩放IDFT输出
对于(int i=0;i
我的主要计算程序是:
pi16Buffer = (int16 *)pBuffer;
//int16* ch1Buffer;
//int16* ch2Buffer;
double* ch1Buffer = NULL;
double* ch2Buffer = NULL;
fftw_complex result[N] ; // output array
// Allocate size to ch1 and ch2
ch1Buffer = (double*)calloc(u32Size, sizeof(double));
ch2Buffer = (double*)calloc(u32Size, sizeof(double));
//ch1ch2ch1ch2... fulfill the buffer
for (i = 0; i < u32Size/2; i++)
{
ch1Buffer[i] += (double)pi16Buffer[i*2];
ch2Buffer[i] += (double)pi16Buffer[i * 2 + 1];
}
// here hilbert on the whole ch2
hilbert(ch2Buffer, result); //hilbert(inputarray, outputarray)
for (i = 0; i < u32Size; i++)
{
if (ch1Buffer[i] > max1) //Find max value in each segs of ch1 and ch2
max1 = ch1Buffer[i];
if (abs(result[i]) > max2)
max2 = abs(result[i]); // Calculate the absolute value of hilbert result;
}
Corrected = max2 / max1; //do the signal correction
free(ch1Buffer); //free buffer
free(ch2Buffer);
}
return Corrected;
pi16Buffer=(int16*)pBuffer;
//int16*CH1缓冲器;
//int16*CH2缓冲器;
double*ch1Buffer=NULL;
double*ch2Buffer=NULL;
fftw_复数结果[N];//输出阵列
//将大小分配给ch1和ch2
ch1Buffer=(双*)calloc(u32Size,sizeof(双));
ch2Buffer=(双*)calloc(u32Size,sizeof(双));
//ch1ch2ch1ch2。。。完成缓冲
对于(i=0;imax1)//在ch1和ch2的每个分段中查找最大值
max1=ch1Buffer[i];
如果(abs(结果[i])>max2)
max2=abs(结果[i]);//计算希尔伯特结果的绝对值;
}
校正=最大值2/最大值1//做信号校正
免费(ch1Buffer)//自由缓冲区
免费(ch2Buffer);
}
回程修正;
我很难理解您的代码。这是我的测试代码,在一个简单的N=4情况下。
它应该至少适用于所有偶数大小的输入。要使用奇数输入进行检查 此代码计算分析信号。matlab的
hilbert
函数也有同样的作用
它的实部对应于输入的实部信号。希尔伯特变换对应于虚值 其原理是确保负频率的FFT值为零。
这是通过在频域中进行简单的加窗来实现的
#include <stdio.h>
#include <complex.h>
// Analytic signal calculation
// The real part of it corresponds to the input real signal
// The hilbert transform corresponds to the imaginary value
void print (complex *x, int n) {
for (int i = 0; i < n; ++i) {
printf ("(%lf, %lf) ", creal(x[i]), cimag(x[i]));
}
printf ("\n");
}
void fft4 (complex *x, int n, int inversion) {
complex t0, t1, t2, t3;
t0 = x[0] + x[2];
t1 = x[1] + x[3];
t2 = x[0] - x[2];
if (!inversion) t3 = I * (x[1] - x[3]);
else t3 = -I * (x[1] - x[3]);
x[0] = t0 + t1;
x[2] = t0 - t1;
x[1] = t2 - t3;
x[3] = t2 + t3;
}
#define N 4
int main() {
const int n = N;
complex x[N] = {1, 2, 3, 4};
complex y[N] = {1, 2, 3, 4};
fft4 (y, n, 0); // direct FFT size 4
print (x, n);
print (y, n);
for (int i = 1; i < n/2; ++i) y[i] *= 2.0;
for (int i = n/2+1; i < n; ++i) y[i] = 0.0;
fft4 (y, n, 1); // inverse FFT
for (int i = 0; i < n; ++i) y[i] /= n; // normalisation
print (y, n); // print analytical signal
return 0;
}
#包括
#包括
//解析信号计算
//它的实部对应于输入实信号
//希尔伯特变换对应于虚值
无效打印(复数*x,整数n){
对于(int i=0;i
如果我们看不到代码,则很难更正代码。此外,您应该使用比youtube视频更可靠的来源,例如Hi@Damien,感谢您的通知,我现在附上了我的代码。请注意,matlab函数将原始值放在实部,将Hilbert变换值放在虚部。您可以提供一个非常简单的输入(4或8个元素),以及您的输出和matlab outputHi@Damien,谢谢您的回复,但我不太明白您的想法。请你写一个例子,例如代码,以便更清楚地解释?谢谢我不使用fftw,而是使用我自己的FFT函数。我可以尝试提供一个简单DFT函数的示例。但是,我没有matlab,如果有一个好的输入/输出Hanks的例子,它会帮助我!很抱歉,我应该提供更多关于我的代码和