Takeout JSON

Google Takeout の写真から位置情報が消えた?geoData の意味と GPS を写真に戻す方法

Google Takeout のエクスポートで位置情報がどこへ行くのか、JSON の geoData と geoDataExif の違い、なぜ多くが 0.0 なのか、そして本物の GPS だけを写真に書き戻して海の上に置かない方法を説明します。

Google フォトでは「京都」と検索すれば、あの旅行の写真が出てきた。Takeout のあと、同じ写真に位置情報がまったくない。新しい写真アプリの地図は空っぽ。GPS は .json に入っていると聞いて開いてみたら、0.0 と書いてあった。

何が起きたのか、そして現実に何を取り戻せるのかを説明します。

2 つの位置情報の項目

Takeout の各サイドカーには、位置情報の項目が 2 つあります。

"geoData": {
  "latitude": 35.0116,
  "longitude": 135.7681,
  "altitude": 45.0,
  "latitudeSpan": 0.0,
  "longitudeSpan": 0.0
},
"geoDataExif": {
  "latitude": 35.0116,
  "longitude": 135.7681,
  "altitude": 45.0
}

geoDataExif は、アップロード時に写真自身の EXIF に入っていた位置です。スマートフォンのカメラが GPS を記録していれば、ここにあります。geoData は Google フォトが使っていた位置で、最初は同じ値ですが、アプリ内で手で設定または修正した場所も含みます。

両方の緯度と経度が 0.0 なら、その写真には位置情報がありません。実在の場所ではなく、Google 流の「不明」の書き方です。この状態の写真は、思っているよりずっと多いです。

なぜこんなに多くの写真に GPS がないのか

スマートフォンは、カメラに位置情報の利用を許可しているときだけ座標を記録します。オフにしている人は多いです。スクリーンショット、LINE の画像、ダウンロードした画像、スキャンには最初から GPS がありません。古いカメラには受信機自体がありません。

Google フォトはこれを隠していました。ロケーション履歴や、写真の中に認識したランドマークから場所を推定し、アプリの中でその推定を表示していたのです。推定された場所はサイドカーに入りません。入るのは明示的な位置だけです。EXIF にあったものか、手で設定した場所か。

実際の 991 枚の Takeout パートでは、本物の座標を持つサイドカーは 12 パーセント、0.0 のプレースホルダーが 81 パーセントでした。ライブラリによって変わりますが、位置情報を付けた覚えのない写真が Google フォトの検索で出てきたなら、その検索は返ってこない推定に頼っていたわけです。

なぜファイル自体から GPS が消えるのか

EXIF に GPS があった写真については、Takeout はたいてい EXIF をそのまま保ったファイルを返します。ですから多くのカメラ写真は座標を持ったままで、移った先のアプリがまだ索引していないか、別の項目を見ていただけということがよくあります。

例外は、アップロード前に EXIF が削られた写真と、Google フォト内で場所を設定した写真です。これらについては、サイドカーが唯一のコピーです。書き込まずにサイドカーを消せば、その場所は失われます。

実際に何があるかを確認する

exiftool を使います。

exiftool -r -if 'not $GPSLatitude' -ext jpg -ext heic -filename .

これでファイル内に GPS がない画像が一覧されます。それを、geoData がゼロでないサイドカーと比べます。grep なら次のとおりです。

grep -L '"latitude": 0.0' *.json

重なる部分が、復元できるものです。

手作業で座標を戻す

exiftool はサイドカーの geoData を EXIF の GPS タグにコピーできます。

exiftool -r -tagsfromfile "%d/%F.supplemental-metadata.json" \
  -if '$GeoDataLatitude ne 0 or $GeoDataLongitude ne 0' \
  "-GPSLatitude<GeoDataLatitude" "-GPSLatitudeRef<GeoDataLatitude" \
  "-GPSLongitude<GeoDataLongitude" "-GPSLongitudeRef<GeoDataLongitude" \
  "-GPSAltitude<GeoDataAltitude" \
  -ext jpg -ext jpeg -ext heic -overwrite_original .

-if の行が重要です。これがないと数百枚の写真に 0.0, 0.0 を書き込み、新しいアプリの地図ビューすべてに、西アフリカ沖の大西洋に集まる点が現れます。Ref のタグは座標の符号から決まるので、同じ値から設定します。

古いエクスポートには "%d/%F.json" で繰り返します。切り詰められたサイドカー名と (1) の重複は特別な扱いが必要で、exiftool ガイド で扱っています。

アプリで戻す

Takeout JSON Metadata Fixer は、同じ仕事をコマンドラインなしで、Windows、Mac、Linux で行います。

geoData を先に読み、次に geoDataExif、次にファイルにすでにある GPS を読んで、座標を写真の EXIF に書き込みます。0.0, 0.0 は不明として扱い、海の上に置く代わりに位置情報なしのままにします。日付も同時に書き込みます。2 つの問題はほぼ必ず一緒に起きるからです。

ファイル名やフォルダーに場所を入れたい場合、アプリは座標を市町村名に変換して 2019-07-14-1105_Kyoto.jpg2019/Kyoto のフォルダーにできます。この変換は OpenStreetMap を使うためインターネット接続が必要で、丸めた座標だけをそのサービスに送ります。それ以外は何も送りません。オフにすればアプリは完全にオフラインで動きます。位置情報のない写真は、場所なしの名前になるだけです。

最初の 1000 枚は無料です。その先は 19.99 米ドルの買い切りで無制限になります。

最初から位置情報がなかった写真

記録されなかった位置を、エクスポートから取り戻すことはできません。ただし自分で付けることはできます。Apple の「写真」、digiKam、Immich は写真を地図に置けます。まとめてやるなら、exiftool でフォルダー全体に同じ座標を設定できます。アプリでも、フォルダー単位で日付と場所を手で設定できます。

よくある質問

Google フォトはこの写真に場所を表示していました。なぜサイドカーはゼロなのですか?

その場所がロケーション履歴や画像の内容から推定されたもので、推定はエクスポートされないからです。ファイルにあった座標か、手で編集した座標だけが出てきます。

geoData と geoDataExif のどちらを使うべきですか?

geoData は手での修正を含み、それ以外は geoDataExif と同じです。geoData を使い、ゼロなら geoDataExif に落ちてください。

書き込んだあと、Immich や Apple の「写真」は GPS を読みますか?

はい。どちらも標準の EXIF GPS タグを読み、書き込みはそこに行われます。Immich はファイルを再索引したあと地図ビューに表示します。

プライバシーのために GPS を消したいのですが

できます。exiftool -gps:all= -overwrite_original . でフォルダーから取り除けます。場所入りのフォルダー名が欲しいなら、整理が終わってからにしてください。