Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Objekte zu ihrer Längsachse vertikal ausrichten (https://www.delphipraxis.net/200134-objekte-zu-ihrer-laengsachse-vertikal-ausrichten.html)

newIndy 22. Mär 2019 19:20

Objekte zu ihrer Längsachse vertikal ausrichten
 
Objekte fallen an einer Kamera vorbei.
Diese Objekte sollen für die anschliessende Vermessung,
Erkennung und Visualisierung zu ihrer Längsachse vertikal ausgerichtet werden,
also so, als würden diese Objekte immer vertikal zu ihrer Längsachse fallen.
Ich habe eine funktionierende Methode.
Mit 'LineDDA' wird geprüft, welche 'gedachte' Linie die längste ist,
als Resultat erhält man einen Drehwinkel, mit dem das Objekt ausgerichtet wird.
Gibt es einen besseren Weg?
Danke für eure Antworten.

Delphi-Quellcode:
Procedure CheckPoints(X,Y: Integer; Canvas: TCanvas); StdCall;
var R, G, B:Byte;
    Color:TColor;
begin
     {$R-}
     Color := Canvas.Pixels[X, Y];
     R := GetRValue(Color);
     G := GetGValue(Color);
     B := GetBValue(Color);
     // prüfe, ob Pixelfarbe <> BackgroundTRGBFillColor
     if (R <> MainForm.BackgroundTRGBFillColor.r) and (G <> MainForm.BackgroundTRGBFillColor.g)
        and (B <> MainForm.BackgroundTRGBFillColor.b) then
          Inc(Distance);
     {$R+}
end;

Procedure TMainForm.AlignVertically(var bmp:TBitmap; var angle:Double);
var X1, Y1, X2, Y2, MaxDist,Vektor:Cardinal;
begin
     maxDist := 0;
     angle := 0;
     for Vektor := 1 to 8 do
     begin
          Distance := 1;
          if Vektor = 1 then
          begin
               // keine Drehung  OK
               X1 := bmp.Width div 2; Y1 := 0; X2 := X1; Y2 := bmp.Height;
               //TFNLineDDAProc
               LineDDA(X1, Y1, X2, Y2, @CheckPoints, LongInt(bmp.Canvas));
               if Distance >= maxDist then
               begin
                    maxDist := Distance;
                    angle := 0;
               end;
          end;
          if Vektor = 2 then
          begin
               // Drehung um 90°  OK
               // Horizontal gemessen = grösste Distanz > Drehung um 90°
               X1 := 0; Y1 := bmp.Height div 2; X2 := bmp.Width; Y2 := Y1;
               LineDDA(X1, Y1, X2, Y2, @CheckPoints, LongInt(bmp.Canvas));
               if Distance >= maxDist then
               begin
                    maxDist := Distance;
                    angle := 90;
               end;
          end;
          if Vektor = 3 then
          begin
               // Drehung um 45°     OK
               X1 := 0; Y1 := 0; X2 := bmp.Width; Y2 := bmp.Height;
               LineDDA(X1, Y1, X2, Y2, @CheckPoints, LongInt(bmp.Canvas));
               if Distance >= maxDist then
               begin
                    maxDist := Distance;
                    angle := 315;
               end;
          end;
          if Vektor = 4 then
          begin
               X1 := bmp.Width div 4; Y1 := 0; X2 := X1 * 3; Y2 := bmp.Height;
               LineDDA(X1, Y1, X2, Y2, @CheckPoints, LongInt(bmp.Canvas));
               if Distance >= maxDist then
               begin
                    maxDist := Distance;
                    angle := 337.5;
               end;
          end;
          if Vektor = 5 then
          begin                 // OK ?
               X2 := bmp.Width div 4; X1 := X2 * 3; Y1 := 0; Y2 := bmp.Height;
               LineDDA(X1, Y1, X2, Y2, @CheckPoints, LongInt(bmp.Canvas));
               if Distance >= maxDist then
               begin
                    maxDist := Distance;
                    angle := -340;
               end;
          end;
          if Vektor = 6 then
          begin
               // Drehung um -45°               OK
               X1 := bmp.Width; Y1 := 0; X2 := 0; Y2 := bmp.Height;
               LineDDA(X1, Y1, X2, Y2, @CheckPoints, LongInt(bmp.Canvas));
               if Distance >= maxDist then
               begin
                    maxDist := Distance;
                    angle := -135;
               end;
          end;
          if Vektor = 7 then
          begin        // OK ?
               X1 := 0; Y1 := bmp.Height div 4; X2 := bmp.Width; Y2 := Y1 * 3;
               LineDDA(X1, Y1, X2, Y2, @CheckPoints, LongInt(bmp.Canvas));
               if Distance >= maxDist then
               begin
                    maxDist := Distance;
                    angle := 300;
               end;
          end;
          if Vektor = 8 then
          begin   // OK ?
               X1 := 0; Y2 := bmp.Height div 4; Y1 := Y2 * 3; X2 := bmp.Width;
               LineDDA(X1, Y1, X2, Y2, @CheckPoints, LongInt(bmp.Canvas));
               if Distance >= maxDist then
               begin
                    maxDist := Distance;
                    angle := -300;
               end;
          end;
     end;
end;

hanvas 23. Mär 2019 08:46

AW: Objekte zu ihrer Längsachse vertikal ausrichten
 
Zitat:

Zitat von newIndy (Beitrag 1428444)
Objekte fallen an einer Kamera vorbei.
Diese Objekte sollen für die anschliessende Vermessung,Erkennung und Visualisierung zu ihrer Längsachse vertikal ausgerichtet werden, also so, als würden diese Objekte immer vertikal zu ihrer Längsachse fallen.

Gibt es einen besseren Weg?

Besser in welchem Sinne. Robuster, exakter oder schneller ?

Außerdem wären ein paar Infos hilfreich


Fällt immer nur ein Objekt an der Kamera vorbei oder gibt es mehrere gleichzeitig. Das die Ausrichtung veränderlich ist hat Du ja schon gesagt. Ist die Form und/oder die Größe des vorbeifallenden Objektes - bzw. dessen Abbildung im Bild - immer gleich oder ebenfalls veränderlich.

Ändert sich die Entfernung zur Kamera - und damit die Abbildung - oder ist diese konstant ?

cu Ha-Joe

newIndy 23. Mär 2019 17:54

AW: Objekte zu ihrer Längsachse vertikal ausrichten
 
Erst mal vielen Dank für das Feedback.

Es fallen kontinuierlich mehrere Objekte gleichzeitig an der Kamera(USB 3.0) vorbei.
Der Abstand zur Kamera ist immer gleich, auch die Beleuchtung und der 'Hintergrund' sind immer gleich.
Es ist ein permanenter Produktstrom von Objekten im Bereich von ca. 0.1 mm bis 15 mm mit ca. 50 bis 100 Objekten pro Sekunde.
Die Form ist meistens Oval.

Eine 'mechanische' Ausrichtung der Objekte,
z.B. mit einem Rillenblech ist aus Platzgründen nicht machbar und leider auch nicht sicher.

Mit meiner Routine wird das Objekt quasi in jeder Himmelsrichtung gescannt.
Die 'längste Pixelreihe', die der 'Längsachse' bei einem ovalen oder länglichen Objekt entsprechen müsste,
wird gefunden und der erforderliche Drehwinkel wird ausgegeben.

Die längs ausgerichteten (gedrehten) Objekte werden dann anhand ihrer Merkmale (z.B. Farbe, Farbvorkommen,
Vergleich mit bekannten Mustern aus der Datenbank(z.B. Patternmatching) etc.) klassifiziert und deren Anteile Prozentual ausgegeben.

Da die Erkennung schon viel Rechenpower benötigt, ist jede Geschwindigkeits-Optimierung sinnvoll.

Die von mir vorgestellte Routine funktioniert, aber vielleicht gibt es, wie so oft, oder beim Programmieren immer, eine andere Möglichkeit.
Ich habe trotz langer und häufiger Recherche nichts vergleichbares gefunden.
Wer meine Routine nutzen möchte, muss die Winkel an seine Rotate-Procedure anpassen.

jfheins 23. Mär 2019 21:34

AW: Objekte zu ihrer Längsachse vertikal ausrichten
 
Ich denke, üblicherweise wird so etwas mit einer Hauptachsentransformation gelöst. Oder, indem man eine Ellipse einpasst und deren große Halbachse bestimmt.

Das geht zum Beispiel mit Halcon direkt mit einem Methodenaufruf: https://www.mvtec.com/doc/halcon/181...egion_2nd.html
Oder auch mit MATLABs image processing toolbox mit regionprops

HAT habe ich mal selbst implementiert, den Aufwand würde ich mir aber heute nicht mehr machen. Falls es ein industrieller use case ist, einfach MATLAB kaufen, mit HG Kamera verbinden, 1 Tag Entwicklung, 2 Tage Test und fertig ist die Erkennung ;-)

