我可以向量化这个Python代码吗?

Luc*_*uca 2 python optimization numpy

我编写了这段 python 代码来获取标签的邻居(一组共享一些公共属性的像素)。标签的邻居被定义为位于边界另一侧的其他标签(相邻标签共享边界)。所以,我写的代码可以工作,但速度非常慢:

# segments: It is a 2-dimensional numpy array (an image really)
# where segments[x, y] = label_index. So each entry defines the
# label associated with a pixel.

# i: The label whose neighbours we want.

def get_boundaries(segments, i):
    neighbors = []
    for y in range(1, segments.shape[1]):
        for x in range(1, segments.shape[0]):
            # Check if current index has the label we want 
            if segments[x-1, y] == i:
                # Check if neighbour in the x direction has
                # a different label
                if segments[x-1, y] != segments[x, y]:
                    neighbors.append(segments[x,y])

            # Check if neighbour in the y direction has
            # a different label
            if segments[x, y-1] == i:
                if segments[x, y-1] != segments[x, y]:
                    neighbors.append(segments[x, y])

    return np.unique(np.asarray(neighbors))
Run Code Online (Sandbox Code Playgroud)

你可以想象,我在这里可能完全误用了 python。我想知道是否有一种方法可以优化这段代码,使其更加Pythonic。

Joh*_*nck 5

干得好:

def get_boundaries2(segments, i):
    x, y = np.where(segments == i) # where i is
    right = x + 1
    rightMask = right < segments.shape[0] # keep in bounds
    down = y + 1
    downMask = down < segments.shape[1]
    rightNeighbors = segments[right[rightMask], y[rightMask]]
    downNeighbors = segments[x[downMask], down[downMask]]
    neighbors = np.union1d(rightNeighbors, downNeighbors)
    return neighbors
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,根本没有 Python 循环;我还尝试最小化副本(第一次尝试制作了带有 NAN 边界的副本segments,但后来我设计了“保持在边界内”检查)。

请注意,我并没有i从这里的“邻居”中过滤掉自己;如果你愿意的话,你可以很容易地在最后添加它。一些时间安排:

输入 2000x3000:原始需要 13 秒,我的需要 370 毫秒(35 倍加速)。

输入 1000x300:原始需要 643 毫秒,我的需要 17.5 毫秒(加速 36 倍)。