![]() |
Thread läuft nicht parallel --
Hi Leute,
ich sitze jetzt die halbe Nacht und irgendwie werde ich nicht schlau daraus. Vielleicht könnt ihr mir da weiter helfen. Also die Grundaufgabe ist ein Bildausschnitt in einem großem Bild zu suchen. Die einfache Abarbeitung dauert ca.12 sec bei extrem großen Bildern. Nun kam mir die Idee das Bild aufzuteilen und mit einzelnen Threads Mehrkern-Prozessor besser auszulasten und somit eine erhöhte Geschwindigkeit zu erreichen. Also TThread Klasse benutzt. Sie läuft auch sauber durch nur ist sie etwas langsamer als die normale Abarbeitung. Ich habe es folgendermaßen getestet. Ich habe zwei kleine Bildauschnitte die in dem großen Bild gesucht werden. Also habe ich 4 Bitmaps erstellt. 1 suchbitmap und ein Bitmap in dem gesucht wird für jeder thread. da es 2 Threads sind auch 2x2 Bitmaps. Gedanke: " Sie kommen sich nicht in die Quere und können gleichzeitig suchen. Hier mal die Thread unit
Delphi-Quellcode:
und hier der Aufruf aus dem MainPart
unit imgCompareThread;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.ComCtrls, Vcl.Menus,Vcl.ImgList,SelectKit,picturehelper; type TImageSearch = class(TThread) private { Private-Deklarationen } protected procedure Execute; override; public constructor Create(CreateSuspended : boolean ;var SearchBMP,ScreenBMP : TBitmap;var xyPoint : TPoint);overload; end; implementation { TImageSearch } procedure TImageSearch.Execute; begin { Thread-Code hier einfügen } NameThreadForDebugging(AnsiString(inttostr(GetTickCount))); end; constructor TImageSearch.Create(CreateSuspended: Boolean; var SearchBMP: TBitmap; var ScreenBMP: TBitmap;var xyPoint: TPoint); var x,y: Integer; tempBMP : Tbitmap; rectSource,rectDest : TRect; toBreak : boolean; i: Integer; k: Integer; begin inherited Create (CreateSuspended) ; toBreak := false; // ****************************************************************************** // oben links suchen // ****************************************************************************** Try //showMessage('Suche'); FreeOnTerminate := true; // Declaration tempBMP := Tbitmap.Create; tempBMP.Width := SearchBMP.Width; tempBMP.Height := SearchBMP.Height; tempBMP.PixelFormat := SearchBMP.PixelFormat; for x := 0 to ScreenBMP.Width-tempBMP.Width-1 do begin if toBreak then break; for y := 0 to ScreenBMP.Height-tempBMP.Height-1 do begin // Ausschnittsbereich festlegen rectDest := rect(0,0,tempBmp.Width,tempBmp.Height); rectSource := rect(x,y,x+tempBmp.Width,y+tempBmp.Height); tempBmp.Canvas.CopyMode := cmSrcCopy; // Ausschnittsbereich kopieren rectSource tempBmp.Canvas.CopyRect(rectDest,ScreenBMP.Canvas,rectSource); //imgTemp.Picture.Bitmap.Assign(tempBMP); if Compare2Bitmaps(80,SearchBMP,tempBMP) = ceOK then begin //Label1.Caption := 'Zeit: '+FloatToStr((GetTickCount - startTime)/1000)+' s'; toBreak := true; //showMessage(inttostr(x)+'-'+inttostr(y)); xyPoint.X := x; xyPoint.Y := y; break; end; end; end; Finally tempBMP.Free; End; end; end.
Delphi-Quellcode:
Wo liegt das Problem? Ich habe auch schon probiert mir propertys die Parameter ganz normal zu übergeben und danach zu starten. Führte aber zu keiner Besserung.
var
k : integer; aktScreen1,aktScreen2 : TBitmap; suchbild1,suchbild2 : TBitmap; begin Try fstarttimer := GetTickCount; aktScreen1 := TBitmap.Create; aktScreen2 := TBitmap.Create; suchbild1 := TBitmap.create; suchBild2 := TBitmap.Create; ScreenCapture(aktScreen1); ScreenCapture(aktScreen2); suchbild1.LoadFromFile('C:\Users\s0n\Documents\Delphi\gw2item_neu\Win32\Debug\i1.bmp'); suchBild2.LoadFromFile('C:\Users\s0n\Documents\Delphi\gw2item_neu\Win32\Debug\i2.bmp'); ThreadsRunning := 2; with TImageSearch.Create(false,suchbild1,aktScreen1,xyPoint1) do begin OnTerminate := ThreadDone; end; with TImageSearch.Create(false,suchbild2,aktScreen2,xyPoint2) do begin OnTerminate := ThreadDone; end; Finally suchbild1.Free; suchbild2.Free; aktScreen1.Free; aktScreen2.Free; End; Ich hoffe ihr könnt mir auf die Sprünge helfen, da ich den eindruck habe er arbeitet es nacheinander ab. Grüße s0n |
AW: Thread läuft nicht parallel --
Es sieht für mich so aus, als würde dein Code im Create anstatt in der Execute Methode des Threads ausgeführt werden.
Außerdem musst du mit dem Freigeben der Ressourcen warten bis die Threads fertig sind und das sind sie mit hoher Wahrscheinlichkeit nicht, wenn du im Finally-Block angekommen bist. |
AW: Thread läuft nicht parallel --
Du hast den Arbeitscode in die Create-Routine des Thread geschrieben, so wird der natürlich auch darin ausgeführt. Die Stelle ist als
Delphi-Quellcode:
markiert.
{ Thread-Code hier einfügen }
Der Code gehört nach Execute! Außerdem musst Du dafür sorgen, dass während der Verarbeitung die temporären Objekte weiter existieren und nicht in der aufrufenden Routine zerstört werden (fertige die Kopien in Create an). |
AW: Thread läuft nicht parallel --
Code im Konstruktor eines TThread Objekts wird im Kontext des aufrufenden Threads (üblicherweise der Main-Thread) ausgeführt.
|
AW: Thread läuft nicht parallel --
Außerdem sehe ich kein Start oder Resume Aufruf außerhalb des Threads.
|
AW: Thread läuft nicht parallel --
Ist das denn nötig? Soweit ich gesehen habe steht CreateSuspended ja auf false.
|
AW: Thread läuft nicht parallel --
Zitat:
Ins Bett gehen... Nach dem 1. Kaffee den Code in die Execute verschieben und feststellen, es war gestern doch zu spät für so eine Routine... Mavarik |
AW: Thread läuft nicht parallel --
Mal abgesehen von der falschen Verwendung von Threads...
Das Kopieren eines Ausschnitts der ScreenBMP in die tempBmp ist hier der eigentlich bremsende Faktor. Es erscheint mir sinnvoller die Funktion "Compare2Bitmaps" so anzupassen, dass statt zwei kompletter Bitmaps, nur der angegebene Bereich verglichen wird.
Delphi-Quellcode:
Compare2Bitmaps(80, SearchBMP, ScreenBMP, rectSource);
|
AW: Thread läuft nicht parallel --
hiho,
mmhhhhhh......... also ich habe es jetzt so abgeändert. in formCreate
Delphi-Quellcode:
dann der Thread Aufruf vom Button
aktScreen1 := TBitmap.Create;
aktScreen2 := TBitmap.Create; suchbild1 := TBitmap.create; suchBild2 := TBitmap.Create; suchbild1.LoadFromFile('C:\Users\blabla\Pictures\i1.bmp'); suchBild2.LoadFromFile('C:\Users\blabla\Pictures\2.bmp');
Delphi-Quellcode:
Und hier der komplette thread Part
procedure TfrmMain.searchInventar(Sender: TObject);
begin fstarttimer := GetTickCount; ScreenCapture(aktScreen1); ScreenCapture(aktScreen2); ThreadsRunning := 2; // Threads erzeugen aber nicht ausführen Thread1 := TImageSearch.Create(true); Thread1.OnTerminate := ThreadDone1; Thread1.Searchbmp.Assign(suchbild1); Thread1.screenbmp.Assign(aktScreen1); Thread1.NameThreadForDebugging('Thread1'); Thread2 := TImageSearch.Create(true); Thread2.OnTerminate := ThreadDone2; Thread2.Searchbmp.Assign(suchbild2); Thread2.screenbmp.Assign(aktScreen2); Thread2.NameThreadForDebugging('Thread2'); // Threads starten Thread1.start; Thread2.start; end;
Delphi-Quellcode:
im OnTerminate wollte ich die XY Points holen doch die geben leider immer null zurück.
unit imgCompareThread;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.ComCtrls, Vcl.Menus,Vcl.ImgList,SelectKit,pictureHelper; type TImageSearch = class(TThread) private fScreenBMP : TBitmap; fSearchBMP : TBitmap; fxyPoint : Tpoint; { Private-Deklarationen } protected procedure Execute; override; public //constructor Create(CreateSuspended : boolean ;var SearchBMP,ScreenBMP : TBitmap;var xyPoint : TPoint);overload; constructor Create(CreateSuspended: boolean); overload; property ScreenBMP : TBitmap read FScreenBMP write FScreenBMP; property SearchBMP : TBitmap read FSearchBMP write FSearchBMP; property xyPoint : TPoint read fxyPoint write fxyPoint; end; implementation { TImageSearch } procedure TImageSearch.Execute; var x,y: Integer; tempBMP : Tbitmap; rectSource,rectDest : TRect; toBreak : boolean; i: Integer; k: Integer; begin toBreak := false; // ****************************************************************************** // Inventar oben links suchen // ****************************************************************************** Try // Declaration tempBMP := Tbitmap.Create; tempBMP.Width := FSearchBMP.Width; tempBMP.Height := FSearchBMP.Height; tempBMP.PixelFormat := FSearchBMP.PixelFormat; for x := 0 to FScreenBMP.Width-tempBMP.Width-1 do begin if toBreak then break; for y := 0 to FScreenBMP.Height-tempBMP.Height-1 do begin // Ausschnittsbereich festlegen rectDest := rect(0,0,tempBmp.Width,tempBmp.Height); rectSource := rect(x,y,x+tempBmp.Width,y+tempBmp.Height); tempBmp.Canvas.CopyMode := cmSrcCopy; // Ausschnittsbereich kopieren rectSource tempBmp.Canvas.CopyRect(rectDest,ScreenBMP.Canvas,rectSource); //imgTemp.Picture.Bitmap.Assign(tempBMP); if Compare2Bitmaps(60,FSearchBMP,tempBMP) = ceOK then begin toBreak := true; fxypoint.x := x; fxypoint.y := y; with Tform.Create(nil) do begin FormStyle := fsStayOnTop; Name := 'frmSelection2'; Position := poDesigned; left := x-3; top := y-3; Width := 56; Height := 56; borderstyle := bsNone; color := clWhite; for k := 0 to 5 do begin visible := true; sleep(100); visible := false; sleep(100); end; free; end; break; end; end; end; Finally tempBMP.Free; End; end; constructor TImageSearch.Create(CreateSuspended: Boolean); begin fScreenBMP := TBitmap.Create; fSearchBMP := TBitmap.Create; inherited Create(CreateSuspended); end; end.
Delphi-Quellcode:
Was mache ich da falsch? Wenn ich die Bilder einzeln suche, also ohne Thread gleicher Code, findet er sie einwandfrei.
Dec(ThreadsRunning);
xyPoint2 := Thread2.xyPoint; showMessage('X2: ' +inttostr(Thread2.xyPoint.X)+' Y2: '+inttostr(Thread2.xyPoint.Y)); Die Version von letzter Nacht mach auch alles richtig. Also werte werden richtig zurück gegeben. Grüße s0n |
AW: Thread läuft nicht parallel --
Zitat:
Bin für Kritik und Verbesserung jederzeit zu haben ^^ Grüße s0n |
AW: Thread läuft nicht parallel --
Du weißt dass weder VCL-Zugriffe noch TCanvas threadsave sind?
|
AW: Thread läuft nicht parallel --
Deshalb war der Gedanke für jeden Thread unterschiedliche Bitmaps zu verwenden. Das sie nicht Threadsave sind habe ich in der Hilfe gelesen.
Also Thread 1 bekommt screen1 und search1 und thread 2 bekommt screen2 und search2. Somit sollten sich die Canvas doch nicht ins Gehege kommen oder sehe ich das falsch ? Grüße s0n |
AW: Thread läuft nicht parallel --
Liste der Anhänge anzeigen (Anzahl: 1)
Leider ist dem nicht so. Ich habe mal ein Microdemo angehängt bei dem ein paar Bitmaps parallel erzeugt `bemalt` und gespeichert werden (Pfad anpassen). Wenn man sich das Ergebnis ansieht wird klar dass Canvas nicht Threadsave ist. Über lock ließe sich das ganze verhindern, aber dann ist der Gewinn durch die Threads ebenfalls weg. Ich weiß ja nicht was genau der Vergleich machen soll, aber über Scanlines (wenn Dir das hilft) sollte es keine Probleme geben.
|
AW: Thread läuft nicht parallel --
TBitmap und Co. wären Threadsave, wenn sie "unabhängig" verwendet werden und nichts Globales nutzen.
Aber sie verwenden intern weitere Klasseninstanten und da werden vorallen für TFont, TBrush uvm. globale Instanzen verwendet (wenn man selber nichts eigenes angibt und die Werte auf "Standard" läßt) und da dort überall auf die selben globalen Singletons zugegrifen wird muß es zwangsläufig schief gehn, jenachdem was man mit dem Bitmap macht. Was man machen kann, das Bitmap für die VCL blocken, wenn es z.B. in einem TPicture steckt oder sonstwie angezeigt wird, im Hauptthread sich den Anfang der Daten (ScanLine der letzen Zeile) besorgt und im thread nur "direkt" selber darin rummalt. |
AW: Thread läuft nicht parallel --
Wenn man das Bild nur aufteilt, dann kann es ja auch passieren das sich der gesuchte Bereich in keinem Bild mehr befindet.
Bild: 111111 222222 333333 444444 555555 666666 Aufteilen in 2 Bilder: 111111 222222 333333 444444 555555 666666 Suche nach dem Bereich: 33 44 Habe ich mir zumindest beim Lesen so überlegt... |
AW: Thread läuft nicht parallel --
Mal abgesehen von der Threadproblematik von VCL-Klassen...
Vorschlag: 1. Umwandeln des zu durchsuchenden Bildes in die Daten (GetBitmapBits) - auf diese Daten können alle Threads lesend zugreifen. 2. Umwandeln des/der zu suchenden Ausschnitts/e in die Daten 3. Daten selbst vergleichen (die korrekten Indices zu bestimmen, ist keine Doktorarbeit) 4. Für Thread-Aufteilung lässt sich das Bild(1) in horizontale Streifen aufteilen, die jeweils von einem Thread durchsucht werden können (der Thread beginnt mit jedem Punkt innerhalb des Streifens, der "ObenLinks" des Ausschnitts sein könnte). 5. Die Ergebnisse werden entweder per "PostMessage" oder per Rückruffunktion an den Aufrufer zurückgemeldet. |
AW: Thread läuft nicht parallel --
Erst einmal danke für die ganzen Hinweise. Danke für das snippet ...
danke an Mikkey für die Tipps .. werde mich rantasten und rumprobieren. Wenn ich hängen bleibe habe ich ja euch ^^ Danke nochmals für die Tips Grüße s0n |
AW: Thread läuft nicht parallel --
Zitat:
also 2St. 55x100 der so. sodass definitiv die Suche erfolgreich ist :) Aber recht hast du. Habe ich noch gar nicht dran gedacht ;( |
AW: Thread läuft nicht parallel --
Zitat:
Denn es kann immer noch sein, dass der gesuchte Bildauschnitt auf der Schnittkante der beiden Bilder sich befinden. Meiner Meinung nach müssen bei einer zweiteilung des Bildes 3 Suchabschnitte durchgeführt werden. 1. 00..50 (erster Bildteil) 2. 51..99 (zweiter Bildteil) 3. 25..75 (Schnittmenge, abhänging von der Größe des gesuchten Bildauschnitts) Grüße Klaus |
AW: Thread läuft nicht parallel --
Zitat:
|
AW: Thread läuft nicht parallel --
Zitat:
Beispiel: Gegeben Gesamtbild mit Höhe 120, Ausschnitt mit Höhe 30, 3 Threads Dann sucht Thread 1 in dem Streifen ab vertikaler Position 1 bis 30, Thread 2 ab Position 31-60 und Thread 3 ab Position 61-91 |
AW: Thread läuft nicht parallel --
Zitat:
![]() |
AW: Thread läuft nicht parallel --
Medium hast vollkommen recht 99.47 % der Rechenzeit gehen beim kopieren des Bildausschnittes auf die temp.canvas drauf.
Das lässt mich erstmal daran zweifeln ob die Threadverwendung überhaupt notwendig ist. Denn wieso die Auswirkung versuchen auszubügeln, wenn man doch direkt die Ursache eliminieren kann. Werde jetzt mal versuchen es ohne Canvas versuchen. Danach das Thread trotzdem versuchen hinzubekommen ^^ Grüße s0n |
AW: Thread läuft nicht parallel --
So ...
erst Gehversuche. Gedanken ( straft mich nicht wenn er komplett falsch ist :) ) <--- noch nicht so erfahren 1.Schritt beide Bitmaps in Streams zu speichern. 2.Schritt Header Daten von beiden Bitmaps aus den Streams entfern um die reinen Bilddaten zu haben 3.Schritt in einem TempStream nur die erste Pixelreihe des Suchbildes kopieren um eine Vorsuche zu benutzen, da sonst zu lange rechnet ( getestet ) 4.Schritt in einer forschleife: immer den Pixelreihenabschnitt mit dem aktuellen Pixelreihenabschnitt des Screens ( genauso lang wie Suchabschnitt ) vergleichen anbei mal ein bißchen Code :)
Delphi-Quellcode:
Ist der Gedankengang so erstmal richtig. Funktioniert das überhaupt?
ScreenBMP.PixelFormat := SearchBMP.PixelFormat ;
SearchBMP.SaveToStream(SearchStream); ScreenBMP.SaveToStream(ScreenStream); //showMessage('Größe des Suchbildes x :'+inttostr(SearchBMP.Width)+' Y :'+inttostr(SearchBMP.Height)+' MemorySize :'+inttoStr(SearchStream.Size)); //showMessage('Größe des Screens x :'+inttostr(ScreenBMP.Width)+' Y :'+inttostr(ScreenBMP.Height)+' MemorySize :'+inttoStr(ScreenStream.Size)); // Header vom Suchbild entfernen SearchStream.Position := 53; // Bitmap Header Size = 54, deshalb Position auf 53 SearchStream.Seek(0, soFromBeginning); tempSearch.CopyFrom(SearchStream,SearchStream.Size-54); tempSearch.Position := 0; SearchStream.Clear; SearchStream.CopyFrom(tempSearch,tempSearch.Size); tempSearch.Clear; // Header vom Screen entfernen ScreenStream.Position := 53; // Bitmap Header Size = 54, deshalb Position auf 53 ScreenStream.Seek(0, soFromBeginning); tempScreen.CopyFrom(ScreenStream,ScreenStream.Size-54); tempScreen.Position := 0; ScreenStream.Clear; ScreenStream.CopyFrom(tempScreen,tempScreen.Size); tempScreen.Clear; // erste Zeile vom Suchbild als Vorraster benutzen SearchStream.Position := 0; tempSearch.CopyFrom(SearchStream,SearchBMP.Width*3); startTime := GetTickCount; for I := 0 to ScreenStream.Size-SearchBMP.Width*3-1 do begin ScreenStream.Position := i; // 3 wegen 24Bit tempScreen.Clear; tempScreen.CopyFrom(ScreenStream,SearchBMP.Width*3); tempScreen.Position := 0; tempSearch.Position := 0; if CompareMem(tempScreen.Memory, tempSearch.Memory,SearchBMP.Width*3) then showmessage('gleich'); end; showMessage('Durchlaufzeit: '+Floattostr((GettickCount-starttime)/1000)+' s'); Grüße s0n |
AW: Thread läuft nicht parallel --
Zitat:
Du kannst dir mit Bitmap.ScanLine[0] einen Pointer beschaffen. Das passiert ohne Kopiererei - Windows sagt dir damit nur wo genau die Daten denn jetzt sind. Der Pointer, der da heraus kommt zeigt auf den Anfang der ersten Zeile. Jetzt musst du auf das Bildformat aufpassen (24bit/32bit) und kannst loslegen und vergleichen. Um einen Pixel einzulesen beitet sich die Verwendung von TRGBTriple oder gar TRGBTripleArray an. Die weiteren Zeilen bekommst du, indem du bei ScanLine entsprechen größere Zahlen einsetzt. Hier ist eine relativ ausführliche SO Antwort dazu: ![]() Das sollte dann schonmal relativ flott sein. Wenn du möchtest kannst du auch einen angepassten Boyer Moore (oder einen anderen) Algorithmus benutzen, um die Bytesequenz in der Zeile zu suchen. Das sollte dann für große Suchbilder noch etwas schneller sein. |
AW: Thread läuft nicht parallel --
:( sorry, aber man lernt ja nie aus
okay nun mal ein wenig deinen Link verfolgt und da wird auch einiges klar :) logisch das dies dann schneller sein sollte. Deshalb mal der erste Versuch ...
Delphi-Quellcode:
Es kommt logischerweise der Fehler ... Pointer und TRGBTriplearray unterschiedliche Typen
type
TRGBTripleArray = array [0..50000000] of TRGBTriple; pRGBTripleArray = ^TRGBTripleArray; var x,y : Integer; ScreenP,SearchP : pRGBTripleArray; SearchBMP,ScreenBMP : TBitmap; starttime: integer; begin Try SearchBMP := Tbitmap.create; ScreenBMP := Tbitmap.create; SearchBMP.Assign(Image1.Picture.bitmap); ScreenCapture(ScreenBMP); SearchP := SearchBMP.ScanLine[0]; starttime := GettickCount; for y := 0 to ScreenBMP.Height - 1 do ScreenP := ScreenBMP.ScanLine[y]; for x := 0 to ScreenBMP.Width - 1 do begin if CompareMem(ScreenP,SearchP[x],SearchBMP.width*3) then // <------- Hier der Fehler showMessage('gefunden'); end; Wie lautet der richtige Syntax um dies richtig zu übergeben ? danke im Voraus. s0n |
AW: Thread läuft nicht parallel --
Probier mal:
Delphi-Quellcode:
oder
if CompareMem(ScreenP, ^SearchP[x],SearchBMP.width*3) then
Delphi-Quellcode:
ich verpeile @X und ^X jedes mal....
if CompareMem(ScreenP, @SearchP[x],SearchBMP.width*3) then
|
AW: Thread läuft nicht parallel --
Ihr Seite der absolute Hammer. Vielen Vielen Dank.
Ist echt unglaublich wenn man mit den Zeigern arbeitet wie schnell das geht. also die alte Zeit im schlechtesten fall 14,7 sec. die Zeit ohne canvas,Stream oder sonstwas ... sondern direkt mit Zeigern auf das Bitmap. unglaubliche 0,0061 sec Ich kann es nicht glauben juhu :) nochmals vielen vielen Dank. So sieht das Ergebnis aus.
Delphi-Quellcode:
Es wird gesucht ein 50x50 Bitmap und einem 1920x1080 Bitmap.
function SearchBitmapInOtherBitmap( SearchBMP,ScreenBMP: TBitmap): TPoint;
type TRGBTripleArray = array [0..50000000] of TRGBTriple; pRGBTripleArray = ^TRGBTripleArray; Var x,y,k : Integer; ScreenP,SearchP : pRGBTripleArray; Laenge: integer; RowYes,RowNo : integer; Begin // Startwerte Result.X := -1; Result.Y := -1; RowYes := 0; RowNo := 0; if SearchBMP.PixelFormat <> ScreenBMP.PixelFormat then exit; // { Himitsu } // http://www.delphipraxis.net/202453-post16.html Case SearchBMP.PixelFormat of pf1bit: Laenge := Ceil(SearchBMP.Width / 8); pf4bit: Laenge := Ceil(SearchBMP.Width / 2); pf8bit: Laenge := SearchBMP.Width; pf15bit: Laenge := Ceil(SearchBMP.Width * 15 / 8); pf16bit: Laenge := SearchBMP.Width * 2; pf24bit: Laenge := SearchBMP.Width * 3; pf32bit: Laenge := SearchBMP.Width * 4; End; // end case Try // Zeiger auf erste Pixelreihe in SearchP SearchP := SearchBMP.ScanLine[0]; for y := 0 to ScreenBMP.Height - 1 do begin // Zeiger auf y Pixelreihe in ScreenP ScreenP := ScreenBMP.ScanLine[y]; for x := 0 to ScreenBMP.Width - 1 do begin // Vergleiche beide Pixelreihen ob gleich if CompareMem(SearchP,@ScreenP[x],Laenge) then begin // Pixelreihe gefunden komplettes Suchbild prüfen for k := 0 to SearchBMP.Height-1 do begin ScreenP := ScreenBMP.ScanLine[y]; if CompareMem(SearchP,@ScreenP[x],Laenge) then inc(RowYes); end; // wenn gefunden und jede Pixelreihe dem des Suchbildes entspricht setz result : TPoint if RowYes = SearchBMP.Height then begin result.x := x; result.Y := y; exit; end; end; // end If end; // end for x end; // end for y except raise Exception.Create('Fehler bei SearchInPicture'); End; End; Im schlechtesten Fall die angesprochenen 0,0061 sec. nochmals Danke an alle die mir Tipps und Ratschläge gegeben haben. Vor allem der Hinweis es ohne Canvas zu probieren. Grüße s0n |
AW: Thread läuft nicht parallel --
Bei aller Freude, da sind noch reichlich Fehler drin...
Delphi-Quellcode:
CompareMem vergleicht nur ganze Byte, wenn dein gesuchtes Bild mitten in einem Byte anfängt oder nicht nur ganze Byte belegt, wirst du es so nicht finden.
pf1bit: Laenge := Ceil(SearchBMP.Width / 8);
pf4bit: Laenge := Ceil(SearchBMP.Width / 2);
Delphi-Quellcode:
Diese Pixelformat belegt für jedes Pixel 2 Byte, das restliche Bit wird nicht genutzt.
pf15bit: Laenge := Ceil(SearchBMP.Width * 15 / 8);
...
Delphi-Quellcode:
Hier muss die Breite/Höhe des SearchBMP abgezogen werden, sonst greift CompareMem auf Speicher zu, der nicht mehr zu der Bitmap gehört.
for y := 0 to ScreenBMP.Height - 1 do
for x := 0 to ScreenBMP.Width - 1 do
Delphi-Quellcode:
ScreenP ist vom Type TRGBTripleArray, bei anderen Pixelformaten als pf24Bit wird auf die falsche Adresse zugegriffen.
CompareMem(SearchP,@ScreenP[x],Laenge)
... |
AW: Thread läuft nicht parallel --
hi Blub,
danke für die Hinweise.
Delphi-Quellcode:
Dieses Problem ist heute prompt nach meiner Euphorie aufgetreten ... Das ist schon behoben.
for y := 0 to ScreenBMP.Height - 1 do
for x := 0 to ScreenBMP.Width - 1 do Grüße s0n |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:15 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz