Unzumutbar langsam

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.
pythontester
User
Beiträge: 17
Registriert: Sonntag 21. Februar 2016, 17:08

Hallo,
ich habe mich vor 2 Wochen beigemacht und eine kleine Bildverarbeitung begonnen.

Das Pythonscript bekommt eine PNG zugespielt. Bildaufnahme von der Kamera, Screenshot oder was auch immer.

Ich habe zum testen ein 8x8,1280x800, 1920x1280.

Ausgelesen habe ich das Bild in mehrere Varianten:
getpixel und 2 geschachtelte For Schleifen. Beim mittlersten Bild betrug die Scanzeit(jedes Pixel auslesen und in ein String gepackt, ohne Verarbeitung)-300 Sekunden

Mit der pix Variante 180 Sekunden.

Getdata, braucht 20 Sekunden zum laden der Tuples in ein numpy array.
Das durchlaufen des Arrays 1024000 braucht ewig. Mit RGBW=str(array[1])y habe ich nach kurzer Zeit abgebrochen. Unzumutbar.
sprintf kam auf 120 Sekunden.
Um ein Fehler auszuschliessen, habe ich einfach mal nur test_string="000:255:128:255" durchlaufen lassen. Selbst das brauch 90 Sekunden.

Meine Geduld und die Motivation ist am Ende.
Es gibt einmal das Bild, original_Bild und in diesen Bild wird Muster_Bild gesucht.

Meine Ansaetze waren jetzt folgende:
1. Ganze PNG wird in for Schleifen durch laufen. Sollte ein Scan Pixel mit den ersten Pixel aus dem Muster uebereinstimmen, vergleicht das Programm die Pixel 1:1.. Solang es Treffer gibt geht es weiter. Ist das Musterbild komplett vorhanden, wird die Position zurueckgegben.

2. Es wurde rechts und unten die Height und Width des Musterbilds abgezogen, als kleine Optimierung. Leider ohne merkbaren Unterschied. 10 Sekunden oder so.

3. Gesamte Bild als Array geladen und die Werte in Strings gepackt. Dauerte 29 Minuten bis ein Bild gefunden. Ok das Muster wurde auch gezielt sehr schwer gewaehlt.

4. Pix in ein definierten Bereich(200,200,600,600), damit nur 400x400 gescanned werden muss. Problem an der Sache, ist das Suchmuster ausserhalb, wird ein unbearbeitetes Bild ausgegben.

Die Bereichsbeschraenkung habe ich nur bei pix oder getpixel, getestet.

Bei den Array war es ein kleiner Zwischenschritt mit crop. Leider mit den oben genannten Problem.

Nach 2 Wochen und unzaehligen Stunden in Google und versuchten Optimierungen habe ich das heute hingeworfen und mich in C++ beigemacht.

Mit lodev und Frust, kam nach knapp 45 Minuten die gleiche Funktion wie in Python raus. Fuer das mittlerste Bild lag, die Zeit bei 32 Sekunden. Ebenfalls unzumutbar.

Allerdings ohne Optimierungen und schlechten Code 4x schneller.

Python soll doch die Uebersprache sein, schnell zu lernen, idiotensicher und plattformuebergreifend. Ich hab eher Frust, allein dieses daemliche Intend System.

in c++ gibt es sowas tolles

Code: Alles auswählen

for (int a=0;a<=10;a++)
      {
            cout<<"Integer"
                   <<a
                   <<endl;
      }
Python zwingt ein ja sein daemliches Intend vor.

Also was hab ich falsch gemacht? 30 Sekunden und 120 Sekunden sind ja nun unterschiedliche Zahlen.

Code: Alles auswählen

#for current_pixel_x in range (scan_range_x_start,full_pixel,1):
		#if kanal_dest == 3:
			#r,g,b=raw_pixel_list[(current_pixel_x)]
		#if kanal_dest==4 :
			#r,g,b,w=raw_pixel_list[(current_pixel_x)]
		#test_string=("{3} :: {0}:{1}:{2}".format(r,g,b,current_pixel_x))
		


Das ganze laeuft auf ein Raspberry Pi B@900Mhz.

Ziel ist eine Bildbearbeitung in einer adequaten Zeit. 30 Sekunden waere ok. Ansonsten dauert eine Bearbeitung einer Bildserie, laenger als der Intervall bis zur naechsten Bildserie.

Mir ist bewusst, das ich noch einiges mehr beruecksichtigen muss. Zb. eine Abweichung von 10 % mit einbinden. Damit minimale Beleuchtungsaenderungen, abgefangen werden.

