Array mit fester Größe erstellen?

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.
einfachich
User
Beiträge: 13
Registriert: Mittwoch 27. April 2011, 17:55

Hallo,

in Sprachen wie Java und C muss man beim Anlegen eines Array die Größe festlegen,
also die Anzahl der zu speichernden Elemente.

Beispiel:
Java:
int[] x = new int[213];

C:
int x[213];

Ich weiß, dass man in Python ein Array anlegt mit:
a = []

Elemente fügt man hinzu mit:
a.append(45)
a.append(345)
a.append(12)
usw...

Das geht zwar recht bequem aber die Laufzeit lässt zu wünschen übrig, da bei jedem Hinzufügen eines Elementes das "alte" Array in ein größeres kopiert wird. Es liegt nicht fern, dass es bei 500000 Elementen (Bildverarbeitung) etwas langsam werden könnte.

Deshalb möchte ich von Beginn an die Größe fest vorgeben und über die Indizes auf die einzelnen Elemente zugreifen.

Weiß jemand Rat? danke + gruß
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Also zunächst einmal ist das, was Du da zeigst und beschreibst, in Python kein Array, sondern eine Liste.

Sollte die Laufzeit wirklich ein Problem sein, so leg einfach eine Liste mit Dummy-Werten an. Das scheint bei CPython etwas zu bringen, siehe dazu dieser Thread.

Alternativ kannst Du Dir ja mal das Array-Modul angucken.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

einfachich hat geschrieben:Das geht zwar recht bequem aber die Laufzeit lässt zu wünschen übrig, da bei jedem Hinzufügen eines Elementes das "alte" Array in ein größeres kopiert wird.
Wie kommst du den auf diese falsche Annahme?
BlackJack

@einfachich: Für Bildbearbeitung solltest Du entsprechende Bibliotheken verwenden und das nicht in reinen Python-Schleifen über die Pixel implementieren. Wenn Dir das mit `append()` zu langsam ist, wirst Du mit einer Liste mit Dummywerten und Indexzugriffen auch nicht glücklich werden. Selbst wenn das in einigen Python-Implementierungen etwas schneller sein kann, bleibt es doch verhältnismässig langsam.
einfachich
User
Beiträge: 13
Registriert: Mittwoch 27. April 2011, 17:55

Danke, soweit.

In Java heißt es Array, in C nennt man es Vektor. Im Grunde ist damit jeweils fast das Gleiche gemeint.

Den Gedanken, eine Liste mit Dummywerten zu erstellen, hatte ich auch. Aber irgendwie, ich hatte gehofft, dass sich das auch ohne Dummywerte festlegen lässt, wie in C. Denn der Datentyp ist ja klar.

Ich weiß, dass ich bei C bleiben sollte, wenn es mir um Performance geht. Aber es muss doch auch in Python eine einfache Möglichkeit geben, zu sagen: "Lege im Speicher n Felder für float-Werte an."

Wenn ich eine Liste mit n Dummy-Werten erstelle, muss ich mit einer leeren Liste anfangen und nach und nach Dummy-Werte per Schleife hinzufügen. Sprich: Es muss n Mal die Ausgangsliste in eine neue Liste kopiert werden, die um genau 1 größer ist. Ich habe große Schwierigkeiten mich damit anzufreunden, gerade wenn es um Listen mit z.B. 1280*1024=1.310.720 Listen-Einträgen geht.

Ich möchte von Anfang an sagen können: Mache mir eine Liste, in die n Werte passt.

Leider muss ich mit Python arbeiten, sonst würde ich auf eine andere Sprache ausweichen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

