JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.php?sid=b2bb43a4df6853ea6f39cba73fbef4fcMedaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Sprache zu Text und Text zu Sprache

 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Tutorials
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
AFE-GmdG
JLI MVP
JLI MVP


Alter: 45
Anmeldedatum: 19.07.2002
Beiträge: 1374
Wohnort: Irgendwo im Universum...
Medaillen: Keine

BeitragVerfasst am: 14.02.2012, 21:37    Titel: Sprache zu Text und Text zu Sprache Antworten mit Zitat

Geil - Simpler geht es nicht.
Ich habe gestern ein wenig mit Spracherkennung und Sprachsynthese rumprobiert und habe bemerkt, wie einfach das im Prinzip ist.

Zuerst die Voraussetzungen:
Microsoft Speech Platform - Software Development Kit (SDK) (Version 11)
Microsoft Speech Platform - Runtime Languages (Version 11)
Supported Operating Systems: Windows 7, Windows Server 2008, Windows Server 2008 R2, Windows Vista

Nachdem man das SDK installiert hat benötigt man noch eine Spracherkunnungs-Sprache und eine Text Zu Sprachen-Stimme.
Man sollte die deutsche Spracherkennung (MSSpeech_SR_de-DE_TELE.msi) und die deutsche Stimme (MSSpeech_TTS_de-DE_Hedda.msi) installieren.

Anschließend kann es auch schon losgehen. Man erstellt ein neues C#-Konsolenprojekt und fügt die Referenz "C:\Program Files\Microsoft SDKs\Speech\v11.0\Assembly\Microsoft.Speech.dll" dem Projekt hinzu.

Die Datei Program.cs sieht nun wie folgt aus:
CPP:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
   class Program
   {
      static void Main(string[] args)
      {
      }
   }
}

Für den folgenden Code benötigt man noch ein paar Namespaces, welche ich einfach mal Kommentarlos hier aufführe:
CPP:
using System.Globalization;
using System.Linq;
using System.Threading;
using Microsoft.Speech.Recognition;
using Microsoft.Speech.Synthesis;

Zuerst eine einfache Sprachausgabe. Dazu fügen wir folgende Funktion der Klasse hinzu:
CPP:
private static void Name()
{
   using(var synth = new SpeechSynthesizer()) {
      var sprache = synth.GetInstalledVoices().FirstOrDefault(voice => voice.VoiceInfo.Culture.Name.Equals("de-DE"));
      if(sprache == null)
         return;
      synth.SelectVoice(sprache.VoiceInfo.Name);
      synth.SetOutputToDefaultAudioDevice();
      synth.Rate = 1;
      synth.Speak("Mein Name ist Emi.");
   }
}

Man erstellt einen Sprach-Syntetisierer und sucht sich die deutsche installierte Sprache heraus.
Anschließend setzt man die Sprache und die Ausgabe (in diesem Fall die DefaultSoundausgabe)
Mit der Rate-Eigenschaft kann man die Sprechgeschwindigkeit modifizieren. Es gibt weitere Eigenschaften, welche gesetzt werden können, ich habe mich auf die Geschwindigkeit beschränkt.
Und dann kann einfach losgequasselt werden.

Diese Funktion kann nun einfach aus der Mainfunktion aufgerufen werden.
CPP:
static void Main(string[] args)
{
   Name();
}

Nicht sehr sinnvoll, aber cool. - So einfach ist die Sprachausgabe.
Fügen wir nun einfach ein wenig Code zur Spracherkennung von hinzu.
Ich habe den Code einfach in die Mainfunktion geschrieben, das sollte man natürlich richtig ausprogrammieren:
CPP:
public static void Main()
{
   var exit = false;
   var engines = SpeechRecognitionEngine.InstalledRecognizers();
   var gerEngine = engines.FirstOrDefault(r => r.Culture.Name.Equals("de-DE"));
   if(gerEngine == null) {
      Console.WriteLine("Keine deutsche Spracherkennung installiert.");
      return;
   }
   using(var sre = new SpeechRecognitionEngine(gerEngine.Id)) {
      var sätze = new Choices("Guten Tag", "Hallo", "Wie spät ist es", "Hallo Emi", "Beende das Programm", "Wie heisst du");
      var gb = new GrammarBuilder() { Culture = gerEngine.Culture };
      gb.Append(sätze);
      var g = new Grammar(gb);
      sre.LoadGrammar(g);

      sre.SpeechRecognized += (s, e) => {
         Console.WriteLine("SpeechRecognized: " + e.Result.Text);
         switch(e.Result.Text) {
         case "Guten Tag":
         case "Hallo":
         case "Hallo Emi":
            Grüße();
            break;
         case "Wie heisst du":
            Name();
            break;
         case "Wie spät ist es":
            Uhrzeit();
            break;
         case "Beende das Programm":
            exit = true;
            break;
         }
      };
      sre.SpeechHypothesized += (s, e) => {
         Console.WriteLine("SpeechHypothesized:" + e.Result.Text);
      };
      sre.SpeechRecognitionRejected += (s, e) => {
         Console.WriteLine("SpeechRecognitionRejected: " + e.Result.Text);
      };
      sre.SetInputToDefaultAudioDevice();
      sre.RecognizeAsync(RecognizeMode.Multiple);

      while(!exit) {
         Thread.Sleep(100);
      }
      sre.RecognizeAsyncStop();
   }
}

