Чтобы быстро работать с Numpy, вы, как правило, хотите избегать циклов и вкладывать как можно больше работы в матричные операции Numpy.
Основная идея моего ответа:
- Получить цвета из
phase_color_labels
как ndarray
, phase_colors
. - Использовать широковещание Numpy для вычисления «внешнего расстояния» - евклидова расстояния между каждым изображением в массивеи каждый цвет в
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 здесь . - Затем, взяв сумму вдоль оси 3, вы получите массив формы
(H, W, L)
. - (Ни квадрат, ниПринятие эффекта квадратного корня в форме массива.)
В четвертой строке использование argmin
на оси 2 затем уменьшает массив до формы (H, W)
, причем каждое значение является индексом изуменьшенная ось L
- другими словами, индекс в phase_colors
.
В качестве дополнительного улучшения, поскольку квадратный корень является монотонно возрастающей функцией, он не изменит, какое расстояние наименьшее, так что вы можете удалить его полностью.
Обратите внимание, что при больших image
и phase_color_labels
затраты на вещание могут быть значительными, что также может привести к проблемам с производительностью.