Bitte mal so richtig auseinandernehmen: Handschriftenerkennung



  • MasterCounter schrieb:

    ok, sorry, hat mich halt nur gewundert... 😃

    Ist ja kein Problem, ich würde das nur gerne aus diesem Thread hier raushalten, damit der übersichtlich bleibt.



  • Habe jetzt noch ein bisschen aufgeräumt, das Ding kompiliert jetzt auch mit g++-3.4.3 bei "-Wall -pedantic -std=c++98" ohne Warnungen.



  • Hmm, mir ist nicht so klar wie das ganze funktioniert.
    Eine kurze Anleitung währe mal ganz nett.
    Die Erkennung sieht bei mir irgendwie nach 'random' aus; als ob das Verfahren keinerlei Translations- oder Skalierungsinvarianz besitzt.

    Klärt mich mal auf.
    Gruß



  • grob gesagt: es wird das eingabefeld runtergesampled auf 16x16 pixel. dieses wird dann als 256 bit vektor aufgefasst (schwarz/weis sozusagen). auf diesen wird jetzt die pca angewendet (was im endeffekt v.a. eine dimensionsreduzieurng ist), wie du richtig erkannt hast, ist das verfahren nicht gerade das beste, wenn es um translation oder skalierung geht (ich sag ja: ein neuer extrakter muss her :). dieser minderdimensionale vektor wird jetzt durch einen billigen next-neighbour klassifikator gejagt (oder isses mitlerweile schon ein n-next-neighbour?). thats all 🙂 Ach ja, die Samples werden halt noch gespeichert, damit man nicht immer bei null anfangen muss!



  • Also für ein wenig mehr invarianz sollte das Bild, genauer gesagt der Buchstabe, vorher normiert werden.
    Sehr einfach ist da eine Bounding Box um den Buchstaben zu legen (kleinster x/y-Wert bis größter x/y-Wert) und dann das Rechteck inkl. Inhalt auf die Maße zu skalieren, die auch für die Buchstaben in der Trainingsmenge verwendet wurden.
    Das würde evtl. sogar einen kleinen Teil Affininvarianz bringen...

    Rotationsinvarianz gibt es dann, indem man den Buchstaben vorher noch dreht. (Die Ausrichtung gibts durch die Eigenwerte; oder Momente des äquivalenten Rechtecks).
    http://www.c-plusplus.net/forum/viewtopic.php?t=98145

    Wenn Du einen (k-)NN-Klassifikator mit euklidscher Norm verwendest, kannst Du die Wurzel bei der Berechnung der Distanzen weglassen, da Du nur an dem Minimum interessiert bist.

    Ich hoffe das meintest Du mit auseinandernehmen.

    Gruß



  • jo in die richtung gehts. am klassifikator wird eh noch derb geschraubt. momentan gehts mehr drum, die schnittstellen (extrakter, klassifikator, etc) ordentlich aufzubauen, um spaeter entsprechend unterschiedliche implementierungen anzudocken. (der aktuelle klassifikator war ne 3 minuten nummer, kein "mit hirn" programmierter)



  • Kyon: Ich habe an unserer in einer Nacht gebastelten Erkennung selbst absolut nichts verändert, ich habe sie nur komplett vom GUI losgelöst.
    Mir geht es, wie Korbinian bereits sagte, nur darum, den existierenden Code aufzuräumen, damit wir dann eine fixe Schnittstelle etablieren können.
    Und der Klassifikator ist dann das geringste Problem, wenn die Infrastruktur steht, soll der Klassifikator selbst zur Laufzeit austauschbar werden, so dass man ganz einfach neue Klassifikatoren hinzufügen kann, was natürlich verbunden mit ein paar anderen geplanten Features auch das Testen extrem vereinfachen wird.



  • etwa so soll das ganze dann ausschaun: www.korbinian-riedhammer.de/docs/schrifterkennung-uml.png



  • hi!
    tut sich da was?
    ich hab mich jetzt letztens einmal hingesetzt und mir das angeschaut, versucht ein bisschen umzudesignen (um ehrlich zu sein steck ich mitten drin; ja, ich hab sonst nichts anderes zu tun [semesterferien]), das problem ist nur, dass ich nicht genau weiß, was die einzelnen teile tun und ich ein an der implementation nicht allzugroß herumbauen will/kann. (d.h. was ich tue ist eher ein wrapper, auch wenn ich einzelne sachen schon umgebaut hab [noch funktioniert alles]).
    meine grund-idee wäre (was sich allerdings noch redesignen lässt, allzu viel plan hab dahinter hab ich nicht vorzuweisen)

    using namespace cpp_de;
    
       Classifier* classifier = new NextNeighbourClassifier;
       classifier->add_classes(ClassesFromFile("classes.dat"));
       TokenFromFile token("token");
       Class* which = classifier->class_of(token);
    
       cout << "Erkennung: " << which->name() << endl;
    

    status: ca. 30% fertig (nach wunschvorstellung, keine garantie auf die klassennamen).
    es erwies sich nicht als sinnvoll, den namen "Class" zu verwenden. (class Class class_; sieht doof aus.)
    pca hab ich aufgeteilt in eine factory (ClassesFromFile) und für die projektion (soweit ich das konzept verstanden hab) in einzelne Classes. An den Classifier hab ich mich noch nicht rangemacht.
    achja: was zum teufel macht die funktion PCA::g -- ein sinnvollerer name wäre vielleicht nicht schlecht, die tummelt sich nämlich immer noch mittendrin (private aber doch) immer noch als g (int j, ...) herum.
    wie gesagt: ein absolut tolles konzept kann ich nicht bieten, weil ich mich mit den hintergründen einfach nicht auskenne (ist es sinnvoll den kernel als policy zu implementieren?) bin da also als enduser-wie-würde-ich-gerne-eine-handschrifterkennungs-lib-verwenden rangegangen.

    so viel zeit hab ich allerdings noch nicht verschissen, wenn ihr also meint, nein -- wir haben eine andere vorstellung oder nein, das projekt ist tot oder nein, ich arbeite gerade an etwas anderem -- dann bitte schnell sagen 🙂

    code gibt's erst, wenn ich ihn schön nachbearbeitet hab 😉

    oh und dein uml-diagramm lieber korbinian hab ich leider erst jetzt gesehen...



  • Hallo,
    Steck da bitte nicht zuviel Zeit rein, davie, ich sitz gerade an einer Library-Version bei der man den Klassifikator erst zur Laufzeit als Plugin lädt.
    Bin zwar noch nicht allzu weit bis jetzt, weil ich mich aufs nächste Semester vorbereiten muss, aber ich hab schon eine recht genaue Vorstellung, wie das ungefähr aussehen soll. 🙂
    Ich würde meine Pläne ohnehin gerne noch von irgendjemandem genauer auf Designfehler abklopfen lassen; vielleicht können wir das bei einem weiteren kleinen Wiener-Forumstreffen machen? Ist nämlich verdammt schwer und anstrengend, alle Ideen und Gedanken dahinter in eine halbwegs bequem lesbare schriftliche Form zu bringen... 😉



  • ok, dann stopp ich mal und wir bereden das beim nächsten wien treff.



  • Öhm, warum macht Ihr die Minderdimensionierung und verliert Informationen dadurch ? Mein Vorschlag hier... macht eine Wavelet-Transformation. Ein Bild der Größe 32x32 wird in 4 16x16 Bilder zerlegt. Das erste 16x16 Bild entspricht einem quasi Mittelwert, das zweite alle horizontalen Kantenübergänge, das Dritte alle vertikalen Kantenübergänge und das Letzte jeweils alle diagonalen Kantenübergängen (siehe -> http://nt.eit.uni-kl.de/wavelet/dwt_2d.html, in dem Beispiel dort, wird mehr als eine Transformation gemacht), jeder Buchstabe wird auch hier einen eindeutigen Fingerabdruck hinterlassen und (!) es geht keine (!) Information verloren. Darüberhinaus könnte der Buchstabenerkenner im Fall einer nicht eindeutigen Identifizierung des Buchstabens einfach eine weitere Transformation anwerfen, und so sukzessive den Buchstaben "herauszuschneiden".

    Gruß Winn



  • Ich arbeite momentan in meiner (relativ spärlichen) Freizeit gerade an einer neuen Version, bei der Klassifikatoren einfach als Plugins zur Laufzeit geladen werden; sobald die steht, darfst Du das gerne implementieren, wenn Du glabust, dass es gute Resulatet bringt.
    Bis die Sache mit dem Klassifikatoren in der Library dynamisch laden steht, werde ich an der Erkennung selbst nichts anrühren.



  • wie siehts denn hiermit aus?? gibbet da schon was neues an code schnipsel oder ideen??



  • ahjo, jester und ich geben in den nächsten wochen einen neuen artikel zu bildverarbeitung raus, da wird was reinkommen, das damit sehr verwandt ist, das ganze verpackt in ein nettes code framework mit doku etc damits auch von anderen weiterentwickelt werden kann.



  • MasterCounter schrieb:

    wie siehts denn hiermit aus?? gibbet da schon was neues an code schnipsel oder ideen??

    Nein, das habe ich damals im Alleingang in den Sand gesetzt, sorry. 😕

    Mir fehlte letzten Endes schlichtweg die Zeit, daran weiterzuarbeiten und da ich eines der grundlegendsten OpenSource-Mantras nicht befolgt habe ("Release early, release often"), weil ich alles sauberer und ordentlicher haben wollte, als gesund für das Projekt war, starben meine Pläne recht schnell.

    Wenn ich in der Anfangsphase eine Woche mehr Zeit gehabt hätte, dann hätte alles anders ausgesehen, aber dann habe ich ein paar Aufträge auf einmal übernommen, die schnell sämtliche Zeit für das Projekt auffraßen. (edit: Dabei waren natürlich auch die zwei Studienrichtungen parallel nicht unbedingt hilfreich. ;))

    Aber freut mich wirklich, zu hören, dass Korbinian und Jester jetzt in die Richtung etwas unternehmen, wäre wirklich schade gewesen, wenn das bereits gestorben wäre. 👍



  • Korbinian schrieb:

    ahjo, jester und ich geben in den nächsten wochen einen neuen artikel zu bildverarbeitung raus, da wird was reinkommen, das damit sehr verwandt ist, das ganze verpackt in ein nettes code framework mit doku etc damits auch von anderen weiterentwickelt werden kann.

    Schmeiß mal'n paar Fachbegriffe in die Runde. 🙂 Du hast mich neugierig gemacht, was da wohl alles drinstehen wird. 😋



  • also es wird einen teil zu pca geben (den macht jester), dann einen teil zu klassifikation geben (den mach ich) und dann halt vorallem was zum anschaun (sprich eine anwendung). überlegen gerade noch was genau, jester würde gesichtserkennung sehr interesantfinden, ich fände vielleicht noch gesten oder grimassen (~stimmung) noch interessant. momentan ärgere ich mich mit einer vernünftigen strukturierung rum, aber es sieht schon recht gut aus 🙂 eine _lauffähige version existiert schon, nur _hübsch ist sie noch nicht. sobald das framework übersichtlich ist und steht, werd ich das ganze releasen und jeder kann sich damit austoben.


Anmelden zum Antworten