フォトグラメトリアプリを試してみた(Metacan・RoomPlanなど)

こんにちは、XR開発者の長谷川です。今回は複数のフォトグラメトリアプリを試して比べてみました。

1. フォトグラメトリとは

フォトグラメトリ(photogrammetry)とは、建物や物体などを様々な角度から撮影し、その写真から3DCGモデルを作成する手法です。これまでは高価な専門ソフトウェアや撮影機器が必要でしたが、近年スマホで手軽に撮影してアプリを通してモデルを作れるようになりました。2021年にはAppleMacのMonterey(macOS 12)で使えるAPI・Object Captureを発表して話題になりました。

フォトグラメトリで何ができるか
フォトグラメトリは工学や地形測量、映画作成、スポーツトレーニングなどの場面で活用されてきましたが、最近はフォトグラメトリで作成した3DモデルをUnityに読み込ませ、XRサービス上に登場させるといった使い方があります。 例えば、家具の3Dを作成してARでインテリアの配置イメージを表示する、観光地のモデルを使ってバーチャルツアーを行うなどです。

2. アプリ・APIの紹介・結果

これから紹介するアプリ・APIのテスト結果モデルはSketchfabで公開しています(Polycam・RoomPlanモデルを除く)。

sketchfab.com

今回のテストは以下の被写体・方法を使って行いました。

被写体

ラスカルのぬいぐるみ・部屋(RoomPlan)

方法

iOSアプリ・RoomPlan:アプリ内でLiDAR撮影または静止画撮影 Object Capture:スマホで撮影した静止画を読み込み

2.1. Polycam

公式サイト poly.cam

こちらのアプリはモデルをエクスポートするのに有料バージョンへのアップグレードが必要です(アプリ内で見るのは無料)。

結果

LiDAR使用で少しラスカルの輪郭が粗い気もしますがどちらもかなりの精度で立体化できました。

Polycam 左:LiDAR 右:画像

2.2. Metascan

公式サイト metascan.ai

無料版ではUSDZ形式でのみモデルのエクスポートが可能です。

結果

LiDAR使用(左)ではモデルの輪郭がかなり粗くカクカクになってしまいましたが、写真使用(右)ではラスカルが立体的に再現されました。

Metascan 左:LiDAR 右:画像

2.3. WIDAR

公式サイト widar.io

完全無料のアプリです。作成したモデルはOBJやFBX、glTF、USDZなど複数の形式でエクスポートできます。

結果

Metascanと同様、LiDAR使用(左)ではモデルがカクカクになってしまいました。画像使用(右)は綺麗に再現できているように見えます。

WIDAR 左:LiDAR 右:画像

2.4. Qlone

公式サイト www.qlone.pro

Qloneは無料版では下にQloneシート(アプリから印刷可能)を敷かなければなりません。

結果

プロセスが終わらず結果が出ませんでした…

2.5. Scaniverse

公式サイト scaniverse.com

ScaniverseはLiDAR使用でしかモデルを作成できません。

こちらも完全無料アプリで、FBXやUSDZなど複数形式でエクスポートできます。

結果

Metascan・WIDARのLiDAR使用モデルよりかなり綺麗にモデルが作成できました。

Scaniverse(LiDAR使用)

2.6. Object Capture

公式サイト

developer.apple.com

Appleが提供しているMonterey(macOS 12)のAPIです。Object Captureを使うにはMacでOSがMontereyにアップデートされていることとCPUがM1であるまたはIntelの場合はAMD GPUを積んでいることが必要です。こちらも無料で使用でき、サンプルコードが公開されています。

使用環境

結果

Object Capture

綺麗に形が捉えられています。ラスカルの後ろ側は本来黄色なのですが白っぽくなってしまいました。

2.7. RoomPlan

公式サイト

developer.apple.com

LiDARスキャナー付きのiPhoneiPadを使って部屋の中をスキャンすることで部屋の3Dモデルが作れるフレームワークです。Macでコードをビルドし、iPhoneiPadでビルドしたアプリを開くことで使用できます。こちらも無料で使用でき、サンプルコードが公開されています。

使用環境

使用した部屋の間取り図

部屋間取り図

結果

RoomPlan

窓際のソファーなど一部捉えられていない家具がありますが、部屋の形は概ね正しく認識できました。

3. まとめ

アプリ 形を捉えられているか 輪郭の綺麗さ 手軽さ 処理速度 無料版の使い勝手
Polycam(LiDAR)
Metascan(LiDAR)
WIDAR(LiDAR) ◎ (完全無料)
Qlone N/A N/A N/A
Scaniverse(LiDAR) ◎ (完全無料)
Polycam(画像)
Metascan(画像)
WIDAR(画像) ◎ (完全無料)
Object Capture ◎ (完全無料)
RoomPlan N/A N/A ◎ (完全無料)

