前回の【動物会話】カラスの音声認識・自動分類を「エッジ音声認識アプリ」でやってみた♬を利用して、マイク入力を識別してカラスの「威嚇・怒り」「ノーマル(カーカー)」そして「その他(け・け・け・・・・)」のカラス音声を返すアプリを作成した。以下、3つのアプリを組み合わせるとカラスとの会話ができる。
1)音声を拾ってSTFTして声紋ファイルを作成する
2)声紋ファイルを分析(分類)して、結果をカラス音声で返す
3)動画を撮影して(音声を)記録しつつ、動画の主に見せる。あるいは別カラスの動画を見せる
そして、上記は今までの記事を見るとある程度想像できる範囲だと思うが、カラスと会話するためにはこれらの機能を有機的に結合することが必要だとわかる。
その意味で、今回は簡単なゲームをやったみたので記事にしたいと思う。
とりあえずの目標(関連する記事にリンク)
今回は主に4のカラスバージョンの完成です。
1.犬・猫の音声認識
2.動物の音声認識
3.犬の種類・猫の種類の認識
4.犬・猫・カラスの声にそれぞれの声で反応を返す
5.犬・猫・カラスの話を翻訳して、人の声で返すと翻訳して返す
。。。
最終目標;「動物と日常会話ができるようになる」
やったこと
・上記の3つのアプリを作成した
・カラスと会話する
・上記の3つのアプリを作成した
コードは以下に置きました。
1)音声を拾ってSTFTして声紋ファイルを作成する
これは、上記の自動分類で利用したものとほぼ同じもので、以下に置きました
・hirakegoma/pyaudio_realtime.py
2)声紋ファイルを分析(分類)して、結果をカラス音声で返す
これも上記の自動分類で利用したものとほぼ同じもので、以下のとおりです。
今回は、分類結果に従ってそれぞれのカラスの音声ファイルを再生しています。
コードは以下に置きました。
・hirakegoma/karasu_speak.py
簡単に説明すろと
以下でモデルに基づいて、imgSrcという声紋ファイルから予測(分類)します。
def prediction(imgSrc,model):
#np.random.seed(1337) # for reproducibility
img_rows,img_cols=128, 128
img = np.array(imgSrc)
img = img.reshape(1, img_rows,img_cols,3)
img = img.astype('float32')
img /= 255
t0=time.time()
y_pred = model.predict(img)
return y_pred
予測に基づいて、以下で音声ファイルを指定します。
def karasu_responder(model,path,img_rows,img_cols):
imgSrc=[]
imgSrc = image.load_img(path, target_size=(img_rows,img_cols))
#plt.imshow(imgSrc)
#plt.pause(1)
#plt.close()
pred = prediction(imgSrc,model)
#print(pred[0])
if pred[0][0]>=0.5:
filename = "karasu-miyama_out1.wav"
print("angry")
elif pred[0][1]>=0.5:
filename = "karasu-normal_out1.wav"
print("normal")
elif pred[0][2]>=0.5:
filename = "karasu-others_out1.wav"
print("others")
return filename
モデルをロードしています。
※モデルは、hirakegoma/vgg16_like.pyを使うので、ダウンロードして同じディレクトリに入れてください。
また、学習済weightsが必要ですが、カラスのファイルが(圧縮しても)大きいのでGithubにはおけませんでした。
一応、「ひらけごま・おはよう」の学習済ファイルを置いておきました。ただし、2種類分類なので全結合の部分のモデルパラメータが少し異なります。
num_classes = 3
img_rows,img_cols=128, 128
input_shape = (img_rows,img_cols,3)
model = model_family_cnn(input_shape, num_classes = num_classes)
# load the weights
model.load_weights('params_karasu-0angry-1normal-2others.hdf5', by_name=True)
print('Model loaded.')
path = "./out_test/figure.jpg"
以下は、実際に声紋がpathに存在すればそれをkarasu_responderに渡してその音声ファイルを再生します。
ちなみに、コメントアウトしている部分は、分類に渡す声紋をこちらで指定して決まったカラスの音声を再生するときに使います。
※カラスの声が聞きたいときはこれを使います。。。フィールドでこれを使ってカラスの反応を見たいと思います
s=0
while True:
if os.path.exists(path)==True:
s += 1
for j in range(0,1000000,1):
j += 1
"""
if s%3 == 0:
path="./out_test/figure_angry.jpg"
elif s%3 == 1:
path="./out_test/figure_normal.jpg"
else:
path="./out_test/figure_others.jpg"
"""
filename=karasu_responder(model,path,img_rows,img_cols)
# チャンク数を指定
CHUNK1 = 1024
wf = wave.open(filename, "rb")
# PyAudioのインスタンスを生成
p1 = pyaudio.PyAudio()
# Streamを生成
stream1 = p1.open(format=p1.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True)
# データを1度に1024個読み取る
input1 = wf.readframes(CHUNK1)
# 実行
while stream1.is_active():
output = stream1.write(input1)
input1 = wf.readframes(CHUNK1)
if input1==b'':
os.remove(path)
break
3)動画を撮影して(音声を)記録しつつ、動画の主に見せる。あるいは別カラスの動画(静止画)を見せる
ほぼ、これはミラーでもいいと思いますが、アプリでやるのもありなので、記載しておきます。
当初は、直接動画の主の音声を画像と共に(時間差をつけて)返すようにしていましたが、ハウリングが酷いので制御できるように上記のように分離しました。
※会話というのはどうやら自分の声は聴いていないし、相手の声をオウム返しもしないということのようです
この相手の声を流さないことにより、会話アプリが安定しました。
一応、コードは以下のとおりです。
・hirakegoma/camera_input_movie_karasu.py
一方、動画には音声をつけています。前回の成果を生かして、音声を大きさを少し大きめにして動画に追加しています。
・カラスと会話する
この3つのアプリを同時に動かす。
すると、こちらの声を拾ってSTFTして分類してカラスの音声を返してくれる。同時に動画を画面に出力し、適当な時間が経過すると音声付きで記録してくれる。
この入力をするとカラスの鳴き声が分かってくる。
どういう風に発すれば「カーカー」とか「がーがー」と泣いてくれるか。
案外難しいものである。
そして、「カーカー」と泣いてくれるとある意味ほっとするから不思議だ。
カラスで無く、英会話や方言の話し方やイントネーションなどの練習に使った方がいいかもしれないが、当面は「動物との会話」という人類史上初めての試みに注力したいと思う(笑)
まとめ
・文章は少なく原型でしかないが、なんとなく会話アプリの姿(構造)を理解したような気がする
・会話・同時翻訳アプリも当面は同じつくりなので対応したいと思う
・翻訳や会話の量を爆発的に増やしたいと思う
おまけ
今朝のお花茶屋のカラス、初ショットが撮れました。
以下Youtubeリンクです。