it-roy-ru.com

Сюжеты Matplotlib теряют прозрачность при сохранении в формате .ps/.eps

У меня возникла проблема с попыткой сохранить некоторые графики с прозрачными эллипсоидами на них, если я попытаюсь сохранить их с расширениями .ps/.eps. 

Вот график, сохраненный как .png: png

Если я решу сохранить его как .ps/.eps, вот как это будет выглядеть: ps

Как мне удалось обойти это, было использовать ImageMagick для преобразования исходного PNG в PS. Единственная проблема заключается в том, что размер изображения в формате png составляет около 90 КБ, а после преобразования он становится чуть меньше 4 МБ. Это нехорошо, так как у меня много таких изображений, и сборка моего латексного документа займет слишком много времени. У кого-нибудь есть решение этого?

36
astromax

Проблема в том, что eps изначально не поддерживает прозрачные пленки.

Есть несколько вариантов:

  1. растеризуйте изображение и вставьте его в файл eps (как предлагает @Molly) или экспортируйте в pdf и конвертируйте с помощью какого-либо внешнего инструмента (например, gs) (который обычно также зависит от растеризации)

  2. «имитировать» прозрачность, давая цвет, который выглядит как прозрачный на заднем фоне.

Я обсуждал это наверняка однажды в списке рассылки matplotlib , и я получил предложение растеризовать, что неосуществимо, так как вы получаете либо пикселизированные, либо огромные цифры. И они не очень хорошо масштабируются, когда помещаются, например, в публикацию.

Я лично использую второй подход, и хотя он не идеален, я нашел его достаточно хорошим. Я написал небольшой скрипт Python , который реализует алгоритм из этого SO поста для получения твердого RGB-представления цвета с прозрачностью

ПРАВКА

В конкретном случае вашего графика попробуйте использовать ключевое слово zorder, чтобы упорядочить детали. Попробуйте использовать zorder=10 для синего эллипса, zorder=11 для зеленого и zorder=12 для hexbins. 

Таким образом, синий должен быть ниже всего, затем зеленый эллипс и, наконец, гексбины. И сюжет должен быть читаемым и сплошными цветами. И если вам нравятся оттенки синего и зеленого в png, вы можете попробовать поиграть с mimic_alpha.py.

Правка 2

Если вы на 100% уверены, что у вас есть для использования eps, мне приходит на ум несколько способов (и они определенно более уродливы, чем ваш сюжет): 

  1. Просто нарисуйте границы эллипса поверх гексбинов. 
  2. Получите центр и амплитуду каждого шестиугольника (возможно, отбросьте все нулевые ячейки) и создайте график рассеяния , используя ту же карту цветов, что и в hexbin, и отрегулируйте размер и форму маркера, как вам нравится. Вы могли бы хотеть перерисовать границы эллипсов поверх этого
23
Francesco Montesano

Другой вариант - сохранить их в формате PDF.

savefig('myfigure.pdf')

Это работает с pdflatex, если по этой причине вам нужно было использовать eps, а не svg.

10
P.R.

У меня такая же проблема. Чтобы избежать растеризации, вы можете сохранить изображение в формате pdf, а затем запустить (по крайней мере в unixish системах) в терминале:

pdftops -eps my.pdf my.eps

Который дает файл .eps в качестве вывода.

7
Poshpaws

Вы можете растеризовать рисунок перед сохранением, чтобы сохранить прозрачность в файле eps:

ax.set_rasterized(True)
plt.savefig('rasterized_fig.eps')
7
Molly

Я решил это следующим образом: 1) добавив set_rasterization_zorder (1) при определении области рисунка:

fxsize=16
fysize=8
f = figure(num=None, figsize=(fxsize, fysize), dpi=180, facecolor='w',
edgecolor='k')
plt.subplots_adjust(
left    = (18/25.4)/fxsize, 
bottom  = (13/25.4)/fysize, 
right   = 1 - (8/25.4)/fxsize, 
top     = 1 - (8/25.4)/fysize)
subplots_adjust(hspace=0,wspace=0.1)
#f.suptitle('An overall title', size=20)
gs0 = gridspec.GridSpec(1, 2)

gs11 = gridspec.GridSpecFromSubplotSpec(1, 1, subplot_spec=gs0[0])

ax110 = plt.Subplot(f, gs11[0,0])
f.add_subplot(ax110)

ax110.set_rasterization_zorder(1)

2) zorder = 0 в каждом альфа = любое число на графике:

ax110.scatter(xs1,ys1  , marker='o', color='gray'  , s=1.5,zorder=0,alpha=0.3)#, label=label_bg)

и 3) наконец растеризованный = True при сохранении:

P.savefig(str(PLOTFILENAME)+'.eps', rasterized=True)

Обратите внимание, что это может не работать должным образом с ключевым словом transparent для savefig, поскольку цвет RGBA с альфа <1 на прозрачном фоне будет отображаться так же, как цвет RGB с альфа = 1.

2
Hugo

Как упоминалось выше, лучший и самый простой выбор (если вы не хотите терять разрешение) - это растеризовать фигуру.

f = plt.figure()
f.set_rasterized(True)

ax = f.add_subplot(111)

ax.set_rasterized(True)
f.savefig('figure_name.eps',rasterized=True,dpi=300)

Таким образом, вы также можете управлять размером по dpi. На самом деле, вы также можете поиграть с zorder ниже, вы хотите применить растеризацию:

ax.set_rasterization_zorder(0)

Примечание: важно сохранить f.set_rasterized (True), когда вы используете функции plt.subplot и plt.subplot2grid. В противном случае, метка и область галочки не появятся в файле .eps

1
Luis DG

Мое решение состоит в том, чтобы экспортировать график в формате .eps, загрузить его, например, в Inkscape, затем разгруппировать график, выбрать объект, для которого требуется установить прозрачность, и просто отредактировать непрозрачность заливки на вкладке «Заливка и обводка». , 

Вы можете сохранить файл как .svg, если хотите настроить его позже, или экспортировать изображение для публикации. 

0
ab-user