计算numpy / scipy中的窗口概率

时间:2017-11-04 08:49:19

标签: python numpy scipy

我试图使用numpy / scipy对图像做一些模糊的过滤器(我认为)。我想要的本质上是一个窗口概率分布。我从灰度图像开始。对于给定像素和NxN内核,N奇数,我想计算相对于内核中其他像素的像素值的概率。此外,我想尽快进行此计算。

因此,例如给定图像的3x3区域:

[0, 0, 0;
 0, 0, 0;
 255, 255, 255]

中心像素应从0转换为0.66,因为它在该3x3区域中有2/3的可能性。在代码中,我可以执行以下操作,但它太慢了:

# loops through calculating probability distributions for each window
# generates new_image
for yi in range(0, height):
  for xi in range(0, width):
    window = kernel_region(image, yi, xi, ksize)
    hist = np.histogram(window.ravel(), 256, [0, 256])
    pdf = hist / np.size(window)
    pixel_value = image[yi, xi]
    new_image[yi, xi] = pdf[pixel_value]

# gives ksize x ksize slice of the image (smaller on the edges)
def kernel_region(image, yi, xi, ksize):
  height, width = image.shape[:2]
  offset = math.floor(ksize / 2)
  yStart = max(0, yi - offset)
  yEnd = min(height - 1, yi + offset)
  xStart = max(0, xi - offset)
  xEnd = min(width - 1, xi + offset)
  return image[yStart:yEnd, xStart:xEnd]

我可以在循环中进行一些优化,但我想避免使用循环。是否可以使用" pure" numpy功能?

1 个答案:

答案 0 :(得分:1)

有趣的数学问题,似乎会​​有Scikit-image's view_as_windows的简单解决方案来获取(3,3)滑动窗口,然后与中心像素进行比较,以便在窗口中获取其出现次数并最终划分按内核大小9

因此,图像a的实现将是 -

from skimage.util.shape import view_as_windows

(view_as_windows(a,(3,3)) == a[1:-1,1:-1,None,None]).sum((-2,-1))/9.0

这为我们提供了非边界元素的结果。为了覆盖所有元素,我们可以使用无效的说明符填充图像,在它周围说-1,然后使用建议的方法。

示例运行 -

In [61]: a
Out[61]: 
array([[  1,   0,   0,   0,   3,   4],
       [  2,   0,   0,   0,   6,   0],
       [  4, 255, 255, 255,   8,   2],
       [  0,   5,   0,   5,   6,   2]])

In [76]: (view_as_windows(a,(3,3)) == a[1:-1,1:-1,None,None]).sum((-2,-1))/9.0
Out[76]: 
array([[ 0.44,  0.67,  0.44,  0.11],
       [ 0.22,  0.33,  0.22,  0.11]])

涵盖所有元素 -

In [74]: a1 = np.pad(a, (1,1), 'constant', constant_values=(-1, -1))

In [75]: (view_as_windows(a1,(3,3)) == a1[1:-1,1:-1,None,None]).sum((-2,-1))/9.0
Out[75]: 
array([[ 0.11,  0.44,  0.67,  0.44,  0.11,  0.11],
       [ 0.11,  0.44,  0.67,  0.44,  0.11,  0.11],
       [ 0.11,  0.22,  0.33,  0.22,  0.11,  0.22],
       [ 0.11,  0.11,  0.11,  0.11,  0.11,  0.22]])