Anwendungen gibt es viele, Webcam Bilder bearbeiten, simple Kennzeichenerkennung, Smartphone und Tablet Ueberwachung(Screenshotserien erstellen per ADB zb.) Alarmausloesungen bei abweichenden Bildern in ein gewissen Intervall. Erfassung und Auswertung analoger Messdaten.

Aber dafuer muss es erstmal akzeptabel performant werden.

Python ist deswegen die Wahl geworden, da ich mich beruflich auch mit Python in Zukunft beschaeftigen werden muss und es bestimmt nicht schlecht ist, eine so offene Sprache zu lernen. RAD pur. Zudem kann auch eine kleine Anpassung mal eben erfolgen, ohne grosses neukompilieren usw. .
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Willkommen im Forum und zu Python!

Auch wenn du momentan wohl frustriert zu sein scheinst, ist es nicht toll, wenn man sich erst mal auskotzt.

Ok, dein Programm ist langsam, so viel kommt an. Wir koennen dir aber nicht helfen, denn da wir nicht wissen, wie dein Programm aussieht, koennen wir dir auch nicht sagen, warum dein Programm langsam ist.
Da du OpenCV und NumPy nicht erwaehnt, benutzt du sie wohl auch nicht. Darum der Hinweis sich die anzuschauen, Bilderkennung laeuft sehr haeufig darueber und auch hier im Forum gibt es Beispiele dazu.

Ich weiss nicht was du mit "Intends" meinst, aber ich glaube nicht, dass du damit das Paradigma, das es zwar in anderen Sprachen, aber nicht in Python, gibt meinst.
Darum rate ich mal, dass das Indents sein sollen. Da kann ich dann nur sagen: Lesbaren C++ Code rueckt man auch ein und zwar ziemlich aehnlich. Dann bleiben nur die Braces, die damit dann redundant sind. Keine Ahnung wie dich das so stoeren kann.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Von idiontensicher hab' ich nie was gelesen - und ist es ja auch offensichtlich nicht... (falls das fuer Aufregung sorgt: wer mit Kraftausdruecken ala "zwingt ein ja sein daemliches Intend vor." [sic] in den Wald ruft...)

Python ist keine Sprache fuer das hochperformante durchackern von Unmengen von Daten mit selbstgeschriebenen Algorithmen. Das liegt an seiner dynamischen Natur. Da laesst sich schwer auf Maschinen-Code Ebene optimieren.

*Wozu* es aber geeignet ist, ist das anbinden von Bibliotheken, die so etwas tun. Darum findet es in vielen durchaus performance-kritischen Umfeldern. Wie zB terabyteweise Daten von Radioteleskopen durchforsten.

Und fuer deinen Fall heisst die Loesung OpenCV. Damit kannst du auch auf einem Raspberry PI mit Bilddaten Schindluder treiben - ob das schnell genug ist, haengt dann von der konkreten Awendung ab, aber solange du dabei die angebotenen Strukturen und Algorithmen benutzt, wird es nicht langsamer als in C++ auch.

Ich hab' das hier mal gekauft http://www.pyimagesearch.com/2015/03/30 ... nd-python/. Wahr fair fuer was er geboten hat, und das Schnupperkapitel sollte dir einen Eindruck geben.
pythontester
User
Beiträge: 17
Registriert: Sonntag 21. Februar 2016, 17:08

Hallo,
ich arbeite mit

Code: Alles auswählen

import os, sys, subprocess, time
from PIL import Image
import numpy
Ich dachte das kann man an den Funktionen sehen.

Ich will ja kein Schindluder treiben.

Aber die Sache ist doch eher, das selbst 1 024 000 ein string ein Wert zuzuweisen schon 90 Sekunden dauert. Im Vergleich, in C++ liegt die Zeit bei 2,67 Sekunden lauit Code::Blocks. Sagen wir 3 Sekunden. Rund 300 000 Strings/Sekunden auf die gesamte Laufzeit gerechnet. Python liegt irgendwo bei 11377.

Die For schleife ist oben zu sehen. Was ist dadran verkehrt?

Python unter Linux meckert, bei fehlerhaften einruecken. Besonders toll fand ich den Fehler bei folgenden Code

Code: Alles auswählen

for x in range(0,100)
       #code
       #code
       #code
print("For Schleifer durchlaufen")
Ich musste die gesamte For schleife auskommentieren. Da immer wegen Intend Fehler gemeckert wurde.

Und ja ich bin etwas "eigen" was Code Einrueckung und Format angeht. Bei simplen for schleifen in C++, sind auch mal 8 Zeilen Code in einer Zeile :-) .

