Классифицировать массив Python ближайшим «семенным» регионом?

У меня есть растр экологических местообитаний, который я преобразовал в двумерный массив numpy Python (example_array ниже). У меня также есть массив, содержащий «семенные» регионы с уникальными значениями (seed_array ниже), которые я хотел бы использовать для классификации областей среды обитания. Я бы хотел «вырастить» мои семенные регионы в «области моей среды обитания», чтобы местам обитания присваивался идентификатор ближайшего семенного региона, измеряемый «через» области ареала обитания. Например:

Изображение массивов

Мой лучший подход использовал функцию ndimage.distance_transform_edt для создания массива, изображающего ближайшую «семенную» область для каждой ячейки в наборе данных, которая затем была заменена обратно в массив среды обитания. Однако это не очень хорошо работает, поскольку функция не измеряет расстояния «через» мои области обитания, например, внизу, где красный круг представляет собой неправильно упорядоченную ячейку:

Неправильный вывод с использованием ndimage

Ниже приведены образцы массивов для моей среды обитания и данных семян, а также пример того, какую продукцию я ищу. Мои фактические данные намного больше – более миллиона мест обитания / семян. Любая помощь приветствуется!

 import numpy as np import scipy.ndimage as ndimage import matplotlib.pyplot as plt # Sample study area array example_array = np.array([[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1], [0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0], [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1], [1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1], [1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], [1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0], [1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]) # Plot example array plt.imshow(example_array, cmap="spectral", interpolation='nearest') seed_array = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 0, 0, 2, 2, 0, 0, 0, 0], [0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]) # Plot seeds plt.imshow(seed_array, cmap="spectral", interpolation='nearest') desired_output = np.array([[0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 4, 4, 4, 0, 0, 0, 3, 3, 3], [0, 0, 0, 0, 4, 4, 0, 0, 0, 3, 3, 3], [0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0], [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 3, 3], [1, 1, 0, 1, 0, 0, 0, 0, 2, 2, 3, 3], [1, 1, 1, 1, 0, 0, 2, 2, 2, 0, 0, 3], [1, 1, 1, 1, 1, 2, 2, 2, 2, 0, 0, 0], [1, 1, 1, 1, 0, 0, 2, 2, 2, 0, 0, 0], [1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]) # Plot desired output plt.imshow(desired_output, cmap="spectral", interpolation='nearest') 

One Solution collect form web for “Классифицировать массив Python ближайшим «семенным» регионом?”

Вы можете использовать сегментацию водоразделов от изображения scikits-image:

  • Преобразование расстояния

     from scipy import ndimage as nd distance = nd.distance_transform_edt(example_array) 
  • Сегментация водораздела

     from skimage.morphology import watershed, square result = watershed(-distance, seed_array, mask=example_array, \ connectivity=square(3)) 
  • результат

     subplot(1,2,1) imshow(-distance, 'spectral', interpolation='none') subplot(1,2,2) imshow(result, 'spectral', interpolation='none') 

введите описание изображения здесь


В качестве другого варианта и после вашего первоначального подхода вы можете использовать водораздел, чтобы найти связанных соседей с ближайшими семенами. Как вы упомянули в вопросе:

  • Рассчитать расстояние до семян:

     distance = nd.distance_transform_edt(seed_array == 0) 
  • Вычислить водораздел на расстоянии:

     result = watershed(distance, seed_array, mask=example_array, \ connectivity=square(3)) 
  • Результат расчета:

     figure(figsize=(9,3)) subplot(1,3,1) imshow(distance, 'jet', interpolation='none') subplot(1,3,2) imshow(np.ma.masked_where(example_array==0, distance), 'jet', interpolation='none') subplot(1,3,3) imshow(result, 'spectral', interpolation='none') 

введите описание изображения здесь


Дальнейшее обсуждение: метод Watershed пытается вырастить области от посевных пиков, протекающих через градиент изображения. Поскольку ваше изображение является двоичным, регионы будут одинаково расширяться по всем направлениям от посевных точек и, таким образом, дают вам точку между двумя регионами. Для получения дополнительной информации о водоразделах обратитесь к википедии .

В первом примере преобразование расстояния вычисляется в исходном изображении, и, таким образом, области расширяются равномерно от семян, пока они не достигнут точки разделения в середине.

Во втором примере преобразование расстояния вычисляется из всех пикселей в любую из посевных точек, а затем применяет водораздел в этом пространстве. Watershed в основном назначит каждый пиксель ближайшему семену, но он добавит ограничение связи.

Обратите внимание на разницу знаков в картах расстояний как в плане, так и в воде.

ПРИМЕЧАНИЕ. На картах расстояний (левое изображение на обеих участках) синий означает закрытие, где красный означает далеко.

  • Преобразование выражений sympy в функции массивов numpy
  • SciPy lesssq соответствует синусоидальной волне
  • Библиотека подгонки кривой Python, которая позволяет мне назначать границы параметрам
  • набор питона python / scipy
  • Как получить разреженную матрицу scipy.csr как нормальную плотную матрицу без toDense ()?
  • Установка 2D-гауссовой функции с помощью scipy.optimize.curve_fit - ValueError и minpack.error
  • Как определить неопределенность параметров подгонки с помощью Python?
  • Ошибка импорта scipy.sparse
  • Python - лучший язык программирования в мире.