HSV Bild aus Matrix erstellen

  • VB.NET

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von VB-Robo.

    HSV Bild aus Matrix erstellen

    Hallo
    bin neu hier im Forum.
    ich bin zur zeit dabei eine Webcamerkennung zu programmieren. Diese soll später einmal zwei Lichtpunkte mit einer bestimmten Farbe erkennen und deren genaue Koordinaten daraus berechnen (für nen Roboter).
    So um nun zu prüfen ob sie auch die zwei Lichtpunkte erkennt, will ich mein Webcam bild, welches ich von RGB in HSV umgewandelt und dort die zwei Lichtpunkte isoliert hab, in einer Picturebox wieder ausgeben.

    Nun schaff ich es einfach nicht das Bild auszugeben. hab schon vieles, was ich im Netz gefunden habe ausprobiert aber immer scheiterts an Dateninkompatibilitäten.
    Hab bei der Umwandlung alles in eine Matrix geschrieben. da ich diese wiederum für die Berechnungen benötige. Daher soll aus der Matrix dann das Bild wieder entstehen.
    kann mir da jemand weiter helfen?
    hier auch mal nen codeausschnitt:

    VB.NET-Quellcode

    1. Private Sub cmdBildtoMatrix_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdBildtoMatrix.Click
    2. Dim image1 As Bitmap 'Image eins als Variable vom Typ Bild erzeugen
    3. Dim matrix(320, 240, 1, 1, 1) As Long
    4. Dim px, py, x, y, Max, Min, PR, PG, PB As Integer 'Variablen für Koordinaten der Pixel definieren
    5. Dim bs As New BindingSource
    6. Dim mX, mY As Integer
    7. Dim StartZeit As Date
    8. Dim StopZeit As Date
    9. Dim image2 As Bitmap
    10. StartZeit = DateTime.Now
    11. image1 = CapturePicture(videoHandle) 'Aktuelles Bild der Kamera der Variable image1 zuordnen
    12. 'DataGridView mit Matrix Füllen
    13. DataGridView1.Columns.Add("X", "X") 'DataGridView Spalten erstellen
    14. DataGridView1.Columns.Add("Y", "Y")
    15. DataGridView1.Columns.Add("H", "H")
    16. DataGridView1.Columns.Add("S", "S")
    17. DataGridView1.Columns.Add("V", "V")
    18. For x = 0 To image1.Width - 1 'Schleife durch die Pixel
    19. For y = 0 To image1.Height - 1
    20. Dim pixelColor As Color = image1.GetPixel(x, y)
    21. ' Dim newColor As Color = Color.FromArgb(255, pixelColor.R, pixelColor.G, 250) 'Farbe des Aktuellen Pixels verändern pixelcolor.R = PixelFarbe Rot übernehmen
    22. PR = pixelColor.R 'RGB Werte den Variablen zuordnen
    23. PG = pixelColor.G
    24. PB = pixelColor.B
    25. If PR > PG And PR > PB Then 'Maximalwert von RGB herausfinden und in Variable Max schreiben
    26. Max = PR
    27. ElseIf PG > PR And PG > PB Then
    28. Max = PG
    29. Else
    30. Max = PB
    31. End If
    32. If PR < PG And PR < PB Then 'Minimalwert von RGB herausfinden und in Variable Min schreiben
    33. Min = PR
    34. ElseIf PG < PR And PG < PB Then
    35. Min = PG
    36. Else
    37. Min = PB
    38. End If
    39. If Max = Min Or PR = PG = PB Then 'H wert errechnen
    40. h1 = 0
    41. Else
    42. If Max = PR Then
    43. h1 = 60 * (0 + (PG - PB) / (Max - Min))
    44. ElseIf Max = PG Then
    45. h1 = 60 * (2 + (PB - PR) / (Max - Min))
    46. Else
    47. h1 = 60 * (4 + (PR - PG) / (Max - Min))
    48. End If
    49. End If
    50. If Max = 0 Or PR = PG = PB = 0 Then 'S Wert errechnen
    51. s1 = 0
    52. Else
    53. s1 = (Max - Min) / Max
    54. End If
    55. v1 = Max 'V Ist = dem Maximal wert
    56. matrix(x, y, 0, 0, 1) = h1 'HSV Werte in Matrix schreiben
    57. matrix(x, y, 0, 1, 1) = s1
    58. matrix(x, y, 1, 1, 1) = v1
    59. mX = x
    60. mY = y
    61. DataGridView1.Rows.Add(mX, mY, h1, s1, v1) 'Werte in DataGridView einlesen
    62. Next
    63. Next
    64. StopZeit = DateTime.Now
    65. Label1.Text = CStr(DateDiff(DateInterval.Second, StartZeit, StopZeit)) & " Sekunden"
    66. End Sub
    Hi
    Erst mal ein herzliches Willkommen im Forum!
    Du solltest auf jeden Fall Option Strict und Option Explicit auf On schalten. Dann werden dir ein paar Fehler auffallen. In Vb ist es z.B. nicht möglich, einfach
    a = b = c
    zu schreiben und dabei einen Vergleich der Equivalenz der 3 Einträge zu überprüfen. Es gilt das Gesetz:
    (a das gleiche wie b) und entspricht zugleich dem boolschen Wert von c
    (a = b) ist also immer True/False und c muss somit auch ein Boolean sein. Der Vergleich kann z.B. so aussehen:
    a = b Andalso a = c AndAlso b = c
    AndAlso ist für diese Situation besser, da bei And, Or und Xor eigentlich kein Vergleich, sondern eine logische Verknüpfung stattfindet. Wenn der 1. Ausdruck bereits False zurückgibt, muss der zweite nicht mehr überprüft werden, da ja sowieso kein positives Resultat mehr möglich ist.

    Ganz verstanden habe ich noch nicht, wie die maximalen Werte von H, S und V sind. Jedoch bietet der Color-Wertetyp bereits Methoden an, die dir H (GetHue), S (GetSaturation) und B (GetBrightness) zurückgeben (hoffe, dass V das gleiche ist wie B, denn was anderes würde irgendwie nicht so großen Sinn machen). Die Werte sind Gleitkommazahlen zwischen 0 und 1.

    Wenn du den Code noch einmal durchschaust, kann ich dir vielleicht weiterhelfen. (Außerdem benötige ich noch den maximalen Wert von den selbst errechneten HSV Werten).

    Edit: Verwende doch noch eine Stopwatch statt der DateDiff-Methode.

    Gruß
    ~blaze~

    PS: Muss die Matrix eigentlich aus 64-Bit-Ganzzahlen bestehen? Hier könnte man nämlich auch 32-Bit-Ganzzahlen verwenden.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „~blaze~“ ()

    also danke erstmal für die schnelle antwort
    das mit den Operatorn werde ich auf jedenfall überarbeiten das wusste ich net, dass er immer nur die ersten prüft und den rest nimmer.

    zu HSV: Die formel zur umrechnung habe ich aus nem Artikel aus dem Internet rausgezogen und halt programmiertechnisch umgesetzt.

    Die maximalwerte der HSV werte ändern sich ja ständig. je nach Bild. Hab die kamera ja prakisch in ner willkürlichen Umgebung. Und in dieser Umgebung sollen nun zwei Leuchtfeuer, dessen exakte position bekannt ist, erkannt werden und dann durch Matrixen rechnung die Position der kamera und damit die Position des Roboters später errechnet werden.
    Jetzt hab ich in einem Roboter Forum gelesen, dass es einfacher ist wenn man dies mit HSV realisiert und dann die werte so abändert dass nur noch diese zwei Lichter zu erkennen sind (als weiße Punkte oder so)
    aber so weit bin ich ja noch nicht^^

    mir gehts momentan erstmal nur darum die Matrix visuell darzustellen damit ich kontrollieren kann.

    So und hab das jetzt wie gepostet programmiert, damits lief. da bin ich ja schonmal froh^^ bin kein Profi in sachen Programmierung und programmiere wahrscheinlich noch sehr umständlich und so. Daher hab ich bei der Matrix auch Long geschrieben und net was anderes^^ eigentlich is es egal. hauptsache die werte stimmen hinterher. wenn ich mich recht ensinne ist das ja nur Speicherplatz was da verbraten wird oder?

    So erstmal soviel da dazu.
    Werd jetzt den code überarbeiten und dann nochmal posten.

    EDIT:
    Hier der geänderte Code:

    VB.NET-Quellcode

    1. Private Sub cmdBildtoMatrix_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdBildtoMatrix.Click
    2. Dim image1 As Bitmap 'Image eins als Variable vom Typ Bild erzeugen
    3. Dim matrix(320, 240, 1, 1, 1) As Long
    4. Dim px, py, x, y, Max, Min, PR, PG, PB As Integer 'Variablen für Koordinaten der Pixel definieren
    5. Dim bs As New BindingSource
    6. Dim mX, mY As Integer
    7. Dim StartZeit As Date
    8. Dim StopZeit As Date
    9. Dim image2 As Bitmap
    10. StartZeit = DateTime.Now
    11. image1 = CType(CapturePicture(videoHandle), Bitmap) 'Aktuelles Bild der Kamera der Variable image1 zuordnen
    12. 'DataGridView mit Matrix Füllen
    13. DataGridView1.Columns.Add("X", "X") 'DataGridView Spalten erstellen
    14. DataGridView1.Columns.Add("Y", "Y")
    15. DataGridView1.Columns.Add("H", "H")
    16. DataGridView1.Columns.Add("S", "S")
    17. DataGridView1.Columns.Add("V", "V")
    18. For x = 0 To image1.Width - 1 'Schleife durch die Pixel
    19. For y = 0 To image1.Height - 1
    20. Dim pixelColor As Color = image1.GetPixel(x, y)
    21. ' Dim newColor As Color = Color.FromArgb(255, pixelColor.R, pixelColor.G, 250) 'Farbe des Aktuellen Pixels verändern pixelcolor.R = PixelFarbe Rot übernehmen
    22. PR = pixelColor.R 'RGB Werte den Variablen zuordnen
    23. PG = pixelColor.G
    24. PB = pixelColor.B
    25. If PR > PG And PR > PB Then 'Maximalwert von RGB herausfinden und in Variable Max schreiben
    26. Max = PR
    27. ElseIf PG > PR And PG > PB Then
    28. Max = PG
    29. Else
    30. Max = PB
    31. End If
    32. If PR < PG And PR < PB Then 'Minimalwert von RGB herausfinden und in Variable Min schreiben
    33. Min = PR
    34. ElseIf PG < PR And PG < PB Then
    35. Min = PG
    36. Else
    37. Min = PB
    38. End If
    39. If Max = Min Or PR = PG AndAlso PR = PB Then 'H wert errechnen
    40. h1 = 0
    41. Else
    42. If Max = PR Then
    43. h1 = CInt(60 * (0 + (PG - PB) / (Max - Min)))
    44. ElseIf Max = PG Then
    45. h1 = CInt(60 * (2 + (PB - PR) / (Max - Min)))
    46. Else
    47. h1 = CInt(60 * (4 + (PR - PG) / (Max - Min)))
    48. End If
    49. End If
    50. If Max = 0 Or PR = PG AndAlso PR = PB AndAlso PB = 0 Then 'S Wert errechnen
    51. s1 = 0
    52. Else
    53. s1 = CInt(((Max - Min) / Max) * 100)
    54. End If
    55. v1 = CInt(((100 / 255) * Max)) 'V Ist = dem Maximal wert 'V umrechnen in Prozentwert
    56. matrix(x, y, 0, 0, 1) = h1 'HSV Werte in Matrix schreiben
    57. matrix(x, y, 0, 1, 1) = s1
    58. matrix(x, y, 1, 1, 1) = v1
    59. mX = x
    60. mY = y
    61. DataGridView1.Rows.Add(mX, mY, h1, s1, v1) 'Werte in DataGridView einlesen
    62. Next
    63. Next
    64. StopZeit = DateTime.Now
    65. Label1.Text = CStr(DateDiff(DateInterval.Second, StartZeit, StopZeit)) & " Sekunden"
    66. End Sub


    PS: weis zwar net genau was das mit den Optionen auf sich hat weil er dann da auf einmal fehler bringt. aber na ja. Weil gelaufen is es ja jetzt mit beiden versionen.
    WAs mir noch aufgellen ist. Ist dass ich vergessen hab S und V Wert in Prozent umzurechnen^^

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VB-Robo“ ()

    Ich werde die nächste Zeit leider kaum Zeit haben, noch einmal über den Code zu gehen, allerdings solltest du die Werte vielleicht entweder in Byte oder in Single belassen (am Besten Single, da du dann einige Berechnungen leichter machen kannst. Schreib mir, in welcher Art du es machst, dann kann ich dir, sobald ich doch noch mal Zeit habe, mir noch mal was überlegen. Ich hoffe, du brauchst das ganze nicht zu schnell brauchst, sonst muss ich schauen, ob ich mir noch kurz Zeit nehmen kann oder jemand anders muss dir helfen.

    Gruß
    ~blaze~

    Wikipedia schrieb:

    HSV stands for hue, saturation, and value, and is also often called HSB (B for brightness)


    Das scheint dann doch das gleiche zu sein. Ich persönlich bevorzuge übrigens Farben, die von 0 bis 1 gehen, da da einige Berechnungen wegfallen, die auf 1 reduzieren. Somit ist die Effizienz höher, da Single und Byte fast genauso schnell gerechnet werden (zumindest bei meinen Messungen).

    Gruß
    ~blaze~
    also danke erstmal für eure antworten
    ich bin jetzt schon nen ganz schönes stückchen weiter gekommen.

    ich hab es mitlerweile geschafft, dass mein programm mir in ner picturebox das Bild nocheinmal anzeigt und meinen laserpointer verfolgt und dort wo er gerade ist ein grünes kreuz visuell darzustellen.
    allerdings is est noch nicht zufriedenstellend, da je nach hintergrund er den roten Punkt nich richtig erkennt. und dann hin und her springt.

    das heist ich müsste es jetzt schaffen den Laserpointer punkt zu isolieren. nur wie stell ich das am dümmsten an?
    hab das bild schon in schwarz weiß mithilfe eines graustufenfilter umkovertiert, was das ergebnis schon deutlich verbessert hatte.
    nur wenn jetzt halt ne zweite helle lichtquelle oder der gleichen hinzukommt dann springt er wie gesagt um. und das darf nicht sein. da würde ja der roboter später nur irritiert werden.

    ach so
    man kann das Bild auch gar net direkt als HSV Bild oder so anzeigen kann das sein? also hab ich auf ner seite gelesen. Man muss es immer in RGB wieder zurückkonvertieren. oder ist es doch möglich?

    hab mal nen paar Bilder angehängt worauf man sieht wie das programm den laserpointer verfolgt.





    PS.: es ist nicht so eillig. ist ja eher mein hobby^^ von daher. Aber kanns halt kaum erwarten fortschritte zu machen. aber find bin schon sehr weit gekommen, wenn ich überlege, dass ich erst letzte woche damit angefnagen habe.
    hmm ja ich versuch das mal mit der helligkeit und farbton
    aber werde mir ersteinmal ne ultrahelle LED zulegen und damit testen. da der Laser ja immer nur indirekt abstrahlt daher immer auf eine oberfläche strahlt und je nach oberfläche sieht er ja etwas anderster aus.
    aber danke schonmal
    wenns was neues gibs oder so meld ich mich nochmal^^