Bilderkennung



  • Hi,

    ich habe auch mal eine Bilderkennung geschrieben. Ich habe das so angepackt:
    Lies einfache die einzelnen RGB Werte eines BMP´s ein und entscheide dann mit einem Algowelche Farbe dominiert. Formen erkennst du vielleicht daran, wenn du jeden stärkeren Farbübergang als Linie definierst. Ich weis nicht ob das Ganze in Java zu machen ist aber so ne Bilderkennung braucht halt ziemlich viel Rechenpower.
    Ich hoffe ich habe dir nichts gesagt was du nicht eh schon weist.

    Erni



  • Was genau möchtest du denn erkennen?
    Ich habe mal an einem Fingerprint System gearbeitet.
    Die 2 Möglichkeiten haben am besten abgeschnitten:
    - Vectorisieren, der Hervorstechenden Informationen, dann vergleichen. Eine Prozentzahl gibt die Hemschwelle zwischen ok und false an
    - Oder per Genetischen System einen Algo berechnen lassen



  • Das ist doch ein tolles anwendungsgebiet für neurale Netze. Vor kurzem hatten wir hier einen Thread zu diesem Thema.



  • Also ich denke mal, dass sich diese Geschichte leichter per C++ realisieren lässt, auch wenn ihr zu diesem Thema noch nicht wirklich Bezug genommen habt.

    Was ich genau damit vor habe kann ich nicht sagen,weil ich es auch noch nicht genau weiss. Ein interessantes Thema wäre ein Prog, das die Augenzahl auf einem Würfel zählen kann.

    Mich würde auch mal wirklich ne Realisierung interessieren.
    Wie ließt man beispielsweise die RGB-Werte aus?
    Wie kann ich jedes Bild der Cam in ein BMP umwandeln?
    Was für ne Cam habt ihr benutzt?

    Sowas in der rRichtung würde mich mal interessieren.

    Danke und Bye
    Romeo



  • Ich empfehle dir, vorerst ohne Kamera zu arbeiten, sondern nur mit einzelnen Bildern. Kamera heißt für mich, dass das Ganze mehr oder weniger in Echtzeit ablaufen soll. Das ist eine zusätzliche Schwierigkeit, die du am Schluss immernoch einbauen kannst, falls du dann der Meinung bist, dass dein Algorithmus schnell genug dafür arbeitet.

    Die Augenzahl eines Würfels zählen sollte eigentlich machbar sein. Das hört sich auch für eine Facharbeit angemessen an.



  • Verzichte erst auf die Cam. Mache ein paar Snapshots, konvertiere diese, und vergleiche. Wenn die Resultate stimmen mit einer geringen Fehlerquote, dann kannst du ja einen schritt weiter gehen.
    Wenn das klappt, kannst du Cam support immer noch einbauen



  • Na dann mal Butter bei die Fische.

    Habe mir nen paar Texte zur Theorie durchgelsen, wie man z.B. aus dem Startbild durch Logik ein reines Konturenbild erzeugen kann aber wie sieht es in der Praxis aus?

    Wüsste schon wie man so einiges machen könnte aber mir fehlt ein entscheidender Baustein.
    Wie lese ich die RGB-Werte aus einem bestimmten BMP aus?

    Das dürfte mich schon nen großen Schritt weiter bringen.
    Danke

    Romeo



  • Öhm - unter welchem OS arbeitest du?

    Du könntest die BMP selbst laden - siehe hier: http://www.c-plusplus.net/forum/viewtopic.php?p=339246#339246

    Wenn die Daten erstmal RAW im Speicher sind, kannst du sie ohne Probleme auslesen. Wenn ich mich recht entsinne war BMP im BGR modus geschrieben. Das wirst du aber schnell feststellen, wenn die Farben nicht stimmen 😉

    Somit sind die Daten immer

    8Bit B | 8Bit G | 8Bit R | ... usw.

    Hope this helps



  • Hallo Romeo-G,

    ich beschäftige mich auf Arbeit sehr viel mit Bilderkennung und Verarbeitung im industriellen Bereich. Im Normalfall wird so ein Bild in ein Graustufenbild umgewandelt und dann erst weiterverarbeitet. Es sei den man will zum Bsp. die Augenfarbe erkennen 😃 .

    In deinem Fall (Augenzahl der Würfel) wäre folgendes vorgehen zu empfehlen und programmiertechnisch auch total leicht umzusetzen (auch mit Java).

    1. Umwandlung des Bildes in ein Grauwertbild

    2. Erstellung eines Grauwerthistogrammes aus dem Bild

    3. Bestimmen einer Binärschwelle (unterteilt die Bildbereiche in logisch hell und logisch dunkel) anhand des Histogrammes

    4. erstellen eines Binärbildes aus dem Grauwertbild und der Binärschwelle. (dannach hast du ein schwarz/weis Bild mit den Augen)

    5. Suche nach Objekten Anhand des Binärbildes und diese zählen.

    Gruss Bigwill



  • Bei dem Vorschlag von Bigwill solltest du aber sehr auf die Lichtverhältnisse beim Aufnehmen des Würfels achten (keine Reflektionen, gleichmäßige Ausleuchtung,...). Wenn du darauf nicht achten willst, dann wird es so einfach vermutlich nur in wenigen Fällen funktionieren.



  • Stabile Lichtverhältnisse brauch man eigentlich immer um aus einem Bild Informationen extrahieren zu können (das is nun mal das A & O bei der Sache), deswegen hatte ich das wohl vergessen zu erwähnen.
    Aber ich glaube ohne diese wirst du bei einer anderen Methode eben auch nicht glücklich.



  • Na das ist dochmal ein Ansatz.
    Nur leider gehts dadurch noch nicht wirklich weite.
    Da ich euch aber auch nicht endlos nerven will bitte ich euch mir zu sagen ob es irgendwo auch dazu Tuts gibt.

    Denn in diesem Bereich habe ich noch gar keine Ahung.
    Wie soll ich nen Bild in Graustufen umwandeln?
    Und kann mir nicht mal jemand nen Code geben mit dem ich das Pic in den RAW laden kann ?
    Und wie sieht der RAW aus? Sieht das wie ein Array aus wo dann immer xy Koordinate und Grauwert zusammen stehen ?
    Oder wie soll ich mir das vorstellen ?

    Danke nochmals



  • Bigwill schrieb:

    Stabile Lichtverhältnisse brauch man eigentlich immer um aus einem Bild Informationen extrahieren zu können (das is nun mal das A & O bei der Sache), deswegen hatte ich das wohl vergessen zu erwähnen.
    Aber ich glaube ohne diese wirst du bei einer anderen Methode eben auch nicht glücklich.

    Naja, man kann da schon etwas machen. "adaptive histogram equalization" ist hier das Stichwort. Das dauert aber sehr lange, da kann man die Cam also in jedem Fall vergessen. Sicherlich gibt es auch noch andere Dinge, die man gegen nicht sehr gute Lichtverhältnisse machen kann.



  • Romeo-G schrieb:

    Da ich euch aber auch nicht endlos nerven will bitte ich euch mir zu sagen ob es irgendwo auch dazu Tuts gibt.

    Ich kann dir da nur 2 Bücher nennen. Beide setzen eine Menge mathematisches Vorwissen voraus und haben IMHO ein recht hohes Niveau.

    1. "Digitale Bildverarbeitung" von Bernd Jähne (Springer)

    2. "Image Processing, Analysis, and Machine Vision" von Milan Sonka, Vaclav Hlavac und Roger Boyle (PWS)

    Das 2. Buch ist eigentlich verständlicher geschrieben, dafür ist es in Englisch, extrem teuer und nur über Import zu bekommen.



  • Also RAW ist einfach ein 1D Array oder 2D. Wobei ich 1D bevorzuge.

    Raw kannst du dir simpel vorstellen:

    01 . . . . 5 . . . . 10
    11. . . . 15. . . . 20
    .
    .
    41
    .
    

    Jeder Zahl sind bei RGB 3 * 8 Bits bzw. 3 * 1 Byte zugeordnet für R G und B.

    Eine einfache Möglichkeit, ein Graustufenbild zu erzeugen ist einfach. Ist aber nur als Ansatz gedacht. Zu Artikeln usw. müßtest du selbst mal suchen. Ich lege das ganze mal auf 256 Farben BW aus.

    unsigned char sw = 0;
    
    sw = r[pos] / 3 + g[pos] / 3 + b[pos] / 3;
    


  • Also, ich persönl. arbeite mit dem Borland C++Builder und log. dann auch C++.

    http://www.c-plusplus.net/forum/viewtopic.php?t=11093&start=0&postdays=0&postorder=asc&highlight=graustufen Da steht was zum umwandeln.

    Mit was arbeitest du den nun eigentlich? C oder Java? Danach richtet sich ja auch der Zugriff auf die Bilder.

    Ein Grauwerthistogramm ist im Prinzip nix anderes als eine Mengenverteilung der Grauwerte aus einem Bild. Man geht also alle 255 Grauwerte durch und zählt wie oft diese in dem Bild (als Pixel) vorkommen.
    Wenn man sich diese dann als Diagramm (Grauwert 1 Menge - Grauwert 255 Menge)darstellt, kann man gut erkennen welcher Grauwert als Schwelle für die Binarisierung dienen sollte.

    Versuche das alles erstma Schrittweise umzusetzen, also eine Funktion die dir das Bild umwandelt und eine die dir das Grauwerthistogramm errechnet, dannach kann man dann weitersehen.



  • Also habe mir das hier mal angeschaut, 100%ig schlau werde ich daraus nur leider nicht.

    //--------------------------------------------------------------------------- 
    // funktion mach aus einen RGB-bild ein Graustufen-Bild 
    //--------------------------------------------------------------------------- 
    void __fastcall TForm1::RGBToGray(Graphics::TBitmap *bmp) 
    { 
      Graphics::TBitmap *bmp_gray = new Graphics::TBitmap(); 
    
      bmp_gray->Assign(bmp); 
    
      // über die höhe 
      for (int j = 0; j < bmp_gray->Height; j++) 
      { 
        // eine zeile des bildes einlesen 
        RGBTRIPLE *SL = (RGBTRIPLE *) bmp_gray->ScanLine[j]; 
    
        // über die breite 
        for (int i = 0; i < bmp_gray->Width; i++) 
        { 
          BYTE gray; 
    
          // bild normal ausgrauen oder mit helligkeitsanpassung  
          // (ist für menschliches auge besser erkennbar) 
          if (CheckBox3->Checked) 
            gray = (SL[i].rgbtRed * 0.299) + (SL[i].rgbtGreen * 0.587) + (SL[i].rgbtBlue * 0.114); 
          else 
            gray = (SL[i].rgbtRed + SL[i].rgbtGreen + SL[i].rgbtBlue) / 3; 
    
          // farbwerte wieder zuweisen 
          SL[i].rgbtRed   = gray; 
          SL[i].rgbtGreen = gray; 
          SL[i].rgbtBlue  = gray; 
        } 
      } 
    
      // bild auf formular anzeigen 
      Image1->Picture->Bitmap->Width  = bmp_gray->Width; 
      Image1->Picture->Bitmap->Height = bmp_gray->Height; 
      Image1->Picture->Bitmap         = bmp_gray; 
    
      delete bmp_gray; 
    }
    

    Also hiermit soll das Bild erstmal in Graustufen umgewandelt werden.
    Nur irgendwie fehlt hier noch ne Menge zu bis das Prog ein Bild wirklich umwandelt, oder?

    z.B. welche Headerfiles brauche ich?
    Wo sage ich dem Code wie das BMP File heißt das er umconvertieren soll?
    Oder könnt ihr sonst nochmal 2-3 Takte zu dem Code sagen?

    Danke



  • 1. Eine "Farbe" ist dann ein Grauwert, wenn der R-, G- und B-Wert gleich sind. Deshalb macht er in dem Code am Schluss:

    SL[i].rgbtRed   = gray;  
    SL[i].rgbtGreen = gray;  
    SL[i].rgbtBlue  = gray;
    

    Das mußt du nicht machen, denn eigentlich möchtest du kein Grauwertbild haben, sondern ein Bild mit nur einem "Farbkanal".

    if (CheckBox3->Checked)  
            gray = (SL[i].rgbtRed * 0.299) + (SL[i].rgbtGreen * 0.587) + (SL[i].rgbtBlue * 0.114);  
          else  
            gray = (SL[i].rgbtRed + SL[i].rgbtGreen + SL[i].rgbtBlue) / 3;
    

    Offensichtlich hat der Schreiber des Codes in der GUI eine CheckBox, die einen Text, wie "menschliche Wahrnehmung berücksichtigen" hat. Das menschliche Auge nimmt die unterschiedlichen Farben unterschiedlich stark wahr. Das wird hier simuliert, indem (wenn die Checkbox aktiviert ist) der Rot-Wert zu 29,9% zum Grauwert beiträgt, der Grün-Wert zu 58,7% und der Blau-Wert zu 11,4%. Wenn die menschliche Wahrnehmung nicht berücksichtigt werden soll, dann wichtet er hier alle Farben gleich. Das entspricht der "Intensität".

    Da du nicht wirklich ein Grauwertbild brauchst, sondern im Prinzip nur ein Bild, bei dem jeder Pixel (Picture Element) durch nur einen Wert gekennzeichnet ist, lohnt es sich, sich zu überlegen, ob man diesen einen Wert nicht besser auf eine ganz andere Art und Weise bestimmt. Möglicherweise gibt es eine Variante, bei der die benötigten Merkmale des Bildes nachher besser zu erkennen sind. Angenommen du hast immer einen weißen Hintergrund und einen roten Würfel mit blauen Punkten: In diesem Fall wäre es klug, keine umständliche Grauwert-Berechnung durchzuführen, sondern einfach immer den Blau-Wert anzugucken. Der ist nämlich beim Hintergrund und bei den Punkten hoch, beim Rot des Würfels ist er aber klein.



  • Hast du eigentlich auch schon mal die Hilfe befragt?
    Ich meine, schließlich wird das ja deine Arbeit und nicht die vom Forum hier.

    if (CheckBox3->Checked)   
            gray = (SL[i].rgbtRed * 0.299) + (SL[i].rgbtGreen * 0.587) + (SL[i].rgbtBlue * 0.114);   
          else   
            gray = (SL[i].rgbtRed + SL[i].rgbtGreen + SL[i].rgbtBlue) / 3;
    

    Mit Hilfe des folgenden Codes lässt sich die Graustufe einer
    beliebigen RGB Farbe herausfinden. Das System arbeitet nach dem
    vom amerikanischem NTSC (National Televisision Standards Committee)
    vorgelschlagenem System.
    Es kann unteranderem dazu verwendet werden ein Bild in Graustufen
    darzustellen. (siehe dazu Tipp http://www.swissdelphicenter.ch/de/showcode.php?id=437)

    Ist also nunmal Standard und bevor ich irgendwelche Sonderarten basteln würde, würde ich erstmal nach dem Standard vorgehen.
    Im übrigen möchte ich dir mal empfehlen auch mal Google zu den begriffen zu befragen, da gibts ne ganze Menge.

    Im übrigen ist der Code doch gut dokumentiert. Headerfiles brauchst jetzt glaube keine (zumind. im BCB), das probier ich nachher gleich ma und editier das hier rein.

    So habs getestet. Get so wies dasteht, wobei ci die Checkbox entfernt habe.


Anmelden zum Antworten