ラズパイで音声認識
ラズパイを運よくGETできたのですが、G検定の勉強などなどでずっと放置しておりました。G検定も、なんとか無事に合格できましたので、こちらも少しづつ触っていこうかと思っております。
が、特に何かやるネタがなく…と思っていたところに、RPACommunityでクリスマスイベントをやるとのこと。それに向けてクリスマス感を出す盛り上げツールとして、なんかやってやろうと思いまして、以下のようなモノを考えました。
クリスマスと言えば、🎅とトナカイ。トナカイと言えば、チョッ〇ーということで、チョッ〇ー帽子ですw
さらにそのチョッ〇ー帽子をイルミネーションで光らせれば、クリスマス感が出るのでは?
でも、ただ光らせただけだと面白くないので、特定のキーワードを言うと光る仕組みにしよう!!と思いまして、下記のような仕組みを考えました。
ラズパイで音声認識をさせて、トナカイ帽子に仕込んだLEDを点灯させる
ラズパイにMIC INが無いので、USBマイクを用いて音声入力。GPIOにつなげたイルミネーションを光らせよう、というものです
準備したモノ
ラズパイ本体(RasberryPi Zero 2 W)
USBマイク
ダイソーで買ってきた電池式のLEDイルミネーション(300円)
LEDイルミネーションは電池ボックス付近で切断。被覆を向いて、リード線と接続。
※切断時、プラスとマイナスが分かるようにしておかなと、ちょっと混乱すること(最悪LEDが壊れてしまうので、要注意ですね)。
リード線は、一旦GPIO00とGNDへ接続。これでLEDが光るかどうか確認します。光らない場合は、プラス/マイナスが逆の可能性がありますので、確認してみましょう。
準備としてはこのぐらいかな?
後は、音声認識をさせて、Pythonでその結果を拾って、GPIO経由でLチカさせるだけですね💡
さて、イメージはできたものの、何をどうしていいのかさっぱりわからない。そもそも、ラズパイで音声認識とかどーやるん?って状態…
わからないときはグーグル先生に聞いてみましょう、ということで検索を掛けると「Julius」という音声認識ツールがあるらしい。
ということで、まずはそれをラズパイにインストールするところからスタートです。
Juliusのインストール
音声認識ツール「Julius」のGitHub
Juliusのマニュアル?
Julius以外の音声認識ツールもご紹介されています
ラズパイにJuliusをインストールしてみる
※上記記事内でテキストファイルの編集を行うところがあります。vimを起動するようになっていますが、インストールされてない端末では、もちろん起動せずにエラーになります。
その場合は、vimの代わりにnanoを指定することで動きます。
ちなみに、vimのインストールは下記参照
こちらの記事も、インストールから活用方法まで詳しく書かれていますので参考にしてみてください。
インストールまでであれば、こちらの記事も参考になります。
辞書登録をしてみる
インストールしただけでは、認識精度が非常に悪いです。どうもデフォルトで登録されてる辞書が、かなりアホのようですね^^;
認識精度を上げるには、辞書登録がおすすめです。が、辞書を作るのが案外めんどくさい。そして、慣れないとなかなかうまくいかない…。
で、いろんなサイトを見ていたら、grammarファイルは「:」で区切るようです。「 」(スペース)ではないので、要注意ですね。
自分は2~3日、悩みました(笑)
実行してみる
julius -C ~/julius/julius-kit/dictation-kit-v4.4/am-gmm.jconf -nostrip -gram ~/julius/dict/hello -input mic
これで設定した辞書を参照してJuliusを動かすことができます。上のコマンドでは、辞書を"hello"として登録した場合の例ですので、適切に置き換えてくださいね。
-C [JCONFファイル]
煩雑なオプションを定義したJCONFファイルを指定するオプション
am-gmm.jconfは、デフォで入っているjconfファイル。
-nostrip
零サンプル除去の無効化(知らんけど)
-gram [辞書ファイル]
登録した辞書を参照するためのオプション。
辞書ファイルには、設定した辞書プロファイル名(上の例だとhello)を
設定する。
-input mic
音声をマイクから拾う
-module
バックグラウンドで動き、SOCKET通信で反応するようになります。
音声認識された結果をラズパイで拾う
juliusを実行する際に、-moduleオプションを付けて実行すると、サーバモードで実行されます。内部的にはXMLを返すようで、Socket通信で受信できるみたいです。この機能を使って、Juliusで認識した言葉に反応させることが可能となります。
が、単語辞書を作ると、登録のある言葉に無理やり寄せてきます。例えば、「おはよう」と「こんばんは」が登録されていたとすると、「ごちそうさま」と言っても、「おはよう」か「こんばんは」と反応します。
これでは少々使い勝手悪いですよね。。。
ので、そちらによらせないように、欲しい言葉に似た言葉も正しく登録してしまいます。
「おはよう」と「こんばんは」と「ごちそうさま」を登録しておけば、正しく反応するようになるので、「ごちそうさま」と言えば「ごちそうさま」と反応するようになります。
※欲しいのが「ごちそうさま」だけなのに、めんどいですね。。
Pythonコード
import time
import socket
import string
import json
import requests
import RPi.GPIO as GPIO
IONUM=22
GPIO.setmode(GPIO.BCM)
GPIO.setup(IONUM,GPIO.OUT)
host = "127.0.0.1"
port = 10500
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect((host,port))
data=""
while True:
data=client.recv(4096).decode("utf-8")
strTemp=""
for line in data.split("\n"):
index=line.find('WORD="')
if index!=-1:
line=line[index+6:line.find('"',index+6)]
if line!="[s]":
strTemp=strTemp+line
if strTemp!="":
print("結果:"+strTemp)
if strTemp=="メリークリスマス[/s]":
for num in range(10):
GPIO.output(IONUM,True)
time.sleep(0.1)
GPIO.output(IONUM,False)
time.sleep(0.1)
elif strTemp=="ありがとうございます[/s]":
for num in range(7):
GPIO.output(IONUM,True)
time.sleep(0.1)
GPIO.output(IONUM,False)
time.sleep(0.1)
else:
GPIO.output(IONUM,True)
time.sleep(0.2)
GPIO.output(IONUM,False)
Pythonのコードとしては、こんなモンですね。
なんかしゃべると、else:の処理で0.2秒点灯させます。
”メリークリスマス”としゃべると、0.1秒の点滅を10回繰返し、"ありがとうございます"としゃべると、0.1秒の点滅を7回繰り返すようにしてあります。
完成?
メリークリスマス!としゃべったときは、こんな動きになります。
ホントはもっと…
Juliusの機能を全然引き出せてないのは、重々承知しております。
ホントは、文節で認識させ、その中に含まれる単語で反応させたかったのですが、それがどーにもできず、結果単語だけに反応するような感じになってしまいました。
また、その辺りがわかったら、記事を書こうと思います。