😇

オナ○ールの動きに連動して音声を再生するPoCアプリの開発

6 min read

意義

近年、オナ○ールの商品数が増えており、また、人を超えるレベルのオナホールが次々開発されている。例えば、@cyberiguanaさんが開発したエ○オ○ホは、名器であると言われるエイの○の構造を真似て作られたオナ○ールであり、Twitter上で大きく話題になった。今後もこのような高度なオナホールが開発され、人々のSX(Sexual Experience)は向上していくと予想される。

一方、オナホールとVR、AR、CG技術を連携させたような事例は少ない。豊富な動画コンテンツ、AR、VR単体でも、SXが高いものが非常に多いことから、こういったコンテンツとオナホールをうまく組み合わせる方法を考えることで、SXの劇的な改善ができると想像できる。そのため、こういった技術領域における研究や技術開発は非常に重要であると私は考える。

本稿では、そのような技術開発の一環として、現在開発中のオナホールコントローラーとPoC検証のために開発した音声再生アプリの技術の説明をする。

(大雑把な説明は、発表スライドをご参照ください。
この発表スライドは、YoutubeとIBMのText To SpeechAPIを使って作りました。
別途メモを書きましたので、そちらをご参照ください。)

音声連動アプリ

この動画をご覧ください。(あえぎ声が再生されるので再生環境にはご注意ください)

https://www.youtube.com/watch?v=7gKmur7Lx-w

今回開発したPoCアプリは、このようにおなほを前後に動かす運動を検知すると、あえぎ声が再生されるという仕様になっています。

システムの構成と処理フロー

このシステムで必要なものは、オナホール、デプスカメラ(現在はRealsenseのデプスカメラのみに対応)、スマホホルダー、
(と、現段階では、GPUを搭載したPCが必要)です。
スマホホルダーに画像のようにデプスカメラをつなげて、スマホホルダーを首に掛けることで、
おなほーるを写せるいい位置にデプスカメラを固定できます。

処理の流れを説明します。カメラ入力の各フレーム対して、

  1. 2D物体検出をかけて、2D BoundingBoxを計算する
  2. 2D BoundingBoxと点群を入力として、3D BoundingBoxを計算する
  3. 3D BoundingBoxの重心の動きを解析して前後運動を検知
  4. 音声を再生する

という処理を行います。
それぞれの処理を説明します。

使ったライブラリ

  • 2D物体検出
    • mmdetection
    • Object Dataset Tools
  • 点群処理
    • open3d
    • cupoch
  • モーション解析
    • scikit-spatial

2D物体検出

2D物体検出

yolactというInstance Segmentationのモデルを使って、画像上における二次元の物体位置と大きさを求めています。yolactを選んだ理由は、

  • そこそこリアルタイム(モデルそのままでRTX 3070で約25ms)で動く
  • そこそこ性能がいい。

からです。

学習データセットは、3種類のオナホを用いて様々な照明環境、サイズ、方向に対して、約1万枚の画像を用意しました。
学習には、公式のyolactモデルではなく、mmdetectionというライブラリを用いました。

データセット構築 & 学習

データセット構築にはSLAMを活用しました。SLAMを使うことで一気に数千枚のラベル付き画像が集まるからです。

具体的には、Open3Dの3D復元と、Object Dataset Toolsをマーカーベースの3D復元を使いました。

データセット構築の流れは次の通りです。

まずは、AruCoマーカーを用意します。そして、そのAruCoマーカーで対象の物体を囲って、撮影ツールにてRealsense D435iを使って物体を撮影します。

その撮影したデータを使い、SLAMの手法を用いて次のような3D空間を復元します。

この空間から、ツールが自動的に、マーカーの位置を手がかりに、対象の物体を特定します。

その物体の形状を用いて、マスクと2DBoundingBoxのラベルを生成します。下記画像は、生成したデータをCoco Viewerで可視化したものです。

これをmmdetectionに食わせて1日くらい学習させたところ、
そこそこ使える2D物体検出器ができました。

End to Endの3D Detectionでなく、2D物体検出を活用する理由

最近は、ディープラーニングベースの3DDBoundingBoxの検出手法がちらほら出てきており、点群、RGB、RGBD画像から、3D BoundingBoxの形と姿勢を検出する手法などがあります。

