Farberkennung

  • VB.NET

Es gibt 3 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.

    Farberkennung

    Hallo,

    ich habe folgenden Code geschrieben.

    VB.NET-Quellcode

    1. Public Farbe As Integer
    2. Public Sub Farberkennung()
    3. ...
    4. Dim bmp As Bitmap, FarbeB As Drawing.Color
    5. Dim G As Drawing.Graphics = Graphics.FromImage(Me.p1.Image)
    6. ...
    7. bmp = p1.Image
    8. FarbeB = (bmp.GetPixel(Xpic, Ypic))
    9. Farbe = FarbeB.ToArgb
    10. ...
    11. Dim Pen1 As New Pen(FarbeB, 1)
    12. G.DrawRectangle(Pen1, New Rectangle(40, 40, 1, 1))
    13. ...
    14. End Sub


    Dahinter steht ein Formular mit einer Picturebox (p1) in der ein 8 Farben Bild (importiert als Lokale Resource; nur im Eigenschaftsfenster) untergebracht ist.
    Dieses wir durch zwei Schleifen durchlaufen (Wagerecht und senkrecht; nicht zu sehen [...])

    Mein Problen ist beim 1. Durchlaufen der Sub kommt der Fehler ind Zeile 6.

    "Ein Grafikobjekt kann nicht aus einem Bild mit einem indizierten Pixelformat erstellt werden."

    Was bedeutet das, und wie kann ich diesen beseitigen.

    Grüße
    Hi
    Das heißt, dass deine Bitmap Indizierung zum Darstellen von Pixeln verwendet. In manchen Formaten ist es üblich, eine Farbpalette zu verwenden, wo zum Beispiel 256 Farben darin stehen. Dann wird für jeden Bildpunkt der Bitmap ein Index angegeben, der die jeweilige Farbe in der Farbpalette angibt. Üblich ist das zum Beispiel bei gif-Dateien. Der Vorteil ist einfach die Speicherplatz-Einsparung. Zum Beispiel deine 8-Farben-Bitmap verwendet 3 Bits pro Pixel, statt 32. Dafür ist die Palette halt 8 * 32 bzw. wahrscheinlicher 8 * 24 Bits lang.

    Ich habe zwar keine Funktion parat, weil ich das noch nie machen musste, aber du kannst dir ja eine selber schreiben. Mir würde speziell einmal einfallen, dass du einfach eine neue Bitmap erstellst und diese mit den Pixel-Daten aus der alten füllst (mit GetPixel bzw. LockBits, was in diesem Fall halt etwas kompizierter ausfällt) oder gleich eine eigene Funktion zum Laden erstellst.

    Gruß
    ~blaze~
    Hallo,

    gleiches Programm, andere stelle.
    Ich bin sehr verwirrt

    VB.NET-Quellcode

    1. Private Sub Liste1_SelectedIndexChanged(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles Farbliste_1.SelectedIndexChanged
    2. Dim Bits As New BitArray(7), MyByte(0) As Byte, farbe As String, zeichen As String = "", zähler As Integer
    3. Datenform.List1.Items.Clear()
    4. farbe = Farbliste_1.SelectedItem.ToString
    5. Do Until zeichen = Tab
    6. zähler = zähler + 1
    7. zeichen = farbe.Substring(zähler, 1)
    8. Loop
    9. MyByte(0) = farbe.Substring(zähler)
    10. L1.Text = farbe & " " & MyByte(0)
    11. Bits.CopyTo(MyByte, 0)
    12. For A = 0 To 7
    13. Datenform.List1.Items.Add(Bits(A))
    14. Next
    15. End Sub


    Hier sind 2 Formulare mit Jeweils 1 Liste (Listbox). Die Farbliste enthält eine Liste der Farben (Die Nr des byte und das Byte selbst durch einen Tabulator getrennt) . Sieht ungefähr so au "798 255"...
    Die zweite Liste soll die Bits anzeigen (z.B. als Boolean) wenn ich eine Farbe aus der 1.Liste (Farbliste) auswähle.

    Dabei sind 2 (3) Probleme.
    1. Ich habe den Bitarray auf 7 (also 8 Element) gestellt. In der Ausgabe Datenmform... kommt wärend des Durchlaufs bei 7 eine Fehlermeldung Index außerhalb Bereich. Warum? Der Array geht doch bis 7, die fehlermeldung dürfte doch erst bei 8 kommen. Und wenn das ganze nicht so funktioniert, dann muss die Fehlermeldung doch schon bei der Zuweisung kommen.
    2. Irgendwie wandelt er das Byte nicht um. In meiner 2. Liste steht immer nur "false" egal" welchen Eintrag ich klicke.
    3. Wie wandele ich ein Byte in einen Bittarray um? (Ohne den Umweg über ein Bytearray mit einem Element)

    Inzwischen habe ich auch eine richtige Lösung im Internet gefunden. Nur das Verstehen meiner Problem ist noch schwierig.
    Vor alle da getbytes gar kein Byte als Parameter akzeptiert und er mit eigentlich Bytes ausgeben soll...

    VB.NET-Quellcode

    1. Private Sub Liste1_SelectedIndexChanged(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles Farbliste_1.SelectedIndexChanged
    2. Dim MyByte As Byte, farbe As String, zeichen As String = "", zähler As Integer
    3. Datenform.List1.Items.Clear()
    4. farbe = Farbliste_1.SelectedItem.ToString
    5. Do Until zeichen = Tab
    6. zähler = zähler + 1
    7. zeichen = farbe.Substring(zähler, 1)
    8. Loop
    9. MyByte = farbe.Substring(zähler)
    10. Dim Bits As New BitArray(BitConverter.GetBytes(MyByte))
    11. For A = 0 To 7
    12. Datenform.List1.Items.Add(Bits(A))
    13. Next
    14. End Sub
    Hi

    Erst mal zu deinen ursprünglichen Fragen:
    1. Frage: Das ist die Länge, nicht der maximale Index ==> zu 8 ändern.
    2. Frage: CopyTo kopiert die Einträge IN das angegebene Ziel
    3. Frage: Nimm Bitshifts statt einem Bitarray und verknüpfe mit und (Wert And (1 << x), x ist der Bitindex)

    Dann zu der "Lösung":
    BitConverter wird wahrscheinlich MyByte in ein Short oder so konvertieren, schau dir dazu mal die Länge des BitArrays an. Schau dir außerdem mal IndexOf von String an. Verwende statt Strings der Länge 1 übrigens lieber Chars. Das steigert die Effizienz in den meisten Fällen.

    VB.NET-Quellcode

    1. Dim byteValue As Byte
    2. Dim mask As Byte
    3. For A As Integer = 0 To 7
    4. mask = 1 << A
    5. Datenform.List1.Items.Add(((byteValue And mask) = mask).ToString())
    6. Next


    Dann hab ich noch ein paar Anmerkungen:
    1.: Nimm Chars statt Strings der Länge 1
    2.: Option Strict auf On

    Gruß
    ~blaze~