複数カメラを使った人体運動計測

卒業論文でORB_SLAMを使った論文を書くことにしました。

卒論の内容

ORB_SLAMではカメラ映像からカメラの軌跡を求めることができます。それを使ってモーションキャプチャの代用にしようという内容で書きます。論文の内容を考えていたら、偶然同じような内容で論文を書いている人を発見してしまいました。
http://www.hcilab.jp/~kono/Paper/2016/int2017tai.pdf
卒業研究なので全く同じ研究にしてはいけませんが,まずは複数カメラを使ってSLAMができるか試してみます。

実験内容についてです。人体にスマホを複数台取り付けます。各スマホで同時に動画を撮影して、PCに全ての動画を入力してSLAMを行います。SLAMでは各カメラの姿勢と軌跡を計算して、一つの座標上に表示します。データの出力も行い、pythonを使ってグラフ化も行います。

カメラのキャリブレーション

まず撮影済みの動画で、キャリブレーションファイルを作成します。一分間ほどキャリブレーション用の画像を撮影した動画を用意します。次に撮影済みの動画をROS上でトピックに配信するために以下のパッケージを入れます。

$ sudo apt install ros-kinetic-video-stream-opencv

video-stream-opencvを使って動画をトピックに配信するlaunchファイルを作成します。以下のようなlaunchファイル(videoFile_publish.launch)を作成しました。

<?xml version="1.0"?>
<launch>
   <!-- launch video stream -->
   <include file="$(find video_stream_opencv)/launch/camera.launch" > 
        <arg name="camera_name" value="camera" />
        <arg name="video_stream_provider" value="/home/robolab/ビデオ/iphone/videoName.MOV" />
	<arg name="set_camera_fps" value="30"/>
        <!-- set buffer queue size of frame capturing to -->
        <arg name="buffer_queue_size" value="1000" />
        <!-- throttling the querying of frames to -->
        <arg name="fps" value="30" />
        <arg name="frame_id" value="videofile_frame" />
        <arg name="flip_horizontal" value="false" />
        <arg name="flip_vertical" value="false" />
        <arg name="loop_videofile" value="false" />
        <arg name="visualize" value="false" />
   </include>
</launch>

以下のコマンドで撮影済みの動画をROSトピックに流すことができます。

roslaunch videoFile_publish.launch

あとは自分が過去に書いた以下の記事を参考にしてキャリブレーションを行ってください。以下の記事ではストリーム配信をROSトピックに流して行っていますが、そこが撮影済みの動画に置き換わっただけです。
sh090.hatenablog.com

ROSのcamera_calibrationから出力されたファイルを開いて、元からあるキャリブレーションファイル(~/ORB_SLAM3/Examples/Monocular/TUM1.yaml)を元に新しいキャリブレーションファイルを作成します。

以下がiPhoneXで作成したキャリブレーションファイル(iphone_recordVideo_calib.yaml)の前半部を抜粋した内容です。

%YAML:1.0

#-------------------------------------------
# Camera Parameters. Adjust them!
#------------------------------------------
Camera.type: "PinHole"
# Camera calibration and distortion parameters (OpenCV) 
Camera.fx: 1828.896286
Camera.fy: 1828.370849
Camera.cx: 1002.453202
Camera.cy: 502.978252

Camera.k1: 0.192628
Camera.k2: -0.418260
Camera.p1: -0.004371
Camera.p2: 0.014453
Camera.k3: 0.000000

# Camera frames per second 
Camera.fps: 30.0

# Color order of the images (0: BGR, 1: RGB. It is ignored if images are grayscale)
Camera.RGB: 1

# Camera resolution
Camera.width: 1920
Camera.height: 1080

映像の結合

ORB_SLAM2では、1つ目の映像を流し終わった後、2つ目の映像を流す操作を行えば再び処理してくれました。しかしORB_SLAM3の方では1つ目を流し終わり、その後2つ目の映像を流す処理を行ってもフリーズしたままです。ORB_SLAM3の方が精度が高いので、解決策を考え、二つの映像を結合して一つの映像とすれば処理してくれました。映像の切り替わりの際に自己位置はロストしますが、しばらくして復帰してくれます。
以下の内容でvideo_mergeList.txtというファイルを作り、

file 'video1.AVI'
file 'video2.AVI'

このコマンドで二つの映像を結合しました。

$ ffmpeg -f concat -i video_mergeList.txt -c copy output.AVI

iPhoneで撮影した動画をORB_SLAMに入力

作成したキャリブレーションファイルを指定してORB_SLAMを起動させ、以下のようにroslaunchで動画を流せばSLAMが行えます。

マップの統合について

ORB_SLAMでは、カメラの軌跡とマップポイント(特徴点を三次元上に配置したもの)などを一つの座表上に表し、それをマップといいます。以下の動画は研究室内で映像の撮影をしてSLAMを行ったものです。同時刻に撮影したものではありませんが、別で撮影した二つの映像をORB_SLAMに入力しています。自己位置を失うたびに新しいマップが作成されます。各マップの中に共通の特徴点が見つかれば、マップの統合が行われます。共通の特徴点を作るために、入力した映像ではどちらも最後に自分の机の上を細かく撮影しました。
youtu.be

実験では撮影済みの動画を使ってSLAMを行います。その代わり動画をスロー再生で入力でき、ゆっくり処理を行うため自己位置をロストしにくくなります。

マップ(座標)統合前と統合後の画像です。二つの軌跡が同じ座標で同じスケールに調整されます。

f:id:shibuya_shogo:20201010144709p:plainf:id:shibuya_shogo:20201010144702p:plain

ちなみにVB5500Proという中国製の格安スマホで撮影した映像だとすぐに自己位置をロストしてしまいました。屋外でも屋内でも撮影して試しましたが、うまくいきません。フレームレートが低いのと解像度が低いのが原因かと思います。フレームレートは機器に依存するので上げられませんが、VB5500Proの場合25fpsとなっていました。iPhone Xでは60fpsの動画が撮影できます。あと、2013年発売のiPhone5s以降ではスローモーション撮影が可能で240fpsで撮影が行えます。

二つのiPhoneでSLAM(世代の異なるiPhone)

上記の検証は、同じ一台のiPhoneXを用いて入力動画を撮影しました。今度は二台のiPhone(iPhoneX,iPhone8)を使って検証を行います。同じ世代のiPhoneを用意したかったのですが、この時はありませんでした。iPhoneXとiPhone8を使って2つの入力映像を用意します。そのまま2つの映像を結合しようとすると、うまく行きませんでした。どうやら映像ファイルの音声が原因のようで、以下のコマンドで音声を削除しました。

ffmpeg -i iphoneX_video.MOV -vcodec copy -an iphoneX_video_silent.MOV
ffmpeg -i iphone8_video.MOV -vcodec copy -an iphone8_video_silent.MOV

その後ffmpegを使えば2つの映像を結合できました。結合された映像を使ってSLAMを試します。左が通常撮影、右がスロー撮影したときの結果です。通常撮影もスロー撮影も、撮影時には大体同じ内容のカメラ映像となるようにしました。

f:id:shibuya_shogo:20201020174738p:plainf:id:shibuya_shogo:20201020174742p:plain
通常撮影での結果は軌跡が乱れています。スロー撮影では綺麗に軌跡が撮れました。スロー撮影は240fpsで撮影して、入力する際には30fpsで入力しています。なので8倍スローでSLAMを行いました。


あとは論文に書きます。