Zuerst erstelle ich das ErkennungsObjekt und suche aus den im System installierten Sprachen die mit der deutschen Unterstützung raus.
Dann füge ich die zu erkennenden Sätze hinzu und registriere die Ereignisse, welche aufgerufen werden, wenn:
- Ein Satz erkannt wird
- Ein Satz wahrscheinlich wird
- Eine wahrscheinliche Erkennung verworfen wird.
Ich habe mich hier für die Inlinenotation (C# Lambdaausdrücke) entschieden, das könnte man natürlich auch auslagern.
Anschließend wird das StandardEingabemikro ausgewählt und die erkennung gestartet.
In einer Simplen Endlosschleife wird dann auf das Programmende gewartet und die Erkennung gestoppt.

Ich habe noch zwei weitere Sprachausgabefunktionen hinzugefügt:
CPP:
private static void Grüße()
{
   using(var synth = new SpeechSynthesizer()) {
      var sprache = synth.GetInstalledVoices().FirstOrDefault(voice => voice.VoiceInfo.Culture.Name.Equals("de-DE"));
      if(sprache == null)
         return;
      synth.SelectVoice(sprache.VoiceInfo.Name);
      synth.SetOutputToDefaultAudioDevice();
      synth.Rate = 1;
      synth.Speak("Hallo Andreas!");
   }
}

private static void Uhrzeit()
{
   using(var synth = new SpeechSynthesizer()) {
      var sprache = synth.GetInstalledVoices().FirstOrDefault(voice => voice.VoiceInfo.Culture.Name.Equals("de-DE"));
      if(sprache == null)
         return;
      synth.SelectVoice(sprache.VoiceInfo.Name);
      synth.SetOutputToDefaultAudioDevice();
      synth.Rate = 1;
      var builder = new PromptBuilder(CultureInfo.GetCultureInfo("de-DE"));
      builder.StartSentence();
      builder.AppendTextWithHint("Es ist jetzt", SayAs.Text);
      var now = DateTime.Now.ToString("HH U\\hr mm", CultureInfo.GetCultureInfo("de-DE"));
      builder.AppendTextWithHint(now, SayAs.Time24);
      builder.EndSentence();
      synth.Speak(builder);
   }
}

In der zweiten Funktion deute ich an, wie man genauer bestimmen kann, wie bestimmte Texte betont werden müssen. Dazu nutzt man die Prompt-Klasse, welche neben den Texten auch die Betonungsinformationen enthält. Den Prompt kann man mit einem PromptBuilder erstellen.

Und das war auch schon alles.
Das Programm versteht jetzt mehrere Sätze und antwortet darauf.
Die Herausforderung besteht jetzt darin, eine Datenbasis für möglichst intelligente Antworten zu schaffen, vielleicht indem man nicht auf volle Sätze reagiert, sondern auf einzelne Worte, welche in einem Kontext zu vorher gesprochenen Worten gesetzt die richtigen Antworten liefern.

Wie wäre es z.B. mit einem Tachenrechner, dem man einfach die Rechenaufgabe ansagt?
Viel Spaß beim rumprobieren.

AFE-GmdG
_________________
CPP:
float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;}
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Jonathan_Klein
Living Legend


Alter: 37
Anmeldedatum: 17.02.2003
Beiträge: 3433
Wohnort: Siegerland
Medaillen: Keine

BeitragVerfasst am: 15.02.2012, 20:53    Titel: Antworten mit Zitat

Hört sich ja ulkig an Very Happy

Habs mal nach Tutorials verschoben.
_________________
https://jonathank.de/games/
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Jones
Senior JLI'ler


Alter: 33
Anmeldedatum: 03.03.2005
Beiträge: 208
Wohnort: Köln
Medaillen: Keine

BeitragVerfasst am: 16.02.2012, 23:18    Titel: Antworten mit Zitat

Klingt nach ner interessanten Sache. Hatte bisher immer die Meinung das Spracherkennung ne komplizierte Sache sind, aber wie sich dein Post lesen lässt scheints ja gar nicht so kompliziert zu sein mit der richtigen Grundlage. Werd mir das auf jeden Fall nochmal genauer anschauen.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
magigman
Junior JLI'ler



Anmeldedatum: 25.09.2007
Beiträge: 87

Medaillen: Keine

BeitragVerfasst am: 20.02.2012, 22:47    Titel: Antworten mit Zitat

Sehr coole Sache. Habe mir vor kurzem erst die Speech API gesaugt und werde mal etwas damit herumtüfteln. Man kann das dann auch so weit führen, dass man den ganzen PC damit steuern kann. "Starte den Internetbrowser", "Maximiere dieses Fenster", ...
Sicher, das kann man auch mit der Windows Sprachsteuerung und den Windows Speech Recognition Macros, aber man hat eben Grenzen. Smile
_________________
Wer einen Rechtschreibefehler findet, darf ihn behalten, in ein Regal stellen und jedem der vobei geht sagen, dass ER ihn gefunden hat.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
AFE-GmdG
JLI MVP
JLI MVP


