C # - Поиск пиков в пределах заданной ширины с помощью квадратичной подгонки

Я работаю над алгоритмом поиска пиков в объекте List. Я придумал, что я считал хорошим (или достаточно хорошим) алгоритмом для этого, глядя на точку и ее соседей и, если это был пик, добавлял ее в список результатов. Однако, учитывая некоторые недавние результаты, я не думаю, что этот метод работает так хорошо, как я изначально надеялся. (Я включил код, который использую в настоящее время и надеюсь заменить, ниже). Раньше я немного поработал с LabView и знаю, что способ, которым их модуль находит пики / спады, подходит для того, что мне нужно. Я провел небольшое исследование того, как LabView делает это, и обнаружил следующее:

Этот ВП Peak Detector основан на алгоритме, который подбирает квадратичный полином для последовательных групп точек данных. Количество точек данных, используемых при подгонке, определяется шириной.

Для каждого пика или впадины квадратичное соответствие проверяется относительно порогового значения. Пики с высотой ниже порогового значения или впадины с впадинами выше порогового значения игнорируются. Пики и впадины обнаруживаются только после того, как 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;
}

person JToland    schedule 14.03.2011    source источник


Ответы (1)


Я использовал Math.NET для подобных операций с матрицами в C #. В нем есть все инструменты, которые могут вам понадобиться для решения задач наименьших квадратов, таких как QR-разложение или SVD. Для общего обзора того, как их применять, я думаю, что wikipedia неплохо справляется. .

person Tom Makin    schedule 30.09.2012