Python代码如下

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt # 读取数据
data = pd.read_csv('clean_data_row.csv')
# 进行傅里叶变换
fft_result = np.fft.fft(data)
frequencies = np.fft.fftfreq(len(data)) # 计算功率谱密度
power_spectrum = np.abs(fft_result)**2 / len(data)
print(len(power_spectrum))
frequencies_positive = frequencies[:len(frequencies)//2] # 绘制频谱图和功率谱密度图
# 频谱图
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.plot(frequencies, np.abs(fft_result))
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
plt.title('Frequency Spectrum')
# 功率谱密度图
plt.subplot(1, 2, 2)
plt.plot(frequencies_positive, power_spectrum[:len(power_spectrum)//2])
plt.xlabel('Frequency (Hz)')
plt.ylabel('Power')
plt.title('Power Spectrum Density') plt.tight_layout()
plt.show()

下面我们修改成C#代码

创建控制台程序,Nuget安装 CsvHelper 和 pythonnet

public class Program
{
const string PathToPythonDir = "D:\\Python311";
const string DllOfPython = "python311.dll"; static void Main(string[] args)
{
// 傅里叶变换
FFT();
}
/// <summary>
/// 傅里叶变换
/// </summary>
static void FFT()
{
try
{
Runtime.PythonDLL = Path.Combine(PathToPythonDir, DllOfPython);
PythonEngine.Initialize();
using (Py.GIL())
{
dynamic pd = Py.Import("pandas");
dynamic np = Py.Import("numpy");
dynamic plt = Py.Import("matplotlib.pyplot");
dynamic fft = Py.Import("scipy.fftpack"); using dynamic scope = Py.CreateScope();
scope.Exec(@"def get_slice(net_array): return net_array[:len(net_array)//2]"); // 读取数据
var data = pd.read_csv("clean_data_row.csv");
int listLength = data.__len__();
Console.WriteLine("读取长度:" + listLength); // 进行傅里叶变换
var fft_result = fft.fft(data); // 对数据进行傅里叶变换
var frequencies = fft.fftfreq(listLength); // 计算功率谱密度
var power_spectrum = np.square(np.abs(fft_result)) / listLength;
var frequencies_positive = scope.get_slice(frequencies); /*
// 如果是api接口,直接返回x轴和y轴数据
double[] xAxis = frequencies.As<double[]>();
PyObject yAxisDatas = np.abs(fft_result);
double[][] yAxis = yAxisDatas.As<dynamic[]>()
.Select(s => (double[])s.As<double[]>())
.ToArray(); double[] xAxis2 = xAxis.Take(listLength / 2).ToArray();
PyObject yAxisDatas2 = power_spectrum;
double[][] yAxis2 = yAxisDatas2.As<dynamic[]>()
.Select(s => (double[])s.As<double[]>())
.Take(listLength / 2)
.ToArray();
*/ // 绘制频谱图和功率谱密度图
plt.figure(figsize: new dynamic[] { 12, 6 }); // 频谱图
plt.subplot(1, 2, 1);
plt.plot(frequencies, np.abs(fft_result));
plt.xlabel("Frequency (Hz)");
plt.ylabel("Amplitude");
plt.title("Frequency Spectrum"); // 功率谱密度图
plt.subplot(1, 2, 2);
plt.plot(frequencies_positive, scope.get_slice(power_spectrum));
plt.xlabel("Frequency (Hz)");
plt.ylabel("Power");
plt.title("Power Spectrum Density"); // 布局调整,防止重叠
plt.tight_layout();
// 显示图表
plt.show();
}
}
catch (Exception e)
{
Console.WriteLine("报错了:" + e.Message + "\r\n" + e.StackTrace);
}
} /// <summary>
/// 读取CSV数据
/// </summary>
/// <param name="filePath">文件路径</param>
/// <returns>文件中数据集合,都是double类型</returns>
static List<double[]> ReadCsvWithCsvHelper(string filePath)
{
using (var reader = new StreamReader(filePath))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
var result = new List<double[]>();
// 如果你的CSV文件有标题行,可以调用ReadHeader来读取它们
csv.Read();
csv.ReadHeader();
while (csv.Read())
{
result.Add(new double[] {
csv.GetField<double>(0),
csv.GetField<double>(1),
csv.GetField<double>(2),
});
}
return result;
}
}
}

以下是运行后结果,

源代码:https://gitee.com/Karl_Albright/csharp-demo/tree/master/PythonnetDemo/PythonnetFFT

这里有人会问,为什么不用 MathNet.Numerics 直接计算,因为计算结果和Python的结果差别太大了,希望有知道为什么的大佬留言,这里我也记录以下实现步骤

创建Windows 窗体应用(WinForm),Nuget安装 CsvHelper、MathNet.Numerics、OxyPlot.Core、OxyPlot.WindowsForms

public partial class Form1 : Form
{
double[] xAxis = new double[0];
double[][] yAxis = new double[0][];
double[] xAxis2 = new double[0];
double[][] yAxis2 = new double[0][];
public Form1()
{
InitializeComponent(); var datas = ReadCsvWithCsvHelper("clean_data_row.csv");
CalcFFT(datas);
DrawPlot();
}
OxyColor[] colors =
[
OxyColors.Blue,
OxyColors.Yellow,
OxyColors.Red,
OxyColors.Green,
OxyColors.Pink,
OxyColors.Black,
OxyColors.Orange,
];
public List<double[]> ReadCsvWithCsvHelper(string filePath)
{
using (var reader = new StreamReader(filePath))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
var result = new List<double[]>();
// 如果你的CSV文件有标题行,可以调用ReadHeader来读取它们
csv.Read();
csv.ReadHeader();
while (csv.Read())
{
result.Add([
csv.GetField<double>(0),
csv.GetField<double>(1),
csv.GetField<double>(2),
]);
}
return result;
}
} public void CalcFFT(List<double[]> datas)
{
var first = datas.First();
yAxis = new double[first.Length][];
yAxis2 = new double[first.Length][];
for (int i = 0; i < first.Length; i++)
{
// 将数据转换为Complex32数组以便进行傅里叶变换
Complex32[] dataComplex = datas.Select(item => new Complex32((float)item[i], 0)).ToArray(); // 进行傅里叶变换
Fourier.Forward(dataComplex, FourierOptions.AsymmetricScaling); var len = dataComplex.Length;
// 计算频率
double[] frequencies = Fourier.FrequencyScale(len, 1); xAxis = frequencies;
yAxis[i] = dataComplex.Select(x => Math.Abs(Math.Round(x.Magnitude, 7))).ToArray(); xAxis2 = frequencies.Take(len / 2).ToArray();
yAxis2[i] = dataComplex.Select(x => Math.Abs(Math.Round((x.Magnitude * x.Magnitude / len), 7))).Take(len / 2).ToArray();
} } public void DrawPlot()
{
// 绘制频谱图和功率谱密度图(这里使用OxyPlot库)
var plotModel = new PlotModel { Title = "Spectrum Analysis" }; // 频谱图
int xAxisLength = xAxis.Length;
int yAxisLength = yAxis.Length; for (int i = 0; i < yAxisLength; i++)
{
var frequencySeries = new LineSeries
{
Title = "Item" + (i + 1),
MarkerType = MarkerType.None,
Color = colors[i]
};
for (int j = 0; j < xAxisLength; j++)
{
frequencySeries.Points.Add(new DataPoint(xAxis[j], yAxis[i][j]));
}
plotModel.Series.Add(frequencySeries);
}
plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = "Frequency (Hz)" });
plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Title = "Amplitude" });
this.plotView1.Model = plotModel; var plotModel2 = new PlotModel { Title = "Power Spectrum Density" };

