Как нарисовать многоугольник (детали были согнуты внутрь) ребра на группе точек с помощью Python? - PullRequest
3 голосов
/ 19 июня 2019

Я пытаюсь нарисовать ребро многоугольника (вогнутого) на кластере K-средних, показанном ниже (рис_1).

enter image description here

С помощью @ ypnos этот фрагмент кода отображает все, кроме края.

df = pd.read_csv('https://raw.githubusercontent.com/MachineIntellect/dataset.ml/master/watermelon/watermelon_4_0.csv')
X = df.iloc[:,1:].to_numpy()
m0 = X[5]
m1 = X[11]
m2 = X[23]
centroids = np.array([m0, m1, m2])
labels = pairwise_distances_argmin(X, centroids)
m0 = X[labels == 0].mean(0)
m1 = X[labels == 1].mean(0)
m2 = X[labels == 2].mean(0)
new_centroids = np.array([m0, m1, m2])
plt.xlim(0.1,0.9)
plt.ylim(0, 0.8)
plt.scatter(X[:,0], X[:,1])
plt.scatter(new_centroids[:,0], new_centroids[:,1], c='r', marker = '+')
for i in range(3):    
    points = X[labels == i]
    hull = ConvexHull(points)
    for simplex in hull.simplices:
        plt.plot(points[simplex, 0], points[simplex, 1], 'r-')

enter image description here (Fig_2)

Документ Scikit-Learn , кажется, вдохновляет

Вопрос в том, что ребра, указанные стрелкой на рис_1, отличаются от соответствия на рис_2.

край многоугольника, на который указывала стрелка, был согнут внутрь (благодаря @dwilli).

Благодаря напоминанию @ ImportanceOfBeingErnest, scipy.spatial.ConvexHull, возможно, не сможет производить вогнутость.

Есть ли другой модуль / пакет для этого (вогнутый)?

любая подсказка будет оценена.

Ответы [ 4 ]

2 голосов
/ 19 июня 2019

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

Полигоны, которые вы показываете на своем первом рисунке, являются приблизительным приближением к выпуклой оболочке членов вашего кластера.Вы можете использовать scipy.spatial.ConvexHull или cv2.convexHull() (из OpenCV) для его вычисления.Документация первого также дает пример того, как его построить .

1 голос
/ 27 июня 2019

alphashape для этого случая.

url = 'https://raw.githubusercontent.com/MachineIntellect/dataset.ml/master/watermelon/watermelon_4_0.csv'
df = pd.read_csv(url)
X = df.iloc[:,1:].to_numpy()
m0 = X[5]
m1 = X[11]
m2 = X[23]
centroids = np.array([m0, m1, m2])
labels = pairwise_distances_argmin(X, centroids)
m0 = X[labels == 0].mean(0)
m1 = X[labels == 1].mean(0)
m2 = X[labels == 2].mean(0)
new_centroids = np.array([m0, m1, m2])

fig, ax = plt.subplots()
plt.xlim(0.1,0.9)
plt.ylim(0, 0.8)
ax.scatter(X[:,0], X[:,1])
ax.scatter(new_centroids[:,0], new_centroids[:,1], c='r', marker = '+')
for i in range(3):
    points = X[labels == i]
    alpha_shape = alphashape.alphashape(points, 5.0)
    ax.add_patch(PolygonPatch(alpha_shape, alpha=0.2))
plt.show()

enter image description here

0 голосов
/ 27 июня 2019

Вы пытались определить свои ребра с помощью активной модели контура ?

Возможно ли найти его реализацию Skimage: https://scikit -image.org / docs/dev/auto_examples/edges/plot_active_contours.html

и другая версия https://github.com/brikeats/Snakes-in-a-Plane без предварительной обработки изображения

0 голосов
/ 22 июня 2019

Для генерации полигона вы можете попробовать следующие шаги

  • Создайте полигоны вокруг каждого кластера, обрабатывая каждый кластер как в отдельной части графика.

  • Вы можете создать грубый многоугольник, используя метод выпуклой оболочки, упомянутый @ypnos, но чтобы получить лучший результат, взгляните на Delaunay triangulation method.

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

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

Ожидаемый результат на некоторых выборочных данных

Result

Для достижения результата требуется совсем немного кода, здесь - ссылка на подробное руководство по созданию образца графика.

...