Bitmap mit Kurvendiagramm einlesen und in Tabelle umwandeln

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 26. September 2012, 13:23

Hi, ich möchte eine Grafik wie diese in eine Tabelle umwandeln. Dafür möchte ich Spalte für Spalte den jeweiligen Wert der Kurve ermitteln. Muss ich da Pixel für Pixel nach einer bestimmten Farbe suchen oder gibt es Funktionen, die dabei etwas helfen?
Trichter
User
Beiträge: 45
Registriert: Montag 20. April 2009, 10:21

Mittwoch 26. September 2012, 13:35

Bei einer Rastergrafik (png, jpg, gif) wird dir wohl nichts anderes übrig bleiben, als die Koordinaten der Punkte mit einer bestimmten Farbe zu suchen und dir daraus eine Kurve zu interpolieren. In dem von dir gezeigten Beispiel kannst du z. B. die Werte der blauen Kurve an den Stellen, wo sie von der roten überdeckt wird gar nicht direkt auslesen.

Bei einer Vektorgrafik (ps, eps, svg) sollte es möglich sein, die Werte direkt aus der Bilddatei mit einer entsprechenden library oder "per Hand" mit einem Skript auszulesen. Da musst du nur in den Formatspezifikationen nachschauen wo und in welchem Format die Daten für die Kurven abgespeichert sind.
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 26. September 2012, 13:44

Leider habe ich keine Vektorgrafik. Die Diagramme stammen aus PDF Dateien. Die einzige Möglichkeit, die ich habe, ist die PDF Datei zum Beispiel in Gimp zu importieren und in eine Bitmap zu wandeln. Mit dem fehlenden Bereich bei der Überschneidung komme ich klar. Entweder kopiere ich die Kurven in getrennte Grafiken und fülle die Lücke von Hand oder ich mache anschließend im Programm eine lineare Verbindung von einem Endpunkt zum anderen.

Meine Frage ist: gibt es eine einfachere Methode als Pixel für Pixel nach Farbwerten zu suchen? Wenn ja, wie? Vielleicht gibt es ja eine Library mit einer Funktion, die selbst in der Lage ist, eine Spalte zu "Parsen" und die Pixelposition zurückliefert. Wenn die in C geschrieben wäre ginge es deutlich schneller als wenn ich das von Hand in Python mache.

Aber wenn nein, wie dann? Was ist besser dafür geeignet? PIL oder Image Magick? Hab leider bei beiden noch keine Funktion gefunden, um an einem bestimmten Pixel den Farbwert zurückzuliefern
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 26. September 2012, 13:50

Am liebsten wäre mir eine Funktion, der ich die gewünschte Spalte und die zu suchende Farbe übergebe und die mir die Position jedes gefundenen Pixels in einer Liste oder Tuple oder was auch immer zurück gibt, da ich sowieso den Mittelwert berechnen will. Wenn mir die Funktion gleich den Mittelwert liefert umso besser
EyDu
User
Beiträge: 4874
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Mittwoch 26. September 2012, 14:12

Das sollte doch mit PIL und Numpy schnell gemacht sein. Bild nach gesuchter Farbe filtern, Spaltenweise den Schwerpunkt bestimmen, Spline durchlegen, Werte auslesen und fertig.
Das Leben ist wie ein Tennisball.
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 26. September 2012, 14:19

EyDu hat geschrieben:Das sollte doch mit PIL und Numpy schnell gemacht sein. Bild nach gesuchter Farbe filtern, Spaltenweise den Schwerpunkt bestimmen, Spline durchlegen, Werte auslesen und fertig.
Wozu noch einen Spline? Wegen den Lücken?
BlackJack

Mittwoch 26. September 2012, 14:34

@burli: Wie bekommst Du die Bilder eigentlich aus dem PDF heraus? Die Methode in Gimp-Importieren dürfte nicht die verlustfreieste sein sofern die Daten in dem PDF nicht als Vektorgrafik gespeichert sind. Denn dann bekommst Du höchstens mit sehr viel Glück die Pixeldaten 1:1 in der Auflösung wie sie in das PDF eingebettet wurden, sondern eine skalierte Pixelgrafik. Die Pixel so wie sie im PDF gespeichert sind, bekommt man unter Linux (Debian) wohl am einfachsten mit ``pdfimages`` aus dem `xppf-utils`- beziehungsweise aus dem `poppler-utils`-Paket exportiert.

