我正在研究一种算法来查找 List 对象中的峰值。我想出了一个我认为很好(或足够好)的算法,通过查看一个点及其邻居,如果它是一个峰值,则将其添加到结果列表中。然而,鉴于最近的一些结果,我认为这种方法并不像我最初希望的那样有效。(我已经包含了我目前正在使用的代码,并希望在下面替换)。我以前用 LabView 做过一些工作,我知道他们的模块查找峰/谷的方式适用于我需要做的事情。我对 LabView 如何做到这一点进行了一些研究,并发现了这一点:
“这个峰值检测器 VI 基于一种算法,该算法将二次多项式拟合到连续的数据点组。拟合中使用的数据点的数量由宽度指定。
对于每个峰或谷,根据阈值测试二次拟合。高度低于阈值的峰或谷值高于阈值的谷将被忽略。只有在 VI 处理超出峰或谷位置的大约宽度/2 个数据点后,才能检测到峰和谷。这种延迟仅对实时处理有影响。”
好的,所以现在我一直在尝试在 C# 中做类似的事情,但是,在我所有的搜索中,似乎将二次多项式拟合到数据中肯定不是微不足道的。我认为这个问题会被探索很多很多次,但我一直没有成功地获得一个很好的算法或找到一个库来做这件事。
非常感谢您对此问题的任何帮助。谢谢。
原始/当前代码:
public static List<double> FindPeaks(List<double> values, double rangeOfPeaks)
{
List<double> peaks = new List<double>();
int checksOnEachSide = (int)Math.Floor(rangeOfPeaks / 2);
for (int i = checksOnEachSide; i < values.Count - checksOnEachSide; i++)
{
double current = values[i];
IEnumerable<double> window = values;
if (i > checksOnEachSide)
window = window.Skip(i - checksOnEachSide);
window = window.Take((int)rangeOfPeaks);
if (current == window.Max())
peaks.Add(current);
}
return peaks;
}