Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Rechteck auf Image zeichnen funktioniert nicht immer (https://www.delphipraxis.net/184454-rechteck-auf-image-zeichnen-funktioniert-nicht-immer.html)

Creepy666 28. Mär 2015 00:52

Delphi-Version: 7

Rechteck auf Image zeichnen funktioniert nicht immer
 
Hallo Gemeinde

Ich verwende die ImageSearchDLL.dll, um ein Bild in einem Image zu suchen.
Das gesuchte Bild kann mehrfach vorkommen.
Dafür erzeuge ich zur Laufzeit einen Screenshot (test.bmp), bei dem ich jeweils das gefundene Bild mit einem roten Rechteck übermale,
das Image abspeicher, wieder lade und dann den Suchlauf nochmals starte, bis alles gefunden wurde und die Suchfunktion abbricht.

Das Problem ist, es wird nur beim ersten mal ein rotes Rechteck gezeichnet, aber selbst das wird dann so behandelt,
als ob es gar nicht da wäre.

Loop durch das Bild...
Delphi-Quellcode:
while imgtest = true do                                                // Suchbild kann ?-mal vorkommen
   begin
      Form2.Image.Picture.LoadFromFile('test.bmp');                            // Image (erneut) laden
      _ImageSearch(FImagepath + 'bluespot.png', strtoint(Form1.lbledt1.Text)); // Aufruf Suchfunktion
      Form2.Image.Picture.SaveToFile('test.bmp');                              // Abspeichern mit rotem Rechteck
      Form2.Image.Picture.Assign(nil);                                         // <--- auch damit funktioniert es nicht
   end;
Suchfunktion...
Delphi-Quellcode:
ergebnis := ImageSearch(0, 0, Screen.Width, Screen.Height, PCHAR(findImage));
  try
    Split('|', ergebnis, A) ;
       if A[0] = '1' then
            begin
              Rec.x := A[1];         // Rec ist ein Record für weitere Verwendung
              Rec.y := A[2];

              Form2.DrawRedRectangle(strtoint(Rec.x), strtoint(Rec.y));

              imgtest := true;
            end
In DrawRedRectangle steht...
Delphi-Quellcode:
procedure TForm2.DrawRedRectangle(X,Y: integer);
begin
    Image.Canvas.Pen.Color := clRed;
    Image.Canvas.Brush.Color := clRed;
    Image.Canvas.Rectangle(X, Y, X+17, Y+9);
    Image.Update;
    Application.ProcessMessages;
end;
Es wird wie gesagt nur beim allerersten Lauf ein Rechteck gezeichnet, das dann auch beim 1. Abspeichern vorhanden ist, nach
jedem weiteren laden wird kein weiteres Rechteck mehr gezeichnet.
Die Suchfunktion ignoriert selbst dieses Rechteck völlig, als ob es gar nicht da wäre und findet immer wieder das gleiche Suchbild
an der gleichen Position, obwohl es übermalt wurde.

Mit Grafiken hab ich relativ wenig zu tun, von daher stehe ich da wie der Ochs vorm Berg und bin auf
euch Grafikprofis angewiesen. :D

Danke schon mal recht herzlich für eure Tips!

Mavarik 28. Mär 2015 09:24

AW: Rechteck auf Image zeichnen funktioniert nicht immer
 
Zitat:

Zitat von Creepy666 (Beitrag 1295140)
Delphi-Quellcode:
Form2.Image.Picture.LoadFromFile('test.bmp');
Form2.DrawRedRectangle(strtoint(Rec.x), strtoint(Rec.y));

Warum immer die absolute Adressierung über Form2. ?
egal...
Zitat:

Zitat von Creepy666 (Beitrag 1295140)
Delphi-Quellcode:
    Image.Canvas.Rectangle(X, Y, X+17, Y+9);
    Image.Update;
    Application.ProcessMessages;

Wie wäre es mit

Delphi-Quellcode:
Image.Picture.Bitmap.Canvas.Rectangle(X, Y, X+17, Y+9);

Mavarik

himitsu 28. Mär 2015 09:51

AW: Rechteck auf Image zeichnen funktioniert nicht immer
 
Wer brngt den Leuten eigentlich immer dieses grauenhafte und fehlerverursachende
Delphi-Quellcode:
if x = true then
bei?

Was ist _ImageSearch, ImageSearch und ImageSearchDLL.dll?

Man verwendet niemals relative Pfadnamen.
('test.bmp' ohne eine Pfadangabe)

Wenn bei Split nicht mindestens 2 Einträge rauskommen, dann knallt es.

Das mit den globalen Variablen (Form1 und Form2) wurde schon gesagt.

Creepy666 28. Mär 2015 11:51

AW: Rechteck auf Image zeichnen funktioniert nicht immer
 
Hallo Mavarik

Form2. nur deshalb, da die Suchfunktion in einer separaten Unit liegt.
Der D7 Editor hat ja leider kein Collapse/Expand. Der Übersichtlichkeit halber lagere ich dann
häufig verwendete Routinen in separate Units aus.

Dein Tip funktioniert übrigens auch, bringt aber im Programmlauf auch keine Besserung.
Ich habe jetzt im Code einige Debugeinträge mitloggen lassen.
Code:
[28.03.2015, 12:11:53] - --- Begin Search ---
[28.03.2015, 12:11:53] - --- Image laden... Durchlauf 1
[28.03.2015, 12:11:53] - --- Suchergebnis: 1|1195|197|15|6
[28.03.2015, 12:11:53] - --- Koordinaten gefunden: 1195:197 - Toleranz: 65
[28.03.2015, 12:11:53] - --- DrawRedRectangle: Rechteck gezeichnet bei 1195:197 
[28.03.2015, 12:11:53] - --- Image laden... Durchlauf 2   // Hier wird jetzt das neue Image mit dem Rechteck geladen (Rechteck ist physikalisch vorhanden)
[28.03.2015, 12:11:53] - --- Suchergebnis: 1|1195|197|15|6   // es wird aber trotz Übermalung weiterhin das Suchbild an der gleichen Position gefunden
[28.03.2015, 12:11:53] - --- Koordinaten gefunden: 1195:197 - Toleranz: 65
[28.03.2015, 12:11:53] - --- DrawRedRectangle: Rechteck gezeichnet bei 1195:197
[28.03.2015, 12:11:53] - --- Image laden... Durchlauf 3
[28.03.2015, 12:11:53] - --- Suchergebnis: 1|1195|197|15|6
[28.03.2015, 12:11:53] - --- Koordinaten gefunden: 1195:197 - Toleranz: 65
[28.03.2015, 12:11:53] - --- DrawRedRectangle: Rechteck gezeichnet bei 1195:197
[28.03.2015, 12:11:53] - --- Image laden... Durchlauf 4
[28.03.2015, 12:11:54] - --- Suchergebnis: 0
[28.03.2015, 12:11:54] - --- End Search ---
Die Suchfunktion bringt trotz des roten Rechtecks im Bild immer wieder die gleichen Koordinaten, als ob das Rechteck
nie gezeichnet wurde.
Mir kommt das so vor, als ob erstgeladene Bild in einer Art Cache liegt und statt des darübergeladenen
neuen Bilds immer und immer wieder verwendet wird.
Kann es sowas geben?


@himitsu
ImageSearchDLL.dll implementiert eine Pixelbereichssuche nach einem Bild auf dem Bildschirm, unterstützt durch die
Angabe einer Farbtoleranz.
Die Funktion wurde hier im Forum bereits vor einiger Zeit gepostet.
http://www.delphipraxis.net/141240-b...-absuchen.html

Deine Einwände sind durchaus berechtigt, danke. Der Programmcode läuft z.Zt. allerdings noch im lokalen Test.
Von daher sind mir die Pfadangaben erstmal unwichtig, solange sich alles im Exepfad abspielt.
Sobald es läuft, wird alles nochmals grundüberholt und aufgeräumt.

Split kracht auch nicht, da in der Prozedur mit Assert gearbeitet wird. ;)
Delphi-Quellcode:
procedure Split(const Delimiter: Char; Input: string; const Strings: TStrings);
begin
   Assert(Assigned(Strings));
   Strings.Clear;
   Strings.Delimiter := Delimiter;
   Strings.DelimitedText := Input;
