2015-11-05 265 views
9

有人知道 - 在Matplotlib中 - 如何用半透明色生成一個漂亮的填充輪廓圖?如果contourf()傳遞用半透明顏色的顏色表,它產生小的間隙的填充區域之間:Matplotlib:用透明色填充等值線圖

small gaps between areas

按照docs,這不是錯誤(」 contourf() [...]不繪製多邊形邊「)。爲了繪製邊緣,建議「通過調用contour()添加線輪廓」。但是,這並不好看無論是作爲邊緣變得太不透明:

edges are too opaque

你可以玩弄的contour()linewidth說法,但不會有什麼幫助。有任何想法嗎?

下面是重現該問題的代碼(我用的是面向對象的API,但結果是pyplot相同):

import matplotlib 
import numpy as np 
from matplotlib.figure import Figure 
from matplotlib.backends.backend_agg import FigureCanvasAgg 

# generate some data 
shape = (100, 100) 
x_rng = np.linspace(-1, 1, shape[1]) 
y_rng = np.linspace(-1, 1, shape[0]) 
x, y = np.meshgrid(x_rng, y_rng) 
z = np.sqrt(x**2 + y**2) 

# create figure 
width_inch, height_inch = 5, 5 # results in 500x500px with dpi=100 
fig = Figure() 
fig.set_size_inches((width_inch, height_inch)) 
FigureCanvasAgg(fig) 
ax = fig.add_axes([0., 0., 1., 1.]) 
ax.set_axis_off() 

# define some colors with alpha < 1 
alpha = 0.9 
colors = [ 
    (0.1, 0.1, 0.5, alpha), # dark blue 
    (0.0, 0.7, 0.3, alpha), # green 
    (0.9, 0.2, 0.7, alpha), # pink 
    (0.0, 0.0, 0.0, alpha), # black 
    (0.1, 0.7, 0.7, alpha), # light blue 
] 
cmap = matplotlib.colors.ListedColormap(colors) 
levels = np.array(np.linspace(0, z.max(), len(colors))) 
norm = matplotlib.colors.BoundaryNorm(levels, ncolors=cmap.N) 

# contourf plot produces small gaps between filled areas 
cnt = ax.contourf(x, y, z, levels, cmap=cmap, norm=norm, 
        antialiased=True, linecolor='none') 

# this fills the gaps, but it makes them too opaque 
# ax.contour(x, y, z, levels, cmap=cmap, norm=norm, 
#   antialiased=True) 

# the same is true for this trick: 
# for c in cnt.collections: 
#  c.set_edgecolor("face") 

filename = "/tmp/contourf.png" 
fig.savefig(filename, dpi=100, transparent=True, format="png") 

PS:同樣的情節看起來不錯,與SVG後端。

PPS:pcolormesh()有類似的問題:

ax.pcolormesh(x, y, z, cmap=cmap, norm=norm, 
       edgecolor="face", antialiased=True) 

enter image description here

+0

備註:''antialiased = True''似乎有效果(但關閉它也不會產生好的結果)。 – weatherfrog

回答

1

我不知道是否能解決你的問題,因爲「好看」是有些主觀,但只有這樣,才能得到一個沒有任何反鋸齒問題或鋸齒狀邊緣的圖像,當放大到該級別時將使用矢量格式,如SVG,EPS等(正如您指出的那樣)。

SVG(可縮放矢量圖形)

enter image description here

如果關閉抗鋸齒,你可以擺脫邊緣和「不透明」的模糊的,但你會得到一個鋸齒邊緣以高縮放級別出現在圓圈中。你可以嘗試增加DPI說,300DPI,並保存爲TIFF:

TIFF,300DPI,抗鋸齒=假

enter image description here

抗鋸齒將會沿着融合圖像因此混合透明粉紅色和綠色會產生較暗的顏色,即使透明度在概念上相同,也可能會產生看起來更不透明的印象。

我得到不同的前瞻性從代碼的輸入/輸出以下各節評論的結果,但結果太主觀說哪個更好看:

設置輪廓,但不是edgecolor:

ax.contour(x, y, z, levels, cmap=cmap, norm=norm, 
      antialiased=True) 

# the same is true for this trick: 
# for c in cnt.collections: 
#  c.set_edgecolor("face") 

不要設置輪廓,但設置邊緣顏色:

# ax.contour(x, y, z, levels, cmap=cmap, norm=norm, 
#   antialiased=True) 

# the same is true for this trick: 
for c in cnt.collections: 
    c.set_edgecolor("face") 

但他們是否好看就看解釋。我發現的另一件事是我的圖像查看器內置了自己的抗鋸齒功能,因此您可能想在嘗試進行比較時關閉此功能。

+0

感謝您選擇這個。我通過繪製沒有透明度的問題解決了這個問題 - 使用RGB顏色作爲RGBA顏色的「佔位符」 - 並在後處理步驟中應用透明度。 我已經提出了你的答案,但沒有接受它,因爲它實際上並沒有解決原來的問題。 – weatherfrog