Подтвердить что ты не робот

Можно ли добавлять аддитивное смешение с matplotlib?

При работе с перекрывающимися разбросами плотности или линейными графиками разных цветов может быть удобно реализовать аддитивные схемы смешивания, где цвета RGB каждого маркера объединяются для получения окончательного цвета на холсте. Это обычная операция в 2D и 3D-рендерерах.

Однако в Matplotlib я нашел поддержку для смешивания альфа/непрозрачности. Есть ли какой-либо окольный способ сделать это, или я придерживаюсь рендеринга в растровое изображение, а затем смешивая их в какой-то программе рисования?

Изменить: вот пример кода и ручное решение.

Это приведет к получению двух частично перекрывающихся случайных распределений:

x1 = randn(1000)
y1 = randn(1000)
x2 = randn(1000) * 5
y2 = randn(1000)
scatter(x1,y1,c='b',edgecolors='none')
scatter(x2,y2,c='r',edgecolors='none')

Это даст в matplotlib следующее: scatter - no blend

Как вы можете видеть, есть некоторые перекрывающиеся синие точки, которые закрыты красными точками, и мы хотели бы их увидеть. Используя сочетание альфа/непрозрачность в matplotlib, вы можете:

scatter(x1,y1,c='b',edgecolors='none',alpha=0.5)
scatter(x2,y2,c='r',edgecolors='none',alpha=0.5)

Что будет производить следующее:

scatter - alpha blend (0.5)

Но я действительно хочу следующее:

scatter - additive blend

Я могу сделать это вручную, создав каждый график независимо от растрового изображения:

xlim = plt.xlim()
ylim = plt.ylim()
scatter(x1,y1,c='b',edgecolors='none')
plt.xlim(xlim)
plt.ylim(ylim)
scatter(x2,y2,c='r',edgecolors='none')
plt.xlim(xlim)
plt.ylim(ylim)
plt.savefig(r'scatter_blue.png',transparent=True)
plt.savefig(r'scatter_red.png',transparent=True)

Что дает мне следующие изображения:

scatter - red/blue channels

Что вы можете сделать тогда, загрузите их как независимые слои в Paint.NET/PhotoShop/gimp и просто добавьте их.

Теперь идеальным было бы сделать это программно в Matplotlib, так как я буду обрабатывать сотни из них!

4b9b3361

Ответ 1

Если вам нужно только изображение в качестве результата, вы можете получить буфер холста как массив numpy, а затем выполнить смешение, вот пример:

from matplotlib import pyplot as plt
import numpy as np

fig, ax = plt.subplots()
ax.scatter(x1,y1,c='b',edgecolors='none')
ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)
ax.patch.set_facecolor("none")
ax.patch.set_edgecolor("none")
fig.canvas.draw()

w, h = fig.canvas.get_width_height()
img = np.frombuffer(fig.canvas.buffer_rgba(), np.uint8).reshape(h, w, -1).copy()

ax.clear()
ax.scatter(x2,y2,c='r',edgecolors='none')
ax.set_xlim(-4, 4)
ax.set_ylim(-4, 4)
ax.patch.set_facecolor("none")
ax.patch.set_edgecolor("none")
fig.canvas.draw()

img2 = np.frombuffer(fig.canvas.buffer_rgba(), np.uint8).reshape(h, w, -1).copy()

img[img[:, :, -1] == 0] = 0
img2[img2[:, :, -1] == 0] = 0

fig.clf()

plt.imshow(np.maximum(img, img2))
plt.subplots_adjust(0, 0, 1, 1)
plt.axis("off")
plt.show()

результат:

enter image description here