Hallo zusammen, hallo @RodFromGermany
ich hab mal wieder ein kleines Anliegen. Die Farbstreifenerkennung von damals funktioniert im Moment wie sie soll und deshalb sollte ich mich nun auch mal mit den Felgen beschäftigen.
Nun gibt es sogenannte Matchpunkte auf Felgen und Reifen wenn der Reifen vom Hersteller kommt.
Um die Gewichtung der Räder beizubehalten muss entweder Felge oder Reifen gedreht werden, bis die Matchpunkte untereinander liegen.
Im Moment geht es hier nur um die Erkennung der Matchpunkte, ist das geschafft, ist der Rest ein Kinderspiel.
Nun zum Glück bekomme ich vom Kunden einige Raddaten vorgegeben. Felgenmittelpunkt auf dem Bild, Felgendurchmesser (in Millimeter, Umrechnung in Pixel <> Millimeter erfolgt bereits), kompletter Raddurchmesser (also Felge + Reifen) und noch einige andere Dinge, z.B. Farbe vom Matchpunkt, und noch viel mehr für dieses Topic uninteressante Daten.
Ich hatte mir jetzt überlegt, dass ich mit dem Reifenmatchpunkt anfange. Dieser ist denke ich einfacher als der Felgenmatchpunkt weil dieser in verschiedenen Farben und auf verschiedenen Hintergründen vorkommt. (Felgen variieren farblich und manchmal muss ein weißer Matchpunkt auf silberner Felge erkannt werden, was dann schon ziemlich schwierig wird, weil auf den silbernen Felgen dann auch noch Seifenflecken drauf sind.)
Also zu meiner Vorgehensweise:
Da ich Raddurchmesser sowie Felgendurchmesser vorgegeben habe, dachte ich mir wäre es sinnvoll, den Reifen aus dem Bild freizustellen. Dafür muss ich ja eigentlich nur die Fläche vom Kreis der sich durch den Felgendurchmesser ergibt von der Fläche des Kreises abziehen der sich durch den Raddurchmesser ergibt. So weit so gut. Nur wie mache ich das genau? Ich habe selbst schon eine Lösung dafür, bin mir nur nicht sicher ob es nicht vielleicht doch noch viel eleganter und dadurch auch performanter geht.
Meine Lösung bisher: Iteriere alle Pixel vom kompletten Bild und berechne zu jedem Pixel die Distanz zum Mittelpunkt.
Wenn die Distanz größer ist als der Radius vom Raddurchmesser oder kleiner ist als der Radius vom Felgendurchmesser wird der Pixel auf schwarz gesetzt (im Moment noch, später werde ich von den Pixeln im validen Bereich ein kleineres Bild erstellen).
Somit habe ich dann den Reifen freigestellt. (Abbildung: freigestellt.bmp)
Diese Lösung funktioniert, ist aber wahrscheinlich alles andere als performant. Da ich großen Wert auf Performance legen muss und mich selbst auch immer von eleganteren Lösungen überzeugen lassen möchte, frage ich hier, wie man das ganze anders lösen kann.
Das Problem an der Sache ist, dass ich immer die Länge vom Vektor berechnen muss. Wenn ich die Länge vom Vektor berechnen möchte muss ich die Wurzel ziehen. Da ich weiß, dass die Wurzel ziehen schon lange dauert, dachte ich mir, quadriere ich einfach die Distanz und vergleich also nicht Länge, sondern LenthSquared. So bin ich dann durch das weglassen von Math.Sqrt() wenigstens schon mal etwas schneller.
Aber gibt es für das ganze nicht doch eine ganz andere wesentlich elegantere Lösung?
Mit meiner Lösung bin ich jetzt bei der Freistellung schon bei 500ms (beachtet wurde bereits, dass in den zwei loops keine Properties abgerufen werden. Properties sind in C# nämlich langsamer als ganz normale Member Variablen.)
Hier meine Lösung:
Danke im Voraus
ich hab mal wieder ein kleines Anliegen. Die Farbstreifenerkennung von damals funktioniert im Moment wie sie soll und deshalb sollte ich mich nun auch mal mit den Felgen beschäftigen.
Nun gibt es sogenannte Matchpunkte auf Felgen und Reifen wenn der Reifen vom Hersteller kommt.
Um die Gewichtung der Räder beizubehalten muss entweder Felge oder Reifen gedreht werden, bis die Matchpunkte untereinander liegen.
Im Moment geht es hier nur um die Erkennung der Matchpunkte, ist das geschafft, ist der Rest ein Kinderspiel.
Nun zum Glück bekomme ich vom Kunden einige Raddaten vorgegeben. Felgenmittelpunkt auf dem Bild, Felgendurchmesser (in Millimeter, Umrechnung in Pixel <> Millimeter erfolgt bereits), kompletter Raddurchmesser (also Felge + Reifen) und noch einige andere Dinge, z.B. Farbe vom Matchpunkt, und noch viel mehr für dieses Topic uninteressante Daten.
Ich hatte mir jetzt überlegt, dass ich mit dem Reifenmatchpunkt anfange. Dieser ist denke ich einfacher als der Felgenmatchpunkt weil dieser in verschiedenen Farben und auf verschiedenen Hintergründen vorkommt. (Felgen variieren farblich und manchmal muss ein weißer Matchpunkt auf silberner Felge erkannt werden, was dann schon ziemlich schwierig wird, weil auf den silbernen Felgen dann auch noch Seifenflecken drauf sind.)
Also zu meiner Vorgehensweise:
Da ich Raddurchmesser sowie Felgendurchmesser vorgegeben habe, dachte ich mir wäre es sinnvoll, den Reifen aus dem Bild freizustellen. Dafür muss ich ja eigentlich nur die Fläche vom Kreis der sich durch den Felgendurchmesser ergibt von der Fläche des Kreises abziehen der sich durch den Raddurchmesser ergibt. So weit so gut. Nur wie mache ich das genau? Ich habe selbst schon eine Lösung dafür, bin mir nur nicht sicher ob es nicht vielleicht doch noch viel eleganter und dadurch auch performanter geht.
Meine Lösung bisher: Iteriere alle Pixel vom kompletten Bild und berechne zu jedem Pixel die Distanz zum Mittelpunkt.
Wenn die Distanz größer ist als der Radius vom Raddurchmesser oder kleiner ist als der Radius vom Felgendurchmesser wird der Pixel auf schwarz gesetzt (im Moment noch, später werde ich von den Pixeln im validen Bereich ein kleineres Bild erstellen).
Somit habe ich dann den Reifen freigestellt. (Abbildung: freigestellt.bmp)
Diese Lösung funktioniert, ist aber wahrscheinlich alles andere als performant. Da ich großen Wert auf Performance legen muss und mich selbst auch immer von eleganteren Lösungen überzeugen lassen möchte, frage ich hier, wie man das ganze anders lösen kann.
Das Problem an der Sache ist, dass ich immer die Länge vom Vektor berechnen muss. Wenn ich die Länge vom Vektor berechnen möchte muss ich die Wurzel ziehen. Da ich weiß, dass die Wurzel ziehen schon lange dauert, dachte ich mir, quadriere ich einfach die Distanz und vergleich also nicht Länge, sondern LenthSquared. So bin ich dann durch das weglassen von Math.Sqrt() wenigstens schon mal etwas schneller.
Aber gibt es für das ganze nicht doch eine ganz andere wesentlich elegantere Lösung?
Mit meiner Lösung bin ich jetzt bei der Freistellung schon bei 500ms (beachtet wurde bereits, dass in den zwei loops keine Properties abgerufen werden. Properties sind in C# nämlich langsamer als ganz normale Member Variablen.)
Hier meine Lösung:
C#-Quellcode
- var rows = CVImage.Rows;
- var cols = CVImage.Cols;
- var minDist = (AppSettings.Instance.Rim.RimDiameter / AppSettings.Instance.Calibration.CalibrationFactor) / 2;
- var maxDist = (AppSettings.Instance.Wheel.WheelDiameter / AppSettings.Instance.Calibration.CalibrationFactor) / 2;
- var RimCenter = new Vec2(AppSettings.Instance.Rim.RimCenterX, AppSettings.Instance.Rim.RimCenterY);
- var binarizedImage = CVImage.Clone();
- var imgData = CVImage.Data;
- for(int x = 0; x < cols; x++)
- {
- for(int y = 0; y < rows; y++)
- {
- Vec2 pos = new Vec2(x, y);
- var len = (RimCenter - pos).LengthSquared();
- if (len < (minDist * minDist) || len > (maxDist * maxDist))
- {
- imgData[y, x, 0] = 0;
- imgData[y, x, 1] = 0;
- imgData[y, x, 2] = 0;
- }
- }
- }
- binarizedImage.Data = imgData;
Danke im Voraus
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „seh“ ()