Julius音声認識ソフト番外編!音声でロボット操作準備で障害続出

2017年12月6日

60爺は、前回の記事(Julius 音声認識ソフト part4)で、音声による操作のための準備を行いました。そして、まア何とかなるだろうとの感触を経て、6脚ロボットの音声操作に取り掛かりました。

6脚ロボットは、稼動設定の終わっている状態であります。そのため、このRaspberrypi3に、音声操作のためのJuliusをインストールし、ロボット操作用の辞書を作成すれば良いわけです。

そして、ロボットを操作するためのプログラムを作成すれば、音声操作の6脚ロボットが完成します。

まずは、Juliusをインストールしましょう。

今回は、part4まで使用したバージョンではなく、最新版(4.4.2)のJuliusに挑戦しました。しかし、これが悲劇の幕開けだったとは、人間たる60爺には思い当たることも無かったのです。

スポンサーリンク

イメージカード死す

Julius 4.4.2 インストールは、下記の手順でインストールできます。

pi@raspbian:~ $ wget https://ja.osdn.net/projects/julius/downloads/66547/julius-4.4.2.tar.gz
pi@raspbian:~ $ tar xvzf julius-4.4.2.tar.gz
pi@raspbian:~ $ cd julius-4.4.2/
pi@raspbian:~/julius-4.4.2 $ ./configure
pi@raspbian:~/julius-4.4.2 $ make
pi@raspbian:~/julius-4.4.2 $ sudo make install
pi@raspbian:~/julius-4.4.2 $ julius -version
JuliusLib rev.4.4.2 (fast)

そして、ディクテーションキットと文法認識キットのダウンロードも問題なく実施できました。

pi@raspbian:~ $ wget https://osdn.net/projects/julius/downloads/66544/dictation-kit-v4.4.zip
pi@raspbian:~ $ wget https://osdn.net/projects/julius/downloads/51159/grammar-kit-v4.1.tar.gz
pi@raspbian:~ $ mkdir /home/pi/julius-kits
pi@raspbian:~ $ cd /home/pi/julius-kits
pi@raspbian:~ $ unzip /home/pi/dictation-kit-v4.4.zip
pi@raspbian:~ $ tar xvzf /home/pi/grammar-kit-v4.1.tar.gz

次に、USBマイクの設定を行いました。

モジュールの優先順位を変更します。モジュールの優先順位を確認すると、下記のように USBマイクの優先度が低いので、順位を変えます。

pi@raspbian:~ $ sudo vi /proc/asound/modules
0 snd_bcm2835
1 snd_usb_audio?
pi@raspbian:~ $ sudo vi /etc/modprobe.d/alsa-base.conf
options snd slots=snd_usb_audio,snd_bcm2835
options snd_usb_audio index=0
options snd_bcm2835 index=1

ここで、rebootしたわけなんですが、Raspberrypiが立ち上がらなくなっちゃいました。
電源が入っても、うんともすんとも言わないのです。

そこで、microSDのイメージをPCで書き出して、その内容をmicroSDに上書きして起動してみましたがダメです。立ち上がろうとはしますが、そこまで・・。OSが起動できないようです。そこで、新しいmicroSDに先ほどのイメージを書き込んで立ち上げてみましたが、全く同じ状態です。

別の RaspberryPi で動かしてみましたが、こちらも同じ状態です。

どうやら、イメージが死んでしまったようです(涙)。ラズパイのOSを容れ直して再実行しかないようです。


環境再設定

翌日、気を取り直して、RaspberryPiのOSを入れ直しました。update、upgrade(ものすごい時間:半日以上がかかりました)を行って、やっと再開です。

マイクの入力

今回は、マイクの入力から始めます。

pi@raspberrypi:~ $ lsusb
Bus 001 Device 010: ID 056e:700d Elecom Co., Ltd
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

最初から、変なエラー! usb_audioがない?なんで?

pi@raspberrypi:~ $ cat /proc/asound/modules
1 snd_bcm2835

USBマイクを別USB口に変えました。すると、復活!?です。

pi@raspberrypi:~ $ cat /proc/asound/modules
1 snd_bcm2835
2 snd_usb_audio

USBサウンドカードの位置を確認してみます。

pi@raspberrypi:~ $ arecord -l
**** ハードウェアデバイス CAPTURE のリスト ****
カード 2: series [UCAM-DLN130T series], デバイス 0: USB Audio [USB Audio]
サブデバイス: 1/1
サブデバイス #0: subdevice #0