newIndy 24. Mär 2019 06:47

AW: Objekte zu ihrer Längsachse vertikal ausrichten
 
Danke für deine Antwort.
Das ist eine diskussionswürdige Vorlage.

mensch72 24. Mär 2019 06:55

AW: Objekte zu ihrer Längsachse vertikal ausrichten
 
..."freier Fall und 50 bis 100 Objekte pro Sekunde"...
mit einer normalen billigen 50Hz Kammera wird das kaum etwas werden.

Zeit & Bild "sicher" wird es rechnerisch mit einer 200Bilder/sec Kamera... dann hast du 5msec pro Bild zum Vorverarbeiten("Erkennen","Markieren","Verfolgen") .

Bei bis zu 100 erkannten Objekten, hast du dann "parallel" je 10msec Zeit deren Größe und Lage rechnerisch zu bestimmen... das funktioniert ist aber für einen StandardPC ohne Spezial-Hardware&Software ne sportliche Aufgabe.

Ich würde kein Mathlab nehmen, sondern ne intelligente Kamera nehmen:
https://www.vision-control.com/produ...8e1753a05152c4

newIndy 24. Mär 2019 07:11

AW: Objekte zu ihrer Längsachse vertikal ausrichten
 
Stimmt.
Wir sprechen von keiner billigen Kamera, sondern von einer mit Global Shutter und sehr hohen Frame-Raten.

