使用scipygeneric_filter和numpy平均数滤波器计算移动中值会给出不同的输出 [英] Computing moving median with scipy generic_filter and numpy median_filter gives different outputs

查看:656
本文介绍了使用scipygeneric_filter和numpy平均数滤波器计算移动中值会给出不同的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻求实现快速中位数,因为我必须为我的程序做很多中位数.我想使用python内置函数,因为它们会比我能做的更好.

I am looking to implement a fast moving median as I have to do a lot of medians for my program. I would like to use python builtins functions as they would be more optimized than what I could do.

我的中位数应该是: -提取5个值, -拆下中间一个, -找到其余4个值的中位数.

My median should do : - extract 5 values, - remove the center one, - find the median of the remaining 4 values.

基本上多次调用:

numpy.median(np.array([0, 1, 2, 3, 4])[np.array([True, True, False, True, True])])
# (1. + 3.) / 2. = 2.0

我发现了两个函数:scipygeneric_filter和numpy位数_filter.我的问题是,即使它们似乎具有相同的参数,generic_filter也会提供正确的输出,而不是位数_filter.此外,generic_filter比中位数_filter慢.因此,我想知道我在对middle_filter的调用中做错了什么,并将其用于速度目的.

I have found two functions : scipy generic_filter and numpy median_filter. My problem is that generic_filter gives the right output, and not median_filter, even though they seem to have the same parameters. Moreover, generic_filter is slower than median_filter. So I would like to know what I am doing wrong in my call to median_filter and use this one for speed purpose.

import numpy as np
import scipy.ndimage as sc

v = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

print(sc.generic_filter(v, sc.median, footprint=np.array([1, 1, 0, 1, 1]), mode = "mirror", output=np.float64))
%timeit sc.generic_filter(v, sc.median, footprint=np.array([1, 1, 0, 1, 1]), mode = "mirror", output=np.float64)

print(sc.median_filter(v, footprint=np.array([1, 1, 0, 1, 1]), output=np.float64, mode="mirror"))
%timeit sc.median_filter(v, footprint=np.array([1, 1, 0, 1, 1]), output=np.float64, mode="mirror")

如您所见,generic_filter提供了正确的输出: [1.5 1.5 2. 3. 4. 5. 6. 6. 7. 8. 8.5 8.5] 每个回路327 µs±15.2 µs(平均±标准偏差,共运行7次,每个回路1000个)

As you can see, generic_filter gives the right output : [1.5 1.5 2. 3. 4. 5. 6. 7. 8. 8.5 8.5] 327 µs ± 15.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

和mid_filter更快,但是我不明白它的输出: [2. 2. 3. 4. 5. 6. 7. 7. 8. 9. 9. 9.] 每个循环12.4 µs±217 ns(平均±标准偏差,共运行7次,每个循环100000次)

and median_filter is faster but I don't understand its output : [2. 2. 3. 4. 5. 6. 7. 8. 9. 9. 9.] 12.4 µs ± 217 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

你知道我的电话怎么了吗?

Do you know what is wrong with my call ?

推荐答案

唯一的区别似乎是由于如何处理联系":

the only difference seems to be due to how "ties" are handled:

  • sc.median返回联系的均值
  • sc.median_filter似乎系统地返回了较大的值
  • sc.median returns the mean of ties
  • sc.median_filter seems to systematically return the larger value

按照 已实施对于偶数个元素的中位数应返回均值"的情况,处理特殊/特殊情况很尴尬

given the way median_filter is implemented it's awkward to handle the special/specific for the case of "medians over an even number of elements should return the mean of ties" efficiently

我已经破解了处理这种情况的版本:

I've hacked together a version that handles this case:

from scipy.ndimage.filters import _rank_filter

def median_filter(input, footprint, output=None, mode="reflect", cval=0.0, origin=0):
    filter_size = np.where(footprint, 1, 0).sum()
    rank = filter_size // 2
    result = _rank_filter(
        input, rank, None, footprint, output, mode, cval, origin, 'dummy')
    if filter_size % 2 == 0:
        if result is output:
            tmp = result.copy()
        else:
            tmp = result
        rank -= 1
        assert rank > 0
        result = _rank_filter(
            input, rank, None, footprint, output, mode, cval, origin, 'dummy')
        # fix up ties without creating any more garbage
        result += tmp
        result /= 2
    return result

但是它有点笨拙,并且使用了scipy的内部功能(我使用的是1.3.0),因此将来可能会崩溃

but it's kind of clunky, and uses internal functionality from scipy (I'm using 1.3.0) so is likely to break in the future

在我的计算机上,这些基准为:

on my machine these benchmark as:

  • sc.generic_filter每个循环耗时578 µs±8.51 µs
  • sc.median_filter每个循环耗时27.4 µs±1.37 µs
  • 我的median_filter每个循环耗时65.6 µs±1.29 µs
  • sc.generic_filter takes 578 µs ± 8.51 µs per loop
  • sc.median_filter takes 27.4 µs ± 1.37 µs per loop
  • my median_filter takes 65.6 µs ± 1.29 µs per loop

这篇关于使用scipygeneric_filter和numpy平均数滤波器计算移动中值会给出不同的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