USBマイクのボリューム調整を行います。

pi@raspberrypi:~ $ amixer sset Mic 50 -c 1
amixer: Unable to find simple control 'Mic',0

エラーですね。マイクのカード番号は2でした。うまくいったようです。

pi@raspberrypi:~ $ amixer sset Mic 50 -c 2
Simple mixer control 'Mic',0
Capabilities: cvolume cswitch
Capture channels: Front Left - Front Right
Limits: Capture 0 - 44
Front Left: Capture 44 [100%] [16.00dB] [on]
Front Right: Capture 44 [100%] [16.00dB] [on]

juliusインストール

さて、それでは、juliusをインストールしましょう(それぞれのコマンドは、本ページの始めに出てま--す)。そして、ディクテーションキットを続けてインストールします。

全く問題なくインストール出来ました。順調です。

julius起動

続いて、ディクテーションキットのディレクトリに移動してjuliusを起動します。

pi@raspberrypi:~/julius-kits $ cd /home/pi/julius-kits/dictation-kit-v4.4
pi@raspberrypi:~/julius-kits/dictation-kit-v4.4 $ julius -C main.jconf -C am-gmm.jconf -demo
----------------------- System Information end -----------------------
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)
Error: adin_oss: failed to open /dev/dsp
failed to begin input stream

エラー発生!やっぱり、1回で成功しないですね。このエラー発生時は、次のコマンドを打ってrebootすればいいですね。。

pi@raspberrypi:~ $ sudo sh -c "echo snd-pcm-oss >> /etc/modules"

ここで、サウンドを見てみると、あれ、usbサウンドが無い。またです。

pi@raspberrypi:~ $ cat /proc/asound/modules
1 snd_bcm2835

仕方ないので、USBを口を差替えて見てみると登場しました。何なんだろ、一体。

pi@raspberrypi:~ $ cat /proc/asound/modules
0 snd_usb_audio
1 snd_bcm2835

それでは、もう一度実行してみます。

pi@raspberrypi:~ $ cd /home/pi/julius-kits/dictation-kit-v4.4
pi@raspberrypi:~/julius-kits/dictation-kit-v4.4 $ julius -C main.jconf -C am-gmm.jconf
・
・
Warning: strip: sample 0-1023 is invalid, stripped
Warning: strip: sample 0-577 has zero value, stripped

stripのワーニングが発生、これって、part1 で julius 入れたとき、発生した奴ですね。
オプション -nostrip を追加して再実行してみました。

<<< please speak >>>WARNING: adin_thread_process: too long input (> 320000 samples), segmented now
Warning: input buffer overflow: some input may be dropped, so disgard the input
STAT: skip CMN parameter update since last input was invalid

part1に戻って、よーく見てみると、-lv が必要でした。

pi@raspberrypi:~/julius-kits/dictation-kit-v4.4 $ julius -input mic -lv 10000 -C
main.jconf -C am-gmm.jconf -nostrip
### read waveform input
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
pass1_best: こんにちは 。
pass1_best_wordseq: <s> こんにちは+感動詞 </s>
pass1_best_phonemeseq: silB | k o N n i ch i w a | silE
pass1_best_score: -3358.766602
### Recognition: 2nd pass (RL heuristic best-first)
STAT: 00 _default: 23851 generated, 2254 pushed, 299 nodes popped in 140
sentence1: ほんと だ よ 。
wseq1: <s> ほんと+名詞 だ+助動詞 よ+助詞 </s>
phseq1: silB | h o N t o | d a | y o | silE
cmscore1: 0.669 0.074 0.038 0.004 1.000
score1: -3379.684326

何とか動きました。前のバージョンより、はるかに認識率がよろしいですね。

辞書の作成

「julius-kits」ディレクトリに移動し、辞書ファイル「houkou.yomi」を作成して、音声コマンド用の方向を示すワードを登録します。記事にありますように、「まえへ」と「マエエ」の間はタブにしています。

pi@raspberrypi:~ $ cd /home/pi/julius-kits
pi@raspberrypi:~/julius-kits $ sudo vi houkou.yomi
pi@raspberrypi:~/julius-kits $ cat houkou.yomi
まえへ マエエ
ばっく バック
うしろへ ウシロエ
みぎへ ミギエ
ひだりへ ヒダリエ
すとっぷ ストップ
すたんばい スタンバイ
ばるす バルス