end;

himitsu 28. Mär 2015 12:43

AW: Rechteck auf Image zeichnen funktioniert nicht immer
 
Code auslagern ist gut und schön, aber man sollte dem dann lieber alles übergeben und nicht daß er sich alles selber holt. Und schon ist die globale Variable nicht mehr da.

Zitat:

Zitat von Creepy666 (Beitrag 1295157)
Split kracht auch nicht, da in der Prozedur mit Assert gearbeitet wird. ;)

Es ging auch mehr um den Code nach dem Split :zwinker:

Wenn sichergestellt ist, daß Split immer genügend Zeilen liefert, dann OK, aber ansonsten kann dar blinde Zugriff auf einen nichtexistierenden Index Probleme bereiten.
A hätte auch ein Array sein können, aber als TStringList ist da zumindestens eine Prüfung integriert.

Zitat:

// Hier wird jetzt das neue Image mit dem Rechteck geladen (Rechteck ist physikalisch vorhanden)
Du hast natürlich auch geprüft, daß es dort wirklich bereits übermalt ist,
bzw., daß vor dem Speichern auch wirklich übermalt wurde?

Zitat:

Mir kommt das so vor, als ob erstgeladene Bild in einer Art Cache liegt und statt des darübergeladenen
neuen Bilds immer und immer wieder verwendet wird.
Kann es sowas geben?
Kann natürlich sein (VirtalStore)

Erstmal der relative Pfad ... also weiß hier keiner wo das Bild eigentlich liegt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:37 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