Bilder ohne Zwischenspeichern übergeben

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.
Antworten
Speedy77
User
Beiträge: 18
Registriert: Samstag 13. März 2021, 13:14

Hallo liebe Wissenden,

ich arbeite auf einem System: RPi4 mit Python3

ich stehe im Bereich Programmierung eher am Anfang und habe mir bis jetzt nur kleinere Projekte vorgenommen...

Bei meiner derzeitigen Aufgabe, die ich mir selbst vorgenommen habe geht es um eine Zählerauslesung eines Stromzählers. Hier habe ich mir mittels Elektronik und etwas Zeit etwas gebastelt, um von dem Zähler Bilder zu machen und diese dann mittels tesseract in text umzuwandeln...
Hierbei wird in frei bestimmbaren Abständen das Licht angeschaltet, und eine frei bestimmbare Anzahl von Bildern mit der WebCam geschossen...
Ich habe mich für 6 Durchläufe (ergibt 6 x Bilder holen) entschieden. nun wird das Bild bei der Auflösung mit ca. 14,4 MB auf der Speicherkarte zwischengespeichert um es hinterher wieder zu öffnen.
Zum Einen finde ich es als den größten Zeitfresser im Ablauf des Programms, als Zweiten als nicht gerade speicherkartenschonend bei 6 Bilder x 60 je Std. x 24 Std/Tag = 8640 Bilder am Tag und als Drittes eigentlich überflüssig. Ich suche eine Variante das Bild von SS direkt an P0 zu übergeben ohne es zwischenzuspeichern. Da das Bild anschliesend weiterbearbeitet wird (siehe unten) bekomme ich logischer weise den Fehler:

Code: Alles auswählen

	AttributeError: 'pygame.Surface' object has no attribute 'crop'
wenn ich SS direkt an P0 übergebe...

Gibt es da nicht eine Lösung ohne

Code: Alles auswählen

	pygame.image.save(SS,'/home/pi/Dokumente/PyPro/B.BMP')
Der gesamte Code zur Bildbearbeitung...

Code: Alles auswählen

	def MakePic(Turns):
		PL=[]
		PV=0
		aktTime = time.localtime()
		aktDate = time.strftime("%d.%m.%Y, %H:%M:%S", aktTime)
		aktSekJahr = (((((((aktTime[7] - 1) * 24) * 60) + aktTime[3]) * 60) + aktTime[4]) * 60) + aktTime[5]
		for i in range(Turns):
			SS = C.get_image()
			pygame.image.save(SS,'/home/pi/Dokumente/PyPro/B.BMP')
			P0 = Image.open('/home/pi/Dokumente/PyPro/B.BMP')
			P0 = C.get_image()
			PV= i % 2
			for D1 in range(PCAD):
				SN = '/home/pi/Dokumente/PyPro/P'+str("{0:03d}".format((D1*100)+i))+'.bmp'
				P = P0.crop((PCA[D1][0][0]+PV, \
						PCA[D1][0][1]+PV, \
						PCA[D1][1][0]+PV, \
						PCA[D1][1][1]+PV))
				P = P.point(lambda x: 255-x)
				P = P.point(lambda i: 0 if i < PCA[D1][2][0] else 255)
				P = P.convert('1')
				Pix = P.load()
				PL.append(Pix)
				P.save(SN, 'BMP')
		return PL, aktTime, aktDate, aktSekJahr
Vielen Dank für eure Unterstützung...

Speedy77
Sirius3
User
Beiträge: 18226
Registriert: Sonntag 21. Oktober 2012, 17:20

Kryptischer kann man ja nicht programmieren. Variablennamen sollten aussagekräftig sein. SS, PL, PV, P0? Wer soll das verstehen?
Du verrätst auch nicht was C oder PCA ist.
Du schreibst ein Bild B.BMP, lädst das gleich wieder in P0 rein, überschreibst aber P0 sofort wieder. Was soll das?
Was hat pygame hier zu suchen?
Natürlich geht das viel einfacher, wenn man wüßte, was Du da machst.
Und auch wenn nicht, könnte man die Bilder in einer RAM-Disk speichern.
Variablennamen schreibt man nach Konvention komplett klein, Eingerückt wird mit 4 Leerzeichen pro Ebene.
Speedy77
User
Beiträge: 18
Registriert: Samstag 13. März 2021, 13:14

Hi Siri,

(sorry für den Kommetar)

die vom IPhone hätte freundlicher reagiert, aber das war das erste an was ich denken musste... noch einmal Sorry... :mrgreen:

Also ich versuch Deinen Rückschuss erstmal zu entwirren...
Kryptischer kann man ja nicht programmieren. Variablennamen sollten aussagekräftig sein.
Das diese Aussage kommt, hatte ich mir fast gedacht... Aber nichts für ungut... Ich verstehe meine Variablen ja und normalerweise bin ich eher der Typ, der sich Tage lang durch Google kämpft und nicht direkt in einem Forum fragt. (Ist mein erstes mal... :wink: ) Da ich aber schon seid ca. 2 Wochen suche, habe ich mich dafür entschieden und möchte meinen Code nicht unbedingt komplett anpassen, Sorry... Der Code war also nie für die Öffentlichkeit bestimmt.
SS, PL, PV, P0? Wer soll das verstehen?
Du verrätst auch nicht was C oder PCA ist.
Da ich darauf hingewiesen habe, dass es mir lediglich um die ein Zeile geht, und ich hier ja eigentlich nur mit Spezialisten schreibe, und wie schon erwähnt meinen ersten Versuch in einem Forum starte, war mir nicht klar wie weit ich hier was beschreiben muss...

SS ist das Bild was ich mir von der WebCam hole, die über pygame initialisiert wird

