人工知性を作りたい

私が日々、挑戦したことや学んだことなどを紹介していく雑記ブログです。 (新しいAI技術HTM, 専門の音声信号処理, 趣味のアニメ等も書いてます。)

テキストから音声の生成モデル「DiffSound」を動かす【#Text-to-Sound】【#音声AI】

avatar

 

 

今期はテキストから音声を生成するモデル"DiffSound"をpretraindeモデルで動作させる方法を記載します。

入力テキストには「Birds and insects make noise during the daytime」のような文章を使用し、その文章に適した音声が生成されるというモデルになります。このモデルはテキストから音声への生成結果が良いだけでなく、生成速度も早く、従来のARデコーダの5倍の生成速度であることが論文内で示されています。

DiffSound作成者が公開しているデモページがあるのでご確認ください。

Diffsound: Discrete Diffusion Model for Text-to-sound Generation | text-to-sound-synthesis-demo

 

 

本記事のテーマ

テキストから音声の生成モデル「DiffSound」を動かす【#Text-to-Sound】

DiffSoundのgithubだけでなく、他のモデルも組み合わせて全体のシステムが作成されているためコードの配置やpretrainモデルを配置することが難しかった。

その方法を紹介する。

 

論文のAbstract

人間が求める効果音を生成することは、重要なテーマである。しかし、この分野の音生成の研究はほとんどない。本研究では、テキストプロンプトを条件とした音声生成について検討し、テキストエンコーダ、VQ-VAE(Vector Quantized Variational Autoencoder)、デコーダ、ボコーダからなる新しいテキスト-音声生成フレームワークを提案する。このフレームワークは、まずデコーダでテキストエンコーダから抽出したテキスト特徴をVQ-VAEの助けを借りてメルスペクトログラムに転送し、次にボコーダで生成されたメルスペクトログラムを波形に変換するものである。その結果、デコーダが生成性能に大きく影響することがわかった。そこで、本研究では、優れたデコーダの設計に焦点を当てる。まず、従来の音声生成で最先端であることが証明されている自己回帰型復号器について説明します。しかし、ARデコーダは常にメルスペクトログラムのトークンを1つずつ順番に予測するため、一方向の偏りや誤差の累積の問題が発生する。また、ARデコーダでは、音声の長さに比例して音声生成時間が増加する。このようなARデコーダの欠点を克服するために、我々は離散拡散モデルに基づく非自己回帰型デコーダDiffsoundを提案する。具体的には、Diffsoundは1つのステップでmel-spectrogramの全てのトークンを予測し、次のステップで予測されたトークンを洗練させるため、数ステップ後に最良の予測結果を得ることが可能である。実験の結果、提案するDiffsoundはARデコーダと比較して、テキストから音声への生成結果が良好であるだけでなく、生成速度も速く、例えば、MOS: 3.56 v.s 2.786 と、ARデコーダの5倍の生成速度であることが示された。さらに、生成されたサンプルの品質を自動的に評価するために、3つの異なる客観的評価指標(例えば、FID、KL、オーディオキャプションロス)を定義し、生成サンプルの関連性と忠実度を包括的に評価できるようにした。コード、事前学習済みモデル、および生成されたサンプルを公開します 1 。

Translated by DeepL

arxiv.org

DiffSoundを動かす

1.コードをCloneする。

git clone https://github.com/yangdongchao/Text-to-sound-Synthesis.git

github.com

2.環境構築を行う

Text-to-sound-Synthesis/Diffsound/README.md内のEnviromentに記載されているライブラリをInstallする。

※その他実行中に足りないものが出てきた場合はInstallしてください。

pip install torch==1.9.0 torchvision --no-cache-dir -U | cat
pip install omegaconf pytorch-lightning --no-cache-dir -U | cat
pip install timm==0.3.4 --no-cache-dir -U | cat
pip install tensorboard==1.15.0 --no-cache-dir -U | cat
pip install lmdb tqdm --no-cache-dir -U | cat
pip install einops ftfy --no-cache-dir -U | cat
pip install git+https://github.com/openai/DALL-E.git --no-cache-dir -U | cat

3.pre-trained modelをダウンロードする

Text-to-sound-Synthesis/Diffsound/README.md内のAbout the pre-trained modelに記載されているURLからダウンロードを行う。

4.generate_samples_batch.pyの実行

今回はREADMEのSamplingに記載されているevaluate/generate_samples_batch.pyを実行してDiffSoundを動かす。

動かすためにはスクリプト内に記載されている。Pathを自身のPCと合わせないといけない。その手順を以下に示す。

■evaluate/generate_samples_batch.py

