GenDCデータの可視化
このチュートリアルでは、前回のチュートリアルで解析したサンプルGenDCデータを可視化する方法を学びます。
前提条件
- GenDC Separator
- matplotlib
- numpy
pip3 install -U pip
pip3 install matplotlib
pip3 install numpy
pip3 install gendc-python==0.2.8
- GenDCデータ(前回のチュートリアルで取得したもの、またはこちらのページからサンプルをダウンロード)。
チュートリアル
前回のチュートリアルでは、バイナリファイルからGenDCデータを解析する方法を学びました。各パートデータを取得した後、それをアプリケーションで使用できるようにフォーマッティングする例として、このチュートリアルでは各データをmatplotlibを使ってグラフに描画します。
このチュートリアルではサンプルデータを使用します。
GenDC
GenDCの概要を学びたい場合は、こちらのページをご覧ください。GenDCの概念と大まかな構造が説明されています。
バイナリファイルの検索と読み込み
バイナリファイルの読み込みについては、前回のチュートリアルを確認してください。Part では、画像の生データを取得できます。
binary_image = part.get_data()
画像の可視化
前回のチュートリアルでは、画像データを持つComponentが 0
であることを確認しました。
また、以下のデータもあります:
- dimension = (1920, 1080)
- byte_depth = 1
これらのプロパティを使って、バイナリ画像データを uint8
型のnumpy配列に変換できます。
np_image = np.frombuffer(binary_image, dtype=get_numpy_dtype(byte_depth, unsinged=True))
現在の np_image
は1D配列なので、幅 x 高さの形に再形成できます。
get_dimension()
で取得したリストに入っている次元情報は画像の幅と高さの順序で返されますが、matplotlibは高さ、幅の順序を要求します。
WxH = dimension
HxW = dimension[::-1]
image_data = np_image.reshape(HxW)
上記のコードスニペットは、次のように1行で書くこともできます:
image_data = np.frombuffer(part.get_data(), dtype=get_numpy_dtype(byte_depth, unsinged=True)).reshape(dimension[::-1])
これで、imshow()
を使って画像データを表示できます。
image_fig = plt.figure(figsize=(15, 5))
plt.imshow(image_data, cmap='gist_gray')
plt.show()
.
音声データの可視化
前回のチュートリアルでは、音声データを持つComponentが 1
であることを確認しました。
また、以下のデータも取得しています。
- channel = 2
- dimension = (800,)
- byte_depth = 2
これらのプロパティを使って、画像Componentと同様にバイナリ音声データを int16
型のnumpy配列に変換できます。
for j in range(part_count):
part = audio_component.get_part_by_index(j)
dimension = (800,)
byte_depth = 2
audio_part_data = np.frombuffer(part.get_data(), dtype=get_numpy_dtype(byte_depth, unsinged=False)).reshape(dimension)
この音声センサーデータは、1フレームの画像データを取得する間に得られたサンプルを格納しており、そのフレームレートは60fpsです。
したがって、描画するサンプルが取得された時間の範囲は0から1/60秒です。
num_samples = audio_part_data.shape[0]
times = np.linspace(0, 1/image_fps, num=num_samples)[:num_samples]
次のようにsubplotを使って、2つのPartの図を同じ図に配置できます:
audio_fig = plt.figure(figsize=(15, 5))
for j in range(part_count):
part = audio_component.get_part_by_index(j)
dimension = (800,)
byte_depth = 2
audio_part_data = np.frombuffer(part.get_data(), dtype=get_numpy_dtype(byte_depth, unsinged=False)).reshape(dimension)
ax = audio_fig.add_subplot(part_count, 1, j+1)
ax.plot(times, audio_part_data)
plt.show()
.
一部の音声センサーは、LchとRchを交互に同じPartに格納するインタリーブ構造を使用します。
この場合、audio_component.get_part_count()
は1を返しますが、データを2次元に再形成して次のように使用する必要があります:
part = audio_component.get_part_by_index(j)
dimension = (800, 2)
byte_depth = 2
audio_part_data = np.frombuffer(part.get_data(), dtype=get_numpy_dtype(byte_depth, unsinged=False)).reshape(dimension)
Lch_data = audio_part_data[:, 0]
Rch_data = audio_part_data[:, 1]
アナログデータの可視化
前回のチュートリアルでは、アナログデータを持つComponentが 2
, 3
, および 4
であることを確認しました。
また、以下のデータも取得しています。
- channel = 1
- dimension = (16,)
- byte_depth = 2
Partデータを取得し、X軸の時間軸を生成する方法は次の通りです:
for j in range(part_count):
part = analog_component.get_part_by_index(j)
dimension = (16,)
byte_depth = 2
analog_part_data = np.frombuffer(part.get_data(), dtype=get_numpy_dtype(byte_depth, unsinged=False)).reshape(dimension)
num_samples = analog_part_data.shape[0]
times = np.linspace(0, num_samples/(image_fps * num_samples), num=num_samples)[:num_samples]
dimensionは1/60秒間に取得されたサンプルの数を表しているため、視覚化には16のデータポイントが表示されます。
analog_fig = plt.figure(figsize=(15, 5))
ax = analog_fig.add_subplot(1, 1, +1)
ax.plot(times, analog_part_data, marker = 'o')
plt.show()
.
PMODデータの可視化
前回のチュートリアルでは、加速度計データを持つComponentが 5
であることを確認しました。
また、以下のデータも取得しています。
- channel = 3
- dimension = (16,)
- byte_depth = 2
各PartはX、Y、Zの座標を表しているので、各Partのデータを XYZ
のリストに追加します。
XYZ = []
for j in range(part_count):
part = pmog_component.get_part_by_index(j)
dimension = (16,)
byte_depth = 2
pmod_part_data = np.frombuffer(part.get_data(), dtype=get_numpy_dtype(byte_depth, unsinged=False)).reshape(dimension)
XYZ.append(pmod_part_data)
これで、XYZを3D空間にプロットしてカメラの加速度を見ることができます。センサーが一部の時点で加速していなかったため、サンプル数が16未満に見えることがあります。
pmod_fig = plt.figure(figsize=(15, 10))
ax = pmod_fig.add_subplot(projection='3d')
ax.plot(XYZ[0], XYZ[1], XYZ[2], marker = 'o')
plt.show()
.
一部の加速度計センサーは、X、Y、Zの座標を交互に同じPartに格納するインタリーブ構造を使用します。
この場合、pmog_component.get_part_count()
は1を返しますが、次のように4次元(x、y、z、およびパディング)にデータを再形成する必要があります:
part = pmod_component.get_part_by_index(j)
dimension = (800, 4)
byte_depth = 2
pmod_part_data = np.frombuffer(part.get_data(), dtype=get_numpy_dtype(byte_depth, unsinged=False)).reshape(dimension)
X = pmod_part_data[:, 0]
Y = pmod_part_data[:, 1]
Z = pmod_part_data[:, 2]
Complete code
このチュートリアルで使用される完全なコードはこちらです。