【问题标题】:Rolling median in C - Turlach implementationC - Turlach 实现中的滚动中位数
【发布时间】:2011-07-28 11:58:57
【问题描述】:

有谁知道C语言中是否有Turlach滚动中值算法的干净实现?我无法将 R 版本移植到干净的 C 版本。有关算法的更多详细信息,请参阅here

编辑: 正如darkcminor 指出的那样,matlab 有一个函数medfilt2,它调用ordf,这是一个滚动顺序统计算法的c 实现。我相信算法比 O(n^2) 快,但它不是开源的,我不想购买图像处理工具箱。

【问题讨论】:

标签: c algorithm matlab


【解决方案1】:

我已经实现了 rolling median calculator in C here (Gist)。它使用 max-median-min 堆结构:中位数位于 heap[0](位于 K-item 数组的中心)。从 heap[1] 开始有一个 minheap,在 heap[-1] 有一个 maxheap(使用负索引)。
它与Turlach implementation from the R source 不完全相同:它支持动态插入值,而 R 版本一次作用于整个缓冲区。但我相信时间复杂度是一样的。它可以很容易地用于实现整个缓冲区版本(可能会添加一些代码来处理 R 的“endrules”)

界面:

//Customize for your data Item type
typedef int Item;
#define ItemLess(a,b)  ((a)<(b))
#define ItemMean(a,b)  (((a)+(b))/2)

typedef struct Mediator_t Mediator;

//creates new Mediator: to calculate `nItems` running median. 
//mallocs single block of memory, caller must free.
Mediator* MediatorNew(int nItems);

//returns median item (or average of 2 when item count is even)
Item MediatorMedian(Mediator* m);

//Inserts item, maintains median in O(lg nItems)
void MediatorInsert(Mediator* m, Item v)
{
   int isNew = (m->ct < m->N);
   int p = m->pos[m->idx];
   Item old = m->data[m->idx];
   m->data[m->idx] = v;
   m->idx = (m->idx+1) % m->N;
   m->ct += isNew;
   if (p > 0)         //new item is in minHeap
   {  if (!isNew && ItemLess(old, v)) { minSortDown(m, p*2);  }
      else if (minSortUp(m, p)) { maxSortDown(m,-1); }
   }
   else if (p < 0)   //new item is in maxheap
   {  if (!isNew && ItemLess(v, old)) { maxSortDown(m, p*2); }
      else if (maxSortUp(m, p)) { minSortDown(m, 1); }
   }
   else            //new item is at median
   {  if (maxCt(m)) { maxSortDown(m,-1); }
      if (minCt(m)) { minSortDown(m, 1); }
   }
}

【讨论】:

  • 我可以确认这是可行的,而且速度很快。如果能够在不插入的情况下弹出元素(以容纳缺失值)并指定任意百分位数,那就太好了。不过,这些可能很容易调整。干得好!
  • 实现 PopOldest() 会很简单:堆中最旧项目的位置是 p=pos[(idx-ct+N)%N]。如果它在 minheap 中,将其交换到最后,然后进行排序以确保交换的项目在正确的位置:if (p&gt;0) {exchange(p,minCt); m-&gt;ct--; minSortDown(p*2);。否则对 maxheap 执行相同操作 - 除了处理 p==0 的特殊情况,您需要执行 maxSortDown( p*2||-1)
  • 实现“KthPercentile”会有点棘手,但还不错。对于介于 0.0 和 1.0 之间的 K,heap 将指向元素 KN。 maxCt 是 ctk,minCt 是 ct-1-maxCt。棘手的部分是初始化 pos 数组,以便正确分布初始元素。这将是这样的:对于每个 i:将 pos[i] 指向 maxheap 上的下一个元素,直到它包含到目前为止超过 K% 的项目,然后转移到 minheap。
  • 以下是一些基准测试:github.com/suomela/median-filter — 简而言之,这种方法总体上看起来效果很好,但对于某些数据分布,使用基于排序的算法可能会做得更好。跨度>
  • 感兴趣的人请注意,此代码也可以在 GNU 科学图书馆 (GSL; gnu.org/software/gsl) 的 movstat/medacc.c 中找到,并可通过 gsl_movstat_median() 界面访问。
【解决方案2】:

OpenCV 有一个medianBlur 函数,它似乎可以满足您的需求。我知道这是一个滚动中位数。我不能说它是否具体是“Turlach滚动中位数”。虽然它非常快,并且在可用时支持多线程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-13
    • 1970-01-01
    • 2010-10-14
    • 2021-11-29
    • 1970-01-01
    • 2017-04-16
    • 2011-09-29
    • 1970-01-01
    相关资源
    最近更新 更多