if __name__ == '__main__':
# Note that cap_text.yaml includes the config of vagan, we must choose the right path for it.
config_path = '/work/hiro877/Text-to-sound-Synthesis/Diffsound/evaluation/caps_text.yaml'
#config_path = '/apdcephfs/share_1316500/donchaoyang/code3/VQ-Diffusion/OUTPUT/caps_train/2022-02-20T21-49-16/caps_text256.yaml'
pretrained_model_path = '/work/hiro877/Text-to-sound-Synthesis/Diffsound/OUTPUT/pretrained_model/audioset_pretrain_diffsound.pth'
save_root_ = '/apdcephfs/share_1316500/donchaoyang/code3/DiffusionFast/OUTPUT/caps_train_vgg_pre/2022-05-18T01-00-38'
random_seconds_shift = datetime.timedelta(seconds=np.random.randint(60))
key_words = 'Real_vgg_pre_399'
now = (datetime.datetime.now() - random_seconds_shift).strftime('%Y-%m-%dT%H-%M-%S')
save_root = os.path.join(save_root_, key_words + '_samples_'+now, 'caps_validation')
# print(save_root)
# assert 1==2
os.makedirs(save_root, exist_ok=True)
# val_path = 'data_root/audiocaps/new_val.csv'
val_path = 'data_root/audiocaps/new_mytest.csv'
ckpt_vocoder = 'vocoder/logs/vggsound/'
Diffsound = Diffsound(config=config_path, path=pretrained_model_path, ckpt_vocoder=ckpt_vocoder)
Diffsound.generate_sample(val_path=val_path, truncation_rate=0.85, save_root=save_root, fast=False)

設定するPathは以下の4つ。

・config_path = '/work/hiro877/Text-to-sound-Synthesis/Diffsound/evaluation/caps_text.yaml'

・pretrained_model_path = '/work/hiro877/Text-to-sound-Synthesis/Diffsound/OUTPUT/pretrained_model/audioset_pretrain_diffsound.pth'

・save_root_ = '/apdcephfs/share_1316500/donchaoyang/code3/DiffusionFast/OUTPUT/caps_train_vgg_pre/2022-05-18T01-00-38'

・val_path = 'data_root/audiocaps/new_mytest.csv'

・ckpt_vocoder = 'vocoder/logs/vggsound/'

config_path 

・config_path = '/work/hiro877/Text-to-sound-Synthesis/Diffsound/evaluation/caps_text.yaml'

ここはText-to-sound-Synthesis/Diffsound/evaluationのフォルダ内に存在するcaps_text.yamlを指定すればよい。

pretrained_model_path 

・pretrained_model_path = '/work/hiro877/Text-to-sound-Synthesis/Diffsound/OUTPUT/pretrained_model/audioset_pretrain_diffsound.pth'

ここは、Downloadしたフォルダ内に存在するaudioset_pretrain_diffsound.pthを配置してPathを設定する

save_root_ 

・save_root_ = '/apdcephfs/share_1316500/donchaoyang/code3/DiffusionFast/OUTPUT/caps_train_vgg_pre/2022-05-18T01-00-38'

ここは実行後の音声ファイルが保存されるPathであるため任意のPathを指定する。

val_path 

・val_path = 'data_root/audiocaps/new_mytest.csv'

ここは元の設定のままで動作する。

このファイルが入力するテキストになるため、ここを編集することで好きな音声を生成することが出来る。

ckpt_vocoder 

・ckpt_vocoder = 'vocoder/logs/vggsound/'

ここは元の設定のままで動作する。

ViT-B-32モデルのダウンロード

このまま実行すると"/apdcephfs/share_1316500/donchaoyang/code3/VQ-Diffusion/OUTPUT/pretrained_model/ViT-B-32.pt"が見つかりませんというエラーが発生する。

ViT-B-32.ptをダウンロードするにはDiffSound/sound_synthesis/modeling/modules/clip/clip.pyのload()関数内を少し変更する必要がある。
model_path = _download(_MODELS[name])のコメントアウトを外すことでモデルをダウンロードしてくれる。一度ダウンロードした後は必要ないので再度コメントアウトを行う。

ダウンロード先は_download()関数の中のdownload_targetを変更することで任意の場所に保存できる。また、load()関数内のmodel_pathの方も変更するように注意する。

 

def load(name: str, device: Union[str, torch.device] = "cuda" if torch.cuda.is_available() else "cpu", jit=True):
"""Load a CLIP model

Parameters
----------
name : str
A model name listed by `clip.available_models()`, or the path to a model checkpoint containing the state_dict

device : Union[str, torch.device]
The device to put the loaded model

jit : bool
Whether to load the optimized JIT model (default) or more hackable non-JIT model.

Returns
-------
model : torch.nn.Module
The CLIP model

preprocess : Callable[[PIL.Image], torch.Tensor]
A torchvision transform that converts a PIL image into a tensor that the returned model can take as its input
"""
if name in _MODELS:
model_path = _download(_MODELS[name]) ☆ここのコメントアウトを外す
# model_path = "/apdcephfs/share_1316500/donchaoyang/code3/VQ-Diffusion/OUTPUT/pretrained_model/ViT-B-32.pt"

 

