l'ennesimo ritorno del speech to text

ebbene si sono qui perchè sto creando un’applicazione che dovrà interfacciarsi con arduino e controllare entrate e uscite (nei vari modi con programmazione unica lato arduino) tramite un programma in C# ed ovviamente questo programma sarà interattivo con la voce.

per rendermi le cose più difficili ho deciso di non usare il kinect, questo perchè voglio rendere il codice open source e mentre quasi tutti avranno un microfono per il pc non tutti hanno un kinect e non voglio far comprare hardware aggiuntivo :wink: (e poi non ho il kinect quindi… :smiley: )

sto usando le sapi di microsoft (speech api insomma) che mi permettono di fare il tts (text to speech) e l’stt (speech to text).
naturalmente la lingua italiana non è supportata, ho studiato un po’ e dopo 2 o 3 prove (windows settato in inglese) ho notato che impostando i grammar giusti è possibile arrivare a distinguere i comandi in italiano anche se sotto il profilo inglese.
mi sono detto “perfetto, è ora di tornare con windows in italiano!”.

per non aver problemi di riconoscimenti errati dal punto di vista del “controllo vocale” di windows integrato sto usando la classe SpeechRecognitionEngine invece che la SpeechRecognizer che mi permette anche quindi di avere una grammatica più rigida.
ricordate però? il riconoscimento vocale in italiano non c’è, tuttavia ho pensato che ci fosse un modo per forzare il motore inglese (ho i pacchetti per la lingua inglese installati ovviamente) e farlo funzionare anche in italiano.
beh probabilmente sbagliavo…

questo è il mio codice attuale quindi:

using SpeechLib;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Speech;
using System.Speech.Recognition;
using System.Speech.Synthesis;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        // inizializzo voce e riconoscimento
        SpeechRecognitionEngine reco = new SpeechRecognitionEngine(new System.Globalization.CultureInfo("en-US"));
        SpeechSynthesizer voice = new SpeechSynthesizer();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            reco.Dispose();

            //setto l'input
            reco.SetInputToDefaultAudioDevice();

            //creo la grammatica
            Choices comandi = new Choices();
            comandi.Add("a");
            comandi.Add("lorenzo");
            comandi.Add("due");
            comandi.Add("tre");
            comandi.Add("mamma");
            comandi.Add("diciassei");
            comandi.Add("venticinque");

            // scarico eventuali grammar e poi carico i comandi
            reco.UnloadAllGrammars();
            reco.LoadGrammar(new Grammar(new GrammarBuilder(comandi)));

            // attivo l'evento sul riconoscimento
            reco.SpeechRecognized +=
                new EventHandler<SpeechRecognizedEventArgs>(
                                     SpeechRecognizedHandler);

            // faccio partire il riconoscimento in tutte le modalità
            reco.RecognizeAsync(RecognizeMode.Multiple);

        }

        // funzione al riconoscimento
        void SpeechRecognizedHandler(object sender, SpeechRecognizedEventArgs e)
        {
            SetText(e.Result.Text.ToString());
        }

        // parte per evitare l'errore dei thread
        delegate void SetTextCallback(string text);

        private void SetText(string text)
        {
            if (this.textBox1.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.textBox1.Text = text;
            }
        }

    }
}

(sono un hobbysta siate clementi dai :smiley: è il mio primo codice in C# che diventerà una figata :wink: )

se la lingua del sistema è in inglese funziona, mentre se in italiano no, ma in teoria con

SpeechRecognitionEngine reco = new SpeechRecognitionEngine(new System.Globalization.CultureInfo("en-US"));

dovrei appunto “forzare” il recognition engine inglese e quindi dovrebbe andare giusto?

qualcuno di voi ha esperienze in merito?

grazie a tutti, alla fine il codice sarà 100% open source!

Un anno o due fa anche io provai con il text2speech e in tutti, ma tutti i forum/siti Micro$oft si affermava che l'italiano proprio NON lo ca**no neppure di striscio :grin:

Avevano implementato le lingue più disparate ma non l'italico. Magari nel frattempo han fatto il passo verso l'italiano, ma ai tempi mi sembrava non avessero nessuna intenzione di fare una versione ita.

bleah bleah bleah, credi ancora che microsoft rilasci qualche buona libreria? :. googla un pò cmu sphinx e poi ne riparliamo ;) oppure da un occhiata a voce è solo una banale finalizzazione di quello che puoi fare con sphinx http://voce.sourceforge.net/

ps attenzione sphinx è un motore sql di ricerca cmusphinx è un riconoscitore vocale :grin:

Siete OT, almeno finché mostrate codice per C# e parlate di programmazione lato Windows.

Microzozz ha pubblicato anche un engine text2speech in italiano ma per le vecchie versioni di Windows XP e risalgono a circa 10 anni fa. In realtà si trattava di roba realizzata da altri ma che era stata messa gratuitamente a disposizione. L'ho anche usata ma sotto VB6. Il riconoscimento invece era solo inglese. Allora avevo realizzato una chiamata di allarme su GSM ma poi risultò più comodo mandare SMS.