einfachich hat geschrieben:In Java heißt es Array, in C nennt man es Vektor.
In C nennt man das doch auch Array, oder nicht?
einfachich hat geschrieben: Im Grunde ist damit jeweils fast das Gleiche gemeint.
Eine Liste in Python ist aber vom Prinzip etwas anderes, da diese dynamisch erweiterbar ist.
einfachich hat geschrieben: Aber es muss doch auch in Python eine einfache Möglichkeit geben, zu sagen: "Lege im Speicher n Felder für float-Werte an."
Hast Du Dir mal das Array-Modul angeguckt? Ansonsten gibt es eben z.B. PIL als spezialisiertes Modul für Bildbearbeitung.
einfachich hat geschrieben: Wenn ich eine Liste mit n Dummy-Werten erstelle, muss ich mit einer leeren Liste anfangen und nach und nach Dummy-Werte per Schleife hinzufügen. Sprich: Es muss n Mal die Ausgangsliste in eine neue Liste kopiert werden, die um genau 1 größer ist.
Wie bereits gesagt wurde ist dem eben nicht so!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
einfachich
User
Beiträge: 13
Registriert: Mittwoch 27. April 2011, 17:55

Hallo BlackJack,

ich arbeite mit openVC. Nur eben das Problem, uns wurde am Montag vorletzten Montag gesagt, ihr müsst mit Python arbeiten. Da gibt es zwar Matrizen usw, habe ich habe Stunden gesessen, negative Werte zu speichert. Das lässt es irgendwie nicht zu.

Es geht darum, die Grauwerte zweier aus zwei verschiedenen Perspektiven aufgenommenen SW-Bilder zu subtrahieren. Da kann es zu negativen Werten kommen. Das Problem: Negative Werte werden automatisch zu 0.0, was das Ergebnis verfälscht. Also dachte ich, die einzelnen Pixel in Array/Felder/Listen... zu verarbeiten, die auch negative Werte zulassen.
einfachich
User
Beiträge: 13
Registriert: Mittwoch 27. April 2011, 17:55

Hallo Hyperion,

in C heißt es je nach Literatur Array oder Vektor. Vektor ist der deutsche Begriff für das englische Array und wird so z.B. in "o'reilly - C - kurz&gut" verwendet. Ich wollte mit den Beispielen klar machen, welche Datenstruktur und nach welchem Prinzip ich suche, eine Feld fester größe zu deklarieren.

Du schreibst:
Eine Liste in Python ist aber vom Prinzip etwas anderes, da diese dynamisch erweiterbar ist.

Ja, das weiß ich. Ich möchte eine etwas in der Art eines Arrays, bei dem man von vorn herein die Größe festlegen kann.

Du schreibst:
Hast Du Dir mal das Array-Modul angeguckt? Ansonsten gibt es eben z.B. PIL als spezialisiertes Modul für Bildbearbeitung.

Danke, ich schaue mir das an.

Du antwortest:
Wie bereits gesagt wurde ist dem eben nicht so!

Woher nimmst Du diese Information? Bzw, wie stellst Du Dir denn sonst vor, dass es funktioniert. Auf die dynamisch erweiterbare Datenstruktur mit Direktzugriff auf die einzelnen Elemente, die anders arbeitet, als von mir beschrieben, bin ich gespannt. ;) ;)

Andererseits, da Python-Listenelemente verschiedener Größe und Typs sein können, wird es für alle Listenelemente eine Schlüsselliste geben müssen. Spätestens diese muss aber sukzessive mit Schlüsseln (Referenzen) erweitert werden.

Na, egal, vielleicht weiß es jemand genau. Ich guck mir das Arraymodul erst Mal an.
Zuletzt geändert von einfachich am Mittwoch 27. April 2011, 19:09, insgesamt 1-mal geändert.
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Für 500000 Appends würde Python die Liste nach meiner derzeitigen Einschätzung ca. 60 Mal erweitern [1]. Das ist schon deutlich von den von dir angepeilten 500000 Reallocs entfernt. Anders gesagt: Listen in Python arbeiten prinzipiell schon so, wie du es dir vorstellst - aber natürlich ist es sinnvoll, die Liste vorausschauend zu vergrößern. Und das macht Python auch.

