【问题标题】:Moving median in MATLAB prior to R2016a在 R2016a 之前的 MATLAB 中移动中位数
【发布时间】:2016-07-05 18:01:09
【问题描述】:

在 MATLAB R2016a 中引入了函数 movmedian,但我有一个旧版本。

有谁知道如何在不使用循环的情况下执行与此函数类似的操作?我需要多次调用这个函数,速度很重要。

基本上,我有一个 1000×1 向量X,我想要另一个向量,其中每个元素都等于
Y(i)= median(X((i-50):(i+50)))。如果我使用循环,我可以这样做:

X=rand(1000,1);
Y=zeros(1000,1);

    for i=1:1000
        if i>=51
            start=i-50;
        else
            start=1;
        end
        if i<=950
            end1=i+50;
        else
            end1=1000;
        end
        Y(i)= median(X(start:end1));
    end

但是我将在每次迭代中调用这个循环 1,000 到 100,000 次,其中 X 改变内容(但不是大小),我想看看是否有更快的方法可以做。

我尝试了 medfilt1,它工作得很好,除了我需要截断的系列,当我使用命令时:medfilt1(X,101, 'truncate') 我得到错误'输入参数必须是'双'。即使X是双班!我什至在Matlab webpage for this command 中运行了确切的示例并得到了同样的错误。知道这是怎么回事吗?我试过了,得到了同样的错误:medfilt1(double(X),101, 'truncate')

谢谢!

【问题讨论】:

  • 您是否有测试来支持您的断言,即循环是您算法中的限制因素?
  • 我可能遗漏了一些东西,但median(X(i-50):X(i+50))median(X(i-1):X(i+1) 不一样吗?
  • 循环比其他函数慢很大程度上取决于 MATLAB 版本和函数的编写方式。我建议你创建一些可以运行的东西,然后再担心优化。
  • 太好了,回到我最初的问题,你是否有测试来支持你的断言,即循环是你算法中的限制因素?你目前的算法是什么? Where are the "slowdowns"?
  • 如果你有信号处理工具箱,你可以使用medfilt1。否则,如果您有图像处理工具箱,则可以使用 medfilt2 并选择邻域高度 1。第三种方法是使用 gallery('circul',X),选择适当的列,然后取行的中值。一个更有趣的方法是实现一个专门的移动窗口插入排序。

标签: matlab median


【解决方案1】:

您可以改用medfilt1...

例如,假设我有一个向量 X,那么:

  Xm=medfilt1(X,101);

这里不需要 for 循环...在我的旧笔记本电脑中,使用 timeit 需要 1000 长度的向量大约 6e-4 秒:

f=@() medfilt1(X,101);
timeit(f)

这意味着 1e5 次将需要大约 60 秒。

【讨论】:

  • 谢谢布拉,我很感激。我添加了关于 medfilt1 问题的编辑。
  • 您能否给添加一个演示您的问题的最小代码(X 有多大等)
  • 我在帖子中的代码显示了一个非常接近的示例。向量 X 有大约 1000 个元素,我将调用此函数 1,000 到 100,000 次。
  • 对于 100000 个不同的 X 向量?
  • 是的,X 向量在每次迭代时都会改变,但大小保持不变。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-27
  • 1970-01-01
  • 2014-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多