2014-11-02 24 views
13

Bei überlappenden Streuung- oder Liniendiagrammen unterschiedlicher Farben mit hoher Dichte kann es hilfreich sein, additive Mischschemata zu implementieren, bei denen die RGB-Farben jedes Markers addiert werden, um die endgültige Farbe in der Zeichenfläche zu erzeugen. Dies ist eine gängige Operation in 2D- und 3D-Render-Engines.Ist eine additive Mischung mit Matplotlib möglich?

jedoch in Matplotlib habe ich fand nur Unterstützung für Alpha/Opazität Blending. Gibt es einen Umweg, oder bleibe ich beim Rendern auf Bitmap und mische sie dann in ein Malprogramm?

Edit: Hier ist ein Beispiel-Code und eine manuelle Lösung.

Diese zwei teilweise überlappende Zufallsverteilungen erzeugen wird:

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') 

Dies produzieren matplotlib folgendes: scatter - no blend

Wie Sie sehen können, gibt es einige überlappende blaue Punkte, die durch verdeckt sind rote Punkte und wir würden sie gerne sehen. alpha/Opazität Durch die Verwendung in matplotlib Mischen, können Sie tun:

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

Welche produzieren die folgende:

scatter - alpha blend (0.5)

Aber was ich wirklich will, ist folgendes:

scatter - additive blend

I kann durch Rendering jeder Parzelle unabhängig in eine Bitmap manuell tun:

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) 

Welche mir folgende Bilder gibt:

scatter - red/blue channels

Was tun Sie können dann ist sie als unabhängige Schichten in Paint.NET/PhotoShop/gimp laden und Additiv nur um sie mischen.

Jetzt wäre es ideal, dies programmatisch in Matplotlib zu tun, da ich Hunderte von diesen verarbeiten werde!

+0

Am einfachsten ist es, ein 2D-Histogramm zu erstellen. Bitte zeigen Sie uns einen Beispielcode und Daten, um uns zu starten. –

+0

Danke, nur ein paar Beispielcode und die Schritte für eine manuelle Lösung hinzugefügt. – glopes

+0

Danke, viel bessere Frage jetzt, werde sehen, was ich tun kann. –

Antwort

7

Wenn Sie nur ein Bild als Ergebnis benötigen, können Sie die Leinwand Puffer als numpy Array erhalten, und dann die Mischung zu tun, hier ist ein Beispiel:

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() 

das Ergebnis:

enter image description here

+0

Ich habe gerade die Funktionen buffer_rgba() ausgecheckt, als Ihre Antwort kam. Ja, ich denke, das ist das Beste, was Matplotlib jetzt machen kann. Aus irgendeinem Grund ist das Endergebnis in meiner Version von Matplotlib nicht so hübsch (Transparenz ist vermasselt), aber ich bin mir sicher, dass ich es mit ein wenig Feinabstimmung jetzt zum Laufen bringen werde. Vielen Dank! – glopes