Sollte die Grafik dagegen als Vektorgraphik im PDF stecken kann man das PDF beziehungsweise die Seite mit der Grafik in Inkscape importieren. Da könnte man dann eventuell die beiden Linien sauber voneinander trennen ohne dass es Lücken bei den Überschneidungen gibt.
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 26. September 2012, 14:43

@BlackJack: Das PDF, was ich aktuell hab, speichert das wohl als Vektor ab. Aber das kann von Dokument zu Dokument anders aussehen. Deshalb ist die GIMP Methode die einfachste und universellste und funktioniert auch unter Windows.

Und wie bei Inkscape der PDF Import funktioniert weiß ich nicht. Mit "Import" ist mir Inkscape eben jedenfalls heftig abgeschmiert.
EyDu
User
Beiträge: 4874
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Mittwoch 26. September 2012, 15:04

burli hat geschrieben:Wozu noch einen Spline? Wegen den Lücken?
Wegen der Lücken und des Auslesens. Wenn dir natürlich lineare Interpolation reicht und du keine Werte zwischen den "Messungen" haben willst, dann kannst du dir den Schritt natürlich sparen. Da du den Graph diskretisierst, könnte man noch über einen Filter nachdenken, dazu müsste man im Idealfall natürlich das Modell der Messung kennen. Oder du machst es wie ein Igenieur: einfach so lange an den Filterparametern drehen bis es passt :D
Das Leben ist wie ein Tennisball.
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 26. September 2012, 15:11

Ok, vergessen wir mal Splines, Vektoren usw, damit ich mal weiter komme. Gibt es zwischen einfachem Pixel Parsen und Splines noch eine Möglichkeit, den Mittelpunkt der Linie zu finden? Ich will einfach nur für jede Pixelspalte genau einen Wert am Ende heraus bekommen

Wie kann ich "Spaltenweise den Schwerpunkt bestimmen"?
EyDu
User
Beiträge: 4874
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Mittwoch 26. September 2012, 16:36

Für einen roten Graphen zum Beispiel so:

Code: Alles auswählen

import Image
import numpy as np
import scipy.ndimage

colorkey = [255, 0, 0]

image = Image.open("graph.png").convert("RGB")
array = np.array(np.asarray(image))

mask = np.logical_and.reduce([(array[:,:,i]==colorkey[i]) for i in range(3)])
rows, cols = mask.shape

out = np.zeros(mask.shape, np.uint8)
for i in range(cols):
    y = scipy.ndimage.measurements.center_of_mass(mask[:,i])[0]
    out[int(y), i] = 255

out = Image.fromarray(out, mode="L")

out.show()
Die (i, y) sind die Werte von Interesse.
Das Leben ist wie ein Tennisball.
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 26. September 2012, 17:54

Wollte es gerade mal durchlaufen lassen. Bekomme einen ValueError

Code: Alles auswählen

/usr/lib/python2.7/dist-packages/scipy/ndimage/measurements.py:1038: RuntimeWarning: invalid value encountered in double_scalars
  results = [sum(input * grids[dir].astype(float), labels, index) / normalizer for dir in range(input.ndim)]
Traceback (most recent call last):
  File "read.py", line 16, in <module>
    out[int(y), i] = 255
ValueError: cannot convert float NaN to integer
Hab allerdings keine Idee, was der in dem Fall bedeutet
EyDu
User
Beiträge: 4874
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Mittwoch 26. September 2012, 18:06

Ganz offensichtlich ist in der Spalte kein Wert enthalten. Da kann man aber auch selber drauf kommen, wenn man sich mal y und i anschaut ;-)

Code: Alles auswählen

for i in range(cols):
    coloumn = mask[:,i]
    
    if coloumn.any():
        y = cog(coloumn)[0]
        out[int(y), i] = 255
Das Leben ist wie ein Tennisball.
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 26. September 2012, 18:40

Danke, aber es war mein Fehler. Deine erste Version funktioniert, nur der rot Wert hat nicht gestimmt. Es ist nicht 255 sondern nur 192
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 26. September 2012, 18:57

Ach ja, die blaue Kurve ließt er auch, aber an dem Schnittpunkt produziert er genau den Fehler, den ich erwartet habe. Da dürfte auch mit Splines wenig zu machen sein. Und ich fürchte, dass es bei einigen anderen Grafiken gar nicht funktioniert, weil sich manche Linien über eine noch längere Strecke überlappen.

Also muss ich doch versuchen, die Verktorgrafiken aus dem PDF zu holen
Antworten