更快实现像素映射

时间:2019-04-01 21:35:59

标签: python python-3.x numpy

此方法非常慢。简短而有趣的是,它接收字典phase_color_labels,该字典将任意名称映射到与RGB值相对应的3元素列表,并将输入图像的每个像素映射到最接近的任何像素值在phase_color_labels词典中。我还没有弄清楚是否有矢量版本的运行速度会更快。

image变量只是一个numpy数组[H,W,Channels]。

def map_pixels_to_discrete_values(image, phase_color_labels):
        """
        Takes an image with floating point pixel values and maps each pixel RGB value
        to a new value based on the closest Euclidean distance to one of the RGB sets
        in the phase_label input dictionary.
        """
        mapped_image = np.copy(image)
        for i in range(mapped_image.shape[0]):
            for j in range(mapped_image.shape[1]):
                min_distance = np.inf
                min_distance_label = None
                for phase_name, phase_color in phase_color_labels.items():
                    r = phase_color[0]
                    g = phase_color[1]
                    b = phase_color[2]
                    rgb_distance = (mapped_image[i, j, 0] - r)**2 + (mapped_image[i, j, 1] - g)**2 + (mapped_image[i, j, 2] - b)**2
                    if rgb_distance < min_distance:
                        min_distance = rgb_distance
                        min_distance_label = phase_name

                mapped_image[i, j, :] = phase_color_labels[min_distance_label]
        return mapped_image

1 个答案:

答案 0 :(得分:2)

要快速使用Numpy进行操作,通常希望避免循环并将尽可能多的工作推入Numpy的矩阵运算中。

我的回答的基本概念:

  1. phase_color_labelsndarray的形式从phase_colors获取颜色。
  2. 使用Numpy的broadcasting计算“外部距离”,即数组中每个图像与phase_colors中每种颜色之间的欧式距离。
  3. 找到每个像素具有最小距离的颜色索引,并将其用作phase_colors中的索引。
phase_colors = np.array([color for color in phase_color_labels.values()])

distances = np.sqrt(np.sum((image[:,:,np.newaxis,:] - phase_colors) ** 2, axis=3))
min_indices = distances.argmin(2)

mapped_image = phase_colors[min_indices]

第三行需要一些其他解释。首先,请注意phase_namesphase_colors都具有形状(L, C),其中L是标签数,C是通道数。

  • image[:,:,np.newaxis,:]在第二轴和第三轴之间插入新轴,因此结果数组的形状为(H, W, 1, C)
  • 从形状(L, C)的数组中减去形状(H, W, 1, C)的数组时,Numpy广播该数组以使其形状为(H, W, L, C)。您可以找到有关Numpy的广播语义here的更多详细信息。
  • 然后,沿轴3求和,得到形状为(H, W, L)的阵列。
  • (平方和平方根都不影响数组的形状。)

在第四行中,在轴2上使用argmin,然后将数组缩小为(H, W)的形状,每个值都是从缩小轴L开始的索引,换句话说,索引到phase_colors


作为另一项改进,由于平方根是单调递增的函数,因此不会更改最小的距离,因此可以将其完全删除。

请注意,在imagephase_color_labels较大的情况下,广播的存储成本可能会很明显,这也可能导致性能问题。