hanvas 24. Mär 2019 18:14

AW: Objekte zu ihrer Längsachse vertikal ausrichten
 
Eines vorab, ich habe schon zwei mal versucht einen langen Antwortpost zu erstellen und bin jedesmal rausgeflogen. Sprich mein Name/Passwort wurde erneut abgefragt und dann war der Post weg. Scheinbar wird man nun in kürzerer Zeit abgemeldet als vorher, deswegen teile ich meine Antwort nun auf.

An die Reihenfolge Deiner Beschreibung werde ich mich nicht halten, sondern in der Reihenfolge antworten die ich für sinnvoll halte. Da ich noch ein paar Fragen habe warte ich mit den zweiten Post noch ein wenig ?

Zitat:

Da die Erkennung schon viel Rechenpower benötigt, ist jede Geschwindigkeits-Optimierung sinnvoll.
Deine Routine müsste eigentich auch funktionieren wenn es sich um ein Graustufenbild oder SW Bild handeln würde. Wenn ich Deine Beschreibung richtig gelesen habe, dann bezieht sich Deine Routine auf ein bereits isoliertes Objekt. Das bedeutet das vorher bereits eine Verarbeitung, sei es durch die Kamera, sei es durch Dich stattgefunden hat. Die Isolation der Objekte hat dann vermutlich mit Hilfe von Methoden wie beispielsweise dem Auffinden der größten verbundenen Komponente stattgefunden.