ただ、現時点では、少人数プロジェクトや個人で精度の高い3D BoundingBox検出器を作るのは難しいと感じます。
その理由として、ラベリングツールが豊富でなく、
十分にデータセットが集めるのが難しいこと、
また、2Dの物体検出と比べると、機械学習のモデルのほうが枯れていないことが上げられます。
Googleの豊富なデータセットで学習したObjectronすら、すごい性能!とは言えないレベルです。

試しに学習してみた結果ですが、Boxが大きい、動画の角度意外の方向だと全く動かない。という欠点があります。

そこで、個人開発者としては、ある程度枯れた技術である、2D物体検出やSemantic Segmentationと、古典的な点群処理を組み合わせることで、ある程度3Dの物体検出を達成するという方法が、そこそこ楽に、そこそこ性能が出ていいのではないかと私は思います。

点群処理

ここは単純で、次のような処理をしています。(この処理は約15msで動きます)
このあたりの処理はOpen3DとCupochというライブラリを組み合わせて実現しています。それぞれ、いいところがあるライブラリです。これらのライブラリの使い方は、点群処理ライブラリOpen3Dと爆速ロボティクスライブラリcupochの記事にまとめています。

  1. ダウンサンプリング
  2. 2D BoundingBoxによるフィルタリング
  3. 点群のクラスタリング & BoundingBoxの生成
  4. 三次元トラッキング

1は点群を荒くしてリアルタイムで動くようにするための処理で、
3D BoundingBox検出の正確さが落ちない範囲で下げました。

2はすべての三次元点を投資投影行列により、二次元画像上に投影して、点が2D BoundingBox内の点のみフィルタする処理です。
この処理を入れることで、手やオナホに入っている棒の点群から、オナホールの点群をうまく分離して、オナホの形状や位置を正確に計算することができます。

3の点群のクラスタリングはオナホの点群と背景にあるものを分離するための処理です。非常に思い処理で、Open3DのDBSCANというクラスタリングアルゴリズムではリアルタイムで動きませんでした。CupochのDBSCANアルゴリズムはGPUを活用したアルゴリズムで爆速で動くので、そちらを使いました。
点群からBoundingBoxを作る方法はOpen3Dに用意されています。内部的には、PCAで主軸を求めて、それを長辺として、あとは適当にボックスを作っているようです。

4に関しては、トラッキングと書いていますが、オナホが検出できない場合に、前フレームから現在の位置を等速運動をしていると仮定して現在位置を予測する処理が入っています。これが入っていることで、少しだけ、モーション解析の精度が上がります。KalmanFilterも試しましたが、オナホの前後運動をうまくモデル化できずに、少しイマイチでした。

モーション解析

モーション解析は次のような処理でやっています。
まず、オナホールの使用時は、ある軸に沿って前後運動をしていると仮定します。
挿入する棒は線に近似できるはずなので、その仮定は、ある程度は正しいはずです。

その仮定の上に次のようなアルゴリズムを作りました。

  1. オナホールの前後運動の軸を求めます。(時間によって軸が変わるので、最近の2秒分の位置変化を使っています)
  2. その軸に沿った動きを計算して、オナホが棒を飲み込んだ瞬間っぽいところで音声を再生

1に関しては、2秒間の位置を保存しておいて、直線にフィッティングすることでやっています。
直線フィッティングは最小二乗法などで解けますが、なんと、scikit-spatialというライブラリを使えば、簡単に計算できます!

ここで求めた軸をもとに、おなホールを前後に動かした時の位置と速度の時系列のグラフは次のようになります。
(それぞれ、別の動きから取りました)見ると、いい感じに前後運動が見えるのがわかります。

2に関して、試したアルゴリズムは2つで、

A. 挿入方向の速度があるしきい値以上になったあとに、速度ゼロになった状態を挿入状態として推定するアルゴリズムと
B. あるウィンドウ幅の最大最小振幅を撮って、最小の位置付近に移動した状態を挿入状態として推定するアルゴリズム

の2つを試しました。Aのやり方を図解しますが、
このように速度の方向が逆になる瞬間には速度がゼロに近くなるはずで、このタイミングを挿入完了と推定します。

動画はAのアルゴリズムを使っていて、かなりいいタイミングで音がなるようになっているのがわかります。
Bの方法だと、パラメータの調整が難しく、いい感じに音がなりませんでした。

Conclusion

めっちゃ楽しい。