【问题标题】:Local Maxima with circular window带圆形窗口的局部最大值
【发布时间】:2017-01-09 09:09:30
【问题描述】:

我正在尝试使用圆形内核计算矩阵上的局部最大值滤波器。 输出应该是局部最大值的单元格。对于输入“数据”中的每个像素,我需要通过圆形窗口查看它是否是局部最大值,因此返回值 1,否则返回 0。

我有这段代码,基于这里的答案: How to apply a disc shaped mask to a numpy array?

import numpy as np
import scipy.ndimage as sc

radius = 2
kernel = np.zeros((2*radius+1, 2*radius+1))
y,x = np.ogrid[-radius:radius+1, -radius:radius+1]
mask2 = x**2 + y**2 <= radius**2
kernel[mask2] = 1

def local_maxima(matrix, window_size):
    loc_max = sc.maximum_filter(matrix, window_size, mode='constant')
    return loc_max


data = np.array([(1, 1, 1, 1, 1, 1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1, 1, 1),
                 (1, 1, 1, 1, 1, 1, 1, 1, 1), (1, 1, 1, 1, 4, 1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1, 1, 1),
                 (1, 1, 1, 1, 1, 1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1, 1, 1),
                 (1, 1, 1, 1, 1, 1, 1, 1, 1)])

loc_max = sc.filters.generic_filter(data, local_maxima(data, np.shape(kernel)), footprint=kernel)
max_matrix = np.where(loc_max == data, 1, 0)
np.savetxt('.....\Local\Test_Local_Max.txt', max_matrix, delimiter='\t')

内核有这个形状:

[[ 0.  0.  1.  0.  0.]
 [ 0.  1.  1.  1.  0.]
 [ 1.  1.  1.  1.  1.]
 [ 0.  1.  1.  1.  0.]
 [ 0.  0.  1.  0.  0.]]

因此,搜索单元格将仅是值为 1 的单元格。值为 0 的单元格应从局部最大值搜索中排除。

但是脚本在第 21 行给出了以下错误:

RuntimeError: function parameter is not callable

感谢您的帮助!

【问题讨论】:

  • 问题是你给sc.filters.generic_filter的函数被应用于你给的输入数组的每个元素:data,这是不可能的,因为函数local_maxima将一个数组作为参数并且不是浮点数或整数...我不知道您的代码的确切目标,但您为什么不直接应用它:loc_max = sc.maximum_filter(data, kernel.shape, mode='constant', footprint=kernel)
  • 因为footprint kernel应该只占据内核矩阵中为1的位置,而不是0的位置。

标签: python numpy filtering


【解决方案1】:

sc.filters.generic_filter() 的第二个参数应该是一个函数,你传递给它的是 local_maxima(data, np.shape(kernel)) 调用返回的值,即一个矩阵。

我对你在这里到底做了什么有点困惑,但我认为你根本不需要generic_filter 调用,maximum_filter 应该做你想做的事:

import numpy as np
import scipy.ndimage as sc

radius = 2
kernel = np.zeros((2*radius+1, 2*radius+1))
y,x = np.ogrid[-radius:radius+1, -radius:radius+1]
mask2 = x**2 + y**2 <= radius**2
kernel[mask2] = 1

data = np.array([(1, 1, 1, 1, 1, 1, 1, 1, 1), 
                 (1, 1, 1, 1, 1, 1, 1, 1, 1),  
                 (1, 1, 1, 1, 1, 1, 1, 1, 1),
                 (1, 1, 1, 1, 1, 1, 1, 1, 1),  
                 (1, 1, 1, 1, 4, 1, 1, 1, 1),  
                 (1, 1, 1, 1, 1, 1, 1, 1, 1),
                 (1, 1, 1, 1, 1, 1, 1, 1, 1),  
                 (1, 1, 1, 1, 1, 1, 1, 1, 1),  
                 (1, 1, 1, 1, 1, 1, 1, 1, 1),
                 (1, 1, 1, 1, 1, 1, 1, 1, 1)])

loc_max = sc.maximum_filter(data, footprint=kernel, mode='constant')
max_matrix = np.where(loc_max == data, 1, 0)
np.savetxt('.....\Local\Test_Local_Max.txt', max_matrix, delimiter='\t')

(我没有在这台电脑上安装python,所以我没有测试过,抱歉)

编辑: 我已经测试过了,它似乎给出了正确的结果:

[[1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 1, 1, 0, 1, 1, 1, 1],
 [1, 1, 1, 0, 0, 0, 1, 1, 1],
 [1, 1, 0, 0, 1, 0, 0, 1, 1],
 [1, 1, 1, 0, 0, 0, 1, 1, 1],
 [1, 1, 1, 1, 0, 1, 1, 1, 1],
 [1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 1, 1, 1, 1, 1, 1, 1, 1]]

【讨论】:

  • 它运行了,但这不是我期望的结果。对于输入“数据”中的每个像素,我需要查看它是否是圆形窗口的局部最大值,因此返回值 1,否则返回 0。当单元格为时,您的答案的输出不会加 0不是局部最大值。
  • 我现在已经测试过了,似乎正在做你想要的,我将添加我得到答案的结果
【解决方案2】:

如果访问的单元格是kernel 定义的圆形窗口的局部最大值,您可以使用下面的代码返回1(我只是使用%pylab 来绘制结果作为说明):

%pylab
import scipy.ndimage as sc
data = np.array([(1, 1, 1, 1, 1, 1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1, 1, 1),
                 (1, 1, 1, 1, 1, 1, 1, 1, 1), (1, 1, 1, 1, 4, 1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1, 1, 1),
                 (1, 1, 1, 1, 1, 1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1, 1, 1), (1, 1, 1, 1, 1, 1, 1, 1, 1),
                 (1, 1, 1, 1, 1, 1, 1, 1, 1)])
matshow(data)
colorbar()

radius = 2
kernel = np.zeros((2*radius+1, 2*radius+1))
y,x = np.ogrid[-radius:radius+1, -radius:radius+1]
mask2 = x**2 + y**2 <= radius**2
kernel[mask2] = 1
matshow(kernel)
colorbar()

def filter_func(a):
    return a[len(a)/2] == a.max()
out = sc.generic_filter(data, filter_func, footprint=kernel)
matshow(out)
colorbar()

以下是随机输入数据数组的结果:

data = np.random.random(size=data.shape)
matshow(data)

out = sc.generic_filter(data, filter_func, footprint=kernel)
matshow(out)
colorbar()

【讨论】:

  • 感谢您的回答。这是我需要的。不错的情节! :)
  • 我不知道该接受哪个答案。 pseudoDust 的答案是第一个,但你的更容易理解......
  • 总是选择更好的答案(而不是第一个),以便后来查找此内容的人首先看到更好的答案。在这种情况下,我同意@bougui 的答案更好:)
猜你喜欢
  • 2020-06-21
  • 2018-03-06
  • 1970-01-01
  • 1970-01-01
  • 2012-10-29
  • 2023-01-27
  • 1970-01-01
  • 1970-01-01
  • 2016-02-11
相关资源
最近更新 更多