※追記:私の使用感として下記リンクのコードからダウンロードしたモデルを使用したほうがテキストに近い音声が生成されることが分かった。

# Download ViT-B-32.pt
# aria2cのインストールが必要 aria2c https://facevcstandard.blob.core.windows.net/t-shuygu/release_model/VQ-Diffusion/pretrained_model/ViT-B-32.pt --auto-file-renaming=false -o OUTPUT/pretrained_model/ViT-B-32.pt

https://colab.research.google.com/drive/1kV6lp0wK46oGRtBspvgBt1DDG9CWjf2j?usp=sharing#scrollTo=FqJmBqQ0k-8c

 

まとめ

これまでの設定を行うことでgenerate_samples_batch.pyが動作すると思う。

もし動かない場合は私の方の記載ミスの可能性もあるためコメント頂けますと幸いです。また、他にもご質問等あれば気軽にコメントください!

 

最後に、最近StableDiffutionでAIによる画像生成が注目を集めていますが今回のように音声の方の技術も発展してきています。

DiffSoundの他にもDannce Diffutionというモデルも注目を集めています。

wandb.ai

私は博士課程として研究をする傍ら、インディーゲーム制作を行っているため、一人では大変な絵の作成や効果音、BGMの作成などをAIが行ってくれると大変助かります。

最近のAIによるクリエーターのサポートについて心配する声をよく聞きますが良い点を見てみると今まで大手企業でしか作れなかった大きなプロジェクトを個人または中小企業で作成できる可能性も広がるため、エンタメ界隈全体が賑わっていくのではないのかとポジティブに私は予想しています。

(もちろん学習データには著作権フリーのものを使うなどが必要ですが。)

 

引用

arxiv.org

github.com

【Unity バグ修正】Scene移動先でUIフォーカスがFirstSelectedに設定したものと異なる

 

 

本記事のテーマ

「UIフォーカスがFirstSelectedに設定したものと異なる」問題の解決

制作環境

・Unity2021.3.0.f1

不具合解析

本ゲームはCheckPointScene→MazeSceneという流れになっています。

■現象

 CheckPointからMazeSceneへ移動後、EventSystemのInspectorにあるFirstSelectedに設定されているButtonにフォーカスが当たっていなかった。

■原因

 CheckPointからMazeSceneへ↑矢印キーで移動しながら扉の中に入ってシーンが移動します。その際、Scene移動後すぐに↑矢印キーの入力が入っており、FirstSelectedの上にあるButtonにフォーカスが移動していた。

修正方法

■修正方法1

 First Selectedに割り当てたButtonのInspector内になるButtonComponentのNavigation項目をNoneにしてキー入力によるフォーカスを移動しないようにする。


■修正方法2

ScriptからEventSystemComponetを使用して制御する。

(例)

GameObject firstSelect;
EventSystem.current.SetSelectedGameObject(firstSelect);

 

感想

パッと見では分かりにくいバグであるが、知っていればどうといったことのないバグだったので気づいた時は閃いた感があって嬉しかった。

UIフォーカスという単語自体、はじめは知らなかったので独学の欠点が出てしまった。

また一つ成長できました。

 

カメラを用いた指認識コントローラーの作り方②指認識【Unity, Mediapipe, Websocket】

f:id:hiro-htm877:20220130092803j:plain

 

本記事のテーマ

指に連動してキャラクターが動くアプリを制作する。

制作環境

・Unity2020.3.26.f1

・Mediapipe Python

・NodeJs

本記事ではPythonで指認識を行い、Websocketサーバーへキャラクターの移動量を送信する機能の作り方を説明します。

■前記事

カメラを用いた指認識コントローラーの作り方①リアルタイム同期通信【Unity, Mediapipe, Websocket】 - 人工知性を作りたい

 

仕様書(指認識コントローラー)

■機能

1. 指の形を認識する

 ”1”、”2”、”3”、”4”、”5”、”OK”、キツネ”、”いいね”

 ※上記以外は”1”とする

2. Pythonスクリプトを起動したときに指認識で動かすオブジェクトを生成

 画像の黒い球

3. 手を”1”にしたときの人差し指先端を基準位置として、指の移動量を計算する

4. 3で計算した移動量を随時Websocketサーバーへ送信する。

f:id:hiro-htm877:20220130083214p:plain

 

作成したコード