ラピュタ滅びの呪文を、性懲りも無く、入れています。

音声コマンド用の単語(houkou.yomi)を登録したので、juliusが認識可能な単語辞書ファイル(houkou.dic)に変換します。

pi@raspberrypi:~/julius-kits $ iconv -f utf8 -t eucjp houkou.yomi | /home/pi/julius-kits/grammar-kit-v4.1/bin/yomi2voca.pl > houkou.dic
ius-kits/grammar-kit-v4.1/bin/yomi2voca.pl > houkou.dic
Error: (they were also printed to stdout)
line 1: まえへ マエエ
line 2: ばaく バaク
line 3: うしろへ ウシロエ
line 4: みぎへ ミギエ
line 5: ひ$りへ ヒ%?
レine 6: す?aぷ ス?aプ
line 7: すたんばい スタンバイ
line 8: ば? ぅ丱?pi@raspberrypi:~/julius-kits $ ls
dictation-kit-v4.4 grammar-kit-v4.1 houkou.dic houkou.yomi

うまく行ったようです。
次に、変換した辞書を使うための設定ファイルを作成します。

pi@raspberrypi:~/julius-kits $ sudo vi houkou.jconf
pi@raspberrypi:~/julius-kits $ cat houkou.jconf
-w base_dict.dic
-input mic
-charconv euc-jp utf8
-h model/phone_m/jnas-tri-3k16-gid.binhmm
-hlist model/phone_m/logicalTri
-output 1

さて、各単語を認識するか。

ところが、この設定では、エラーが出てうまくいきません。①base_dict.dicが見つからないと言われます。また、②ERROR: m_chkparam: cannot access model/phone_m/jnas-tri-3k16-gid.binhmmのエラーが発生します。

①は、上記houkou.confでの単純なミスです。base_dict.dicを今回作成したhoukou.dicにせねばなりません。
②も、指定のミスです。model/phone_mには、jnas-tri-3k16-gid.binhmmは存在しませんでした。調べたところ、60爺の環境では、/home/pi/julius-kits/dictation-kit-v4.4/model/phone_m/にありましたので、上記のフォルダにコピーしました。

修正後の houkou.jconf はこうなります。もうひとつ、houkou.jconfは、~/julius-kits/grammar-kit-v4.1に格納します。そうでないと、-hに指定しているフォルダと、うまくつながらないためです。

pi@raspberrypi:~/julius-kits $ cat houkou.jconf
-w /home/pi/julius-kits/houkou.dic
-input mic
-charconv euc-jp utf8
-h model/phone_m/jnas-tri-3k16-gid.binhmm
-hlist model/phone_m/logicalTri
-output 1

これで、実行してみます。

pi@raspberrypi:~/julius-kits/grammar-kit-v4.1 $ julius -C houkou.jconf -lv 10000 -input mic -nostrip
STAT: reading [/home/pi/julius-kits/houkou.dic]...
Stat: init_wordlist: reading in word list
Error: voca_load_wordlist: line 1: logical phone "マエエ" not found
Error: voca_load_wordlist: the line content was: まええ マエエ
Error: voca_load_wordlist: line 2: logical phone "バaク" not found
Error: voca_load_wordlist: the line content was: ばaく バaク
Error: voca_load_wordlist: line 3: logical phone "ウシロエ" not found
Error: voca_load_wordlist: the line content was: うしろえ ウシロエ
Error: voca_load_wordlist: line 4: logical phone "ミギエ" not found
Error: voca_load_wordlist: the line content was: みぎえ ミギエ
Error: voca_load_wordlist: line 5: logical phone "ヒ%?ア not found
Error: voca_load_wordlist: the line content was: ひ$? ぅ劵%?
Error: voca_load_wordlist: line 6: logical phone "ス?aプ" not found
Error: voca_load_wordlist: the line content was: す?aぷ ス?aプ
Error: voca_load_wordlist: line 7: logical phone "スタンバイ" not found
Error: voca_load_wordlist: the line content was: すたんばい スタンバイ
Error: voca_load_wordlist: line 8: logical phone "バ?ア not found
Error: voca_load_wordlist: the line content was: ば? ぅ丱?
Error: voca_load_htkdict: begin missing phones
Error: voca_load_htkdict:
Error: voca_load_htkdict: end missing phones
Error: init_wordlist: error in reading /home/pi/julius-kits/houkou.dic: 8 words failed out of 0 words
ERROR: failed to read word list "/home/pi/julius-kits/houkou.dic"
ERROR: m_fusion: some error occured in reading grammars
ERROR: Error in loading model