Da allora non ho più toccato la cosa.

C'è un motore di riconoscimento vocale in italiano su Android, io non lo uso mai ma c'è. Magari puoi vedere se si può adattare o se l'ha già fatto qualcun altro.

Però se non coinvolgi da subito Arduino leo72 ( o leìtro moderatore) ti sega e ha pienamente ragione, questo è un forum su Arduino.

Non credo completamente OT, la libreria può essere usata su PC per capire comandi vocali e poi comunicare con Arduino. Arduino non può fare questa parte, un PC si e poi possono comunicare.

Ci sono thread in cui si parla di html su PC o di Processing. Mi sembra sottointeso che si faccia lato PC qualcosa che Arduino non può fare e quindi si delega ad un PC.

2 giorni fa ho buttato giù il primo schizzo di codice con arduino (voglio evitare firmata perchè voglio un qualcosa di completamente o quasi fatto da me)

in pratica riceve su seriale e reinvia tramite la stessa gli stati in più ogni minuto dall'ultimo comando manda un summit generale dei vari input/output

il codice è molto semplice ed è il seguente:

int input[] = {2, 3, 4, 5, 6};
int output[] = {7, 8, 9, 12, 13};
int pwmout[] = {10, 11};
int analog[] = {14, 15, 16, 17, 18, 19};

int index = 0;
int datas = 0;

char stats;

unsigned long concheck;
int checkdelay = 60000;

int buffer[3];

int readed;

void setup() {
  Serial.begin(9600);
  updateStats();
  Serial.write(stats);  
  concheck = millis();
}

void loop() {
  if(concheck-millis() > checkdelay)
  {
    Serial.write(stats);
  }

  if(datas == 1) {
    switch(buffer[0])
    {
    case 0: //lettura
    if(inInput(buffer[1])) Serial.write(char(buffer[1])+char(digitalRead(buffer[1])));
    else Serial.write(char(buffer[1])+char(analogRead(buffer[1])));
      break;

    case 1: //scrittura
    digitalWrite(buffer[1], buffer[2]);
    Serial.write(char(buffer[1])+char(digitalRead(buffer[1])));
      break;

    case 2: //scrittura PWM
    analogWrite(buffer[1], buffer[2]);
    Serial.write(char(buffer[1])+"P");
      break;
    }
    
    datas = 0;
    memset(buffer, 0, 3);
  }
  
  updateStats();
}

void serialEvent(){
  datas = 1;
  while(Serial.available() >0) {
    buffer[index] = Serial.read(); // Read a character
    index++; // Increment where to write next
  }
  Serial.flush();
  index = 0;
}

void updateStats() {
  stats = 'I';
  for(int i=0;i=sizeof(input);i++) {
    stats += input[i];
    stats += digitalRead(input[i]);
  }
  stats = 'O';
  for(int i=0;i=sizeof(output);i++) {
    stats += output[i];
    stats += digitalRead(output[i]);
  }
    stats = 'P';
  for(int i=0;i=sizeof(pwmout);i++) {
    stats += pwmout[i];
  }
  stats = 'A';
  for(int i=0;i=sizeof(analog);i++) {
    stats += analog[i];
    stats += analogRead(analog[i]);
  }
}

boolean inInput(int pin) {
  boolean inarray = false;
  for(int i=0; i=sizeof(input); i++) {
    if(input[i] == pin) {
      inarray = true;
      break;
    }
    else inarray = false;
  }
  return inarray;
}

ho visto che è stato aggiungto il serialEvents e spero che faccia quello che dico, altrimenti è una modifica da un attimo.

ho letto invece l'altro giorno del problema del Serial.flush() che non è più quello di una volta e se mi darà problemi dovrò fixarlo.

per ora ho deciso di mantenere il controllo vocale in inglese comunque. la libreria speech to text esiste anche per win vista/7/8 ed è la stessa che gestisce anche il tts (ovvio con classi diverse).

riguardo alla faccenda di android sì: esiste un sistema per poterlo utilizzare: si fa una chiamata post ad una pagina specifica inviando il binario di un file flac contenente ciò che è da "tradurre" e vi è una risposta in json tuttavia ciò implica l'utilizzo di internet continuo ed ho il timore di un paio di cosette 1. se manca internet il sistema non va (e per ora stando in convitto internet mi viene staccato alle 23:30 dal ruter centrale) 2. google notando un eccesso di informazioni potrebbe aver messo un sistema che blocca le chiamate ed io mi scervellerei a capire perchè (il che porta una perdita di tempo) 3. dovendo inviare un file audio dovrei fare prima un sistema che mi crei un file audio ogni parola che dico, questo dovrebbe eliminare il rischio 2 però non saprei come implementarlo per questo cercavo un riconoscimento offline.

quello che speravo è che qualcuno fosse riuscito ad estrapolare i file di lingua per la kinect e trasformarli per le sapi ma purtroppo non è così, un po' lo capisco non essendo una cosa open source quella fatta da microsoft.