・JavaScriptsフォルダ:Websocketサーバー用

・Pythonフォルダ:指認識(Mediapipe)、Websocketクライアント用

・Unityフォルダ:リアルタイム同期通信アプリ、Websocketクライアント用

GitHub - hiro877/FingerController-Unity-Mediapipe

 

実行方法

GitHub - hiro877/FingerController-Unity-Mediapipe

上記のコードをダウンロードする。

1. mediapipe Pythonの環境を構築する(手順は下記サイト参照)

  MediaPipe in Python - mediapipe

2. JavaScriptsフォルダ内のws.jsを起動する

 $ node we.js

3. UnityHub→リストに追加でUnityProjectsフォルダを選択し起動する。

4. 1で作成した環境からPythonフォルダ内のclient.pyを実行する。

※Pythonなどで必要な求められたパッケージをインストールしてください。

 

作り方

指認識にはMediapipeのhand trackingを使用します。

コードはKazuhito00さんが作成しているサンプルを編集しています。

■元コード

・sample_hand.py

https://github.com/Kazuhito00/mediapipe-python-sample

■完成コード

・Python/client.py

 

実装手順

0. sample_hand.pyをダウンロード

1. 指の形認識の処理を追加

2. 指の移動量の計算処理を追加

3. Websocketへの送信

1. 指の形認識の処理を追加

下記記事で説明されているJavaScriptのコードをPythonに置き換えました。

すみませんが、内容については把握していません。

ご存知の方はコメント欄で教えください!

MediaPipe 入門 (6) - 指ポーズの検出|npaka|note

■実装部分

Python/client.py

・calcDistance()

・calcAngle()

・cancFingerAngle()

・detectFingerPose()

2. 指の移動量の計算処理を追加

detectFingerPoseで指の形を認識します。

基準値となるx, y座標を記録するorigin_posを定義しておきます。(初期値は空リスト)

最初のみ、認識した指の形が”1”のときorigin_posに基準値となるx, y座標を記録します。

2回目以降は現在の人差し指の位置と基準値との距離を計算して、基準値で割ることで正規化(-1 ~ 1の間に収める)をしています。

■実装コード

finger_pose = detectFingerPose(landmark_point)
if finger_pose == "1":
    if origin_pos:
        cv.circle(debug_image, origin_pos, 5, (0, 0, 255), 2)
        cv.circle(debug_image, index_finger_pos, 5, (0, 0, 255), 2)
        finger_x, finger_y = (origin_pos[0]-index_finger_pos[0])/origin_pos[0], (origin_pos[1]-index_finger_pos[1])/origin_pos[1]
        data["pos_x"] = -1*finger_x
        data["pos_y"] = finger_y
        ws.send(json.dumps(data))
        result =  ws.recv()
    else:
        origin_pos = index_finger_pos
        cv.circle(debug_image, origin_pos, 5, (0, 0, 255), 2)
else:
    origin_pos = []

 

3. Websocketへの送信

まず、起動後にWebsocketサーバーとのコネクションを確立します。

# Websocket ########################################################
ws = create_connection("ws://192.168.0.29:3000")

次に、指認識で移動させるオブジェクトを生成するJsonデータを生成します。

data_connect = {
"action": "connect",
"room_no": 1,
"user": "mediapipe",
"pos_x": 2,
"pos_y": 0,
"pos_z": 2,
"way": "neutral",
"range": 0,
}
ws.send(json.dumps(data_connect))

その後は、カメラが指を認識している間Websocketサーバーへ移動量を送信します。

data = {
"action": "move",
"room_no": 1,
"user": "mediapipe",
"pos_x": 2.1,
"pos_y": 0.1,
"pos_z": 0,
"way": "mediapipe",
"range": 0,
}
data["pos_x"] = -1*finger_x
data["pos_y"] = finger_y
ws.send(json.dumps(data))

最後に、生成したオブジェクトを退出させる処理をスクリプトが終了する直前に行います。

# キー処理(ESC:終了) #################################################
key = cv.waitKey(1)
if key == 27: # ESC
ws.send(json.dumps(data_disconnect))
result = ws.recv()
ws.close()
break

 

 

以上、ご参考になると幸いです!

質問などは下のコメント欄でお待ちしております!

分かりにくいなどのクレームもお待ちしております!

カメラを用いた指認識コントローラーの作り方①リアルタイム同期通信【Unity, Mediapipe, Websocket】

f:id:hiro-htm877:20220129212027j:plain



 

本記事のテーマ

指に連動してキャラクターが動くアプリを制作する。

制作環境

・Unity2020.3.26.f1

・Mediapipe Python

・NodeJs

概要(設計)

カメラで人差し指の位置を認識し、指の動きに連動してアプリ上のキャラクターを動かす。