Alter: 45
Anmeldedatum: 19.07.2002
Beiträge: 1374
Wohnort: Irgendwo im Universum...
Medaillen: Keine

BeitragVerfasst am: 21.02.2012, 10:36    Titel: Antworten mit Zitat

Leider musste ich bei genaueren Studien der (nicht/nur mangelhaft vorhandenen Dokumentation) feststellen, dass die Funktion für Freitexteingabe (Diktat) nicht funktioniert.
Trotzdem konnte ich mit Hilfe von Silben eine ähnliche Funktionalität nachbilden, allerdings muss man sich damit begnügen, dass der Ausgegebene Text dann "in et wa so aus sie t und man des we gen noch ei nen in te li gen ten par ser bau en muss"
Trotzdem ist es mir gelungen einen Sprachgesteuerten Taschenrechner zu bauen, welcher Zahlen aus der Silben-Text-Form analysiert.
Ich habe noch keine Grenze für die Komplexität einer Grammatik gefunden und werde mir deshalb demnächst einen Grammatikbuilder basteln, der seine Regeln aus einer SQL-Datenbank bezieht. Ich habe da schon die eine oder andere Idee.

Viel Spaß weiterhin beim probieren.

PS.: Kennt jemand eine Möglichkeit die Betonung der Sprachausgabe zu manipulieren? Fragen werden standardmäßig falsch betont und klingen deshalb sch****

AFE-GmdG
_________________
CPP:
float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;}
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Dennis
Mini JLI'ler


Alter: 30
Anmeldedatum: 11.11.2009
Beiträge: 8

Medaillen: Keine

BeitragVerfasst am: 04.02.2013, 15:00    Titel: Antworten mit Zitat

Hört sich ja alles super an!

Meine Frage wäre jetzt nur, ob das SDK auch unter c++ läuft, oder nur c#?

Hab leider keine Zeit mich mit c# auseinander zu setzen, deshalb bitte kein Kommentare in die Richtung, dass c++ ungeeignet sei!

Grüße
Dennis
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
AFE-GmdG
JLI MVP
JLI MVP


Alter: 45
Anmeldedatum: 19.07.2002
Beiträge: 1374
Wohnort: Irgendwo im Universum...
Medaillen: Keine

BeitragVerfasst am: 04.02.2013, 20:46    Titel: Antworten mit Zitat

Ja. Da ist die Version ein wenig anders, aber technisch funktioniert das auch mit C++ (Microsoft Speech SDK, aktuellen Version ist glaube ich 5.1)
Das alles basiert auf COM und die C#-Variante, welche ich hier vorgestellt habe ist eigentlich nur ein "Wrapper"
Microsoft Speech SDK 5.1
_________________
CPP:
float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;}
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Dennis
Mini JLI'ler


Alter: 30
Anmeldedatum: 11.11.2009
Beiträge: 8

Medaillen: Keine

BeitragVerfasst am: 05.02.2013, 10:31    Titel: Antworten mit Zitat

Ist gut.
Ich werde das dann demnächst ausprobieren. Smile

Vielen Dank noch mal
Dennis
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Dennis
Mini JLI'ler


Alter: 30
Anmeldedatum: 11.11.2009
Beiträge: 8

Medaillen: Keine

BeitragVerfasst am: 06.02.2013, 15:30    Titel: Deutsche Sprache Antworten mit Zitat

Hab mich mal ein bisschen mit dem Speech SDK auseinandergesetzt. Allerdings bin ich an dem Versuch gescheitert ein deutsches Sprachpaket zu installieren.
Er zeigt immer nur die "Microsoft Anna" an. Rolling Eyes
Bei Google habe ich auch nichts gefunden...

Vielleicht kann mir ja jemand helfen, verwende Win7 64bit Home Premium.

Danke
Dennis
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
AFE-GmdG
JLI MVP
JLI MVP


Alter: 45
Anmeldedatum: 19.07.2002
Beiträge: 1374
Wohnort: Irgendwo im Universum...
Medaillen: Keine

BeitragVerfasst am: 07.02.2013, 08:12    Titel: Antworten mit Zitat

Such mal hier, Ich glaube da gab es deutschsprechende Voices und Recognizer:
Microsoft German Recognizer
_________________
CPP:
float o=0.075,h=1.5,T,r,O,l,I;int _,L=80,s=3200;main(){for(;s%L||
(h-=o,T= -2),s;4 -(r=O*O)<(l=I*I)|++ _==L&&write(1,(--s%L?_<(L)?--_
%6:6:7)+\"World! \\n\",1)&&(O=I=l=_=r=0,T+=o /2))O=I*2*O+h,I=l+T-r;}
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Tutorials Alle Zeiten sind GMT
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de

Impressum