在 Matlab 中寻找带有噪声数据的近似局部最大值
matlab FAQ 描述了一种用于查找局部最大值的单行方法:
index = find( diff( sign( diff([0; x(:); 0]) ) ) < 0 );
但我相信这仅在数据或多或少平滑的情况下才有效。 假设您的数据以小间隔上下跳跃,但仍然具有一些近似的局部最大值。 您将如何找到这些点? 您可以将向量分成 n 部分,并找到不在每个部分边缘的最大值,但应该有一个更优雅和更快的解决方案。
单行解决方案也很棒。
编辑:我正在处理嘈杂的生物图像,我试图将其分成不同的部分。
The matlab FAQ describes a one-line method for finding the local maximas:
index = find( diff( sign( diff([0; x(:); 0]) ) ) < 0 );
But I believe this only works if the data is more or less smooth. Suppose you have data that jumps up and down in small intervals but still has some approximate local maximas. How would you go about finding these points? You could divide the vector into n pieces and find the largest value not on the edge of each but there should be a more elegant and faster solution.
A one-line solution would be great, too.
Edit: I'm working with noisy biological images which I am attempting to divide into distinct sections.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我不确定您正在处理什么类型的数据,但这是我用来处理语音数据的方法,可以帮助您找到局部最大值。 它使用信号处理工具箱中的三个函数: HILBERT、黄油 和 FILTFILT。
然后,您将在 smoothData 上执行最大值查找。 使用 HILBERT 首先在数据上创建正包络,然后 FILTFILT 使用 BUTTER 中的滤波器系数对数据包络进行低通滤波。
有关此处理如何工作的示例,下面是一些显示录制语音片段结果的图像。 蓝线是原始语音信号,红线是包络(使用HILBERT得到),绿线是低通滤波结果。 下图是第一张图的放大版本。
随机尝试:
这是我的一个随机想法起初...您可以尝试通过找到最大值中的最大值来重复该过程:
但是,根据信噪比,不清楚需要重复多少次才能获得局部最大值您感兴趣。这只是一个可以尝试的随机非过滤选项。 =)
最大值查找:
以防万一您好奇,我见过的另一种单行最大值查找算法(除了您列出的算法之外)是:
I'm not sure what type of data you're dealing with, but here's a method I've used for processing speech data that could help you locate local maxima. It uses three functions from the Signal Processing Toolbox: HILBERT, BUTTER, and FILTFILT.
You would then perform your maxima finding on smoothData. The use of HILBERT first creates a positive envelope on the data, then FILTFILT uses the filter coefficients from BUTTER to low-pass filter the data envelope.
For an example of how this processing works, here are some images showing the results for a segment of recorded speech. The blue line is the original speech signal, the red line is the envelope (gotten using HILBERT), and the green line is the low-pass filtered result. The bottom figure is a zoomed in version of the first.
SOMETHING RANDOM TO TRY:
This was a random idea I had at first... you could try repeating the process by finding the maximas of the maximas:
However, depending on the signal-to-noise ratio, it would be unclear how many times this would need to be repeated to get the local maxima you are interested in. It's just a random non-filtering option to try. =)
MAXIMA FINDING:
Just in case you're curious, another one-line maxima-finding algorithm that I've seen (in addition to the one you listed) is:
根据您的需要,过滤噪声数据通常很有帮助。 查看 MEDFILT1,或使用 CONV 以及 FSPECIAL。 在后一种方法中,您可能希望使用 CONV 的“相同”参数和 FSPECIAL 创建的“高斯”滤波器。
完成过滤后,将其输入最大值查找器。
编辑:运行时复杂度
假设输入向量的长度为X,滤波器内核的长度为K。
中值滤波器可以通过运行插入排序来工作,所以它应该是O(XK + K log K)。 我没有看过源代码,其他实现也是可以的,但基本上应该是O(XK)。
当 K 很小时,conv 使用直接的 O(X*K) 算法。 当 X 和 K 几乎相同时,使用快速傅里叶变换会更快。 该实现是 O(X log X + K log K)。 Matlab 足够智能,可以根据输入大小自动选择正确的算法。
Depending on what you want, it's often helpful to filter the noisy data. Take a look at MEDFILT1, or using CONV along with FSPECIAL. In the latter approach, you'll probably want to use the 'same' argument to CONV and a 'gaussian' filter created by FSPECIAL.
After you've done the filtering, feed it through the maxima finder.
EDIT: runtime complexity
Let's say the input vector has length X and the filter kernel length is K.
The median filter can work by doing a running insertion sort, so it should be O(XK + K log K). I have not looked at the source code and other implementations are possible, but basically it should be O(XK).
When K is small, conv uses a straight-forward O(X*K) algorithm. When X and K are nearly the same, then it's faster to use a fast fourier transform. That implementation is O(X log X + K log K). Matlab is smart enough to automatically choose the right algorithm depending on the input sizes.
如果您的数据上下跳跃很多,那么该函数将有许多局部最大值。
所以我假设您不想找到所有局部最大值。 但是局部最大值的标准是什么? 如果您有一个标准,那么人们可以为此设计一种方案或算法。
我现在猜想也许您应该首先对数据应用低通滤波器,然后找到局部最大值。 尽管滤波后的局部最大值的位置可能与滤波前的位置不完全对应。
If your data jumps up and down a lot, then the function will have many local maxima.
So I'm assuming that you don't want to find all the local maxima. But what is your criteria for what a local maximum is? If you have a criteria, then one can design a schem or algorithm for that.
I'd guess right now that maybe you should apply a low-pass filter to your data first, and then find the local maxima. Although the positions of the local maxima after filtering may not exactly correspond to those before.
有两种方法来看待这样的问题。 人们可以将其视为主要的平滑问题,使用过滤工具平滑数据,然后使用某种插值器(可能是插值样条)进行插值。 找到插值样条线的局部最大值是一件很容易的事情。 (请注意,您通常应该在此处使用真正的样条曲线,而不是 pchip 插值。Pchip 是您在 interp1 中指定“三次”插值时使用的方法,不会准确定位落在两个数据点之间的局部最小化器。
)解决此类问题的方法是我更喜欢的方法。 这里使用最小二乘样条模型来平滑数据并生成近似值而不是插值值。 这种最小二乘样条的优点是允许用户进行大量控制以将他们对问题的了解引入到模型中。 例如,科学家或工程师通常拥有有关所研究过程的信息,例如单调性。 这可以构建到最小二乘样条模型中。 另一个相关选项是使用平滑样条线。 它们也可以通过内置的正则化约束来构建。 如果您有样条线工具箱,那么 spap2 将具有一定的实用性来拟合样条线模型。 然后 fnmin 会找到一个最小化器。 (从最小化代码可以轻松获得最大化器。)
当数据点等距时,采用过滤方法的平滑方案通常是最简单的。 不等间距可能会推动最小二乘样条模型。 另一方面,结的放置可能是最小二乘样条中的一个问题。 我在这一切中的观点是建议这两种方法都有其优点,并且可以产生可行的结果。
There are two ways to view such a problem. One can look at this as primarily a smoothing problem, using a filtering tool to smooth the data, only afterwards to interpolate using some variety of interpolant, perhaps an interpolating spline. Finding a local maximum of an interpolating spline is an easy enough thing. (Note that you should generally use a true spline here, not a pchip interpolant. Pchip, the method employed when you specify a "cubic" interpolant in interp1, will not accurately locate a local minimizer that falls between two data points.)
The other approach to such a problem is one that I tend to prefer. Here one uses a least squares spline model to both smooth the data and to produce an approximant instead of an interpolant. Such a least squares spline has the advantage of allowing the user a great deal of control to introduce their knowledge of the problem into the model. For example, often the scientist or engineer has information, such as monotonicity, about the process under study. This can be built into a least squares spline model. Another, related option is to use a smoothing spline. They too can be built with regularizing constraints built into them. If you have the spline toolbox, then spap2 will be of some utility to fit a spline model. Then fnmin will find a minimizer. (A maximizer is easily obtained from a minimization code.)
Smoothing schemes that employ filtering methods are generally simplest when the data points are equally spaced. Unequal spacing might push for the least squares spline model. On the other hand, knot placement can be an issue in least squares splines. My point in all of this is to suggest that either approach has merit, and can be made to produce viable results.