使用技術

指認識:Mediapipe

データ送信:Websocket

キャラクターを動かすアプリ:Unity

f:id:hiro-htm877:20220129212010p:plain



作り方

今回つくるWebsocket通信と複数アプリ間のキャラクターの位置の同期は以下のサイトを元に作成しました。

ですので基本的には下記サイトを参考に作ってください。

本記事では追加説明を記載いたします。

また、参考サイトには誤字や脱字があったので修正しています。

完成したコードをGithubにおいていますので動かない際はお手数ですが私のGithubのコードと比較しながら作成してください。

■誤字脱字、説明不足パターン

※細かい差分などを覚えていないのでコメント欄でご質問いただけますと幸いです。

・オブジェクトの名前がコードないと異なる。

・オブジェクトの配置位置が記載されていない

・UserLoginDataクラスを作成していない状態で使用するためErrorが発生。

Unity初心者がawsサーバーとWebSocketを使ってのリアルタイム同期通信について学ぶ①

Unity初心者がawsサーバーとWebSocketを使ってのリアルタイム同期通信について学ぶ②

Unity初心者がawsサーバーとWebSocketを使ってのリアルタイム同期通信について学ぶ③

完成コード

github.com

追加説明

③追加するプラグインの配置

参考記事①のWebsocketに関するプラグインの配置です。

・Network.Json.dll

Unity2020からはNetwork.Json.dllと同等の機能のパッケージが入っており、新しく追加しなくても↓のパッケージが使用できます。

using Newtonsoft.Json;
 

・websocket-sharp.dll

Ubuntuでwebsocket-sharp.dllを作成するためにMonodevelopを使用しました。

手順:

1. websocket-sharpのgit repogitoryをダウンロードする。

GitHub - sta/websocket-sharp: A C# implementation of the WebSocket protocol client and server

2. monodevelopをインストールする

下記サイトのUbuntu18.04の手順でUbuntu20.04にダウンロードできました。

Download | MonoDevelop

3. monodevelopをアクティビティから開き,websocket-sharpをBuildする。

手順は下記サイトを参考。ファイル→開く→1でダウウンロードしたファイル内のwebsokcet-sharp.slnを選択する。

Exampleファイルを削除後、Releaseを選択してBuildする。

UnityでWebSocketを使用する - Qiita

Nodejsのインストールと設定

インストールは参考サイトから転載

git clone https://github.com/creationix/nvm.git ~/.nvm

source ~/.nvm/nvm.sh

vi .bashrc(下記を追加)

--------------

# nvm
if -s ~/.nvm/nvm.sh ; then
        source ~/.nvm/nvm.sh ;
fi

-------------

nvm ls-remote

nvm install v16.13.2

nvm use v16.13.2

node -v

npm install ws

この後node ws.jsを実行するとMODULE_NOT_FOUNDとなったので下記サイトを通りにPATHを通してあげると動いた。

Node.jsで、存在するはずのmoduleがrequireでエラーになることについて - Qiita

 

websocketのIPアドレスを指定する

nodejsで立てるサーバーのIPアドレスを確認する。

UbuntuだとIfconfigコマンドで確認できる。

FingerController-Unity-Mediapipe/WebSocketClientManager.cs at main · hiro877/FingerController-Unity-Mediapipe · GitHub

 

残りの手順は次の記事にて記載いたします。

「Mediapipeによる指認識〜Nodejsを通してアプリに位置情報を送信する」

 

www.hiro877.com

 

 

以上、ご参考になると幸いです!

質問などは下のコメント欄でお待ちしております!

分かりにくいなどのクレームもお待ちしております!

Raspberry PiでMediapipeをPythonで使用する【pipでインストール】

f:id:hiro-htm877:20211217074325p:plain

 

本記事のテーマ

Raspberry PiでMediapipeをpipでインストールする

下記問題の解決

・RasbianOSではpipでMediapipeをインストールできない

・python-opencv-contribをインストールすると強制終了する

概要

今回はラズパイでpip installするためのwheelというものを作ってくださっている方がいるという情報を得ましたのでその方法を使用します。

主な流れは下記記事を参考にしました。

Raspberry Piで手軽にMediaPipeを楽しむ方法

 

RasbianOS(64bit)のインストール

Raspberry Pi Imagerを使ってSDカードに焼いているのですが、64ビットのRasbianがありませんでした。

記事によると以下からダウンロードできるということでお借りしました。

(こういう情報をどこから知るんでしょうか...?)

Index of /raspios_arm64/images

f:id:hiro-htm877:20211217070735p:plain

※今回は2021-10-30-raspios-bullseye-arm64.zipを使用

(raspios_arm64-2021-11-08/)

