mapillary_toolsで360度動画をアップロードする

[Mapillary](http://www.mapillary.com/)というユーザーによる写真投稿によってストリートビューを提供するWebサービスがあります。2014年に360度カメラに対応し、より鮮明なWEB歩きが可能となりました。また、MapillaryはCC BY-SA 4.0の元に利用でき、OpenStreetMapなどのサービスにも利用されています。

本来はMapillaryアプリなどで撮影した画像形式でのアップロードとなるのですが、[Mapillary legacy web](https://legacy.mapillary.com/map/login)と後述する[mapillary_tools](https://github.com/mapillary/mapillary_tools)を利用すると動画で撮影したデータを静止画に変換し、アップロード可能です。

しかしながら、Mapillary legacy webは公式からサポート終了が通告されています。2019年11月執筆時では未だ動いていますが、不安定な環境に依存するのも問題がありますのでここではMapillary_toolsを使ったアップロード方法を記載していきます。
#環境
* Windows10
* [RICHO THETA Z1](https://theta360.com/ja/about/theta/z1.html)
* mapillary_tools 0.5.0
* [ffmpeg 4.2.1](https://www.ffmpeg.org/)
* [Python 2.7.15](https://www.python.org/downloads/windows/)
* [Git 2.21.0](https://git-scm.com/)
* [Strava](https://www.strava.com/?hl=ja-jp)

#撮影方法
###用意するもの
* スマートフォン（筆者はiPhone７）
* GPXデータを使えるスマホアプリ（筆者はStravaのアプリを使用しました）
* THETAのスマホアプリ
* THETAのカメラ（筆者はRICOH THETA Z１）
* カメラを自転車に固定する自撮り棒
* 自転車にスマホを固定する用のホルダー
* （人によっては）自撮り棒固定用のガムテープやモバイルバッテリー

![fff.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307125/df015414-8cdb-902b-75e1-b46e608ff8a0.jpeg)

これと上記のものを用意し、カメラを自転車に固定できれば撮影準備は万端です。自撮り棒の高さですが自治体のルールなどを各自確認して判断してください。

###撮影方法
1. カメラの側面にある電源ボタンを押して起動した後Wi-Fi接続でTHETAのカメラとスマホを接続します。
1. 接続後アプリを開いて撮影モードにしてカメラの映像が画面に映っていれば成功です。今回は動画撮影なので動画モードを使います。
1. 次にGPXアプリ（Strava）を起動し記録をつけていきます。
1. その後すぐにTHETAのアプリに戻り撮影開始ボタンを押して周りに気を付け撮影開始です。
1. 撮影終了する時は撮影終了ボタンを押してからStravaの測定を完了させます。これで撮影は終了です。

#注意点
mapillary_toolsにはexe版とpip版が存在します。本来ならばexe版を使用した方がpythonの準備や各種ライブラリのインストールなど、環境構築が不要で便利なのですが後述する***UnicodeDecodeError***により、処理を実行できません。よって今回はpip版を使用してのアップロードとなります。

詳しくは[Pythonの文字コードを変更する](#pythonの文字コードを変更する)をご覧ください。

しかしながら環境構築の部分と、mapillary_toolsを呼び出すコマンド以外は共通しているためある程度は参考になると思います。

#インストール

### 基本環境構築
1. 今回はpip版を使用するのであらかじめPython2.7のインストールとPATHを通しておきます。以下のサイトを参考にしてください。
http://www5f.biglobe.ne.jp/~nobml/ninix/2_python.html
PATHの通し方はほぼWinのバージョンで変わりませんが、以下のサイトにWin10の通し方が載っていますので気になるようでしたら参考にして下さい（たたしバージョン違いに注意）
https://qiita.com/New_enpitsu_15/items/ee95bde0858e9f77acf0

1. 動画を画像化するためにffmpegのインストールとPATHが必要になります。以下のサイトを参考にしてください。
https://fukatsu.tech/windows-ffmpeg

1. 以降のライブラリをインストールするためにGitのインストールとPATHが必要です。以下のサイトを参考にして設定してください。
https://proengineer.internous.co.jp/content/columnfeature/6893


ここまでインストールとPATHがきちんと完了している場合、コマンドプロンプトで以下のコマンドを入力すると同じ結果が返ってくると思います。

```cmd
$ python
Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
```

※画面を閉じるか"exit()"で次のコマンドを入力できます。

```cmd
$ ffmpeg -version
ffmpeg version git-2019-10-26-1054752 Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 9.2.1 (GCC) 20191010
.
.
.
```

```cmd
$ git --version
git version 2.21.0.windows.1
```

ここまで完了したら、次は必須ライブラリのインストールを行います。

###必須ライブラリのインストール

分割した画像にexifを書き込むPiexifをインストールします。

```
$ pip install git+https://github.com/mapillary/Piexif
```

今回の目玉であるmapillary_toolsをインストールします。

```
$ pip install --upgrade git+https://github.com/mapillary/mapillary_tools
```

以上のインストールが完了できれば環境構築は完了です。お疲れさまでした。

#Pythonの文字コードを変更する

※注意
以下の内容は筆者がトライアンドエラーで確認したものであり、理論的な説明はできません。また、2019年11月執筆時には問題なく動いていますが、今後のアップデートで動かなくなる可能性もあります。あくまで可能報告の一つとして参考にしていただくと幸いです。

[注意点](#注意点)で前述しましたが、mapillary_toolsのexe版ではgpxファイルを使用した処理を行うとエラーを吐いてしまいます。その原因が***UnicodeDecodeError***であり、端的に説明すると「文字コードエラー」です。

```
Traceback (most recent call last):
  File "C:\python27\Scripts\mapillary_tools", line 76, in <module>
    command.run(args)
  File "C:\python27\lib\site-packages\mapillary_tools\commands\video_process_and_upload.py", line 163, in run
    **({k: v for k, v in vars_args.iteritems() if k in inspect.getargspec(process_geotag_properties).args}))
  File "C:\python27\lib\site-packages\mapillary_tools\process_geotag_properties.py", line 89, in process_geotag_properties
    verbose)
  File "C:\python27\lib\site-packages\mapillary_tools\processing.py", line 278, in geotag_from_gps_trace
    .format(now.strftime('%Y-%m-%d %H:%M:%S %Z')))
  File "C:\python27\lib\site-packages\dateutil\tz\_common.py", line 22, in adjust_encoding
    name = name.encode()
UnicodeDecodeError: 'ascii' codec can't decode byte 0x93 in position 0: ordinal not in range(128)
```

通常Pythonはデフォルトで文字コードをASCIIで処理しています。gpxファイルの文字コードは'utf-8'であるためこのままでは読み込むことができません。

聡明な読者の方は「ふーん？じゃあ文字コードをutf-8に変えればいいのね？」と思われるかもしれませんが、***違います。***

公式ReadMeでは'utf-8'を指定するように記載されていますが、utf-8では同じようにエラーが発生し処理ができません。このように、「文字コードはutf-8であっているはずなのに指定しても動かない」という現象は他の環境でも起きているようです。

https://qiita.com/tackey/items/5b7b2be23af60335fe11

結論から申し上げると「文字コードを'cp932'に変更したら動いた」とのこと。
それでは文字コードを変更していきましょう。

まず、\Python27\Lib\site-packagesにアクセスします。
![WS000055.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307125/eaeb1753-ec1a-3156-8f29-fc1893785204.jpeg)

以下のダウンローダーからsitecustomize.pyをダウンロードします。
https://ux.getuploader.com/Kouki_T/download/1

ダウンロードしたファイルを先ほど開いたディレクトリにコピーして完了です。


インタプリンタがパッケージされているexe版ではこの処理が行えません。pip版を使用する理由はこの一点にあるといっても過言ではありません。
#初回認証
さて、ここからは本格的にmapillary_toolsを使っていきます。まず最初に認証を完了しましょう。

```
$ C:\python27\python.exe C:\python27\Scripts\mapillary_tools authenticate --advanced
```

※この記事ではPythonとmapillary_toolsのPATHを使用せず、絶対指定でコマンドを入力しています。当環境ではMapiilary_toolsが上手くPATH指定できなかったためですが、もし無事PATHを通せていた場合は、C:\python27\python.exe C:\python27\Scripts\mapillary_toolsをPython mapillary_toolsと読み替えてください。また、インストールディレクトリを変更した場合も同様に指定パスを随時読み替えてください。

ユーザーネーム、メールアドレス、パスワードを入力し、認証を済ませます。

#アップロード
あらかじめ撮影した動画とgpxを別々にフォルダを用意し、格納しておきます。

今回は、
動画ファイル：C:\mply_video
gpxファイル: C:\mply_gpx
としました。

その後コマンドプロンプトで次のコマンドを入力します。

```
$ C:\python27\python.exe C:\python27\Scripts\mapillary_tools video_process_and_upload --advanced --user_name koukitest --geotag_source "gpx" --interpolate_directions --duplicate_distance 5 --duplicate_angle 40 --video_sample_interval 1 --overwrite_all_EXIF_tags --device_make "RICOH" --device_model "RICOH THETA Z1" --video_import_path "C:\mply_video/R0010724.MP4" --geotag_source_path "C:\mply_gpx/2844469305.gpx" --local_time --use_gps_start_time
```

|オプション名|説明|
|:-:|:-:|
|video_process_and_upload|動画を処理し、アップロードします。|
|--advanced|詳細なオプションを設定します。|
|--user_name|アップロードするユーザーを指定します。|
|--geotag_source|GPSデータの形式を指定します。|
|--interpolate_directions|方角を画像に書き込みます。|
|--duplicate_distance|重複と判断する距離（m）|
|--duplicate_angle|重複と判断する角度（度）|
|video_sample_interval|画像化するインターバルを指定します。（秒）|
|--overwrite_all_EXIF_tags|画像にexifを上書きします。|
|--device_make|撮影した機材のメーカーを書き込みます（省略可）|
|device_model|撮影した機材の型番を書き込みます（省略可）|
|--video_import_path|動画の保存先を指定します。|
|--geotag_source_path|GPSデータの保存先を指定します。|
|--local_time|ローカルタイムとして時間を処理します（後述）|
|--use_gps_start_time|GPSデータの開始時間を動画の開始時間として処理します。|

上記のオプションは以下の記事を参考にしました。
https://qiita.com/kudarisenmon/items/e1c0c9fc439dd5ec5a11

* 通常gpxファイルのタイムスタンプはUTC（協定世界時）で保存されています。しかし日本で撮影した動画ファイルの保存時間はUTC+9/TOKYOとなっているはずです。このように差があるとmapillary_toolsは正しく時間処理を行えないため、動画がローカルタイムであることをオプションで指定します。

* また、今回使用したTHETA Z1は動画の開始時間を保存できないため、動画の中にタイムスタンプが保存されていません。そのため少しズレは発生しますが、gpxのタイムスタンプを動画の開始時間として指定します。


コマンドを実行すると動画を画像に分割し、gpxデータから角度・時間・距離などを取得。EXIFとして画像に書き込んだ後シーケンスを形成してアップロードが始まります。15分程度の動画でだいたい30分程度かかります。特に画像への分割とアップロードは使用する環境によって時間が大きく変わりますのでご注意ください。

処理が完了すればアップロード完了です。お疲れさまでした。
実際にMapillaryに反映されるまで大体1-2日かかります。

![WS000053.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307125/47b0c1f2-96e5-abfd-525c-c53ec163cbb7.jpeg)
#補足・gpxデータの編集
今回のようにgpxデータから開始時間を取得する場合、gpxの計測開始と動画の開始を同時に行う必要があります。別々の端末で行っている場合はそれほど誤差が発生しませんが、スマートフォンなどで計測・撮影を行う場合は難しいです。

またgpxの精度は完ぺきではないため、道を外れたりすさまじい時速を計測したりすることがよくあります。このような誤差は外部ソフトを使うことである程度編集することが可能です。

[GPX Editor](https://ja.osdn.net/projects/sfnet_gpxeditor/)や、[GPX Editor and Viewer](https://askz.sakura.ne.jp/gpxev/gpx_editor_and_viewer.cgi?lat=0&lng=180&zoom=2&source=post_page-----bf5b5ef4c437----------------------)など様々な方法がありますが、どれも一長一短なので自身の使いやすいソフトを選ぶべきです。