音声を認識させるには、音声を時系列のスペクトログラムを生成し、畳み込みニューラルネットワークやLSTMのような再帰型ニューラルネットワークに入力すれば行うことができそうです。
その前処理として、Python を使って音声ファイルからスペクトログラムを生成するプログラムを作ってみました。
プログラムの詳しい解説は省きますが、記録したオーディオ信号をFFTのタップ数(frameSize=256)の半分ずつ(overlapFac=0.5,128)を移動しながらFFTをかけています。
プログラム上で注意すべき点は音声ファイルをタップ数に分割して2次元配列にしているところと、横軸と縦軸の物理量の算出あたりでしょうか。
違いが出るのか確認するために、今回は、”イチ”、”二”、”サン”と数字を発音したファイルをそれぞれスペクトログラムに変換してみました。その結果がこれです。
”イチ”
”ニ”
"サン"
結構、特徴が出るものですね。これなら認識できるかな?🤔
( ̄ー ̄)
その前処理として、Python を使って音声ファイルからスペクトログラムを生成するプログラムを作ってみました。
import numpy as np
import scipy.io.wavfile as wav
from matplotlib import pyplot as plt
from numpy.lib import stride_tricks
from numpy.lib.stride_tricks import as_strided
from numpy.fft import rfft
""" short time fourier transform """
def stft(samples, frameSize, overlapFac = 0.5, window = np.hanning):
win = window(frameSize)
hopSize = int(frameSize - np.floor(overlapFac * frameSize))
# cols for windowing
cols = np.floor(len(samples) / hopSize) - 1
# print("cols: ", cols)
# make an array in 2nd dimension with hopSize
frames = as_strided(samples, shape=(int(cols), frameSize), strides = (samples.strides[0] * hopSize, samples.strides[0])).copy()
frames = frames * win
return rfft(frames)
def main():
frameSize = 256
sample_rate, samples = wav.read('./wav/ichi.wav')
print("sample_rate:", sample_rate)
print("num_of_samples:", len(samples))
spectrogram = stft(samples, frameSize)
frequency_map = np.fft.fftfreq(frameSize, 1. / sample_rate)
spectrogram = 20. * np.log10(np.abs(spectrogram)) # amplitude to decibel
# spectrogaram has an extra colum, so slice it
spectrogram = spectrogram[:,:int(np.floor(frameSize/2))]
times, ftaps = np.shape(spectrogram)
print(spectrogram.shape)
plt.figure(figsize=(16, 8))
plt.imshow(np.transpose(spectrogram), origin="lower", aspect="auto", cmap="jet", interpolation="none")
plt.colorbar()
plt.xlabel("time (s)")
plt.ylabel("frequency (hz)")
plt.xlim([0, times-1])
plt.ylim([0, ftaps-1])
xlocs = np.float32(np.linspace(0, times-1, 5))
plt.xticks(xlocs, ["%.02f" % i for i in (xlocs * frameSize / sample_rate)])
ylocs = np.int16(np.floor(np.linspace(0, ftaps-1, 10)))
plt.yticks(ylocs, ["%.02f" % frequency_map[i] for i in ylocs])
plt.show()
plt.clf()
if __name__ == "__main__":
main()
プログラムの詳しい解説は省きますが、記録したオーディオ信号をFFTのタップ数(frameSize=256)の半分ずつ(overlapFac=0.5,128)を移動しながらFFTをかけています。
プログラム上で注意すべき点は音声ファイルをタップ数に分割して2次元配列にしているところと、横軸と縦軸の物理量の算出あたりでしょうか。
違いが出るのか確認するために、今回は、”イチ”、”二”、”サン”と数字を発音したファイルをそれぞれスペクトログラムに変換してみました。その結果がこれです。
”イチ”
”ニ”
"サン"
結構、特徴が出るものですね。これなら認識できるかな?🤔
( ̄ー ̄)
Pythonデータサイエンスハンドブック ―Jupyter、NumPy、pandas、Matplotlib、scikit-learnを使ったデータ分析、機械学習
- 出版社/メーカー: オライリージャパン
- 発売日: 2018/05/26
- メディア: 単行本(ソフトカバー)
現場で使える! Python自然言語処理入門 (AI & TECHNOLOGY)
- 出版社/メーカー: 翔泳社
- 発売日: 2020/01/20
- メディア: 単行本(ソフトカバー)