LiDAR使用ではローカル、画像使用ではクラウドで処理をしているせいか、全体的にLiDARはモデルの輪郭がカクカクになりがちなのに対して画像からのモデル生成では綺麗に立体化できているケースが多かったです。

Qlone以外のiOSアプリはiPhoneで撮影するだけなので手軽でしたが、Qloneは別途シートを印刷する手間がかかります。Object Capture・RoomPlanはMacが必要な上ハードウェア・ソフトウェアの要件があるので準備に時間が掛かりました。処理速度はiOSアプリについてはクラウド処理に時間がかかる写真からのモデル作成よりもローカル処理できるLiDARのほうが早くモデルが完成しました。Object Captureはサンプルコードを実行してモデルを作成するのにかなり時間が掛かった一方、RoomPlanはサンプルコードのビルドに時間がかからない上にビルドしたアプリでのモデル作成はスキャンと同時にリアルタイムでできました。

結論:現時点では完全無料でLiDARスキャンと画像両方からモデルを作成できてエクスポート形式も多いWIDARが一番有用だと思います。

SpeechBrainを使った話者分離の性能検証 ~SepFormerを用いて~

こんにちは。音声認識の研究をしている石井です。

今回は、SpeechBrainを使った話者分離モデルの中でも、2020年に発表されたSepFormer *1についてその性能を検証しました。 評価は訓練済みモデルに対してYouTubeから入手した音源を用いて行いました。 結果、一部の音源に対して上手く複数の人声を分離できたことはありましたが、多くの場合で複数人の声が入ったり、ノイズが残ったりするなどして、残念ながらあまり高い効果は見られませんでした。

SpeechBrainとは

SpeechBrainはPyTorchを用いた最先端の音声ツールキットで、オープンソースで開発が進められています。 SpeechBrainが課題とする技術は今回用いた話者分離に限らず、音声認識・話者認識・音声強調・言語特定など幅広い分野に渡り、そういった課題に対して既にいくつかのシステムで高いパフォーマンスを発揮しています。

研究のモチベーション

話者分離システムを研究する目的としては、日常の会議の録音などを分離してから文字起こしをすることで、いちいち音声を再生して発言者の声を確認しなくとも、誰がこの発言をしたのか容易に特定できるようになる、ということが挙げられます。さらに開発側の観点では、分離後の音声データを他の学習のためのデータセットに用いることで、音声認識等の技術でより精度の高いモデル獲得につながる可能性があります。

論文の紹介

今回モデル評価の対象とした SepFormer は Subakan, Ravanelli, et al. (2020) によって示されました。 SepFormerは従来の音声分離ネットワークと比べて、回帰型ニューラルネットワーク (RNN)を用いておらず、代わりにTransformerを基にすることで並行処理をより容易にし、計算時間の短縮を図っているという特徴があります。 Transformerを提示したVaswani, Shazeer, et al. (2017) *2では機械翻訳での性能を検証していました。今回の論文ではそれを音声分離で効果測定しています。

ここで用いられたモデルは、学習された重み付け関数(マスク)をベースとし、エンコーダ、デコーダ、マスキングネットワークから構成されています (Fig. 1)。

まず、エンコーダは複数音声が入った音源をとり、1層の畳み込みレイヤを用いて短時間フーリエ変換の表現を学習します。 次に、マスキングネットワークはエンコードされた表現をとり、分離されるべきそれぞれのスピーカに対して重みを予測します (Fig. 2)。

最後に、デコーダは重み調整済みソースを畳み込みレイヤの変換行列にかけて、それぞれ分離された音声を出力します。

論文での検証結果は、WSJ0-2mixデータセットでSI-SNRi (scale-invariant signal-to-noise ratio improvement)が22.3 dB、WSJ0-3mixデータセットで19.5 dBとなったとのことです。

ここで、SI-SNRは以下のように定義されます *3