*1 http://www.laurentluce.com/?p=271
einfachich
User
Beiträge: 13
Registriert: Mittwoch 27. April 2011, 17:55

Danke :)
BlackJack

@einfachich: In Java heisst das nicht Array beziehungsweise das was in Java Array heisst, gibt es in Python nicht. In Java gibt es das `List`-Interface und als konkrete Implementierung `ArrayList`. *Das* entspricht am ehesten dem Datentyp `list` in Python. In C gibt es nichts Vergleichbares -- zumindest nicht in der Standardbibliothek.

In C geht es auch nicht ohne Dummywerte denn irgend etwas ist ja auch dort im Array gespeichert. Je nach dem wo/wie es deklariert wurde Nullbytes oder "zufällige" Werte.

Du solltest Dir besser anschauen wie man zwischen `numpy` und opencv Daten austauscht: http://opencv.willowgarage.com/document ... and-opencv
einfachich
User
Beiträge: 13
Registriert: Mittwoch 27. April 2011, 17:55

In Ordnung.

PS:
und Danke
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Viel Wind um wenig.
Hast du mal eine Liste mit 500.000 Werten initialisiert? Das kostet so gut wie nix.

Code: Alles auswählen

>>> import timeit
>>> timeit.Timer('liste = [0]*500000').timeit(1)
0.005980014801025391
Das Python array (aus dem array-Modul) bringt in der Hinsicht übrigens gar nichts (im Gegenteil), weil es einen "initializer" braucht. Im günstigsten Fall ist das eine Liste, dann dauert die Erzeugung rund 10x so lange wie die einer entsprechenden Liste.
Nun könnte man auf die Idee kommen, es ginge schneller, wenn man als initializer einen Iterator nähme, aber das Gegenteil ist der Fall.
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Hallo einfachich,

wenn du effiziente Arrays für mathematische Operationen in Python suchst, ist numpy das was du suchst. numpy ist die Referenz in Sachen wissenschaftliches Rechnen mit Python. In diesem Zusammenhang solltest du dir auch scipy.ndimage anschauen. Das ist eine Bildverarbeitungsbibliothek die sehr gut mit numpy integriert ist und automatisch mit scipy kommt.

Von Vektor sollte man in C nicht sprechen, da man üblicherweise das hier damit verbindet.
Ansonsten gibt es eben z.B. PIL als spezialisiertes Modul für Bildbearbeitung.
Wenn es um Bildverarbeitung geht, kommst du damit nicht weit. Ist aber trotzdem einen Blick Wert weil man damit Bilder in quasi beliebigen Formaten speichern und laden kann.
Leider muss ich mit Python arbeiten, sonst würde ich auf eine andere Sprache ausweichen.
Na, Na... Ich habe schon ganze Bildverarbeitungssysteme, die jetzt weltweit in Produktionsanlagen eingesetzt werden, in Python implementiert. Python und C sind ein gutes Team und können gerade im Bereich BV Wunder bewirken.

MFG HerrHagen
deets

einfachich hat geschrieben:ich arbeite mit openVC. Nur eben das Problem, uns wurde am Montag vorletzten Montag gesagt, ihr müsst mit Python arbeiten. Da gibt es zwar Matrizen usw, habe ich habe Stunden gesessen, negative Werte zu speichert. Das lässt es irgendwie nicht zu.

Es geht darum, die Grauwerte zweier aus zwei verschiedenen Perspektiven aufgenommenen SW-Bilder zu subtrahieren. Da kann es zu negativen Werten kommen. Das Problem: Negative Werte werden automatisch zu 0.0, was das Ergebnis verfälscht. Also dachte ich, die einzelnen Pixel in Array/Felder/Listen... zu verarbeiten, die auch negative Werte zulassen.
Ich nehme mal an, du arbeitest mit OpenCV, nicht openVC. Und damit ist auch diese ganze Diskussion hier irrelevant, denn die gesamten Matrixoperationen, die du da durchnudelst, finden *eh* in C/C++ statt. Und wenn deine Bilddaten einen vorzeichenlosen Datentypen haben, und du auch noch eine Subtraktionsfunktion benutzt, die in die Saettigung geht (ein in der Bildverarbeitung durchaus gaengiges Ding... etwas minus etwas ist schwarz, und nicht ploetzlich wieder grellweiss), dann benutzt du das halt falsch.

