2015-11-05 6 views
9

Знает ли кто-нибудь - в Matplotlib - как создать красивую заполненную контурную графику с полупрозрачными цветами? Если contourf() передается с палитры полупрозрачных цветов, она производит небольшие зазоры между заполненными областях:Matplotlib: заполненный контурный участок с прозрачными цветами

small gaps between areas

Согласно docs, это не ошибка (»contourf() [...] не делает нарисуем края многоугольника "). Чтобы нарисовать края, предлагается «добавить контуры линий с вызовами на contour()». Но это хорошо или как края опаковые не смотрите:

edges are too opaque

Вы можете играть с linewidth аргументом contour(), но это не помогает. Есть идеи?

Вот код, который воспроизводит проблему (я использую объектно-ориентированный 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

Если отключить антиалиасинг, вы можете избавиться от размытия краев и «непрозрачности», но вы получите зазубренный-край внешний вид в кругах с высоким уровнем масштабирования. Вы можете попробовать увеличить точки на дюйм, чтобы сказать, 300dpi, и сохранение в формате TIFF:

Tiff, 300dpi, сглаживание = False

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

Смежные вопросы