Code: Alles auswählen

pygame.camera.init()
CL = pygame.camera.list_cameras()
C = pygame.camera.Camera(CL[0],(W,H))
C.start()
W und H steht übrigens für Width and Height und Sorry hier habe ich nach dem Kommata die Leerzeichen vergessen...

PCA ist ein Array mit den Bereichen die aus dem Bild B.BMP für die Texterkennung ausgelesen werden

Code: Alles auswählen

PCA = np.array([[[ 915,740],[1675,940],[130]],
                [[1730,740],[1830,940],[120]]])
Du schreibst ein Bild B.BMP, lädst das gleich wieder in P0 rein, überschreibst aber P0 sofort wieder. Was soll das?
Genau... pygame holt das Bild von der WebCam, dann speichere ich es und mit Image von PIL öffne ich das bild wieder zur Bearbeitung...
Da ich die einzelnen Bereiche aus dem Bild dann nach der Bearbeitung wieder abspeichere ist P0 (picture_zero ... hies die Variable früher) für mich eine temporäre Variable die bei jedem Turn (Durchlauf) wieder überschrieben wird... Und sofort ??? ich bearbeite erst die Teilbereiche, speichere diese ab und dann hole ich mir wieder ein neues Bild von der WebCam... :?:
Die einzelnen gespeicherten Bilder der Bereiche aus dem Hauptbild, werden dann mit dem Pixelversatz von PV überlagert und alles wird in ein Schwarzweiss-Bild konvertiert:

Code: Alles auswählen

P = P.convert('1')
Diese Überlagerung ergibt extrem scharfe Konturen ohne Rand und Störpixel für die Texterkennung, die geschätzt zu 95% ohne und 99,9% mit meiner nachträglich Fehlerkorrektur funktioniert.

Was hat pygame hier zu suchen?
Das habe ich in dem vorhergehenden Absatz ja mit erläutert... Holt das Bild von der WebCam...
Natürlich geht das viel einfacher, wenn man wüßte, was Du da machst.
Und auch wenn nicht, könnte man die Bilder in einer RAM-Disk speichern.
Bitte ich bin für alles offen,... Mir reichen auch Stichpunkte und Ansätzem damit ich mich durch Google und Co. informieren kann...
Variablennamen schreibt man nach Konvention komplett klein, Eingerückt wird mit 4 Leerzeichen pro Ebene.
Zu den Variablen habe ich die Erklärung weiter oben schon gegeben... Warum bei Copy&Paste die Tabs und Einrücker von Remotedesktop Pi4 - Geany nicht mit den Tabs und Abständen hier zusammenpassen weiß ich nicht und habe aber auch keine Lust jede Textzeile zu korrigieren... Bei Geany rücke ich immer mit einem Tab (entspricht 4 Leerzeichen) ein...

Für Hilfe und weitere Fragen bin ich sehr dankbar...

Es geht immer noch nur um die eine Zeile:

Code: Alles auswählen

pygame.image.save(SS,'/home/pi/Dokumente/PyPro/B.BMP')
Mit freundlichen Grüßen

Speedy77
Sirius3
User
Beiträge: 18226
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn man so schlechte Variablennamen benutzt, dann hat man das Problem selbst meist nicht richtig verstanden. Meine Gehirnkapazität ist mir jedenfalls zu schade, um mir zu merken, was SS bedeutet.
Über einen Index iteriert man nicht und man benutzt keine kryptischen Indizes.
An die Daten von einem pygame-Surface kommt man über get_view.

Code: Alles auswählen

IMAGE_AREAS = [
    ((915, 740), (1675, 940), 130),
    ((1730, 740), (1830, 940), 120),
]

def capture_pictures(camera, turns):
    pictures = []
    for i in range(turns):
        surface = camera.get_image()
        rgb = np.array(surface.get_view('3'))
        gray = rgb.mean(axis=2)
        for (x1,y1), (x2,y2), threshold in IMAGE_AREAS:
            subpicture = (gray[x1:x2, y1:y2] >= threshold) * 255
            pictures.append(subpicture)
    return pictures

def main():
    pygame.camera.init()
    cameras = pygame.camera.list_cameras()
    camera = pygame.camera.Camera(cameras[0],(WIDTH, HEIGHT))
    camera.start()
    pictures = capture_pictures(camera, turns)
    camera.stop()
    ...

if __name__ == "__main__":
    main()
Wie Du dann mit den Bitmaps weiter arbeitest, hast Du ja nicht gezeigt, kann ich also auch nicht verbessern.

Und statt dieses Indexverwurstung mit time benutzt man datetime.
Speedy77
User
Beiträge: 18
Registriert: Samstag 13. März 2021, 13:14

Hallo Sirius,

der Ansatz sieht für mein Vorhaben sehr gut aus und lässt mich den unerwünschten Zwischenschritt isolieren...

Die Variante mit time habe ich anfangs gewählt, da ich den Zeitstempel wollte und da hast Du natürlich recht ist datetime die wesentlich bessere Variante...

Und ich habe es ja gewusst... Ich finde hier die Spezies die die Lösung zu meinem Problem kennen...

werde dies morgen mal einarbeiten...

Danke und noch eine schöne Nacht...

Speedy77
Speedy77
User
Beiträge: 18
Registriert: Samstag 13. März 2021, 13:14

Guten Morgen Sirius3,

ich habe es zwar bei meinem verwurstetem Code belassen, habe aber Deinen Vorschlag eingearbeitet und was soll ich sagen...

Ich ziehe den Hut... Funktioniert perfekt

Danke

PS: und ich werde mich bei den nächsten Projekten bemühen die Verwurstelungen zu vermeiden und mich an die Konventionen zu halten
Antworten