ただいまシステムの中身① Raspberry Piで音声認識
まず前回のおさらい。↓みたいなシステムを作った。
外観写真で説明すると、USBマイクで音声命令を拾って、それをRaspberry Piで認識して、しかるべき制御をサーボモータに送るっていう流れになる。
今回は最初の音声認識部分について書いていくゾ。手順としては、まず音声入力デバイスの優先度を変更して、Juliusっていう音声認識ソフトのセットアップをするだけ。
参考ページ
音声認識を行う上で以下のWebページを参考にさせてもらった。
qiita.com
blog.livedoor.jp
blog.livedoor.jp
USBマイクのセットアップ
事前準備
USBマイクを使えるようにするために、まずはパッケージのアップデートと各種ドライバ・ソフトウェアのインストール、マイクの動作設定とかをやってくよ。
とりあえずパッケージのアップデートから
ライブラリインストール
$ sudo apt-get install alsa-utils sox libsox-fmt-all
ちなみに、ALSA (Advanced Linux Sound Architecture)はLinux用音声ドライバ、soxは音声ファイル形式変換ソフトらしい(上記リンク先のコマンドそのまま打っただけ)
さて、ここまでやったらとりあえずUSBポートにマイクを差して、まずはちゃんとハードウェアが認識されているかのチェック。
ハードウェア認識チェック
$ lsusb Bus 001 Device 004: ID 0d8c:0016 C-Media Electronics, Inc. Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
C-Media Electronics, Inc.がUSBマイクらしいから、これが表示されてれば認識はOK
オーディオモジュールの優先順位変更
おそらく初期設定だと内蔵オーディオモジュールの優先順位のほうが高いはずなので、/proc/asound/modules を見て確認。
モジュール優先度チェック
$ cat /proc/asound/modules 0 snd_bcm2835 1 snd_usb_audio
↑みたいに snd_bcm2835(内蔵オーディオモジュール)が0番だったら、/etc/modprobe.d/alsa-base.conf を変更してUSBマイクの優先順位を変えよう。
(この設定ファイルが生成されていないこともあるから、そのときは新規作成)
マイク感度設定
音声入力するにあたって、マイク感度を適当に調節しとかないといけないから、それの設定。と、その前にサウンドカードの番号をチェック!
サウンドカード番号チェック
$ arecord -l **** List of CAPTURE Hardware Devices **** card 0: Micophone [USB Micophone], device 0: USB Audio [USB Audio] Subdevices: 0/1 Subdevice #0: subdevice #0
card 0 と書いてあればサウンドカード番号は0番だから、感度設定の引数で0を設定
マイク感度設定
$ amixer sset Mic 62 -c 0 Simple mixer control 'Mic',0 Capabilities: cvolume cvolume-joined cswitch cswitch-joined penum Capture channels: Mono Limits: Capture 0 - 62 Mono: Capture 62 [100%] [22.50dB] [on]
マイク感度は0 - 62の63段階で選ぶようになってるけど、まーたぶん最大値で設定して問題ないと思う(ぼくは今のところ問題ない)。
これでUSBマイクは使える状態になったから、こっから音声認識ソフトの設定をやってくよ。
Juliusのインストールと設定
そもそもこのJuliusっていうソフトは何なのかっつーことだけど、公式サイトからまんま引用した以下の文章を読んでくれ。
Julius は,音声認識システムの開発・研究のためのオープンソースの高性能な汎用大語彙連続音声認識エンジンです. 数万語彙の連続音声認識を一般のPCやスマートフォン上でほぼ実時間で実行できる軽量さとコンパクトさを持っています.
言語モデルとして単語N-gram,記述文法,ならびに単語辞書を用いることができます.また音響モデルとしてトライフォンのGMM-HMMおよびDNN-HMMを用いたリアルタイム認識を行うことができます.DNN-HMMの出力計算にnumpyを用いた外部モジュールを利用することも可能です.複数のモデルや複数の文法を並列で用いた同時認識も行うことができます.
Juliusの最大の特徴はその可搬性にあります.単語辞書や言語モデル・音響モデルなどの音声認識の各モジュールを組み替えることで,小語彙の音声対話システムからディクテーションまで様々な幅広い用途に応用できます.
Julius はオープンソースソフトウェアです.プログラムはC言語で書かれており、さまざまなプラットフォームへの移植や改造が容易です.ライセンスはオープンライセンスで,商用利用への制限もありません.
細かい話は専門家じゃないからよく分からんけど、動きは下の画像のような感じ。
音声入力を文字データにして、あらかじめ用意してある辞書データと比較して合致するものを探すみたい。
wgetでJulius本体とディクテーションキットと文法認識キットの3つをインストール。バージョンは適宜変えてくれ。あとディクテーションキットは容量がデカイから時間かかるかも。
Julius本体、ディクテーションキット、文法認識キットのダウンロードとインストール
sudo wget -O julius-4.4.2.tar.gz 'http://sourceforge.jp/frs/redir.php?m=osdn&f=%2Fjulius%2F60273%2Fjulius-4.3.1.tar.gz' sudo wget -O dictation-kit-v4.3.1-linux.tgz 'http://sourceforge.jp/frs/redir.php?m=jaist&f=%2Fjulius%2F60416%2Fdictation-kit-v4.3.1-linux.tgz' sudo wget -O grammar-kit-v4.1.tar.gz 'http://sourceforge.jp/frs/redir.php?m=osdn&f=%2Fjulius%2F51159%2Fgrammar-kit-v4.1.tar.gz' tar zxvf julius-4.4.2.tar.gz cd julius-4.4.2/ ./configure make sudo make install cd .. tar zxvf dictation-kit-v4.3.1-linux.tgz tar zxvf grammar-kit-v4.1.tar.gz
これでとりあえず使えるようにはなってるから、テストしてみよう。
話しかけてみよう!
あらかじめ用意されてるグラマーキット testmic.jconf を使ってきちんと認識するかどうかのテスト。julius -C ./grammar-kit-v4.1/testmic.jconf -charconv EUC-JP UTF-8 を実行すると音声認識スタンバイ状態になるから、話しかけると「あんたが今言ったのこれやな!」って返してくれるよ。
ちなみに、このテスト設定だと「みかん・りんご・ぶどう」の3つの果物について反応するから、適当に「みかん!」とか「りんご!」とか言ってみてね。
Julius動作テスト
julius -C ./grammar-kit-v4.1/testmic.jconf -charconv EUC-JP UTF-8 Notice for feature extraction (01), ************************************************************* * Cepstral mean normalization for real-time decoding: * * NOTICE: The first input may not be recognized, since * * no initial mean is available on startup. * ************************************************************* Stat: adin_oss: device name = /dev/dsp (application default) Stat: adin_oss: sampling rate = 16000Hz Stat: adin_oss: going to set latency to 50 msec Stat: adin_oss: audio I/O Latency = 32 msec (fragment size = 512 samples) STAT: AD-in thread created
この状態の時に話しかければOK。ちゃんと結果が返ってきたら設定とかは問題なし。
辞書データ作成
ここまで来たらあとは自分の用途に合わせて辞書データを作成してあげればOK。認識結果はsocketを介してxmlで渡せるから、それを使って後段のサーボモータ制御をやっていく流れ。
辞書ファイルは
(単語)(タブ区切り)(読み)
の形で記述して、拡張子は.yomiとして保存すること。今回の目的は「ただいま」に反応して動作してくれればいいから基本的には「ただいま」だけ辞書登録しとけば良いんだけど、どうせならいろいろやりたいな、と思って以下のような辞書データを作った。
ただいま ただいま おやすみ おやすみ 部屋つけて へやつけて 部屋消して へやけして 廊下つけて ろうかつけて 廊下消して ろうかけして おはよう おはよう いってきます いってきます パキン ぱきん
機能としては、
ただいま → 部屋も廊下もつく
おやすみ → 部屋も廊下も消える
部屋つけて → 部屋の電気がつく
部屋消して → 部屋の電気が消える
廊下つけて → 廊下の電気がつく
廊下消して → 廊下の電気が消える
おはよう → 部屋の電気がつく
いってきます → 部屋も廊下も消える
パキン → 部屋も廊下もつく
ってなってる。パキンってなんだよパキンってと思うかもしれないけど、これは指パッチンで部屋の電気ついたらクソおもしれぇなと思ってあとから追加した辞書データ。ちなみに動きはこんな感じ。
ただいまシステムを指パッチンで反応するようにしたから夢の指パッチン操作が実現した pic.twitter.com/OUlK70uadA
— Dr. ひらばやしひであき (@hira_hide) 2017年4月17日
超おもしろかった。その代わり判定しきい値をかなり高くしてるからめったに動作しない。隠しコマンド的立ち位置。
それはさておき、辞書データを作ったらJulius用の辞書形式ファイルに変換する。
あ、ルートディレクトリは基本的に home を考えて書いてるから、適宜読み替えてください。
辞書データ変換
cd julius-4.4.2/gramtools/yomi2voca iconv -f utf8 -t eucjp ~/word.yomi | yomi2voca.pl > ~/dictation-kit-v4.3.1-linux/word.dic
そしたら最後に設定データを作成すれば音声認識基盤の完成!
$ vi ./dictation-kit-v4.3.1-linux/word.jconf -w word.dic #単語辞書ファイル -v model/lang_m/bccwj.60k.htkdic #N-gram、または文法用の単語辞書ファイルを指定 -h model/phone_m/jnas-tri-3k16-gid.binhmm #使用するHMM定義ファイル -hlist model/phone_m/logicalTri #HMMlistファイルを指定する -n 5 #n個の文仮説数が見つかるまで検索を行う -output 1 #見つかったN-best候補のうち、結果として出力する個数 -input mic #マイク使用 -input oss #オープンサウンドシステム使用 -rejectshort 600 #検出された入力が閾値以下なら棄却 -charconv euc-jp utf8 #入出力エンコード指定(内部euc-jp, 出力utf-8) -lv 1000 #入力の振幅レベルの閾値(0~32767)
これで julius -C ./dictation-kit-v4.3.1-linux/word.jconf を実行すれば上で作った辞書データを元に音声認識してくれる。
認識結果の受け渡しとそれを利用したサーボ制御については次回。