python - numpy-array 中子矩阵的矢量化提取

标签 python numpy image-processing computer-vision vectorization

我的目标是实现一个中值滤波器,它是一个函数,它将(主要是)二维数组中的每个像素替换为其周围像素的中值。它可用于对图像进行去噪。

我的实现从原始矩阵中提取子矩阵,其中包含像素本身及其邻居。此提取目前使用 for 循环完成,您可以想象 for 循环占用了大约 95% 的执行时间。

这是我目前的实现:

def median_blur(img, fsize=3):
    img_intermediate = np.zeros((img.shape[0] + 2, img.shape[1] + 2), np.uint8)  # First intermediate img, used for padding original image
    img_intermediate[1:img.shape[0]+1, 1:img.shape[1]+1] = img
    img_result = np.empty((*img.shape, fsize, fsize), np.uint8)  # Will contain result, first receives kernel-submatrices

    # Extract submatrices from image
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            img_result[i, j] = img_intermediate[i:i+fsize, j:j+fsize]

    img_result = img_result.reshape(*img.shape, fsize**2)  # Reshape Result-Matrix
    img_result = np.median(img_result, axis=2)  # Calculate median in one go
    return img_result.astype('uint8')

如何使用矢量化操作提取这些子矩阵?

作为奖励,如果有计算机视觉经验的人正在阅读本文:除了将中值滤波器应用于中间零填充矩阵之外,是否还有更好的方法来实现中值滤波器?

非常感谢。

最佳答案

这是一个矢量化的解决方案。但是,您可以通过注意图像数组的内存顺序来提出更快的解决方案:

from numpy.lib.stride_tricks import as_strided

img_padded = np.pad(img, 1, mode='constant')
sub_shape = (fsize, fsize)
view_shape = tuple(np.subtract(img_padded.shape, sub_shape) + 1) + sub_shape
sub_img = as_strided(img_padded, view_shape, img_padded.strides * 2)
sub_img = sub_img.reshape(img.shape + (fsize**2,))
result = np.median(sub_img, axis=2).astype(int)

使用 pad函数先填充然后填充 as_strided获取子矩阵并最终应用 median迈向你的步伐。

更新 :使用 view_as_windows @Divakar 在评论中建议:
from skimage.util.shape import view_as_windows

img_padded = np.pad(img, 1, mode='constant')
sub_shape = (fsize, fsize)
view_shape = view_as_windows(img_padded, sub_shape, 1)
sub_img = view_shape.reshape(img.shape + (fsize**2,))
result = np.median(sub_img, axis=2).astype(int)
view_as_windows还提供类似于步幅的子矩阵。

示例图像和输出:
img: 
[[ 1  2  3  4  5  6]
 [ 7  8  9 10 11 12]
 [13 14 15 16 17 18]
 [19 20 21 22 23 24]]

median_filtered: 
[[ 0  2  3  4  5  0]
 [ 2  8  9 10 11  6]
 [ 8 14 15 16 17 12]
 [ 0 14 15 16 17  0]]

关于python - numpy-array 中子矩阵的矢量化提取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61557367/

相关文章:

python - 使用 scipy、python、numpy 进行非线性 e^(-x) 回归

用于散热的 Python numpy 矢量化

c++ - 仿射变换、简单旋转和缩放或其他完全?

python - 从子目录或相对路径导入包

python - 替换嵌套列表中某些列表中的值

python - 什么是 Python/pandas 相当于这个用于重新排列数据帧列的 R 代码?

python - 使用python处理来自多个目录的同名数据

javascript - 使用 Javascript 在浏览器中编辑图像,然后将图像保存在 Google App Engine 中

python - 在一个子像素位置将一个图像补丁插入另一个图像

python - 如何避免读取 Tensorflow 中每个请求的图表