Du musst deine Graustufenbilder erstmal zB in ein float32-Format bringen, und dann kannst du da auch munter rumsubtrahieren.

Hab' gerade nochmal geschaut, eine dazu hilfreiche Funktion ist

http://opencv.willowgarage.com/document ... nvertscale

mit deinem Bild als src, und einem dest-Array das du mit

http://opencv.willowgarage.com/document ... #createmat

erstellt hast, und zB den Typen CV_32FC1 waehlst. Oder auch einen ganzzahligen Typen.
einfachich
User
Beiträge: 13
Registriert: Mittwoch 27. April 2011, 17:55

Bitte hilf mir noch Mal.
Folgendes Skript erhält 2 sw-Bilder:

Code: Alles auswählen

import sys, cv, math, numpy

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print "left, right Quellen fehlen"
        sys.exit(0)

    b1 = cv.LoadImage(sys.argv[1])
    b2 = cv.LoadImage(sys.argv[2])
    a = cv.CreateMat(b1.height, b1.width, cv.CV_64FC1)
    cv.Sub(b1,b2,a)
Was mache ich falsch?

Code: Alles auswählen

E:\>python test2.py left.png right.png

OpenCV Error: Assertion failed (src1.size == dst.size && src1.type() == dst.type()) in unknown function, file ..\..\..\..\ocv\opencv\modules\core\src\arithm.cpp, line 1788
Traceback (most recent call last):
  File "test2.py", line 18, in <module>
    cv.Sub(b1,b2,a)
cv.error: src1.size == dst.size && src1.type() == dst.type()
Zuletzt geändert von einfachich am Mittwoch 27. April 2011, 21:37, insgesamt 3-mal geändert.
deets

Eine Woche Vollzeit? Das sollte sich doch in 2-3h maximal runterprogrammieren lassen. Wie dem auch sei, nichts von dem hat ja gross was mit Python zu tun. Sondern der OpenCV. Dafuer gibt's ein Buch, das ist ganz gut. Und ich denke euer Lehrer/Ausbilder/Prof hat euch da auch noch was an die Hand gegeben.
einfachich
User
Beiträge: 13
Registriert: Mittwoch 27. April 2011, 17:55

Ähm, nein. Außer ein paar Qullen im Netz und ein Skript mit ein paar Beispielen, die nicht mit der Aufgabe zu tun haben, hat uns unser Prof nicht gegeben. Das Buch openCV habe ich mir bestellt.

Das Problem sind die ständigen Fehlermeldungen und ich finde keine Doku, wie die zu verstehen sind. Siehe oben.

PS. Beide bilder sind gleich groß und vom gleichen Typ.
Zuletzt geändert von einfachich am Mittwoch 27. April 2011, 21:40, insgesamt 1-mal geändert.
deets

Naja, die Fehlermeldung ist doch recht eindeutig. Du hast entweder eine falsche Dimension, oder einen falschen Datentypen. Wenn deine Bilder gleichgross sind (was ich jetzt mal annehme), dann ist es zweiteres. Und das ist doch auch klar. Du machst ja nicht, was ich dir gesagt habe: du musst *erst* die Matrix konvertieren, also deine Bilder in den Zahlenraum CV_64FC1 ueberfuehren, mit ConvertScale. *Dann* kannst du die subtrahieren.
einfachich
User
Beiträge: 13
Registriert: Mittwoch 27. April 2011, 17:55

oh, das klingt interessant. werds gleich probieren.
Antworten