在相交的 Matplotlib 补丁上统一应用 Alpha
Posted
技术标签:
【中文标题】在相交的 Matplotlib 补丁上统一应用 Alpha【英文标题】:Apply Alpha Uniformly on Intersecting Matplotlib Patches 【发布时间】:2021-11-25 22:15:58 【问题描述】:我正在寻找有关如何使用 Matplotlib 补丁创建绘图的建议,其中透明度可以统一应用于所有补丁。具体来说,如果我有重叠的补丁,我希望将 alpha
值应用于两个补丁的联合,而不是单独应用。交叉区域应与单个结构看起来相同,如果补丁定义(例如颜色)存在差异,则应优先添加到集合中的最后一个补丁。
下面是一个不起作用的简单示例。
import matplotlib.pylab as plt
import matplotlib as mpl
f, (ax1, ax2) = plt.subplots(1, 2, tight_layout=True)
# assign alpha to individual patches
patch1 = mpl.patches.Rectangle((0.4, 0.4), .5, .5, alpha=0.5)
patch2 = mpl.patches.Rectangle((0.1, 0.1), .5, .5, alpha=0.5)
ax1.add_patch(patch1)
ax1.add_patch(patch2)
ax1.set_title('individual patches')
# try assigning alpha to collection
patch3 = mpl.patches.Rectangle((0.4, 0.4), .5, .5)
patch4 = mpl.patches.Rectangle((0.1, 0.1), .5, .5)
collection = mpl.collections.PatchCollection([patch3, patch4], alpha=0.5)
ax2.add_collection(collection)
ax2.set_title('patch collection')
# overlap region is darker
plt.show()
基于网上的一些其他讨论,我研究了一些其他技术,例如从与alpha=1
的交叉点渲染图像,然后用alpha < 1
绘制此图像,但因为图像在我的应用程序中会很大,我更喜欢使用几何图元,例如补丁。
关于如何完成这项工作的任何想法?
【问题讨论】:
您是否需要使用 alpha(即是否还有其他需要透明度的绘图元素?)如果没有,并且您只是在绘制这些补丁,您可以通过绘制一个不使用 Alpha 通道的纯色 不幸的是,我确实需要 alpha,因为这些补丁被应用在 pcolormesh 或 imshow 之上,我希望在整个图像中都可见。 这能回答你的问题吗? matplotlib Circle patch with alpha produces overlap of edge and facecolor 很遗憾没有,但我已经通读了几遍试图理解它。在那个问题中,边缘与面部重叠,这与我的情况不同,补丁在哪里相交。 这能回答你的问题吗? Plot unions of polygons in matplotlib 【参考方案1】:如果它对任何人有帮助,我想出了一个基于修改 this 讨论的解决方案。
import matplotlib.pylab as plt
import shapely.geometry as sg
import shapely.ops as so
from typing import List
class Structure:
""" stores a shapely shape and a facecolor """
def __init__(self, shape, fc):
self.shape = shape
self.fc = fc
#constructing the first rect as a polygon
bot_left = Structure(shape=sg.box(0.1,0.1,0.6,0.6), fc='blue')
#a shortcut for constructing a rectangular polygon
top_right = Structure(shape=sg.box(0.4,0.4,0.9,0.9), fc='red')
#constructing the first rect as a polygon
top_left = Structure(shape=sg.box(0.1,0.4,0.6,0.9), fc='brown')
#constructing the first rect as a polygon
bot_right = Structure(shape=sg.box(0.4,0.05,0.9,0.6), fc='blue')
def overlap_union(structures: List[Structure]) -> List[Structure]:
""" returns polygons """
structs_exist = []
for s in structures:
for _s in structs_exist:
intersection = s.shape & _s.shape
_s.shape = _s.shape - intersection
structs_exist.append(s)
return structs_exist
def overlap_union_merge(structures: List[Structure]) -> List[Structure]:
""" merges two polygons if they intersect with same facecolor """
structs_exist = []
for s in structures:
append_this_struct = True
for _s in structs_exist:
if s.shape & _s.shape:
if s.fc == _s.fc:
_s.shape = _s.shape | (s.shape - _s.shape)
append_this_struct = False
else:
_s.shape = _s.shape - s.shape
if append_this_struct:
structs_exist.append(s)
return structs_exist
structs_before = [bot_left, top_right, top_left, bot_right]
plot_edges = True
ec = 'k' if plot_edges else 'none'
_, (ax1, ax2, ax3) = plt.subplots(1, 3, tight_layout=True, figsize=(15, 5))
for struct in structs_before:
xs, ys = struct.shape.exterior.xy
ax1.fill(xs, ys, alpha=0.4, fc=struct.fc, ec=ec)
ax1.set_title('naive (no union)')
structs_after = overlap_union(structs_before)
for struct in structs_after:
xs, ys = struct.shape.exterior.xy
ax2.fill(xs, ys, alpha=0.4, fc=struct.fc, ec=ec)
ax2.set_title('simple version')
structs_after_merge = overlap_union_merge(structs_before)
for struct in structs_after_merge:
xs, ys = struct.shape.exterior.xy
ax3.fill(xs, ys, alpha=0.4, fc=struct.fc, ec=ec)
ax3.set_title('merged version')
for ax in (ax1, ax2, ax3):
ax.set_xlim(0, 1)
ax.set_ylim(0,1)
plt.show()
【讨论】:
以上是关于在相交的 Matplotlib 补丁上统一应用 Alpha的主要内容,如果未能解决你的问题,请参考以下文章
为啥 matplotlib.PatchCollection 会弄乱补丁的颜色?
探索 dotnet core 为何在 Windows7 系统需要补丁的原因
matplotlib 中 Poly3DCollection 图的透明度