Pythonで単語リストからJuliusの単語辞書を作成する方法

前回、[**Windows環境のJulius4.6で特定の単語を認識させる方法**](https://qiita.com/phiniki/items/babc93c10bdaa16d0f01)でJuliusの単語辞書を作成した。
大量の単語を処理する場合、すごく手間だと感じたため、Pythonで単語リストから単語辞書を作成するプログラムを書いてみました。

# 単語一覧を作成
まず、単語一覧ファイル **word_list.txt** を作成する。
```word_list.txt
おはよう
こんにちは
こんばんは
宜しく
```

# 読みファイルの作成
```python:make_yomi
from pykakasi import kakasi

dict_name = 'mydict'

kakasi = kakasi()

def make_yomi():
    f = open('word_list.txt', 'r')
    data = f.read()
    f.close()

    yomi_list = []
    for i in data.split('\n'):
        kakasi.setMode('J', 'H') #漢字からひらがなに変換
        kakasi.setMode("K", "H") #カタカナからひらがなに変換
        conv = kakasi.getConverter()
        yomi_list.append(i + '\t' + conv.do(i)) #[単語] + [Tab] + [ひらがな]

    yomi = '\n'.join(yomi_list)

    f = open(dict_name + '.yomi', 'w')
    f.write(yomi)
    f.close()

list2yomi()
```
今回は、漢字からひらがなに変換するために **pykakasi** を使用した。

https://qiita.com/kazu8/items/ae864a2c8820dcb6def8

実行して **mydict.yomi** が作成され、以下のようになっていればOK。
```mydict.yomi
おはよう	おはよう
こんにちは	こんにちは
こんばんは	こんばんは
宜しく	よろしく
```

# 音素ファイルの作成
```python:make_phone
import subprocess

dict_name = 'mydict'

def make_phone():
    yomi2voca = 'C:/Julius/julius-4.6-win32bin/bin/yomi2voca.pl'
    cmd = "perl {0} ./{1} > ./{2}".format(yomi2voca, dict_name + '.yomi', dict_name + '.phone')
    proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

yomi2phone()
```

実行して **mydict.phone** が作成され、以下のようになっていればOK。
```mydict.phone
おはよう	o h a y o u
こんにちは	k o N n i ch i h a
こんばんは	k o N b a N h a
宜しく	y o r o sh i k u
```

# 構文ファイルの作成
```python:make_grammar
dict_name = 'mydict'

def make_grammar():
    f = open(dict_name + '.phone', 'r')
    data = f.read()
    f.close()

    grammar = ['S : NS_B WORD NS_E']
    for i in data.split('\n')[:-1]:
        word = i.split('\t')[1].upper().replace(' ', '') #すべて大文字に変換、スペース削除
        grammar.append('WORD : ' + word)

    grammar = '\n'.join(grammar)

    f = open(dict_name + '.grammar', 'w')
    f.write(grammar)
    f.close()

make_grammar()
```

実行して **mydict.grammar** が作成され、以下のようになっていればOK。
```mydict.grammar
S : NS_B WORD NS_E
WORD : OHAYOU
WORD : KONNICHIHA
WORD : KONBANHA
WORD : YOROSHIKU
```

# 語彙ファイルの作成
```python:make_voca
dict_name = 'mydict'

def make_voca():
    f = open(dict_name + '.phone', 'r')
    data = f.read()
    f.close()

    voca = []
    for i in data.split('\n')[:-1]:
        word = i.split('\t')[1].upper().replace(' ', '') #すべて大文字に変換、スペース削除
        voca.append('% ' + word + '\n' + i)
    voca.append('% NS_B')
    voca.append('[s] silB')
    voca.append('% NS_E')
    voca.append('[/s]    silE')

    voca = '\n'.join(voca)

    f = open(dict_name + '.voca', 'w')
    f.write(voca)
    f.close()

make_voca()
```

実行して **mydict.voca** が作成され、以下のようになっていればOK。
```mydict.voca
% OHAYOU
おはよう	o h a y o u
% KONNICHIHA
こんにちは	k o N n i ch i h a
% KONBANHA
こんばんは	k o N b a N h a
% YOROSHIKU
宜しく	y o r o sh i k u
% NS_B
[s] silB
% NS_E
[/s]    silE
```

# 辞書ファイルの作成
```python:make_dict
dict_name = 'mydict'

def make_dict():
    mkdfa = 'C:/Julius/julius-4.6-win32bin/bin/mkdfa.pl'
    cmd = "perl {0} {1}".format(mkdfa, dict_name)
    proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

make_dict()
```

実行して **mydict.dfa**、**mydict.term**、**mydict.dict**、**mydict.dfa.forward** の4ファイルが生成されればOK。

# Juliusで実行
最後に、Juliusで動作確認をします。
```
chcp 65001
C:\Julius\julius-4.6-win32bin\bin\julius -C C:\Julius\dictation-kit-4.5/am-gmm.jconf -nostrip -gram ./mydict -input mic
```

登録した単語を話して反応すればOK。
以上、Pythonで単語リストからJuliusの単語辞書を作成する方法でした。

# ソースコード
ソースコードや使用したファイルは[**こちら**](https://github.com/phiniki/Julius/tree/main/Dict_Python)にアップしています。
```python:make_dict.py
from pykakasi import kakasi
import subprocess

dict_name = 'mydict'

kakasi = kakasi()

def make_yomi():
    f = open('word_list.txt', 'r')
    data = f.read()
    f.close()

    yomi_list = []
    for i in data.split('\n'):
        kakasi.setMode('J', 'H') #漢字からひらがなに変換
        kakasi.setMode("K", "H") #カタカナからひらがなに変換
        conv = kakasi.getConverter()
        yomi_list.append(i + '\t' + conv.do(i)) #[単語] + [Tab] + [ひらがな]

    yomi = '\n'.join(yomi_list)

    f = open(dict_name + '.yomi', 'w')
    f.write(yomi)
    f.close()

def make_phone():
    yomi2voca = 'C:/Julius/julius-4.6-win32bin/bin/yomi2voca.pl'
    cmd = "perl {0} ./{1} > ./{2}".format(yomi2voca, dict_name + '.yomi', dict_name + '.phone')
    proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

def make_grammar():
    f = open(dict_name + '.phone', 'r')
    data = f.read()
    f.close()

    grammar = ['S : NS_B WORD NS_E']
    for i in data.split('\n')[:-1]:
        word = i.split('\t')[1].upper().replace(' ', '') #すべて大文字に変換、スペース削除
        grammar.append('WORD : ' + word)

    grammar = '\n'.join(grammar)

    f = open(dict_name + '.grammar', 'w')
    f.write(grammar)
    f.close()

def make_voca():
    f = open(dict_name + '.phone', 'r')
    data = f.read()
    f.close()

    voca = []
    for i in data.split('\n')[:-1]:
        word = i.split('\t')[1].upper().replace(' ', '') #すべて大文字に変換、スペース削除
        voca.append('% ' + word + '\n' + i)
    voca.append('% NS_B')
    voca.append('[s] silB')
    voca.append('% NS_E')
    voca.append('[/s]    silE')

    voca = '\n'.join(voca)

    f = open(dict_name + '.voca', 'w')
    f.write(voca)
    f.close()

def make_dict():
    mkdfa = 'C:/Julius/julius-4.6-win32bin/bin/mkdfa.pl'
    cmd = "perl {0} {1}".format(mkdfa, dict_name)
    proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

make_yomi()
make_phone()
make_grammar()
make_voca()
make_dict()
```