\displaystyle{
\begin{align}
\left\{
\begin{array}{ll}
&s_{target} := \frac{\langle\hat{s}, s\rangle s}{\|s\|^2} &\\
&e_{noise} := \hat{s}-s_{target} &\\
&SI\text{-}SNR := 10\log_{10} \frac{\|s_{target}\|^2}{\|e_{noise}\|^2} &
\end{array}
\right.
\end{align}
}

ここで、

  • \displaystyle{ \hat{s}\in\mathbb R^ {1 \times T} }: 予測クリーンソース (正規化する)
  • \displaystyle{ s\in\mathbb R^ {1 \times T} }: オリジナルクリーンソース(平均を0となるように移動)
  • \displaystyle{ |s|^ 2=\langle s, s\rangle }: シグナルの力
  •  T: 分類予測するソースの数

この結果はDPRNNやDPTNetを用いたものに比べ優れており、さらに計算時間やメモリ利用量の点でも勝っています (Fig. 3; WSJ0-3mixで他のモデルと比較した場合でも同様の傾向)。 これは、著者によると、Transformerによる並列演算だけでなく、畳み込みレイヤのストライドを8とすることでモデルの計算量を減らすことに成功しているからだといいます。

検証手法

SepFormerの追加検証はGoogle Colab上で、YouTubeから入手した音源を用いて行いました。SpeechBrainのチュートリアルも参照 *4

まず、 SpeechBrainをインストール:

pip install speechbrain

そして、以下で訓練済みのWSJ0-2/3mixのモデルを用い、実際に用意した音源を分離します。 ここで、model2/3はそれぞれWSJ0-2/3mixのモデルを用い、音源を2/3分割。 関数split2/3で分離したい音源を取って分離後の音声ファイルを保存。 関数play_split2/3Google Colab上で分離前後のファイルをIPython.displayで簡単に確認するためのものです。

import speechbrain as sb
from speechbrain.pretrained import SepformerSeparation as separator
import torchaudio
import os
import IPython

# Use a pretrained model for SepFormer on WSJ0-2Mix
model2 = separator.from_hparams(source="speechbrain/sepformer-wsj02mix", savedir='pretrained_models/sepformer-wsj02mix')
# Use a pretrained model for SepFormer on WSJ0-3Mix
model3 = separator.from_hparams(source="speechbrain/sepformer-wsj03mix", savedir='pretrained_models/sepformer-wsj03mix')

def split2(PATH):
    est_sources = model2.separate_file(path=PATH)
    root, ext = os.path.splitext(PATH)
    torchaudio.save(root + '_1of2' + ext, est_sources[:, :, 0].detach().cpu(), 8000)
    torchaudio.save(root + '_2of2' + ext, est_sources[:, :, 1].detach().cpu(), 8000)

def play_split2(PATHtoSource):
    print("Source: ", PATHtoSource)
    IPython.display.display(IPython.display.Audio(PATHtoSource))

    root, ext = os.path.splitext(PATHtoSource)
    print("1st split: " + root + "_1of2" + ext)
    IPython.display.display(IPython.display.Audio(root + '_1of2' + ext))
    print("2nd split: " + root + "_2of2" + ext)
    IPython.display.display(IPython.display.Audio(root + '_2of2' + ext))

def split3(PATH):
    est_sources = model3.separate_file(path=PATH)
    root, ext = os.path.splitext(PATH)
    torchaudio.save(root + '_1of3' + ext, est_sources[:, :, 0].detach().cpu(), 8000)
    torchaudio.save(root + '_2of3' + ext, est_sources[:, :, 1].detach().cpu(), 8000)
    torchaudio.save(root + '_3of3' + ext, est_sources[:, :, 2].detach().cpu(), 8000)

def play_split3(PATHtoSource):
    print("Source:", PATHtoSource)
    IPython.display.display(IPython.display.Audio(PATHtoSource))

    root, ext = os.path.splitext(PATHtoSource)
    print("1st split: " + root + "_1of3" + ext)
    IPython.display.display(IPython.display.Audio(root + '_1of3' + ext))
    print("2nd split: " + root + "_2of3" + ext)
    IPython.display.display(IPython.display.Audio(root + '_2of3' + ext))
    print("3rd split: " + root + "_3of3" + ext)
    IPython.display.display(IPython.display.Audio(root + '_3of3' + ext))

なお、作業をGoogle Colab上で完結させるため、音源はyoutube-dlを用いてダウンロードし、検証に使う範囲をffmpegで切り取って用いました *5 *6

# youtube-dlをインストール
!curl -L https://yt-dl.org/downloads/latest/youtube-dl -o /usr/local/bin/youtube-dl
!chmod a+rx /usr/local/bin/youtube-dl

!youtube-dl --extract-audio --audio-format mp3 https://www.youtube.com/watch?v=URL_for_the_source_video -o /path/to/audio_source_original.mp3
!ffmpeg -i audio_source_original.mp3 -ss <開始時間> -to <終了時間> audio_source_cut.mp3

音源の用意ができた後、model2を用いて2分割しIPython.displayで結果を確認します (3分割も同様)。

PATH = "/path/to/audio_source_cut.mp3"
split2(PATH)
play_split2(PATH)

検証結果

合計9つの動画から音源を入手し2/3分割しました。 このうち3つの音源である程度満足できる結果が得られた一方、その他の音源では複数の声を拾ったり、雑音しか残っていなかったりなどあまりうまくいきませんでした。 ここでは一部の音源に対して参照のためのYouTube動画を提示し、実験結果を文章で説明します。 また、無料版Google Colab上での分離処理にかかった時間は20秒前後の音源で約50秒、1分前後の音源で3分強ほどだった。

音源1 (全範囲)

テレビ東京のニュース番組WBSから。 効果音 → 田中アナ(女性) → 全日空社長(男性)VTR → 田中アナ、の順。

このまま2分割すると、1つ目のファイルでは効果音とVTR後の田中アナの声が、2つ目のファイルでは元の音源にノイズが入っただけのような印象で、あまりうまくいかなかった。

効果音、田中アナ、全日空社長で3分割できるかと思いmodel3を試すと、1つ目は全日空社長だけ上手く拾い、2つ目は田中アナメインだが全日空社長の声も少し残る、3つ目は始めの効果音だけはっきり、残りはノイズっぽくなった。これはそれなりに上手く言った印象。

一方ではじめの効果音の2秒間をカットし、残りの部分で2分割すると、全日空社長のVTR前後で分けられているように思われた。

音源2 (0:5:50 - 0:6:15)

若い男性3人の対談。3分割してみたが、やはり声質が似ているからか同じファイルが3つ出来上がったのではと思うほど分けられていなかった。

音源3 (0:0:07 - 0:0:25)

気象予報番組で女性キャスター、男性予報士、BGMの構成。2分割したところ1つ目で男性とBGMを、2つ目は女性のみをおよそ綺麗に分けられた。

音源4 (0:1:00 - 0:1:20)

テレビ番組で女優のEmma Watsonと男性MC (Jimmy Fallon)との対談。2分割した結果そこそこ上手く1人ずつ分けられた。

音源5 (0:1:30 - 0:2:32)

男女それぞれ2人ずつの議論。2・3分割ともに上手くいかず、いずれのファイルにも全員の声が入ってしまった。

音源6 (0:0:40 - 0:1:02)

こちらは男性2人+女性1人の議論。3分割したところ、1つ目のファイルは男性2人の声を拾い、2つ目は3人の声、3つ目は女性のみ拾おうとしている傾向が見られたが、全体的にノイズっぽくなってしまった。

音源7 (0:1:17 - 0:2:30)

女性2人+男性司会者の議論。3分割するもほぼ全員の声が3つすべてのファイルに入ってしまった。

手元で実験した限りでは、音源の言語が日本語か英語であるかは分離精度にあまり関係がないように思われます。 また、2人の音源の一部で上手くいっていたのに対し、3人以上ではほとんど上手く分離できなかったことを鑑みると、人数が増えるごとに分離するのが難しくなる傾向があるのかもしれません。

今後の課題

より様々な条件で、実験で用いたモデルがどのような反応を示すか試したいです。 例えば、通訳を介した複数の言語が入った音源や発話者の性別、BGM・ノイズの有無はどれほど分離精度に影響するのでしょうか...?

さらに、音声分離後の用途(音声認識、文字起こし、...?)などから、どれくらいのモデル精度が必要なのかもはっきりわかればよさそうです。 また、SepFormerと他の音声分離モデルとを比較することで、より精度・計算コスト的に有利な方法も導き出せるとよいのではないでしょうか。

*1:Subakan, C., Ravanelli, M., Cornell, S., Bronzi, M., & Zhong, J. (2020). Attention is All You Need in Speech Separation. https://doi.org/10.48550/ARXIV.2010.13154

*2:Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., Kaiser, L., & Polosukhin, I. (2017). Attention Is All You Need. https://doi.org/10.48550/ARXIV.1706.03762

*3:Luo, Y., & Mesgarani, N. (2019). Conv-TasNet: Surpassing Ideal TimeFrequency Magnitude Masking for Speech Separation. IEEE/ACM Transactions on Audio, Speech, and Language Processing, 27(8), 1256-1266. https://doi.org/10.1109/taslp.2019.2915167

*4:https://huggingface.co/speechbrain/sepformer-wsj02mix

*5:https://github.com/ytdl-org/youtube-dl

*6:https://qiita.com/yang_orz/items/4f19e88a456e56aadc55