ダウンロードしたZipファイルをRaspberry Pi ImagerのCHOOSE OS→USE CUSTOMから選択します。

起動後、とりあえずお作法として

sudo apt-get update && sudo apt-get upgradeしています。

スワップファイルの拡張

pipでpython-opencv-contribをインストールするためにスワップファイルの拡張を行います。(これをしないと私は強制終了されてインストールできませんでした。。)

方法は下記を参考にしました。

ラズパイ(Raspbian Jessie)とスワップメモリ容量の変更(環境設定の続き) - 今日も微速転進

☆引用

エディタで/etc/dphys-swapfileを開き、CONF_SWAPSIZE という行の値を変更。例えば2048MB(2GB)なら以下のように変更。

CONF_SWAPSIZE=2048

設定したいSwapのサイズをMB単位で指定。

$ sudo systemctl stop dphys-swapfile
$ sudo systemctl start dphys-swapfile

systemctl経由でstop/start する。実際に呼び出されるのは/etc/init.d/dphys-swapfile。 なお、swapの容量を変更した直後は内部でddコマンドが呼び出されるので非常に時間がかかります。

最後にfree -hで意図した容量に設定されているか確認。

$ free -h
             total       used       free     shared    buffers     cached
Mem:          862M       833M        28M       6.3M        36M       656M
-/+ buffers/cache:       140M       721M
Swap:         2.0G         0B       2.0G

-hは人間が読みやすい単位で出力するというオプション。

mediapipeのwheelを取得

github.com

今回の1. Binary typeはDebian/Bullseyeです。

v0.8.4/numpy120x/mediapipe-0.8-cp39-none-linux_aarch64_numpy120x_debian11_download.sh

f:id:hiro-htm877:20211217071726p:plain

下記コマンドを実行してインストールします。

$ sudo apt update && \
  sudo apt install -y python3-dev protobuf-compiler python3-pip git make libssl-dev
$ sudo pip3 install pip --upgrade
$ cd && git clone https://github.com/PINTO0309/mediapipe-bin && cd mediapipe-bin
$ ./v0.8.4/numpy120x/mediapipe-0.8-cp39-none-linux_aarch64_numpy120x_debian11_download.sh
$ sudo pip3 install *.whl $ sudo pip3 install opencv-python

この時、libcblas.so.3が見つからないというErrorが出たので下記を追加しました。

$ sudo apt-get install libatlas-base-dev

下記サイトを参考にしましたので他に足らないものがあればインストールしてみたら改善するかもしれません。

【Raspberry Pi】Raspberry Pi Zero WにOpenCVの環境を構築する - ソースに絡まるエスカルゴ

Sampleを動かす

以下コマンドで実行できます。


    $ cd && git clone https://github.com/Kazuhito00/mediapipe-python-sample
    $ cd mediapipe-python-sample
    $ python3 sample_hand.py

この時model_complexityが見当たらないと言われたので#でコメントアウトすれば動くようになりました。

    hands = mp_hands.Hands(

#        model_complexity=model_complexity,

        max_num_hands=max_num_hands,

        min_detection_confidence=min_detection_confidence,

        min_tracking_confidence=min_tracking_confidence,

    )

 

f:id:hiro-htm877:20211217074106j:plain

 

以上、ご参考になると幸いです!

質問などは下のコメント欄でお待ちしております!

Raspberry PiでMediapipeの環境構築とBuild、Run【フリーズ問題解決】

f:id:hiro-htm877:20211213193606p:plain

本記事の特徴

・OpenCVのセットアップでフリーズ

・ハローワールドのビルドでフリーズ

上記の問題を解決します。

 

本記事のテーマ

【Raspberry PiでMediapipeのビルドが止まる問題の解決!】

・exampleにあるHallo Worldを動かす

環境構築からHalloWorldの手順

主に公式のInstallationの通りに行うのが良いと思います。

Installation - mediapipe

他の日本の方がまとめているサイトで参考にしたのは下記のサイトです。

dev.classmethod.jp

 

※追記:問題1と問題2を同時に解決する方法

スワップファイルを拡張することで解決できました!

ラズパイ(Raspbian Jessie)とスワップメモリ容量の変更(環境設定の続き) - 今日も微速転進

☆引用

エディタで/etc/dphys-swapfileを開き、CONF_SWAPSIZE という行の値を変更。例えば2048MB(2GB)なら以下のように変更。

CONF_SWAPSIZE=2048

設定したいSwapのサイズをMB単位で指定。

$ sudo systemctl stop dphys-swapfile
$ sudo systemctl start dphys-swapfile

systemctl経由でstop/start する。実際に呼び出されるのは/etc/init.d/dphys-swapfile。 なお、swapの容量を変更した直後は内部でddコマンドが呼び出されるので非常に時間がかかります。