// 功率谱密度图
int xAxis2Length = xAxis2.Length;
int yAxis2Length = yAxis2.Length; for (int i = 0; i < yAxis2Length; i++)
{
var powerSeries = new LineSeries
{
Title = "Item" + (i + 1),
MarkerType = MarkerType.None,
Color = colors[i]
};
for (int j = 0; j < xAxis2Length; j++)
{
powerSeries.Points.Add(new DataPoint(xAxis2[j], yAxis2[i][j]));
}
plotModel2.Series.Add(powerSeries);
} plotModel2.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = "Frequency (Hz)" });
plotModel2.Axes.Add(new LinearAxis { Position = AxisPosition.Right, Title = "Power" });
this.plotView2.Model = plotModel2;
}
}

源代码:https://gitee.com/Karl_Albright/csharp-demo/tree/master/PythonnetDemo/PythonnetFFTWinFormsApp

C# pythonnet(2)_FFT傅里叶变换的更多相关文章

  1. 基于傅里叶变换和PyQt4开发一个简单的频率计数器

    小学期的<信号与系统>课,要求写一个频率计数器,下面是我个人理解的频率计数 傅里叶变换的代码: # coding=utf-8 import numpy as np from scipy.i ...

  2. 数字信号处理--Z变换,傅里叶变换,拉普拉斯变换

    傅立叶变换.拉普拉斯变换.Z变换最全攻略 作者:时间:2015-07-19来源:网络       傅立叶变换.拉普拉斯变换.Z变换的联系?他们的本质和区别是什么?为什么要进行这些变换.研究的都是什么? ...

  3. OpenCV基于傅里叶变换进行文本的旋转校正

    傅里叶变换可以用于将图像从时域转换到频域,对于分行的文本,其频率谱上一定会有一定的特征,当图像旋转时,其频谱也会同步旋转,因此找出这个特征的倾角,就可以将图像旋转校正回去. 先来对原始图像进行一下傅里 ...

  4. 傅里叶变换库FFTW的安装配置(VS2010)

    FFTW是用来计算一维或者多维的离散傅里叶变换,输入可以为实数序列也可以为复数序列的C语言的子函数库,FFTW是免费软件,是作为fft函数库的各种应用的上佳选择. 1. 从网站http://www.f ...

  5. FFT教你做乘法(FFT傅里叶变换)

    题目来源:https://biancheng.love/contest/41/problem/C/index FFT教你做乘法 题目描述 给定两个8进制正整数A和B(A和B均小于10000位),请利用 ...

  6. 傅里叶变换:MP3、JPEG和Siri背后的数学

    九年前,当我还坐在学校的物理数学课的课堂里时,我的老师为我们讲授了一种新方法,给我留下了深刻映像.我认为,毫不夸张地说,这是对数学理论发现最广泛的应用.应用的领域包括:量子物理.射电天文学.MP3和J ...

  7. 完全搞懂傅里叶变换和小波(2)——三个中值定理<转载>

    书接上文,本文章是该系列的第二篇,按照总纲中给出的框架,本节介绍三个中值定理,包括它们的证明及几何意义.这三个中值定理是高等数学中非常基础的部分,如果读者对于高数的内容已经非常了解,大可跳过此部分.当 ...

  8. 完全搞懂傅里叶变换和小波(1)——总纲<转载>

    无论是学习信号处理,还是做图像.音视频处理方面的研究,你永远避不开的一个内容,就是傅里叶变换和小波.但是这两个东西其实并不容易弄懂,或者说其实是非常抽象和晦涩的! 完全搞懂傅里叶变换和小波,你至少需要 ...

  9. 【DWT笔记】傅里叶变换与小波变换

    [DWT笔记]傅里叶变换与小波变换 一.前言 我们经常接触到的信号,正弦信号,余弦信号,甚至是复杂的心电图.脑电图.地震波信号都是时域上的信号,我们也成为原始信号,但是通常情况下,我们在原始信号中得到 ...

  10. 【转】傅里叶变换 拉普拉斯变 z变换 DFT DCT意义

    傅里叶变换在物理学.数论.组合数学.信号处理.概率论.统计学.密码学.声学.光学.海洋学.结构动力学等领域都有着广泛的应用(例如在信号处理中,傅里叶变换的典型用途是将信号分解成幅值分量和频率分量). ...