Oft werden solche Methoden auf S/W Bildern oder Graustufenbildern durchgeführt, was mir sagt das ein solches vermutlich zeitgleich existiert. Wenn das so ist, dann verwende dieses Graustufenbild mit Deiner Methode, was die Methode um ca. 2/3 beschleunigt.

Zitat:

Eine 'mechanische' Ausrichtung der Objekte, z.B. mit einem Rillenblech ist aus Platzgründen nicht machbar und leider auch nicht sicher.
Je mehr sich das Objekt während des Fallens oder davor mit der Längsachse parallel zur Blickrichtung der Kamera dreht, umso kürzer erscheint die tatsächliche Längsache und die "längste Achse" im Bild ist nicht zwangsläufig die längste tatsächliche Achse. Falls dieses Problem vorkommen kann brauchst Du eine zweite Kamera.

Must Du jedes Objekt klassifizieren oder könntest Du nicht klassfizierte Objekte "im Kreislauf" fahren?

Hanst Du viele Klassen und damit eine sehr große Referenzdatenbank oder ist die Anzahl der Klassen überschaubar.

cu Ha-Jö

hanvas 24. Mär 2019 18:20

AW: Objekte zu ihrer Längsachse vertikal ausrichten
 
Delphi-Quellcode:
Procedure CheckPoints(X,Y: Integer; Canvas: TCanvas); StdCall;
var R, G, B:Byte;
    Color:TColor;
begin
     {$R-}
     Color := Canvas.Pixels[X, Y];
     R := GetRValue(Color);
     G := GetGValue(Color);
     B := GetBValue(Color);
     // prüfe, ob Pixelfarbe <> BackgroundTRGBFillColor
     if (R <> MainForm.BackgroundTRGBFillColor.r) and (G <> MainForm.BackgroundTRGBFillColor.g)
        and (B <> MainForm.BackgroundTRGBFillColor.b) then
          Inc(Distance);
     {$R+}
end;
Der Zugriff mittels Canvas.Pixels ist in der Regel sehr langsam.

Eine ausführliche Erklärung findest Du hier :

https://wiki.delphigl.com/index.php/...ildbearbeitung

cu Ha-Joe

newIndy 24. Mär 2019 18:55

AW: Objekte zu ihrer Längsachse vertikal ausrichten
 
Danke für deine Mühe.

[
Zitat:

Deine Routine müsste eigentich auch funktionieren wenn es sich um ein Graustufenbild oder SW Bild handeln würde.
Das ist richtig, ich habe es auch in Erwägung gezogen, an der Stelle mit einem SW-Bild zu arbeiten.
Die Objekte sind bereits isoliert. Die Bilder sind in Farbe, Umwandlung ist nat. kein Problem.

Zitat:

Je mehr sich das Objekt während des Fallens oder davor mit der Längsachse parallel zur Blickrichtung der Kamera dreht, umso kürzer erscheint die tatsächliche Längsache und die "längste Achse" im Bild ist nicht zwangsläufig die längste tatsächliche Achse. Falls dieses Problem vorkommen kann brauchst Du eine zweite Kamera.
Auch wieder richtig. Dafür habe ich jetzt eine praktische Lösung. Der freie Fall wird durch eine schräg stehende 'Rutsche aufgelöst.
Dadurch sollten die 'quer' fallenden Objekte von jetzt bis zu 20% auf Null gehen.

Zitat:

Must Du jedes Objekt klassifizieren oder könntest Du nicht klassfizierte Objekte "im Kreislauf" fahren?
Jedes Objekt wird klassifiert, dann ist es weg.
Zitat:

Hanst Du viele Klassen und damit eine sehr große Referenzdatenbank oder ist die Anzahl der Klassen überschaubar.
Es gibt keine Klassenanzahlbegrenzung, es können in der Praxis aber ca. 5 bis 20 sein, je nach Produkt.

Das Problem mit Canvas.Pixels ist bekannt, die Bilder der einzelnen Objekte sind aber relativ klein.


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:45 Uhr.
Seite 1 von 2  1 2      

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