此方法非常慢。简短而有趣的是,它接收字典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
答案 0 :(得分:2)
要快速使用Numpy进行操作,通常希望避免循环并将尽可能多的工作推入Numpy的矩阵运算中。
我的回答的基本概念:
phase_color_labels
,ndarray
的形式从phase_colors
获取颜色。phase_colors
中每种颜色之间的欧式距离。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_names
和phase_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的更多详细信息。(H, W, L)
的阵列。在第四行中,在轴2上使用argmin
,然后将数组缩小为(H, W)
的形状,每个值都是从缩小轴L
开始的索引,换句话说,索引到phase_colors
。
作为另一项改进,由于平方根是单调递增的函数,因此不会更改最小的距离,因此可以将其完全删除。
请注意,在image
和phase_color_labels
较大的情况下,广播的存储成本可能会很明显,这也可能导致性能问题。