複数カメラを使った人体運動計測
卒業論文で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
マップの統合について
ORB_SLAMでは、カメラの軌跡とマップポイント(特徴点を三次元上に配置したもの)などを一つの座表上に表し、それをマップといいます。以下の動画は研究室内で映像の撮影をしてSLAMを行ったものです。同時刻に撮影したものではありませんが、別で撮影した二つの映像をORB_SLAMに入力しています。自己位置を失うたびに新しいマップが作成されます。各マップの中に共通の特徴点が見つかれば、マップの統合が行われます。共通の特徴点を作るために、入力した映像ではどちらも最後に自分の机の上を細かく撮影しました。
youtu.be
実験では撮影済みの動画を使ってSLAMを行います。その代わり動画をスロー再生で入力でき、ゆっくり処理を行うため自己位置をロストしにくくなります。
マップ(座標)統合前と統合後の画像です。二つの軌跡が同じ座標で同じスケールに調整されます。
ちなみに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を試します。左が通常撮影、右がスロー撮影したときの結果です。通常撮影もスロー撮影も、撮影時には大体同じ内容のカメラ映像となるようにしました。
あとは論文に書きます。