代码之家  ›  专栏  ›  技术社区  ›  Joe Soul-bringer

利用MATLAB中的噪声数据求一个近似的局部极大值

  •  3
  • Joe Soul-bringer  · 技术社区  · 16 年前

    matlab faq描述了一种用于查找局部最大值的单行方法:

    index = find( diff( sign( diff([0; x(:); 0]) ) ) < 0 );
    

    但我相信这只在数据或多或少平滑的情况下才有效。假设您有以小间隔上下跳跃的数据,但仍然有一些近似的局部最大值。你如何找到这些点?您可以将向量分成n个部分,找到最大值,而不是每个部分的边缘,但应该有一个更优雅、更快的解决方案。

    一线解决方案也很好。

    编辑: 我正在处理嘈杂的生物图像,我正试图将其分为不同的部分。

    4 回复  |  直到 12 年前
        1
  •  2
  •   Mr Fooz    16 年前

    根据需要,过滤噪声数据通常很有用。看一看 MEDFILT1 或使用 CONV 随着 FSPECIAL .在后一种方法中,您可能希望对conv使用“相同”参数,并使用fspecial创建的“高斯”过滤器。

    完成过滤后,通过Maxima查找器输入。

    编辑: 运行时复杂性

    假设输入向量的长度为x,过滤器内核的长度为k。

    中值过滤器可以通过执行插入排序来工作,因此它应该是O(X k+k log k)。我还没有研究过源代码和其他实现是可能的,但基本上应该是O(X K)。

    当k很小时,conv使用正向o(x*k)算法。当x和k几乎相同时,使用快速傅立叶变换会更快。该实现是O(x log x+k log k)。Matlab足够智能,可以根据输入大小自动选择正确的算法。

        2
  •  3
  •   Community CDub    8 年前

    我不知道你在处理什么类型的数据,但这里有一个方法,我已经用于处理语音数据,可以帮助你定位本地最大值。它使用信号处理工具箱中的三个功能: HILBERT , BUTTER FILTFILT .

    data = (...the waveform of noisy data...);
    Fs = (...the sampling rate of the data...);
    [b,a] = butter(5,20/(Fs/2),'low');  % Create a low-pass butterworth filter;
                                        %   adjust the values as needed.
    smoothData = filtfilt(b,a,abs(hilbert(data)));  % Apply a hilbert transform
                                                    %   and filter the data.
    

    然后你就可以在 平滑数据 . 使用hilbert首先在数据上创建一个正包络,然后filtfilt使用从butter到low-pass的过滤系数过滤数据包络。

    对于这个处理过程的一个例子,这里有一些显示录制语音片段结果的图像。蓝线是原始语音信号,红线是信封(用希尔伯特得到),绿线是低通滤波结果。下图是第一个的放大版本。

    alt text

    随机尝试:

    这是我起初的一个随机想法…您可以尝试通过找到最大值的最大值来重复这个过程:

    index = find(diff(sign(diff([0; x(:); 0]))) < 0);
    maxIndex = index(find(diff(sign(diff([0; x(index); 0]))) < 0));
    

    但是,根据信噪比的不同,不清楚需要重复多少次才能得到您感兴趣的局部最大值。这只是一个随机的非过滤选项。=)

    最大值发现:

    为了以防万一,我看到的另一个单行最大值查找算法(除了您列出的算法)是:

    index = find((x > [x(1) x(1:(end-1))]) & (x >= [x(2:end) x(end)]));
    
        3
  •  1
  •   Matthias Wandel    16 年前

    如果您的数据跳上跳下很多,那么函数将有许多局部极大值。 所以我假设你不想找到所有当地的格言。但是你的标准是什么,当地的最大值是多少?如果你有一个标准,那么你可以为它设计一个方案或者算法。

    我想现在也许你应该先对你的数据应用一个低通滤波器,然后找到局部最大值。虽然滤波后局部极大值的位置可能与滤波前的位置不完全一致。

        4
  •  1
  •   user85109    16 年前

    有两种方法来看待这样的问题。我们可以将其视为一个主要的平滑问题,使用过滤工具来平滑数据,之后才使用各种各样的插值,可能是插值样条线来插值。找到插值样条的局部最大值是一件很容易的事情。(请注意,这里通常应该使用真正的样条曲线,而不是PChip插值。pchip是在interp1中指定“三次”插值时使用的方法,它无法精确定位位于两个数据点之间的局部最小化器。)

    解决这个问题的另一种方法是我倾向于采用的方法。在这里,我们使用最小二乘样条模型来平滑数据,并生成一个近似值而不是插值值。这种最小二乘样条的优点是,用户可以通过大量的控制将他们对问题的了解引入到模型中。例如,科学家或工程师通常掌握有关所研究过程的信息,如单调性。这可以建立在最小二乘样条模型中。另一个相关选项是使用平滑样条线。它们也可以用内置的正则化约束来构建。如果您有样条线工具箱,那么SPAP2将具有一些实用程序来适合样条线模型。然后Fnmin会找到一个极小值。(从最小化代码中很容易获得最大化器。)

    当数据点间距相等时,使用过滤方法的平滑方案通常最简单。不等间距可能会推动最小二乘样条模型。另一方面,在最小二乘样条曲线中,结的放置可能是一个问题。我在所有这一切中的观点是,建议任何一种方法都有优点,并且可以产生可行的结果。