Ich mag keine aufgeblasenen Sourcecodes, ala boah 1000 Zeilen an 2 Tagen programmiert. Ich steh auf viele, ganz viele Infos auf einmal zu sehen.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@pythontester: ohne Dein konkretes Problem zu kennen, kann man da wenig sagen. Wenn Du wirklich einzelne Bytes in einen String umwandeln willst, mag das ja langsamer sein als Dein C++ Code. Aber das ist nicht ein typischer Anwendungsfall beim Verarbeiten von Bildern. Was willst Du also wirklich machen?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Neben der reinen Ausführungsgeschwindikeit von äquivalenten Programmen in verschiedenen Sprachen, muss man sich über zwei Dinge im klaren sein:

1.) Die Geschwindigkeit hängt u.a. von der Implementierung der Sprache ab (bei Python gibt es z.B. PyPy als Interpreter, der oftmals viel schneller als der Standardinterpreter CPython ist, bei C++ gibt es diverse Compiler, die unterschiedlich optimierten Code erzeugen)
2.) Wie stellt man die Äquivalenz am besten sicher? Bei zwei verschiedenen Sprachen, muss man eben die Besonderheiten berücksichtigen. So sind Strings in Python viel mächtigere Objekte als in C++, wo sie nur dünne Wrapper über ``char *```sind. Zudem sind Strings in Python unveränderlich. Wenn Du z.B. viel ``+=`` in Deinem Code verwendest, um aus kleinen Strings einen großen zu bauen, ist das sehr ineffizient und entspricht algorithmisch nicht mehr dem C++ Code!

Also: Gib uns doch mal ein minimales, lauffähiges Beispiel ohne spezielle Abhängigkeiten, die das Problem aufzeigen. Evtl. ist Dein Ansatz einfach falsch?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
pythontester
User
Beiträge: 17
Registriert: Sonntag 21. Februar 2016, 17:08

Code: Alles auswählen

def speed(deep_scan_x,deep_scan_y, screen_png_dest_file, screen_png_src_file, pos_mode):
	print("Bild in Bild Suche\nScanmodus: "+str(deep_scan_x)+":"+str(deep_scan_y))
	#Bereit stellen der Dest Daten
	#screen_png_dest_file='/home/ich/Entwicklung/python/Test/screenshots/screenshot_aktuell_portrait.png'
	png_dest=Image.open(screen_png_dest_file)
	#pix = png_dest.load()
	png_dest_image_width, png_dest_image_height=png_dest.size
	print ("Zielimage: Weite: "+str(png_dest_image_width)+" Hoehe: "+str(png_dest_image_height))
	current_pixel_width=0;
	current_pixel_height=0;
	#Bereit stellen der Source Daten
	#screen_png_src_file='/home/ich/Entwicklung/python/Test/sources/test_1.png'
	png_src=Image.open(screen_png_src_file)
	dest_pix = png_src.load()
	png_src_image_width, png_src_image_height=png_src.size
	print ("Quellimage: Weite: "+str(png_src_image_width)+" Hoehe: "+str(png_src_image_height))
	current_pixel_width_src=0;
	current_pixel_height_src=0;
	first_pixel_src=remove_transparenz(str(png_src.getpixel((0,0))))
	offset_dest_x=0
	offset_dest_y=0
	src_scan_x=0
	src_scan_y=0
	scan_range_x_start=0
	#scan_range_x_end=png_dest_image_width-png_src_image_width
	scan_range_x_end=png_dest_image_width
	scan_range_y_start=0
	#scan_range_y_end=png_dest_image_height-png_src_image_height
	scan_range_y_end=png_dest_image_height
	#pix = im.load()
	datei=open("debug.txt","w")
	start_zeit=time.time()
	#pix_unsort=numpy.array
	print ("Read Image")
	raw_pixel_list = numpy.array(png_dest.getdata())
	print ("Create Array")
	#sort_pixel_array=[[0 for x in range(png_dest_image_width+1)] for x in range(png_dest_image_height+1)] // geht immer nur bis 800 und 800, obwohl 1280 und 800 sein muessten
	end_zeit=time.time()
	dauer=end_zeit-start_zeit
	print(dauer)
	full_pixel=png_dest_image_width*png_dest_image_height
	#for current_pixel_y in range (scan_range_y_start,scan_range_y_end,deep_scan_y):
	#kanal_dest=len(raw_pixel_list[1])
	#print("Kanaele im Dest. "+str(kanal_dest))
	#for current_pixel_x in range (scan_range_x_start,full_pixel,1):
		#if kanal_dest == 3:
			#r,g,b=raw_pixel_list[(current_pixel_x)]
		#if kanal_dest==4 :
			#r,g,b,w=raw_pixel_list[(current_pixel_x)]
		#test_string=("{3} :: {0}:{1}:{2}".format(r,g,b,current_pixel_x))
		#test_string=(" %d :: %d:%d:%d" % (current_pixel_x,raw_pixel_list[(current_pixel_x)][0],raw_pixel_list[(current_pixel_x)][1],raw_pixel_list[(current_pixel_x)][2]))
		#datei.write("\r\n"+" %d :: %d:%d:%d" % (current_pixel_x,raw_pixel_list[(current_pixel_x)][0],raw_pixel_list[(current_pixel_x)][1],raw_pixel_list[(current_pixel_x)][2]))
		#print("HHW "+test_string)
		#print (current_pixel_x,r,g,b, sep=":")
			#print(str(current_pixel_y)+" ::"+str(current_pixel_x))
			#sort_pixel_array[current_pixel_x-1][current_pixel_y-1]=str(raw_pixel_list[(current_pixel_x)+(current_pixel_y-1*png_dest_image_height)])
			#print(str(current_pixel_x)+":"+str(current_pixel_y))
		#current_pixel_x % 1280 == 0 :
		
	end_zeit=time.time()
	dauer=end_zeit-start_zeit
	print(dauer)
	#print(sort_pixel_array)
	
	#for current_pixel_x in range (scan_range_x_start,scan_range_x_end,deep_scan_x):
		#for current_pixel_y in range (scan_range_y_start,scan_range_y_end,deep_scan_y):
		
			#scan_pix_dest=remove_transparenz(str(pix[current_pixel_x, current_pixel_y]))
			#print(scan_pix_dest)
			#datei.write("\r\n"+str(sort_pixel_array[current_pixel_x][current_pixel_y])+" :: "+remove_transparenz(str(pix[current_pixel_x, current_pixel_y])))
	'''if scan_pix_dest == first_pixel_src :
				datei.write("\r\nTreffer Start")
				scan_pix_dest_off=remove_transparenz(str(pix[current_pixel_x, current_pixel_y]))
				scan_pix_src=remove_transparenz(str(dest_pix[0,0]))
				first_hit=True
				offset_dest_x=current_pixel_x
				offset_dest_y=current_pixel_y
				src_scan_x=0
				src_scan_y=0
				while scan_pix_dest_off == scan_pix_src :
					scan_pix_src=remove_transparenz(str(dest_pix[src_scan_x,src_scan_y]))
					scan_pix_dest_off=remove_transparenz(str(pix[offset_dest_x+src_scan_x,  offset_dest_y+src_scan_y]))
					#datei.write("\r\nHit Offset X:Y"+str(offset_dest_x)+":"+str(offset_dest_y))
					src_scan_y +=1
					if scan_pix_dest_off == scan_pix_src :
						datei.write("\r\nLINE 123:: Offset:"+str(offset_dest_x)+":"+str(offset_dest_y)+" :: Currrent Position:"+str(src_scan_x)+":"+str(src_scan_y)+" :: "+scan_pix_dest_off+" :: "+scan_pix_src)
					
					if src_scan_y==png_src_image_height:
						datei.write("\r\nReihe Fertig")
						src_scan_x +=1	
					if src_scan_y==png_src_image_height and src_scan_x==png_src_image_width:
						datei.write("ENDE")
						datei.close()
						end_zeit=time.time()
						print("Trace Time :"+str(end_zeit-start_zeit))
						print("FOUND")
						if pos_mode=="top_left":
							return current_pixel_x, current_pixel_y
						if pos_mode=="center":
							return current_pixel_x+(png_src_image_width/2), current_pixel_y+(png_src_image_height/2)	
					if src_scan_y==png_src_image_height:
						datei.write("\r\nReihe Fertig")
						src_scan_y=0
			'''
	#print(str(current_pixel_x+1)+" :: "+str(current_pixel_y+1)+" :: "+ str(png_dest.getpixel((current_pixel_x, current_pixel_y))))
	datei.write("ENDE")
	datei.close()
	end_zeit=time.time()
	dauer=end_zeit-start_zeit
	print(dauer)
	return -1,-1
pythontester
User
Beiträge: 17
Registriert: Sonntag 21. Februar 2016, 17:08

Sieht mies aus, ist bestimmt die 10. Variante.

Und hier ein ganz kleine und schnelle C/C++ Variante. G++ Compiler

Code: Alles auswählen

#include <iostream>
#include <time.h>
#include <string>
#include <sstream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;

//int pixel=8*8;
//int pixel=1920*1280;
int pixel=1280*800;

string RGBA="";

char alles[1024]="";

int main()
{
	cout<<pixel<<endl;
    cout << "Simple For Schleife" << endl;
	for (int a=0;a<pixel;a++)
		{
			/*ostringstream sstr;
			sstr<<a<<"::000:255:255:000";
			RGBA=sstr.str();
			Auch sehr lahm, 30 Sekunden
			*/
			int n= sprintf(alles,"%d 000:255:128:255",a);
		}
    return 0;
}
Es wurde jetzt gezielt nur der String Teil getestet. Korrektur der Pythonwerte. Es sind 91 Sekunden, wenn wirklich nur stumpf die For Schleife genommen wird.

Das gesamte Bild in array packen kostete 20 Sekunden. Also ist die Array Methode schlechter, da die auch bei 1/10 des Bildausschnittes alles laedt.

Python bringt mich immer mehr durcheinander. Das gesamte Bild in ein Vector laden, braucht rund 2 Sekunden, das verarbeiten in ein Array rund 6 Sekunden in c++. Also hakt es schon bei dem laden des Bildes in ein array.

Ich komm garnicht mehr klar. Das ist aber ein simpler einzeiler.
Zuletzt geändert von pythontester am Sonntag 21. Februar 2016, 18:55, insgesamt 1-mal geändert.
BlackJack

@pythontester: „Aber die Sache ist doch eher, das selbst 1 024 000 ein string ein Wert zuzuweisen schon 90 Sekunden dauert.“

Äh, wie meinen? Man kann Zeichenketten keine Werte zuweisen, Zeichenketten sind selbst ja schon Werte. Das geht auch in C++ nicht. Also was meinst Du *tatsächlich*? Deine Beiträge sind nicht nachvollziehbar. Wir wissen nur das Du irgendwas machst, und das Dir das zu langsam ist. Und das Du irgendwas in C++ machst. Und dass das schneller ist. Ist es auch äquivalent? Keine Ahnung…

An der ``for``-Schleife ist vielleicht verkehrt das Du überhaupt eine ``for``-Schleife verwendest. Allerdings müsste man da jetzt auch wieder wissen was Du da überhaupt machst, welche Daten reinkommen, wie das Ergebnis aussehen soll. Du musst einfach mal konkreter werden. Was willst Du mit Millionen von Zeichenketten anfangen die jeweils ein Pixel sehr ”geschwätzig” beschreiben?

Wenn Du ”eigen” bist was den Quelltext angeht, dann ist Python nicht die richtige Sprache für Dich. Einrückung und Formatierung, auch Leerraum, und Namensschreibweisen sind in Style Guide for Python Code ”vorgegeben”. Mit dem gleichen Hintergedanken wie all die anderen Stilrichtlinien bei Programmiersprachen und Projekten: Code der das gleiche macht, sollte auch gleich aussehen, egal wer den geschrieben hat. Das erleichtert am Ende jedem das lesen und verstehen und die zusammenarbeit. Zu letzterem gehört auch das präsentieren von Problemen in Foren, damit die Helfer sich da nicht erst in irgendeinen komischen Stil einlesen müssen.

Ganz viele Infos auf einmal zu sehen ist massiv unübersichtlich, also schlecht für die Lesbarkeit. Es sollte weder das Ziel sein möglichst viele Zeilen zu produzieren, noch so wenig wie möglich in dem man so viel wie möglich in die Zeilen quetscht. Beides dient nicht der Lesbarkeit. Der Style Guide gibt eine Anweisung pro Zeile vor und einen eingerückten Block auch wenn der nur aus einer Zeile besteht. Das Semikolon wird man also so gut wie nie brauchen. Das führt trotzdem nicht zu langen Quelltexten weil Python sehr ausdruckststark ist. Mal als Vergleich etwas was gerade in einem anderen Thema hier diskutiert wurde. Java:

Code: Alles auswählen

    public static void main(String args[]) {
        boolean isPrime;
        final ArrayList<Integer> primes = new ArrayList<Integer>();
        primes.add(2);

        for (int candidate = 3; candidate < 2000000; candidate += 2) {
            isPrime = true;
            for (int prime : primes) {
                if (candidate % prime == 0) {
                    isPrime = false;
                    break;
                }
            }
            if (isPrime) {
                primes.add(candidate);
            }
        }

        long result = 0;
        for (int prime : primes) {
            result += prime;
        }
        System.out.println(result);
    }
Und die gleiche Funktion in Python:

Code: Alles auswählen

def main():
    primes = [2]
    for candidate in range(3, 2000000, 2):
        if all(candidate % prime != 0 for prime in primes):
            primes.append(candidate)
    print(sum(primes))
BlackJack

@pythontester: Ähm, jetzt mal bitte äquivalenten Quelltext in beiden Sprachen, ohne irgendwelche auskommentierten Zeilen, also wirklich nur der Code der tatsächlich berücksichtigt werden soll, und dann bitte etwas *sinnvolles*, also zur Not mit einer Beschreibung warum der Code das tut was er tut.

Die Sprache C/C++ gibt es übrigens nicht. Man programmiert entweder in C oder in C++. Idiomatischer Code in den beiden Sprachen ist doch sehr verschieden.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@pythontester:
Dein C-Code mit C++-Anleihen macht was ganz anderes, und in jedem Fall nicht das, was Du möchtest. Wenn Du über die Pixel iterieren willst, musst Du wissen, wie die in dem char* abgelegt sind, bei RGBA z.B. steht jedes 4. Byte für R, jedes (4+1). für G usw. Daher musst Du, um pixelweise zu iterieren, mit einem typisierten Pointer drüber laufen oder das Array entsprechend so für den Indexzugriff konstruieren - einfach bytesweise drüberzulaufen ist Käse.

Den Pythoncode schau ich mir nicht an, das ist mir zu unleserlich.
pythontester
User
Beiträge: 17
Registriert: Sonntag 21. Februar 2016, 17:08

Ok

Code: Alles auswählen

def test_scan(deep_scan_x,deep_scan_y, screen_png_dest_file, screen_png_src_file, pos_mode):
	start_zeit=time.time()
	print("Bild in Bild Suche\nScanmodus: "+str(deep_scan_x)+":"+str(deep_scan_y))
	#Bereit stellen der Dest Daten
	png_dest=Image.open(screen_png_dest_file)
	png_dest_image_width, png_dest_image_height=png_dest.size
	print ("Zielimage: Weite: "+str(png_dest_image_width)+" Hoehe: "+str(png_dest_image_height))
	print ("Read Image")
	raw_pixel_list = numpy.array(png_dest.getdata())
	print ("Create Array")
	#sort_pixel_array=[[0 for x in range(png_dest_image_width+1)] for x in range(png_dest_image_height+1)]//warum wird hier ein Fehler geworfen ab der 800. Stelle?
	end_zeit=time.time()
	dauer=end_zeit-start_zeit
	print(dauer)
	full_pixel=png_dest_image_width*png_dest_image_height
	kanal_dest=len(raw_pixel_list[1])
	print("Kanaele im Dest. "+str(kanal_dest))
	for current_pixel_x in range (0,full_pixel,1):
		if kanal_dest == 3:
			r,g,b=raw_pixel_list[(current_pixel_x)]
		if kanal_dest==4 :
			r,g,b,w=raw_pixel_list[(current_pixel_x)]
		#langsamer
		test_string=("{3} :: {0}:{1}:{2}".format(r,g,b,current_pixel_x))
		#schneller
		#test_string=("%d :: %d:%d:%d" % (current_pixel_x,raw_pixel_list[(current_pixel_x)][0],raw_pixel_list[(current_pixel_x)][1],raw_pixel_list[(current_pixel_x)][2]))
	end_zeit=time.time()
	dauer=end_zeit-start_zeit
	print(dauer)
	return -1,-1
Ausgabe

Code: Alles auswählen

Bild in Bild Suche
Scanmodus: 1:1
Zielimage: Weite: 800 Hoehe: 1280
Read Image
Create Array
21.14890432357788
Kanaele im Dest. 4
154.55368947982788
Der Zweite

Code: Alles auswählen

def test_scan(deep_scan_x,deep_scan_y, screen_png_dest_file, screen_png_src_file, pos_mode):
	start_zeit=time.time()
	print("Bild in Bild Suche\nScanmodus: "+str(deep_scan_x)+":"+str(deep_scan_y))
	#Bereit stellen der Dest Daten
	png_dest=Image.open(screen_png_dest_file)
	png_dest_image_width, png_dest_image_height=png_dest.size
	print ("Zielimage: Weite: "+str(png_dest_image_width)+" Hoehe: "+str(png_dest_image_height))
	print ("Read Image")
	raw_pixel_list = numpy.array(png_dest.getdata())
	print ("Create Array")
	#sort_pixel_array=[[0 for x in range(png_dest_image_width+1)] for x in range(png_dest_image_height+1)]//warum wird hier ein Fehler geworfen ab der 800. Stelle?
	end_zeit=time.time()
	dauer=end_zeit-start_zeit
	print(dauer)
	full_pixel=png_dest_image_width*png_dest_image_height
	kanal_dest=len(raw_pixel_list[1])
	print("Kanaele im Dest. "+str(kanal_dest))
	for current_pixel_x in range (0,full_pixel,1):
		if kanal_dest == 3:
			r,g,b=raw_pixel_list[(current_pixel_x)]
		if kanal_dest==4 :
			r,g,b,w=raw_pixel_list[(current_pixel_x)]
		#langsamer
		#test_string=("{3} :: {0}:{1}:{2}".format(r,g,b,current_pixel_x))
		#schneller
		test_string=("%d :: %d:%d:%d" % (current_pixel_x,raw_pixel_list[(current_pixel_x)][0],raw_pixel_list[(current_pixel_x)][1],raw_pixel_list[(current_pixel_x)][2]))
	end_zeit=time.time()
	dauer=end_zeit-start_zeit
	print(dauer)
	return -1,-1
Zugehoerige Ausgabe

Code: Alles auswählen

Bild in Bild Suche
Scanmodus: 1:1
Zielimage: Weite: 800 Hoehe: 1280
Read Image
Create Array
18.871086359024048
Kanaele im Dest. 4
149.56746816635132
Waere der Pythoncode. Ja aber C++/C kann man ja mischen. C++ konform waere stringstream zum casten, schneller geht printf.
BlackJack

@jerch: Der erste C++-Code enthält ja gar keine Pixeldaten in irgendeiner Form. Die Variable `pixel` enthält die *Anzahl* der Pixel. Das ist so wie es da steht einfach nur sinnlos.
pythontester
User
Beiträge: 17
Registriert: Sonntag 21. Februar 2016, 17:08

Ich hab http://lodev.org/lodepng/picopng.cpp zum PNG einlesen benutzt. Hab ich da ein Denkfehler? Der schiebt doch alle Pixel nacheinander in ein Vector. Um die in ein array zu kriegen, erzeuge ich mir ein mehrdimesnionales array und habe da ja meine "x" und "y" Achse und im Feld steht mein RGBA Wert.

Ich lese immer 4 Bytes ein, und verarbeite diese Werte, fuer ein Pixel.1. Pixel 0-3, der 2. Pixel waere 4-7, der Dritte 8-11 usw. .
BlackJack

@pythontester: Das `sprintf()` ist aus zwei Gründen schneller: es macht etwas anderes, nämlich weniger als der andere Code der alle Pixel in einer Zeichenkette sammelt, und die `tostr()`-Zeile im anderen Code gehört da nicht hin. Das ist superungünstig die dort zu schreiben, weil dadurch quadratisch mehr Arbeit geleistet werden muss, die völlig unnötig ist.
pythontester
User
Beiträge: 17
Registriert: Sonntag 21. Februar 2016, 17:08

Puh ihr habt schon mein Pythoncode und den daemlichen C/C++ Aqualanzcode zerpflueckt. Da wird mein C mit C++ ANleihen Code noch mehr zerrissen.

Ich habe sowas nie studiert, das was ich kann erlesen oder ergoogled. Mir ist es es etwas befremdlich, warum Anfanger und Amateure hier so zerrissen werden.

Jetzt kapier ich garnix mehr.

Code: Alles auswählen

def test_scan(deep_scan_x,deep_scan_y, screen_png_dest_file, screen_png_src_file, pos_mode):
	start_zeit=time.time()
	print("Bild in Bild Suche\nScanmodus: "+str(deep_scan_x)+":"+str(deep_scan_y))
	#Bereit stellen der Dest Daten
	png_dest=Image.open(screen_png_dest_file)
	png_dest_image_width, png_dest_image_height=png_dest.size
	print ("Zielimage: Weite: "+str(png_dest_image_width)+" Hoehe: "+str(png_dest_image_height))
	print ("Read Image")
	raw_pixel_list = numpy.array(png_dest.getdata())
	print ("Create Array")
	#sort_pixel_array=[[0 for x in range(png_dest_image_width+1)] for x in range(png_dest_image_height+1)]//warum wird hier ein Fehler geworfen ab der 800. Stelle?
	end_zeit=time.time()
	dauer=end_zeit-start_zeit
	print(dauer)
	full_pixel=png_dest_image_width*png_dest_image_height
	kanal_dest=len(raw_pixel_list[1])
	print("Kanaele im Dest. "+str(kanal_dest))
	for current_pixel_x in range (0,full_pixel,1):
		#if kanal_dest == 3:
		#	r,g,b=raw_pixel_list[(current_pixel_x)]
		#if kanal_dest==4 :
		#	r,g,b,w=raw_pixel_list[(current_pixel_x)]
		#langsamer
		#test_string=("{3} :: {0}:{1}:{2}".format(r,g,b,current_pixel_x))
		#schneller
		test_string="TESTTESTTEST"
		#test_string=("%d :: %d:%d:%d" % (current_pixel_x,raw_pixel_list[(current_pixel_x)][0],raw_pixel_list[(current_pixel_x)][1],raw_pixel_list[(current_pixel_x)][2]))
	end_zeit=time.time()
	dauer=end_zeit-start_zeit
	print(dauer)
	return -1,-1
Ausgabe davon:

Code: Alles auswählen

Image Engine Raspberry
Bild in Bild Suche
Scanmodus: 1:1
Zielimage: Weite: 800 Hoehe: 1280
Read Image
Create Array
19.60144329071045
Kanaele im Dest. 4
20.632265329360962
pythontester
User
Beiträge: 17
Registriert: Sonntag 21. Februar 2016, 17:08

Ist der Array Zugriff der Flaschenhals und nicht die string Funktionen in der Forschleife?

Code: Alles auswählen

Image Engine Raspberry
Bild in Bild Suche
Scanmodus: 1:1
Zielimage: Weite: 800 Hoehe: 1280
Read Image
Create Array
17.882009983062744
Kanaele im Dest. 4
24.910288095474243

Code: Alles auswählen

test_string=("TESTTESTTEST:%d" % (current_pixel_x))
8 Sekunden.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@BlackJack:
Ja schon klar, so wie es dasteht, macht es überhaupt keinen Sinn.

@pythontester:
Du iterierst mit `pixel` über `alles`, was selbst ein char[] ist. Damit iterierst Du nicht über die Pixel bei RGBA, sondern über alle Bytes, also Pixel*Kanäle. Ich vermutete, dass Du mit Bilddaten in `alles` arbeiten möchtest, das geht aber auf die von Dir gezeigte Weise nicht.

Die Pixeldaten sind so normalerweise so angeordnet:

Code: Alles auswählen

[R1, G1, B1, A1, R2, G2, B2, A2, ...] // Nummer steht für Pixel
Wenn Du hier mit char iterierst, bekommst Du das auch so getrennt --> 0: R1, 1: G1, ..., 4: R2, ... usw.
Das kannst Du so machen, ist aber eher ungünstig, da Du die Indexposition in Pixel (index/4) und Kanal (index%4) jedesmal umrechnen bzw. den Index aus Pixel und Kanal berechnen müsstest. Das können die C-Compiler besser mit typisierten Pointern bzw. verschachelten Arrays.
BlackJack

@pythontester: Dein erster Beitrag war: Python ist unzumutbar langsam und einrücken ist doof und in C++ ist es auch recht langsam. Stell Dir vor Du gehst in eine Fussballkneipe und Dein erster Satz ist „Euer Verein spielt schlecht und die Trikofarben sind doof und Handball ist auch nicht viel besser. “ Würdest Du viel Freundlichkeit erwarten‽ ;-)

Ansonsten ist das zerpflücken von Quelltext grundsätzlich nicht persönlich gemeint, sondern eine sachliche Auseinandersetzung mit dem Code.

Mein grösstes Problem mit Deinen Beiträgen ist das die ziemlich wirr sind, und Du einfach wild irgendwelche Sachen auszuprobieren scheinst, ohne die Datentypen, die Operationen, und was die bewirken, so in Hinsicht auf Speicherverbrauch und Laufzeit, zu kennen. Ausserdem erklärst Du den Sinn nicht. Und das was man erahnen kann, ein Bild in einem anderen Bild zu suchen, löst man wie schon gesagt wurde nicht selbst. Dafür gibt es bereits Bibliotheken. Egal ob man das in Python oder in C++ macht. OpenCV wäre für beide Sprachen eine Möglichkeit.
pythontester
User
Beiträge: 17
Registriert: Sonntag 21. Februar 2016, 17:08

@jerch, ich bin gerade komplett verwirrt.
std::vector<unsigned char> buffer, image;

if(image.size() > 4) std::cout << "width: " << w << " height: " << h << " first pixel: " << std::hex << int(image[0]) << int(image[1]) << int(image[2]) << int(image[3]) << std::endl;

Sagt picopng in der Beispiel C++. Ich habe doch ein char array/Vektor und muss mir doch die RGBA Werte selbst besorgen. Ich muss den Byte doch irgendwie in ein Hexformat oder Dec Format kriegen. Damit es schoen lesbar ist.

Ich hatte diese Struktur fuer ein Array angelegt
X Y R:G:B:A

Und 4 Bytes sind 1 Pixel, bei groesser als 1 Reihe in die naechste Spalte springen. So habe ich ein sauberes array, mit den ich arbeiten kann und kann Pixelwerte menschlich lesbar holen mit position[421][657].
Antworten