最後にfree -hで意図した容量に設定されているか確認。

$ free -h
             total       used       free     shared    buffers     cached
Mem:          862M       833M        28M       6.3M        36M       656M
-/+ buffers/cache:       140M       721M
Swap:         2.0G         0B       2.0G

 

問題1:OpenCVビルドでフリーズ

Installationの3Install OpenCV and FFmpeg.のOption2であるsetup_opencv.shを実行すると途中でフリーズするという現象に会いました。

試行錯誤した結果、viなどでsetup_opencv.shを以下のように変更するとフリーズせずにビルドが通るようになりました。

77行めのmake -j 16を -j4に変更する。(使用する並列処理の数を減らす)


77    make -j 16 → make -j 4
78    sudo make install
79    rm -rf /tmp/build_opencv
80    echo "OpenCV has been built. You can find the header files and libraries in /usr/local/include/opencv2/ and /usr/local/lib"

 

問題2:bazel runでフリーズ

問題1と同様にjobsを下げてみたがそれでもフリーズした。

調査した結果、bazelには--jobsだけでなく,--local_ram_resourcesでCPUのリソースの調整もできるらしい。

少しずつCPUの使用率を減らしていった結果、次のパラメータでビルドが通るようになった。(しかし2回失敗した後、3回めで成功。)


    # cd ~/mediapipe
    export GLOG_logtostderr=1

    bazel run --copt -DMESA_EGL_NO_X11_HEADERS --copt -DEGL_NO_X11 \
    mediapipe/examples/desktop/hello_world:hello_world --jobs 4\
    --local_ram_resources 280

ramのリソースは使用するラズパイのCPUによって変わるため、コマンド(free -h)を用いて最大使用できるCPUリソースを確認してから減らすと良いと思います。

・freeコマンドの使い方(サイト内のメモリ容量参照)

Linux のメモリ容量・CPUコア数・ディスク容量を確認する - 猫でもわかるWebプログラミングと副業

 

参考文献

・bazelのjobsリファレンス

Command-Line Reference - Bazel main

・bazelのlocal_ram_resources

Command-Line Reference - Bazel 0.23.0

 

 

以上、ご参考になると幸いです!

質問などは下のコメント欄でお待ちしております!

ホログラムディスプレイを作ってみた(Unity、100均材料、IPad、ペッパーズ・ゴースト)

本記事のテーマ

「ホログラムディスプレイを作ってみた」

よめ子さんというYoutuberの方の動画に感化されて作ってみました。

普段プログラミングという目に見えないものづくりしかしていないので久々に段ボールを切ったりしたりするのが新鮮で楽しかったです。


www.youtube.com

 

・よめ子さんの動画


www.youtube.com

 

作り方

下記の動画を参考に作りました。


www.youtube.com

 

私が使用したもの

・透明な下敷き(ダイソー)※CDケースの代わり

・黒の厚紙(ダイソー)

・段ボール(スーパーから無料でもらう)

・グルーガン(ダイソーにもある)

 

完成品画像

・正面

f:id:hiro-htm877:20211211104228j:plain

f:id:hiro-htm877:20211211104449j:plain

・横(段ボール3枚)

f:id:hiro-htm877:20211211104320j:plain

・裏面

f:id:hiro-htm877:20211211104405j:plain

 

関連記事

Unityで3D映像を表示するアプリを作る際にいくつか課題にぶつかりましてその解決方法を別の記事にまとめています。

 

www.hiro877.com

www.hiro877.com

 

 

【Unity】背景の色が開発環境(黒、Linux)と実機(白、IPad[IOS])で異なる問題解決

 

背景の色を黒に設定したのですがIPad (IOS)で実行すると白になってなんでだろう〜と考えて半日ぐらいかかったので解決方法を共有します!

 

本記事のテーマ

「背景の色が開発環境(黒、Linux)と実機(白、IPad[IOS])で異なる問題解決」

 

動作環境

  • 開発:Ubuntu20.04
  • 実機:IPad

不具合解析

解析結果

下記画像のUbuntuの背景設定(メインカメラのBackground)でアルファ値(A)を0にして透明にしてしまっていた。

f:id:hiro-htm877:20211210201434p:plain



IPadとの比較のためにAndroidでもアプリをビルドして確認していたのですがAndroidでは背景が黒になっていました。

ですので、どうやら背景を透明にした場合Linux、Androidでは黒、IPadでは白になるようです。

この結果は個人的にとても興味深かく、Linux, AndroidとIPadではViewレイヤーなどの作り方が違っていて背景を透明化することでデフォルトの色が出てきているのかなぁーと想像しました。

 

最後に

