Заполнение определенной формы в массиве numpy

#python #numpy

#python #numpy

Вопрос:

У меня есть 2d массив numpy, и я хотел бы увеличить значения определенной его части на 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]]
  

Мы решили основывать нашу область, например, на 3 точках ( [[0,2], [2,4], [3,1]] ) но количество точек также может быть больше:

 [[0 0 1 0 0]
 [0 0 0 0 0]
 [0 0 0 0 1]
 [0 1 0 0 0]
 [0 0 0 0 0]]
  

И заполните форму внутри этого полигона единицами:

 [[0 0 1 0 0]
 [0 0 1 1 0]
 [0 1 1 1 1]
 [0 1 1 0 0]
 [0 0 0 0 0]]
  

Как я могу сделать это автоматизированным способом? Что-то вроде:

 arr = np.zeros([5,5])
shapePoints = [[0,2], [2,4], [3,1]]
valueToFill = 1
arr = fillShape(arr, shapePoints, valueToFill)
  

… где fillShape — это функция, которую я ищу. Это должно существовать в numpy?

Комментарии:

1. Является ли количество вершин, которые вы пытаетесь заполнить, фиксированным (в данном случае вершин: три, форма: треугольник), или оно может измениться в будущем?

2. Да, это может измениться — минимум 3 и максимум, возможно, 20 или около того

3. Вы пробовали Cairo, я точно не знаю, зачем вам это нужно, но cairo позволяет создавать поверхности. cairographics.org

4. В конечном итоге речь идет не столько о построении графика, сколько о создании значений массива np … Я могу построить все свои фигуры с помощью PolygonPatch, но я хочу отобразить их на массив np, чтобы выполнить дальнейшие вычисления над ними

Ответ №1:

У Scikit есть реализация для такого алгоритма рисования полигонов. Смотрите skimage.draw.polygon

Редактировать: конкретный код для вопроса

 from skimage.draw import polygon, polygon_perimeter
import numpy as np
arr = np.zeros((5, 5))
shapePoints = np.array([[0,2], [2,4], [3,1]])
points_r, points_c = shapePoints[:, 0], shapePoints[:, 1]
interior_r, interior_c = polygon(points_r, points_c)
perimeter_r, perimeter_c = polygon_perimeter(points_r, points_c)
arr[perimeter_r, perimeter_c] = 3
arr[points_r, points_c] = 2
arr[interior_r, interior_c] = 1    
  

Обратите внимание, что это приводит к результату, отличному от приведенного в вопросе, чтобы проиллюстрировать разницу между интерьером и периметром.

 >>> arr
array([[0., 0., 2., 0., 0.],
       [0., 0., 1., 3., 0.],
       [0., 3., 1., 1., 2.],
       [0., 2., 3., 0., 0.],
       [0., 0., 0., 0., 0.]])
  

Комментарии:

1. пожалуйста, рассмотрите возможность добавления решения здесь, на благо всех

2. Это было бы просто копированием примера документации. Это здесь поощряется?

3. лучше, чем ничего не иметь, IMO 🙂