駄目ですね。エラー発生です。なんか、単語辞書がおかしいような・・・。いろいろとググってみたりしたんですけど、もう一度、記事と60爺の単語表を比べたら、何とバカな事をやっていたのを発見しましたーー。

辞書の中身ですが、記事は、カタカナ→ひらがなの順なのに、60爺は、ひらがな→カタカナの順にしていました。これを直してやってみました。すると、辞書作成時に、何の表示もでないんですね。あれは、エラーだったのか!

pi@raspberrypi:~/julius-kits $ iconv -f utf8 -t eucjp houkou.yomi | /home/pi/julius-kits/grammar-kit-v4.1/bin/yomi2voca.pl > houkou.dic
pi@raspberrypi:~/julius-kits $

で、これで実行してみると、ちゃんと動きましたーーー。

pi@raspberrypi:~/julius-kits/grammar-kit-v4.1 $ julius -C houkou.jconf -lv 10000 -input mic -nostrip
STAT: include config: houkou.jconf
STAT: jconf successfully finalized
・
・
・
----------------------- System Information end -----------------------
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. *
*************************************************************
------
### read waveform input
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
・
pass1_best: マエエ
pass1_best_wordseq: マエエ
pass1_best_phonemeseq: silB m a e e silE
pass1_best_score: -2288.345947
sentence1: マエエ
wseq1: マエエ
phseq1: silB m a e e silE
cmscore1: 0.945
score1: -2288.345947
pass1_best: ウシロエ
pass1_best_wordseq: ウシロエ
pass1_best_phonemeseq: silB u sh i r o e silE
pass1_best_score: -2672.608887
sentence1: ウシロエ
wseq1: ウシロエ
phseq1: silB u sh i r o e silE
cmscore1: 0.987
score1: -2672.608887
pass1_best: ヒダリエ
pass1_best_wordseq: ヒダリエ
pass1_best_phonemeseq: silB h i d a r i e silE
pass1_best_score: -2388.519287
sentence1: ヒダリエ
wseq1: ヒダリエ
phseq1: silB h i d a r i e silE
cmscore1: 0.954
score1: -2388.519287
pass1_best: ミギエ
pass1_best_wordseq: ミギエ
pass1_best_phonemeseq: silB m i g i e silE
pass1_best_score: -2522.857910
sentence1: ミギエ
wseq1: ミギエ
phseq1: silB m i g i e silE
cmscore1: 0.723
score1: -2522.857910
pass1_best: ストップ
pass1_best_wordseq: ストップ
pass1_best_phonemeseq: silB s u t o q p u silE
pass1_best_score: -2687.319336
sentence1: ストップ
wseq1: ストップ
phseq1: silB s u t o q p u silE
cmscore1: 0.992
score1: -2687.319336
pass1_best: スタンバイ
pass1_best_wordseq: スタンバイ
pass1_best_phonemeseq: silB s u t a N b a i silE
pass1_best_score: -2862.957764
sentence1: スタンバイ
wseq1: スタンバイ
phseq1: silB s u t a N b a i silE
cmscore1: 0.619
score1: -2862.957764
pass1_best: バルス
pass1_best_wordseq: バルス
pass1_best_phonemeseq: silB b a r u s u silE
pass1_best_score: -2101.563477
sentence1: バルス
wseq1: バルス
phseq1: silB b a r u s u silE
cmscore1: 0.907
score1: -2101.563477

つまらんミスで、余計な時間を食ってしまいました。しかし、これで前に進めます。

モジュールモードでの確認

今度は、モジュールモードで動かしてみます。

pi@raspberrypi:~/julius-kits/grammar-kit-v4.1 $ julius -C houkou.jconf -lv 10000 -input mic -nostrip -module
・
・
STAT: [5] prepare for real-time decoding
STAT: All init successfully done
Stat: server-client: socket ready as server
///////////////////////////////
/// Module mode ready
/// waiting client at 10500
///////////////////////////////

もうひとつ、teratermの画面を立ち上げて、次のプログラムを流します。
さて、きちんと音声認識してくれるでしょうか?

pi@raspberrypi:~ $ python print.py

