Подтвердить что ты не робот

Matplotlib - извлечение данных из контурных линий

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

Основываясь на примере, найденном в аналогичном вопросе: Как я могу получить значения (x, y) строки, которые обозначены контурным графиком (matplotlib)?

>>> import matplotlib.pyplot as plt
>>> x = [1,2,3,4]
>>> y = [1,2,3,4]
>>> m = [[15,14,13,12],[14,12,10,8],[13,10,7,4],[12,8,4,0]]
>>> cs = plt.contour(x,y,m, [9.5])
>>> cs.collections[0].get_paths()

Результатом этого вызова в cs.collections[0].get_paths() является:

[Path([[ 4.          1.625     ]
 [ 3.25        2.        ]
 [ 3.          2.16666667]
 [ 2.16666667  3.        ]
 [ 2.          3.25      ]
 [ 1.625       4.        ]], None)]

На основе графиков этот результат имеет смысл и, по-видимому, представляет собой совокупность (y, x) пар для контурной линии.

Кроме ручного циклирования по этому возвращаемому значению, извлечению координат и сборке массивов для линии, есть ли лучшие способы вернуть данные из объекта matplotlib.path? Есть ли ошибки, которые следует учитывать при извлечении данных из matplotlib.path?

Альтернативно, существуют ли альтернативы в пределах matplotlib или еще лучше numpy/scipy, чтобы сделать аналогичную вещь? Идеальная вещь заключалась бы в том, чтобы получить вектор с высоким разрешением пар (x, y), описывающих линию, которые могут быть использованы для дальнейшего анализа, поскольку, как правило, мои наборы данных не являются небольшими или простыми, как пример выше.

4b9b3361

Ответ 1

Для данного пути вы можете получить такие точки:

p = cs.collections[0].get_paths()[0]
v = p.vertices
x = v[:,0]
y = v[:,1]

Ответ 2

from: http://matplotlib.org/api/path_api.html#module-matplotlib.path

Пользователи объектов Path не должны обращаться к массивам вершин и кодов непосредственно. Вместо этого они должны использовать iter_segments(), чтобы получить пары вершин/кодов. Это важно, поскольку многие объекты Path, как оптимизация, не сохраняют коды вообще, но имеют значение по умолчанию предоставленные для них iter_segments().

В противном случае я не уверен, в чем ваш вопрос. [Zip] - иногда полезная встроенная функция при работе с координатами. 1

Ответ 3

Я столкнулся с аналогичной проблемой и наткнулся на это обсуждение списка матплотбликов.

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

import matplotlib.pyplot as plt
import matplotlib._cntr as cntr
import scipy as sp

data = sp.zeros((6,6))
data[2:4,2:4] = 1

plt.imshow(data,interpolation='none')
level=0.5
X,Y = sp.meshgrid(sp.arange(data.shape[0]),sp.arange(data.shape[1]))
c = cntr.Cntr(X, Y, data.T)
nlist = c.trace(level, level, 0)
segs = nlist[:len(nlist)//2]
for seg in segs:
    plt.plot(seg[:,0],seg[:,1],color='white')

plt.show()

Ответ 4

Вершины всех путей могут быть возвращены в виде массива float64 просто через:

cs.allsegs[i][j]  # for element j, in level i

Подробнее...

Просматривать коллекции и извлекать пути и вершины - не самая прямая и самая быстрая вещь. Возвращенный объект Contour фактически имеет атрибуты для сегментов с помощью cs.allsegs, который возвращает вложенный список формы [уровень] [элемент] [vertex_coord]:

num_levels = len(cs.allsegs)
num_element = len(cs.allsegs[0])  # in level 0
num_vertices = len(cs.allsegs[0][0])  # of element 0, in level 0
num_coord = len(cs.allsegs[0][0][0])  # of vertex 0, in element 0, in level 0

См. ссылку:https://matplotlib.org/3.1.1/api/contour_api.html