用python matplotlib绘制阈值以上网格的外边缘

hrirmatl  于 2023-03-19  发布在  Python
关注(0)|答案(2)|浏览(134)

我用matplotlib的pcolor创建了一个2D伪彩色图。我想突出显示值高于阈值的网格的外边缘,如图所示。Goal
我已经通过创建矩形并使用add_patch. This is what I have now绘制了网格的所有边
但是我想我需要先把所有的矩形连接成一个形状,然后画出外边缘,我该怎么做呢?
下面是我的代码:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle

z = np.array([[0,0,0,1,1],[1,0,6,1,3],[1,7,10,1,2],[1,1,0,0,2],[0,0,2,1,2]])
threshold = 5

fig = plt.figure(figsize =(12, 10))
ax = fig.add_axes([0, 0, 1, 1])
c = ax.pcolor(z, cmap = 'viridis')
for i in range(z.shape[0]): 
    for j in range(z.shape[1]): 
        if z[i, j] > threshold:
            ax.add_patch(Rectangle((j, i), 1, 1, fc='none', ec='crimson', lw=5))
ax.axis('off')  
fig.colorbar(c, ax=ax)
plt.show()
cetgtptt

cetgtptt1#

一个简单的黑客(不需要使用任何额外的库)可以创建2层补丁。
1.较低级别的面片需要更宽一些,并具有边框所需的颜色。
1.上层面片基本上是底层图值的重复,并且除了加宽区域外,到处都遮挡了下层面片。
请看下面的代码示例:

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle

z = np.array([[0,0,0,1,1],[1,0,6,1,3],[1,7,10,1,2],[1,1,0,0,2],[0,0,2,1,2]])
threshold = 5

fig = plt.figure(figsize = (6, 5))
ax = fig.add_axes([0, 0, 1, 1])
cmap = matplotlib.cm.get_cmap('viridis')
c = ax.pcolor(z, cmap=cmap)

for i in range(z.shape[0]):
    for j in range(z.shape[1]):
        if z[i, j] > threshold:
            print(f'i = {i}, j = {j}, z = {z[i,j]}')
            ax.add_patch(Rectangle((j-0.06, i-0.06), 1.12, 1.12, fc='crimson', lw=0))

for i in range(z.shape[0]):
    for j in range(z.shape[1]):
        if z[i, j] > threshold:
            rel_value = (z[i, j] - np.min(z)) / (np.max(z) - np.min(z))
            ax.add_patch(Rectangle((j, i), 1, 1, fc=cmap(rel_value), lw=0))

ax.axis('off')  
fig.colorbar(c, ax=ax)
ax.tight_layout()

plt.show()

t9aqgxwy

t9aqgxwy2#

下面是一个使用shapely的解决方案。可能不是最有效的解决方案,但其思想非常简单:在阈值以上的每个像素创建一个矩形,合并它们,并显示结果多边形。

# [...]

from matplotlib.patches import Polygon as mplPolygon
from shapely.geometry import Polygon as shPolygon
from shapely.ops import unary_union

# [...]
c = ax.pcolor(z, cmap = 'viridis')

# Get pixel position above the threshold
Y, X = np.where(z > threshold)
positions = np.dstack((X, Y))[0]

# Create a rectangle per position and merge them.
rectangles = [shPolygon([xy, xy + [1, 0], xy + [1, 1], xy + [0, 1]]) for xy in positions]
polygons = unary_union(rectangles)

# Shapely will return either a Polygon or a MultiPolygon. 
# Make sure the structure is the same in any case.
if polygons.geom_type == "Polygon":
    polygons = [polygons]
else:
    polygons = polygons.geoms

# Add the matplotlib Polygon patches
for polygon in polygons:
    ax.add_patch(mplPolygon(polygon.exterior.coords, fc='none', ec='crimson', lw=5))

# [...]

以下是一些结果示例:

相关问题