そして、前え、後ろえ

---- replace ----
***** m a e e *****
0.994
---- replace ----
***** u s i r o e *****
0.998
---- replace ----
***** b a k k u *****
1.0
---- replace ----
***** m i g i e *****
0.976
---- replace ----
***** h i d a r i e *****
0.466
---- replace ----
***** s u t o p p u *****
0.531
---- replace ----
***** s u t a n b a i *****
0.946
---- replace ----
バルス
0.947
##### THE END #####

なかなかの認識率です。
バックのスコアなぞ、100%です。音声の認識は多分大丈夫ですね。

プログラムを掲載しておきます。

#!/usr/bin/python
# -*- coding: utf-8 -*-
import socket
import xml.etree.ElementTree as ET
import subprocess
import sys
import re
def main():
host = 'localhost'
port = 10500
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))
try:
data = ''
while 1:
if '\n.' in data:
# print data
r_data = data.replace('\n', '@@@')
r = re.compile("(.*)(/RECOGOUT)(.*)")
m = r.match(r_data)
if m != None:
a = m.group(1)
data = a.replace('@@@', '\n') + '/RECOGOUT>\n.'
print '---- replace ----'
# print data
else:
print '---- None ----'
# print data
root = ET.fromstring('\n' + data[data.find(''):].replace('\n.', ''))
for whypo in root.findall('./SHYPO/WHYPO'):
command = whypo.get('WORD')
score = float(whypo.get('CM'))
# print command
if command == u'マエエ':
print '***** m a e e *****'
print score
elif command == u'ウシロエ':
print '***** u s i r o e *****'
print score
elif command == u'バック':
print '***** b a k k u *****'
print score
elif command == u'ミギエ':
print '***** m i g i e *****'
print score
elif command == u'ヒダリエ':
print '***** h i d a r i e *****'
print score
elif command == u'ストップ':
print '***** s u t o p p u *****'
print score
elif command == u'スタンバイ':
print '***** s u t a n b a i *****'
print score
# PG終了 ラピュタ滅びの呪文「バルス」
elif command == u'バルス':
print command
print score
print '##### THE END #####'
sys.exit()
else:
print '----- e t c ! -----'
print command
print score
data = ''
else:
data = data + client.recv(1024)
except KeyboardInterrupt:
client.close()
if __name__ == "__main__":
main()
スポンサーリンク

6脚ロボット駆動

6脚ロボット駆動用の全てのプログラムが消えてしまったので、再びダウンロードを行います。プログラム自体は、サポートページからダウンロードすればいいので、さほど苦にはなりません。

はたして、すんなり動くかどうかやってみます。その前に配線を確認します。これも、大した配線ではないので、書籍を見ながら設定します。さァ、実行します。

あれれ、エラーですね。

・
・
・
File "bb2-08-02-6legs-pca9685.py", line 36, in setPCA9685Duty3
bus.write_i2c_block_data(address_pca9685, channelpos, data)
IOError: [Errno 121] Remote I/O error

こいつは、いつもの奴--電源が足りないようです。

ですので、モーターを電源を、単3電池3本⇒4本の電池パックで代替させました。また、スマホの充電用バッテリは使わないのでどかしました。

これで実行したところ、無事に稼動しました。

さて、次は「6脚ロボット音声操作プログラムの作成」なんですが、こいつが最後の難関です。

しかし、ここ迄来るのに、思いのほかページを食ってしまいましたので、ここで完了とし、本題は次のpartで実施させてください。

最後に

Julius音声認識で、音声でロボット操作を実施する予定で準備に張りました。

ところが、環境設定時に、OSが死ぬというアクシデントがあり、大変な思いをさせられました。

めげずに時間をかけて環境設定を実施しました。

しかし、最後の難関である「6脚ロボット音声操作プログラムの作成」をやる時間が尽きてしまいました。

■思えば、「Julius音声認識」の記事も増えてきました

スポンサーリンク
この記事を書いた人

60爺

60路を越え、RaspberryPi と出会い、その関係でブログ開設(2017/2~)となりました。始めてみると、コツコツやるのが性に合ってしまい、漢字の記事から家の補修・将棋・windows10関係・別名・言い方などジャンルを拡大して今に至ってます。まだまだ、元気なので新たな話題を見つけて皆様に提供できればと思っています。「プロフィールはこちら

Julius音声認識

Posted by 60爺