随机推荐

  1. 大模型_2.2:Prompt示例

    1.行业洞察分析 行业洞察分析的方法论:使用麦肯锡工作法可以快速了解一个行业. Step1:通过搜索分析几十个与该行业相关的关键词,覆盖该行业的上下游,以获取全面的信息. Step2:阅读一些行业最新 ...

  2. 分享一张2020年用jaegertracing画的tomcat8.5启动流程图

    今天整理电脑的时候意外发现一张tomcat8.5的启动流程图,是笔者2020年借助jaegertracing绘制的,想想还比较有意思,在这里分享一下,当初闲来无事折腾了小半天,具体过程已经是记不起来了 ...

  3. 【源码研读】MLIR Dialect 分层设计

    以「疑问 - 求解」的形式来组织调研,此处记录整个过程. 1. MLIR 中的 Dialect 是「分层」设计的么? 先问是不是,再谈为什么.从 LLVM 社区 可以看出,至少在做 Codegen 时 ...

  4. 数据转换2-无人机航拍倾斜摄影转换成OSGB格式

    首先软件的下载和安装参考下面链接 http://www.xue51.com/soft/53013.html 0.首先打开软件,要打开2个哦. 打数据处理开后台 ContextCapture Engin ...

  5. c 语言不输出空数据 (全面覆盖)

    目录 去除空值的专栏 解决方案 一.通过数组的自身性质,让其值大于零 1. short 数组测试 2. int 数组测试 3. long 数组测试 4. float 数组测试 5. float 数组测 ...

  6. CICD详解之gitlab,Jenkins

    持续集成概念 持续集成Continuous Integration 持续交付Continuous Delivery 持续部署Continuous Deployment 什么是持续集成: 持续集成是指开 ...

  7. efcore如何优雅的实现按年分库按月分表

    efcore如何优雅的实现按年分库按月分表 介绍 本文ShardinfCore版本 本期主角: ShardingCore 一款ef-core下高性能.轻量级针对分表分库读写分离的解决方案,具有零依赖. ...

  8. TypingLearn解决了我在学习英语中的一大痛点

    上一次在博客园发贴还是在上一次(2021年),那个时候博客园就遇到了危机(被罚款).彼时在疫情期间,我个人生活也受到了影响,先后去了多个城市,最终在上海找到了 .NET Web开发的岗位,还是比较幸运 ...

  9. winfrom 程序自己删除自己

    [DllImport("kernel32.dll")] public static extern uint WinExec(string lpCmdLine, uint uCmdS ...

  10. windows安装mysql8(5分钟)

    1.下载 MySQL https://dev.mysql.com/downloads/mysql/ 下载完成后,解压缩到你的目录里. 2.配置 MySQL 的配置文件 创建一个文件,名称为:my.in ...