AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Thread läuft nicht parallel --

Ein Thema von sonny2007 · begonnen am 9. Jan 2014 · letzter Beitrag vom 11. Jan 2014
Antwort Antwort
Seite 3 von 3     123   
Mikkey

Registriert seit: 5. Aug 2013
265 Beiträge
 
#21

AW: Thread läuft nicht parallel --

  Alt 9. Jan 2014, 13:15
Wenn man das Bild nur aufteilt, dann kann es ja auch passieren das sich der gesuchte Bereich in keinem Bild mehr befindet.
So war das in meinen Beitrag mit den Streifen gedacht:

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
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.686 Beiträge
 
Delphi 2007 Enterprise
 
#22

AW: Thread läuft nicht parallel --

  Alt 9. Jan 2014, 23:34
Wenn man das Bild nur aufteilt, dann kann es ja auch passieren das sich der gesuchte Bereich in keinem Bild mehr befindet.
Diese sehr richtige und wichtige Aussage macht deinen aktuellen Ansatz eigentlich komplett zunichte. So sehr, dass ich nicht mehr versuchen würde krampfhaft die Geschwindigkeit eines Verfahrens zu verbessern, dass konzeptionell bereits nicht funktioniert. Entweder du suchst im gesamten Bild Pixel für Pixel (man könnte dabei z.B. gerade und ungerade Zeilen auf 2 Threads verteilen - dann bliebe der Lerneffekt "Umgang mit Threads" erhalten), oder man greift gleich zur Bei Google suchenAutokorrelation, die genau solche Probleme sehr gut löst.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
sonny2007

Registriert seit: 27. Aug 2009
39 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#23

AW: Thread läuft nicht parallel --

  Alt 10. Jan 2014, 07:52
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
  Mit Zitat antworten Zitat
sonny2007

Registriert seit: 27. Aug 2009
39 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#24

AW: Thread läuft nicht parallel --

  Alt 10. Jan 2014, 09:49
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:
    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');
Ist der Gedankengang so erstmal richtig. Funktioniert das überhaupt?

Grüße
s0n
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#25

AW: Thread läuft nicht parallel --

  Alt 10. Jan 2014, 10:16
Zitat:
1.Schritt beide Bitmaps in Streams zu speichern.
Ist schon falsch, da auch hier Daten herumkopiert werden.

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: http://stackoverflow.com/a/13583452

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.

Geändert von jfheins (10. Jan 2014 um 10:28 Uhr)
  Mit Zitat antworten Zitat
sonny2007

Registriert seit: 27. Aug 2009
39 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#26

AW: Thread läuft nicht parallel --

  Alt 10. Jan 2014, 11:04
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:
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;
Es kommt logischerweise der Fehler ... Pointer und TRGBTriplearray unterschiedliche Typen
Wie lautet der richtige Syntax um dies richtig zu übergeben ?

danke im Voraus.
s0n
  Mit Zitat antworten Zitat
Photoner

Registriert seit: 6. Dez 2012
Ort: Nürnberg
103 Beiträge
 
Delphi 10.1 Berlin Starter
 
#27

AW: Thread läuft nicht parallel --

  Alt 10. Jan 2014, 13:04
Probier mal:
if CompareMem(ScreenP, ^SearchP[x],SearchBMP.width*3) then oder
if CompareMem(ScreenP, @SearchP[x],SearchBMP.width*3) then ich verpeile @X und ^X jedes mal....
Chris

Geändert von Photoner (10. Jan 2014 um 13:29 Uhr)
  Mit Zitat antworten Zitat
sonny2007

Registriert seit: 27. Aug 2009
39 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#28

AW: Thread läuft nicht parallel --

  Alt 10. Jan 2014, 15:49
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:
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;
Es wird gesucht ein 50x50 Bitmap und einem 1920x1080 Bitmap.
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

Geändert von sonny2007 (10. Jan 2014 um 16:27 Uhr)
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.464 Beiträge
 
Delphi 12 Athens
 
#29

AW: Thread läuft nicht parallel --

  Alt 10. Jan 2014, 17:44
Bei aller Freude, da sind noch reichlich Fehler drin...

Delphi-Quellcode:
pf1bit: Laenge := Ceil(SearchBMP.Width / 8);
pf4bit: Laenge := Ceil(SearchBMP.Width / 2);
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.

Delphi-Quellcode:
pf15bit: Laenge := Ceil(SearchBMP.Width * 15 / 8);
...
Diese Pixelformat belegt für jedes Pixel 2 Byte, das restliche Bit wird nicht genutzt.

Delphi-Quellcode:
for y := 0 to ScreenBMP.Height - 1 do
  for x := 0 to ScreenBMP.Width - 1 do
Hier muss die Breite/Höhe des SearchBMP abgezogen werden, sonst greift CompareMem auf Speicher zu, der nicht mehr zu der Bitmap gehört.

Delphi-Quellcode:
CompareMem(SearchP,@ScreenP[x],Laenge)
...
ScreenP ist vom Type TRGBTripleArray, bei anderen Pixelformaten als pf24Bit wird auf die falsche Adresse zugegriffen.
  Mit Zitat antworten Zitat
sonny2007

Registriert seit: 27. Aug 2009
39 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#30

AW: Thread läuft nicht parallel --

  Alt 11. Jan 2014, 03:21
hi Blub,

danke für die Hinweise.
Delphi-Quellcode:
for y := 0 to ScreenBMP.Height - 1 do
  for x := 0 to ScreenBMP.Width - 1 do
Dieses Problem ist heute prompt nach meiner Euphorie aufgetreten ... Das ist schon behoben.

Grüße
s0n
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:28 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz