【问题标题】:numpy vectorize / more efficient for loopnumpy 向量化/更有效的 for 循环
【发布时间】:2018-11-25 21:34:13
【问题描述】:

我正在对图像进行腐蚀。图像已相应填充。 简而言之,我有一个交叉元素(+),我将它放在图像的每个像素上,并从上方、下方、右侧、左侧和自身的像素中选择该像素的最低值。

效率低下,我无法确定矢量化版本。这一定是可能的,因为所有计算都是相互独立完成的。

for y in range(t,image.shape[0]-b):
    for x in range(l,image.shape[1]-r):
        a1 = numpy.copy(str_ele)
        for filter_y in range(a1.shape[0]):
            for filter_x in range(a1.shape[1]):
                if (not (numpy.isnan(a1[filter_y][filter_x]))):
                    a1[filter_y][filter_x] = str_ele[filter_y][filter_x]*image[y+(filter_y-str_ele_center_y)][x+(filter_x-str_ele_center_x)]
        eroded_image[y][x] = numpy.nanmin(a1)   

基本上:

最终图像中的每个像素 = 原始图像的 min(pixel, above, below, left, right)

 for y in range(len(eroded_image)):
     for x in range(len(eroded_image[1])):
         eroded_image2[y][x] = numpy.nanmin(str_ele*image2[y:y+len(str_ele),x:x+(len(str_ele[1]))])

这就是我现在拥有的。还是 2 个循环。

【问题讨论】:

    标签: python numpy image-processing vectorization image-morphology


    【解决方案1】:

    如果image 是一个以 NaN 填充的数组,并且您正在使用十字形足迹进行侵蚀, 您可以通过堆叠image 的切片来删除 for 循环(以有效地向上、向左、向右和向下移动图像) 然后将np.nanmin 应用于切片堆栈。

    import numpy as np
    
    def orig(image):
        t, l, b, r = 1, 1, 1, 1
        str_ele = np.array([[np.nan, 1, np.nan], [1, 1, 1], [np.nan, 1, np.nan]], dtype='float')
        str_ele_center_x, str_ele_center_y = 1, 1
        eroded_image = np.full_like(image, dtype='float', fill_value=np.nan)
        for y in range(t,image.shape[0]-b):
            for x in range(l,image.shape[1]-r):
                a1 = np.copy(str_ele)
                for filter_y in range(a1.shape[0]):
                    for filter_x in range(a1.shape[1]):
                        if (not (np.isnan(a1[filter_y][filter_x]))):
                            a1[filter_y][filter_x] = str_ele[filter_y][filter_x]*image[y+(filter_y-str_ele_center_y)][x+(filter_x-str_ele_center_x)]
                eroded_image[y][x] = np.nanmin(a1)   
        return eroded_image
    
    def erode(image):
        result = np.stack([image[1:-1, 1:-1], image[2:, 1:-1], image[:-2, 1:-1], image[1:-1, 2:], image[1:-1, :-2]])
        eroded_image = np.full_like(image, dtype='float', fill_value=np.nan)
        eroded_image[1:-1, 1:-1] = np.nanmin(result, axis=0)
        return eroded_image
    
    image = np.arange(24).reshape(4,6)
    image = np.pad(image.astype(float), 1, mode='constant', constant_values=np.nan)
    

    产量

    In [228]: erode(image)
    Out[228]: 
    array([[nan, nan, nan, nan, nan, nan, nan, nan],
           [nan,  0.,  0.,  1.,  2.,  3.,  4., nan],
           [nan,  0.,  1.,  2.,  3.,  4.,  5., nan],
           [nan,  6.,  7.,  8.,  9., 10., 11., nan],
           [nan, 12., 13., 14., 15., 16., 17., nan],
           [nan, nan, nan, nan, nan, nan, nan, nan]])
    

    对于上面的小例子 imageerode 似乎比 orig 快 33 倍左右:

    In [23]: %timeit erode(image)
    10000 loops, best of 3: 35.6 µs per loop
    
    In [24]: %timeit orig(image)
    1000 loops, best of 3: 1.19 ms per loop
    
    In [25]: 1190/35.6
    Out[25]: 33.42696629213483
    

    【讨论】:

    • 对于正确的图像 (scipy.misc.face().mean(2),我通过沿轴 0 而不是 -1 堆叠(并采用 nanmin)获得了两倍以上的加速。
    • @PaulPanzer:非常感谢您的改进。
    猜你喜欢
    • 2013-07-21
    • 2018-08-26
    • 2016-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-10
    • 2017-04-29
    • 1970-01-01
    相关资源
    最近更新 更多