

Microsoft Speech Recognition Engine Ve Kendi Gramerini Oluşturma [Döküman]
-
Microsoft Speech Recognition Engine nedir? Microsoft'un ses tanıma işlemleri için sunduğu bir kütüphane. Türkçe desteği yok ancak bu yazıda kolay anlaşılsın diye Türkçe üzerinden anlatılacaktır ve Microsoft Speech Recognition Engine yerine kısaca SRE denecektir.
Öncelikle SpeechRecognizer diye bir sınıf tanımlıyoruz.
public static double validity = 0.82; public static SpeechRecognitionEngine recognizer; private static bool Continue;Buradaki validity değeri SRE'nin döndürdüğü sonucu dediğimizi ne kadar doğru anladığına göre filtreliyor. Yani siz "Mahmut Ayşeye zıpzıp top al" dediğinizde onun döndürdüğü sonuç bazen "Mahmut Ayşeyi zıplat." gibi nahoş bir anlam çıkabilir. Ancak bunun Confidence değeri düşük olacağından , validity değerini belirleyerek böyle yorumlamaların önüne geçeceğiz.
Ardından recognizerı kurmak için InitializeRecognizer diye bir metod tanımlıyoruz.
public void InitializeRecognizer() { recognizer = new SpeechRecognitionEngine(new System.Globalization.CultureInfo("en-US")); string xmlGrammar = Environment.CurrentDirectory+"grammar.grxml"; string cfgGrammar = Environment.CurrentDirectory+"grammar.cfg"; FileStream fs = new FileStream(cfgGrammar, FileMode.Create); ... }ilk satırda yeni bir recognizer tanımlıyoruz.
Sonraki xmlGrammar ve cfgGrammar değişkenlerine bakalım. Konu başlığında gramer oluşturmadan bahsettim. Yani söylediğiniz şeyi belli bir gramatik sıralama ve düzene uyup uymadığına göre denetleyebiliyorsunuz, ayrıca bu söylediklerinizin doğru anlaşılmasını da pratikte artırıyor. Bunun nedeni o gramerde belirtilenden başka şekilde yorumlamaması. Peki gramer dediğim ne? Bir Xml dosyası, aslında grxml :) Bu dosyayı oluşturduktan sonra yolunu xmlGrammar'e aktarıyoruz. Bu dosyanın kullanılabilmesi için derlenmesi lazım. Derlendiğinde oluşan dosya .cfg uzantılı olacak. Onun yolunu da cfgGrammar'e yazıyoruz.
Ardından Create modunda bir FileStream nesnesi yaratarak grammar.cfg'yi oluşturuyoruz. Şimdi ... koyduğum kısma bakalım:
XmlReaderSettings settings = new XmlReaderSettings(); settings.DtdProcessing = DtdProcessing.Parse; XmlReader reader = XmlReader.Create(xmlGrammar, settings); SrgsGrammarCompiler.Compile(reader, (Stream)fs); fs.Close(); Grammar g = new Grammar(cfgGrammar, "commands"); recognizer.LoadGrammar(g); recognizer.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(recognizer_SpeechRecognized); recognizer.SetInputToDefaultAudioDevice();settings nesnesi ile bir XmlReader için ayarları belirliyoruz. Burada Dtd işlemeyi açtık. Ardından bir XmlReader nesnesi yaratıyoruz ve bizim grammar.xml dosyamızla ayarlarımızı parametre olarak veriyoruz. Altındaki satırda gramer dosyasını derliyoruz ve filestream'e yazıyoruz. Ardından da filestream i kapıyoruz.
Sonra derlenmiş gramer dosyamızı ve onun ana kuralını belirterek yeni bir gramer nesnesi yaratıyoruz ve recognizer'a ekliyoruz. Ardından da Ses tanıma gerçekleştiğinde çalışacak event'i tanımlıyoruz. Son satırda ise recognizer'ın girişini bilgisayarın varsayılan ses girişi olarak belirliyoruz.
Şimdi StartRecognizing diye bir metod tanımlayalım:
public void StartRecognizing() { recognizer.RecognizeAsync(RecognizeMode.Multiple); Continue = true; while (Continue) { Console.WriteLine("..."); } }Burada ilk satırda recognizerı başlatıyoruz sonra continue değerini true yapıyoruz. While döngüsü recognizerın tanıması için şart bu nedenle aklınızda bulunsun StartRecognizing'i kullanırken async olarak veya ayrı bir thread'de çalıştırın.
Ve EndRecognizing:
public void EndRecognizing() { Continue = false; recognizer.RecognizeAsyncStop(); }Şimdi de ses tanınma eventini yazalım:
void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e) { if (e.Result.Confidence >= validity) { Console.WriteLine("Recognized text: " + e.Result.Text); } }Burada e.Result.Confidence eğer daha önce belirlediğimiz validity'den yüksekse işleme sokmasını söylüyoruz. Böylece Mahmut'un Ayşe'ye kötü muamelelerde bulunmasını önlüyoruz. Peki ben yukarda niye 0.82 diye belirledim. Kullandığım projede en güzel sonucu o değer veriyordu çünkü. Biraz deneme yanılmayla sizde kendi değerinizi belirleyebilirsiniz.
Şimdi gelelim zurnanın zırt dediği yere yani gramerimizi oluşturmaya. Önce bir giriş yapalım:
<grammar version="1.0" xml:lang="en-US" root="commands" xmlns="http://www.w3.org/2001/06/grammar">
buradaki root kısmına ana kuralımızı yazıyoruz. Kural derken? Gramer bir kurallar bütünü olduğundan tüm cümleyi kapsayan kuralı ana kural olarak belirliyoruz.
NOT: Birazdan göreceğiniz kodlarda
<rule>: Kuralları belirlemek için,
<item>: Dilin herhangi bir öğesi olarak,
<one-of>: Bu grup ise içindekilerden sadece bir tanesinin seçilmesi
için kullanılıyor olacaktır.
Şimdi kurmak istediğimiz cümleler "Ali topu at." cümlesini temel alsın. Ali olmasın ama sadece Mahmut olsun Abdulsuavi olsun Necmiye olsun ama başkası da olmasın. Sonra bunlar topu atsın başka şeyleri de atsın, hatta "topu ve [başka şeyleri]" de atabilsin. Ve tüm bunları yaparken "atsın" başka bir eylem yapmasın. Bunları gramere dökelim:
Önce atacaklar için bir kural belirleyelim:
<rule id="atacaklar"> <one-of> <item>Ali</item> <item>Mahmut</item> <item>Abdulsuavi</item> <item>Necmiye</item> </one-of> </rule>
Burada one-of ile Ali,Mahmut,Abdulsuavi ve Necmiye'den sadece birinin olabileceğini belirtiyoruz. Şimdi de atılabilecek şeyler için bir kural belirleyelim:
<rule id="atilacaklar"> <one-of> <item>Masayı</item> <item>Topu</item> <item>Sandalyeyi</item> <item>Yumruk</item> </one-of> </rule>
Şimdi ana kuralımızı yani cümle yapmızı belirleyelim:
<rule id="commands"> <ruleref uri="#aticaklar" /> <ruleref uri="#atilacaklar" /> <item repeat="0-1"> <item>ve</item> <ruleref uri="#aticaklar"> </item> <item>at</item> </rule>
Burada daha önce bahsetmediğim şeyler var. Birincisi ruleref. Ruleref etiketi sizin daha önce tanımladığınız başka bir kurala referans vermenizi sağlar böylece bir kuralı ana kuralınızın içine defalarca yazmaktan kurtulursunuz.
Diğer bahsetmediğim şey ise item etiketinin repeat özelliği. Biz bunu ne için kullandık? Bunun için cümle yapımızı inceleyelim. Şu şekilde ana kuralmızı daha semantik ifade edebiliriz:
[ _atacaklar_ ] [ _atilacaklar_ ] [ ve _atilacaklar_](0-1) [at]
1- Cümle atacak kişilerden birinin ismiyle başlayacak.
2- Atılacak eşyalarıdan biriyle devam edecek.
3- Ardından opsiyonel olarak "ve" + yine atilacak eşyalardan biri gelecek. Burada opsiyonelliği sağlayan şey item etiketinin repeat özelliğidir. Biz 0-1 diyerek 0 kereyle 1 kere arasında tekrar edilebilir diyerek opsiyonel olmasını sağladık. Farklı şekillerde de kullanılabilir elbette.
4- Cümleyi "at" ile bitirdik.
Bu sayede kendi gramerimizi oluşturmuş olduk. Gramer oluşturmanın şöyle bir artısı var. Mesela siz bu grameri uyguladıktan sonra "Ali Ayşeye koş." dediniz ama yazdığınız program onu bu gramere göre yorumlamaya çalışacağından muhtemelen "Ali sandalyeyi at." gibi bir şey çıkaracaktır.
Ee, bunun neresi artı? Eğer validity değerini de doğru ayarlarsanız ufak tefek yanlışlıkları düzeltmiş olursunuz.
Döküman burada bitmiştir. SRE ve gramer oluşturma aslında çok daha geniş bir konu. Semantik etiketler vs. oluşturabiliyorsunuz, ben hakim olduğum kadarıyla aktarmaya çalıştım. Daha detaylı bilgi için MSDN kaynaklarına bakabilirsiniz.
Dipnot: Bu döküman Lightsaber tarafından Tahribat.Com için yazılmıştır, kaynak göstermeden yayınlamayınız.
Lightsaber tarafından 18/Ağu/15 14:02 tarihinde düzenlenmiştir -
adamin dibisin
-
Çocuk hergeçen gün kendini 2x geliştiriyor abi
Eline sağlık
-
Teşekkürler.
-
eyvallah hocam
-
görmeyenler için up, anlaşılmayan bi şey varsa sorabilirsiniz
-
Eline sağlık şöyle bi bakınca çok kolay gözüküyor tabi xml dosyalarıyla uğraşması grameri oluşturması var orası ayrı da gayet açıklayıcı bilale anlatır gibi .
bir cw klasiği olarak
Eline sağlık (Lale.gif)
gramer speech recognition microsoft speech recognition engine msre sre