Linuxの上にAndriodが作られているのでViewの構造などは同じになっている確率が高く感じます。そういった観点でも上記の考察を捉えることができるので個人的に面白い発見となる課題解決になりました!

皆さんの興味深かった不具合などありましたらコメント欄で共有いただけますと嬉しいです。

【Unity】外部コントローラの入力キーが異なる問題解決「開発環境(Linux)と実機(IPad, IOS)」

 

外部コントローラのキー入力を使う際、開発環境(Linux)では上手くいくのに実機(IPad, IOS)では上手くいかなかったのでその時の解決方法をもとに説明していきます!

 

本記事のテーマ

「外部コントローラの入力キーが異なる問題解決「開発環境(Linux)と実機(IPad, IOS)」」

 

動作環境

・開発環境

Ubuntu20.04

Unity

・実機

IPad

・使用コントローラ

dualshock 4(PS4のコントローラ)

 

解決方法

結論から申し上げますと、無料Assets「Controller Tester」を使うだけです。

assetstore.unity.com

 

使い方は簡単で新しいUnityプロジェクトにControllerTesterをImportしてビルドするだけです。

手順

まず、IPadでController Testerアプリを使うためにIOS用にビルド後、MacBookなどのXcodeが使える環境に作成したフォルダをコピーします。

その後、フォルダ内にある「Unity-iPhone.xcodeproj」ファイルをダブルクリックしてXcodeで開きます。

開いたら、Signing情報を設定した後ビルドして実機でアプリを立ち上げます。

Dualshock 4とIPadの繋ぎ方は真ん中下にあるPlayStationマークとSHAREボタンの長押しでコントローラが点滅するまで待ってください。

すると、IPadのBlueTooth設定画面にDualshockが出てきますのでタップするだけでつながります。

 

IPad内でのDualshock 4のキーコード対応表

実際にボタンとキーコードの対応関係をまとめましたのでよければお使いください。

f:id:hiro-htm877:20211210200817j:plain



最後に

IPadとコントローラをつなぐという経験は初めてだったので開発環境で動いていたものが実機で動かないという問題に気づくのが遅れました。

同じ問題で困っている人の助けになれば良いなと思います。

(自分もまた同じ問題にぶつかるかもしれないのでその時はこの記事を見返します笑)

ご質問等あれば下のコメント欄でおまちしております!

 

Controller Testerの画面

丸ボタンのキーコード

・UbuntuのUnityエミュレータ

キーコード:1

f:id:hiro-htm877:20211210200947j:plain

・IPadアプリ

キーコード:13

f:id:hiro-htm877:20211210201051j:plain

 

Tensor.kthvalueの動作概要

f:id:hiro-htm877:20211015130632p:plain

Tensor.kthvalueの使い方について公式のDocumentではよく分からなかったので自分で動作確認した結果をまとめる。

・公式ドキュメント

pytorch.org

 

本記事のテーマ

「Tensor.kthvalueの動作概要」

について実動作確認した結果をまとめる。

関数の説明

x.kthvalue(n, dim=1, keepdim=True)で動作確認をおこなった。

kthvalueはn番目に小さな値を抽出する関数です。

dimで選択した次元を探索します。

 

動作確認

動作確認した結果を紙にまとめました。

例として作ったTensorは

x: Tensor

x.shape: (2, 3, 6)

x[0]:

[[ 1,  2,   3,  1000,   5,   6]

 [  7,   8,   9,   10,  11,  12]

 [13, 14, 15, 16, 17, 1000]]

x[1]:

[[ 19,  20,  21,  22,  23,  24]

 [ 25,  26,  27,  28,  29,  30]

 [ 31,  32,  33,  34, 1000, 36]]

f:id:hiro-htm877:20211015124034p:plain

x.kthvalue(3, dim=1, keepdim=True)を実行すると、写真の左の図に記載されているように1次元目を縦に探索して3番めに小さい数字、1次元目のサイズは3なため、最も大きい数字を探索していることになる。(x[0次元目][1次元目][2次元目])

結果は3番めに小さい数字とその数字が格納されているIndexの配列をTupleとして出力してくれる。

torch.return_types.kthvalue(
values=tensor([  13.,   14.,   15., 1000.,   17., 1000.,
         31.,   32.,   33.,   34., 1000.,   36.]),
indices=tensor([2, 2, 2, 0, 2, 2,
        2, 2, 2, 2, 2, 2]))、

 

■indecesの見方

dimで1次元目を探索するようにしているため、x[1次元目]に当たるIndexの数字が出力される。

つまり、唯一0になっている箇所を確認すると、x[0][0][3]=1000で1次元目のIndexは0なので出力結果のindecesも0になる。他も同様に確認すると全て2になることが分かる。