vi terrò informati sugli aggiornamenti (ora sto cercando un sistema comodo che analizzi le frasi e possa determinare i comandi e le "opzioni" su di essi)

@zoomx: non deformiamo i nomi delle società o dei prodotti perché poi partono le solite guerre di religione tra i sostenitori di questo e quello ;)

@nid69ita: finché si parla ANCHE di Arduino, non siamo OT. Ma se si chiede aiuto su una cosa che è solo lato PC, indipendentemente da cosa si usi per programmare (non è perché si usa Processing, che è la base dell'IDE di Arduino, che non si va OT ;) ) lo si è.

Ora superlol ha pubblicato lo sketch per Arduino, quindi non si è più OT. Con solo il primo post si era OT.

Ho dato una occhiata a quanto offre attualmente Windows e purtroppo la risposta è:

La funzionalità Riconoscimento vocale è disponibile solo in inglese, francese, spagnolo, tedesco, giapponese, cinese semplificato e cinese tradizionale.

Ci sarebbe anche roba gratuita, come http://www.voxforge.org/ http://julius.sourceforge.jp/en_index.php http://cmusphinx.sourceforge.net/ ma il modello acustico in italiano ancora non c'è (servono ore di campioni audio).

leo72: non deformiamo i nomi delle società o dei prodotti perché poi partono le solite guerre di religione tra i sostenitori di questo e quello ;)

Ok, anche se io non sono un sostenitore fanatico di un sistema rispetto ad un altro ed uso prevalentemente proprio Windows.

appunto il problema rimane il poter avere una compatibilità con la lingua in italiano. non sono in grado in nessun modo di poter creare un modello in italiano anche avendo tempo perchè non ne ho le capacità e conoscenze inoltre credo ci voglia anche un linguista che aiuti nell'adattare il modello anche alle pronunce delle varie zone d'italia. infatti io sono un trentino che studia a forlì 6 giorni a settimana e posso garantire che gli accenti e la "ritmica" diciamo con cui vengono pronunciate le parole varia molto.

comunque ciò che non mi piace sono 2 fatti in particolare: 1. non riesco a forzare l'engine in inglese se la lingua di visualizzazione di windows è in italiano 2. non capisco perchè mentre su kinect il modello italiano esiste nelle sapi no, ed a quanto ho letto le sapi è esattamente ciò che usa kinect...

comunque io sono un sostenitore dell'open source e di linux (in particolare ubuntu, distribuzione molto user-friendly, quasi quanto mint) però per esigenze di hobby/lavoro necessito di windows (alcuni programmi che uso non esistono nemmeno per mac figuriamoci per ubuntu).

salve a tutti.. bene bene, questo argomento è di mio interesse,

ma vi volevo porre un quesito: - quando parlate di speech recognition, a quale tipo vi riferite? riconoscimento continuo o non continuo... - inoltre, state parlando di speech dependent o speech indipendent? - di quante parole sarà formata la vostra libreria comandi?

il motore cambia sensibilmente a seconda della tipologia ma comunque le sapi supportano perfettamente la lingua italiana.

ciao e buona serata.

cyclone: salve a tutti.. bene bene, questo argomento è di mio interesse,

ma vi volevo porre un quesito: - quando parlate di speech recognition, a quale tipo vi riferite? riconoscimento continuo o non continuo... - inoltre, state parlando di speech dependent o speech indipendent? - di quante parole sarà formata la vostra libreria comandi?

il motore cambia sensibilmente a seconda della tipologia ma comunque le sapi supportano perfettamente la lingua italiana.

ciao e buona serata.

supportano la lingua italiana? hai un link in cui mi spieghi come fare? :P

comunque riconoscimento continuo in quanto all'arrivo della prima "parola d'ordine" si dovrà attivare il riconoscimento della frase quindi necessito della parola singola in ogni caso che io andrò poi a concatenare con quelle precedenti fino a che non viene riconosciuta la fine di un comando.

ovvio uno speech dependent avrebbe più accuratezza nel riconoscimento delle parole ma richiederebbe una fase di training (erro?) che vorrei evitare almeno per ora. certo sarebbe figo se alla fine fosse in grado di realizzare anche l'utente che sta dettando i comandi..

la libreria comandi avrà molti vocaboli, inanzitutto tutti i numeri fino direi a 2-300 quindi tutti i comandi veri e propri quali accendi, spegni, apri, chiudi ecc..

per aver un miglior sistema di riconoscimento pensavo di dividere i comandi in più grammatiche, una riferita ai parametri, una ai sub-parametri e una ai comandi del tipo: "apri porta 3" in questo caso avremo "apri" che apparterrà alla grammatica nominata "comandi", poi "porta" che apparterrà ai parametri e "3" che sarà nei subparametri. però potrebbe succedere che si dica anche "accendi 3" in tal caso il motore non riconoscendo un parametro ma direttamente un sub parametro assumerà tale come parametro (così da non avere ripetizioni delle grammatiche).

direi che la libreria arriverà a più o meno 4-500 parole, non oltre.

consigli?