#python #numpy #scipy-spatial
#python #numpy #scipy-пространственный
Вопрос:
Я пытаюсь получить ndarray точек вдоль границы фигуры, обозначенной 1 в массиве. Я пытался использовать scipy.spatial.ConvexHull
, но граница, созданная выпуклой оболочкой, не учитывала отверстие в середине формы (мне тоже нужна граница вокруг отверстия). Это та граница, которую я пытаюсь создать из массива. Как я могу учесть отверстие в форме?
Область, выделенная цветом, — это область, из которой должны быть вычислены граничные точки.
import numpy as np
from skimage.measure import label, regionprops
import matplotlib.pyplot as plt
from scipy.spatial import Voronoi, voronoi_plot_2d, ConvexHull
arr = np.array([
[1,1,1,1,1,1,0,0,0,1,0],
[1,1,1,1,1,1,0,0,0,1,0],
[1,1,0,0,0,1,1,1,1,1,0],
[1,1,0,1,1,1,1,1,0,0,0],
[1,1,1,1,1,1,0,0,0,0,0],
[0,1,1,1,1,0,0,0,0,0,0],])
coords = []
for x in range(arr.shape[0]):
for y in range(arr.shape[1]):
if arr[x][y] > 0:
tile = [x,y]
coords.append(tile)
# print("tile", tile)
coords = np.array(coords)
# print(coords)
hull = ConvexHull(coords)
plt.plot(coords[:,0], coords[:,1], 'o')
for simplex in hull.simplices:
plt.plot(coords[simplex, 0], coords[simplex, 1], 'k-')
plt.plot(coords[hull.vertices,0], coords[hull.vertices,1], 'r--', lw=2)
plt.plot(coords[hull.vertices[0],0], coords[hull.vertices[0],1], 'ro')
Комментарии:
1. Например, мне непонятно, почему изображение является
(3, 2)
частью границы, но не(1, 3)
является?2. @vlizana обновил изображение, чтобы показать изображение, из которого я пытаюсь сделать границу
3. спасибо, но я все еще не могу сказать, собираетесь ли вы перейти на v4 или v8 frontier. Например, на картинке, которую вы только что загрузили, при использовании окрестности v8 каждая точка (1) будет частью границы, где, как и в виде v4, есть несколько внутренних точек.
4. На картинке я нарисовал границу v4. Я предполагаю, что метод будет таким же для v4, как и для v8
Ответ №1:
Это немного банально, но если вы свернете нули с помощью правильного ядра (v4 или v8), вы получите внешнюю часть плюс границу, поэтому, если вы выполните and
какую-либо операцию с внутренней частью, вы получите только границу. Вот пример:
import numpy as np
from scipy.signal import convolve2d
arr = np.array([
[1,1,1,1,1,1,0,0,0,1,0],
[1,1,1,1,1,1,0,0,0,1,0],
[1,1,0,0,0,1,1,1,1,1,0],
[1,1,0,1,1,1,1,1,0,0,0],
[1,1,1,1,1,1,0,0,0,0,0],
[0,1,1,1,1,0,0,0,0,0,0],
])
# v4 example,
kernel = np.array([
[0,1,0],
[1,0,1],
[0,1,0],
])
# you have to zero pad first in order to get the edges
padded = np.pad(arr, ((1, 1), (1, 1)), 'constant', constant_values=0)
# the `astype(bool)` is for normalization
# the `and` operation in this case is the elementwise product
frontier = convolve2d(1-padded, kernel, mode='valid').astype(bool) * arr