numpy 从matplotlib.pyplot.contour()中查找等高线

hyrbngr7  于 2023-10-19  发布在  其他
关注(0)|答案(4)|浏览(145)

我正在寻找(但不是画!)某些数据的等高线:

from pprint import pprint 
import matplotlib.pyplot 
z = [[0.350087, 0.0590954, 0.002165], [0.144522, 0.885409, 0.378515], 
     [0.027956, 0.777996, 0.602663], [0.138367, 0.182499, 0.460879], 
     [0.357434, 0.297271, 0.587715]] 
cn = matplotlib.pyplot.contour(z)

我知道cn包含我想要的轮廓线,但我似乎无法得到它们。我试过几种方法:

print dir(cn) 
pprint(cn.collections[0]) 
print dir(cn.collections[0]) 
pprint(cn.collections[0].figure) 
print dir(cn.collections[0].figure)

但毫无结果我知道cn是一个ContourSetcn.collections是一个LineCollection s的数组。我认为LineCollection是一个线段数组,但我不知道如何提取这些线段。
我的最终目标是创建一个KML文件,在世界Map上绘制数据,以及这些数据的轮廓。
然而,由于我的一些数据点靠得很近,而另一些数据点离得很远,所以我需要组成轮廓的实际多边形(线串),而不仅仅是轮廓的栅格化图像。
我有点惊讶qhull没有做这样的事情。
使用Mathematica的ListContourPlot,然后导出为SVG工作,但我想使用开源的东西。
我不能使用著名的CONREC算法,因为我的数据不在网格上(给定的x值并不总是有多个y值,反之亦然)。
解决方案不一定要使用python,但必须是开源的,并且可以在Linux上运行。

ds97pgxw

ds97pgxw1#

您可以通过循环遍历集合和路径并使用matplotlib.path.Pathiter_segments()方法来获取顶点。
这里有一个函数,它返回顶点作为一组嵌套的轮廓线列表,轮廓截面和x,y顶点数组:

import numpy as np

def get_contour_verts(cn):
    contours = []
    # for each contour line
    for cc in cn.collections:
        paths = []
        # for each separate section of the contour line
        for pp in cc.get_paths():
            xy = []
            # for each segment of that section
            for vv in pp.iter_segments():
                xy.append(vv[0])
            paths.append(np.vstack(xy))
        contours.append(paths)

    return contours

编辑:

也可以使用未文档化的matplotlib._cntr C模块计算轮廓而不绘制任何内容:

from matplotlib import pyplot as plt
from matplotlib import _cntr as cntr

z = np.array([[0.350087, 0.0590954, 0.002165],
              [0.144522,  0.885409, 0.378515],
              [0.027956,  0.777996, 0.602663],
              [0.138367,  0.182499, 0.460879], 
              [0.357434,  0.297271, 0.587715]])

x, y = np.mgrid[:z.shape[0], :z.shape[1]]
c = cntr.Cntr(x, y, z)

# trace a contour at z == 0.5
res = c.trace(0.5)

# result is a list of arrays of vertices and path codes
# (see docs for matplotlib.path.Path)
nseg = len(res) // 2
segments, codes = res[:nseg], res[nseg:]

fig, ax = plt.subplots(1, 1)
img = ax.imshow(z.T, origin='lower')
plt.colorbar(img)
ax.hold(True)
p = plt.Polygon(segments[0], fill=False, color='w')
ax.add_artist(p)
plt.show()

cgh8pdjw

cgh8pdjw2#

我建议使用scikit-image find_contours
它返回给定标高的等高线列表。
matplotlib._cntr从matplotlib v2.2起被移除(参见here)。

epfja78i

epfja78i3#

轮廓数据似乎位于plt.contour()函数返回的QuadContourSet对象的.allsegs属性中。
.allseg属性是所有级别的列表(可以在调用plt.contour(X,Y,Z,V)时指定)。对于每个级别,您将获得 n x 2 NumPy数组的列表。

plt.figure()
C = plt.contour(X, Y, Z, [0], colors='r')

plt.figure()
for ii, seg in enumerate(C.allsegs[0]):
    plt.plot(seg[:,0], seg[:,1], '.-', label=ii)
plt.legend(fontsize=9, loc='best')

在上面的例子中,只给出了一个水平,所以len(C.allsegs) = 1。你得到:
等高线图

提取的曲线

vfh0ocws

vfh0ocws4#

所有路径的顶点可以简单地通过以下方式作为float64的numpy数组返回:

vertices = cn.allsegs[i][j]  # for element j, in level i

其中cn定义为原始问题:

import matplotlib.pyplot as plt
z = [[0.350087, 0.0590954, 0.002165], [0.144522, 0.885409, 0.378515], 
     [0.027956, 0.777996, 0.602663], [0.138367, 0.182499, 0.460879], 
     [0.357434, 0.297271, 0.587715]] 
cn = plt.contour(z)

更详细:

遍历集合并提取路径和顶点并不是最直接或最快的事情。返回的Contour对象实际上通过cs.allsegs具有片段的属性,它返回shape [level][element][vertex_coord]的嵌套列表:

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

参见参考文献:https://matplotlib.org/3.1.1/api/contour_api.html

相关问题