简体   繁体   English

具有多维(或非标量)输出的Scipy滤波器

[英]Scipy filter with multi-dimensional (or non-scalar) output

Is there a filter similar to ndimage 's generic_filter that supports vector output? 是否有类似于ndimagegeneric_filter的过滤器支持向量输出? I did not manage to make scipy.ndimage.filters.generic_filter return more than a scalar. 我没有设法使scipy.ndimage.filters.generic_filter返回超过标量。 Uncomment the line in the code below to get the error: TypeError: only length-1 arrays can be converted to Python scalars . 取消注释下面代码中的行以获取错误: TypeError: only length-1 arrays can be converted to Python scalars

I'm looking for a generic filter that process 2D or 3D arrays and returns a vector at each point. 我正在寻找一个处理2D或3D数组的通用过滤器,并在每个点返回一个向量。 Thus the output would have one added dimension. 因此,输出将具有一个附加维度。 For the example below I'd expect something like this: 对于下面的例子,我希望这样的事情:

m.shape    # (10,10)
res.shape  # (10,10,2)

Example Code 示例代码

import numpy as np
from scipy import ndimage

a = np.ones((10, 10)) * np.arange(10)

footprint = np.array([[1,1,1],
                    [1,0,1],
                    [1,1,1]])

def myfunc(x):
    r = sum(x)
    #r = np.array([1,1])  # uncomment this
    return r

res = ndimage.generic_filter(a, myfunc, footprint=footprint)

The generic_filter expects myfunc to return a scalar, never a vector. generic_filter期望myfunc返回一个标量,而不是一个向量。 However, there is nothing that precludes myfunc from also adding information to, say, a list which is passed to myfunc as an extra argument. 但是,没有任何东西阻止myfunc 将信息添加到例如作为额外参数传递给myfunc的列表中。

Instead of using the array returned by generic_filter , we can generate our vector-valued array by reshaping this list. 我们可以通过重新整理此列表来生成矢量值数组,而不是使用generic_filter返回的数组。


For example, 例如,

import numpy as np
from scipy import ndimage

a = np.ones((10, 10)) * np.arange(10)

footprint = np.array([[1,1,1],
                      [1,0,1],
                      [1,1,1]])

ndim = 2
def myfunc(x, out):
    r = np.arange(ndim, dtype='float64')
    out.extend(r)
    return 0

result = []
ndimage.generic_filter(
    a, myfunc, footprint=footprint, extra_arguments=(result,))
result = np.array(result).reshape(a.shape+(ndim,))

I think I get what you're asking, but I'm not completely sure how does the ndimage.generic_filter work (how abstruse is the source!). 我想我得到了你所要求的,但我不完全确定ndimage.generic_filter是如何工作的(源代码有多深奥!)。

Here's just a simple wrapper function. 这里只是一个简单的包装函数。 This function will take in an array, all the parameters ndimage.generic_filter needs. 这个函数将接受一个数组, ndimage.generic_filter需要的所有参数。 Function returns an array where each element of the former array is now represented by an array with shape (2,), result of the function is stored as the second element of that array. 函数返回一个数组,其中前一个数组的每个元素现在由一个形状为(2,)的数组表示,函数的结果存储为该数组的第二个元素。

def generic_expand_filter(inarr, func, **kwargs):
    shape = inarr.shape
    res = np.empty((  shape+(2,) ))
    temp = ndimage.generic_filter(inarr, func, **kwargs)
    for row in range(shape[0]):
        for val in range(shape[1]):
            res[row][val][0] = inarr[row][val]
            res[row][val][1] = temp[row][val]
    return res

Output, where res denotes just the generic_filter and res2 denotes generic_expand_filter , of this function is: 输出,其中res表示generic_filter ,res2表示generic_expand_filter ,此函数是:

>>> a.shape #same as res.shape
(10, 10)
>>> res2.shape
(10, 10, 2)

>>> a[0]
array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])
>>> res[0]
array([  3.,   8.,  16.,  24.,  32.,  40.,  48.,  56.,  64.,  69.])
>>> print(*res2[0], sep=", ") #this is just to avoid the vertical default output
[ 0.  3.], [ 1.  8.], [  2.  16.], [  3.  24.], [  4.  32.], [  5.  40.], [  6.  48.], [  7.  56.], [  8.  64.], [  9.  69.]

>>> a[0][0]
0.0
>>> res[0][0]
3.0
>>> res2[0][0]
array([ 0.,  3.])

Of course you probably don't want to save the old array, but instead have both fields as new results. 当然,您可能不想保存旧数组,而是将两个字段都作为新结果。 Except I don't know what exactly you had in mind, if the two values you want stored are unrelated, just add a temp2 and func2 and call another generic_filter with the same **kwargs and store that as the first value. 除了我不知道你究竟想到了什么,如果你想要存储的两个值是不相关的,只需添加一个temp2func2并调用另一个带有相同**kwargs generic_filter并将其存储为第一个值。

However if you want an actual vector quantity that is calculated using multiple inarr elements, meaning that the two new created fields aren't independent, you are just going to have to write that kind of a function, one that takes in an array, idx , idy indices and returns a tuple\\list\\array value which you can then unpack and assign to the result. 但是,如果你想要一个使用多个inarr元素计算的实际矢量,意味着两个新创建的字段不是独立的,那么你只需要编写一种函数,一个接收数组的函数, idxidy索引并返回一个元组\\ list \\ array值,然后您可以将其解压缩并分配给结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM