matplotlib - 从轮廓线中提取数据

时间:2011-04-14 15:59:11

标签: python numpy matplotlib scipy contour

我想从均匀间隔的2D数据(类似图像的数据)的单个轮廓中获取数据。

基于类似问题中的示例:How can I get the (x,y) values of the line that is ploted by a contour plot (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)对的高分辨率矢量,可以用于进一步分析,因为通常我的数据集不像上面的例子那么小或简单。

4 个答案:

答案 0 :(得分:43)

对于给定的路径,您可以获得如下所示的点:

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

答案 1 :(得分:9)

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

  

Path对象的用户不应访问顶点和代码数组   直。相反,他们应该使用iter_segments()来获取   顶点/代码对。这很重要,因为很多Path对象都是如此   优化,根本不存储代码,但具有默认代码   由iter_segments()提供给他们。

否则,我不确定你的问题是什么。使用坐标时,[Zip]有时是有用的内置函数。 1

答案 2 :(得分:3)

我遇到了类似的问题,偶然发现this matplotlib list discussion

基本上,可以剥离绘图并直接调用底层函数,而不是超级方便,但可能。解决方案也不是像素精确的,因为底层代码中可能会进行一些插值。

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()

答案 3 :(得分:1)

所有路径的顶点都可以通过以下方式以float64的numpy数组形式返回:

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

更详细:

遍历集合并提取路径和顶点并不是最直接或最快的操作。返回的Contour对象实际上通过cs.allsegs拥有线段的属性,该属性返回嵌套的[level] [element] [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