GIS奮闘記

元GISエンジニアの技術紹介ブログ。主にPythonを使用。

スポンサーリンク

piexif を使って画像にジオタグを追加する方法

さて、本日は 久しぶりに Python を使ってみようと思います。piexif というライブラリがあるのですが、これを使って画像にジオタグを追加する方法を紹介します。ライブラリの詳細は以下のリンクを参照してください。

piexif.readthedocs.io

今回のエントリーに至った経緯

実は以下のエントリーで過去にも同じことをしていたのですが、最近そのコードが動かないことが判明しました(当時使用していたライブラリ(pyexiv2)の仕様が変わった?!もしくは何か依存ライブラリが足りてないのか調べても原因はわかりませんでした・・・)。今回はせっかくなので、別のライブラリ(piexif) を使ってみようと思います。

www.gis-py.com

www.gis-py.com

ジオタグとは

ジオタグとは、写真や動画、あるいは SNS の投稿といったさまざまなメディアに追加することができる、位置情報 (緯度・経度) を示すメタデータのことです。

使用するライブラリ

piexif
Pillow

実行環境

Windows 10
ArcGIS Pro 2.4
Python 3.6.6
piexif 1.1.3
Pillow 6.1.0

使用するデータ

以下の画像を使用します。

f:id:sanvarie:20191026105621p:plain

使用する緯度経度

緯度: 35.678601
経度: 139.740286

ここがどこかといいますと永田町駅ですね。

f:id:sanvarie:20191026091618p:plain

サンプルコード

1ファイルだけを対象としたサンプルコードです。

from fractions import Fraction
import piexif
from PIL import Image

in_file = r"D:\data\picture\arcgis.jpg"         # 使用する画像
out_file = r"D:\data\picture\arcgis_geotag.jpg" # 出力する画像
lat = 35.678601
lon = 139.740286

def to_deg(value, loc):
    """緯度、経度を10進法→60進法(度分秒)に変換"""
    if value < 0:
        loc_value = loc[0]
    elif value > 0:
        loc_value = loc[1]
    else:
        loc_value = ""
    abs_value = abs(value)
    deg =  int(abs_value)
    t1 = (abs_value-deg)*60
    min = int(t1)
    sec = round((t1 - min)* 60, 5)
    return (deg, min, sec, loc_value)

def change_to_rational(number):
    """有理数に変換"""
    f = Fraction(str(number))
    return (f.numerator, f.denominator)

def atattch_geotag(file_name, lat, lng):
    """ジオタグに追加する情報を作成"""
    lat_deg = to_deg(lat, ["S", "N"])
    lng_deg = to_deg(lng, ["W", "E"])

    # 緯度、経度を10進法→60進法(度分秒)に変換
    exiv_lat = (change_to_rational(lat_deg[0]), change_to_rational(lat_deg[1]), change_to_rational(lat_deg[2]))
    exiv_lng = (change_to_rational(lng_deg[0]), change_to_rational(lng_deg[1]), change_to_rational(lng_deg[2]))

    gps_ifd = {
        piexif.GPSIFD.GPSVersionID: (2, 0, 0, 0),
        piexif.GPSIFD.GPSLatitudeRef: lat_deg[3],
        piexif.GPSIFD.GPSLatitude: exiv_lat,
        piexif.GPSIFD.GPSLongitudeRef: lng_deg[3],
        piexif.GPSIFD.GPSLongitude: exiv_lng,
    }

    exif_dict = {"GPS": gps_ifd}
    exif_bytes = piexif.dump(exif_dict)

    # ジオタグ付きの画像を作成
    create_picture_geotag(exif_bytes)

def create_picture_geotag(exif_bytes):
    """ジオタグを貼り付けた画像を作成"""
    im = Image.open(in_file)
    im.save(out_file, exif = exif_bytes)

atattch_geotag(in_file, lat, lon)

結果を確認してみると、出力された画像にジオタグが追加されていることがわかります。

f:id:sanvarie:20191026103815p:plain

追加されたジオタグが正しいか確認

ArcGIS Pro を使って追加されたジオタグが正しいか確認してみます。「ジオタグ付き写真 → ポイント」というジオプロがあるので、ArcPy を使って実行してみようと思います。

import arcpy
arcpy.GeoTaggedPhotosToPoints_management(r"D:\data\picture", r"D:\Sample\Sample.gdb\python_GeoTaggedPhotosToPoints", "", "ONLY_GEOTAGGED", "ADD_ATTACHMENTS")

設定した緯度経度(永田町)にポイントが作成されました。

f:id:sanvarie:20191026104804p:plain

ポップアップを構成して属性ウインドウに写真を表示してみました。
f:id:sanvarie:20191026105055p:plain

この piexif というライブラリですが、とても簡単に画像にジオタグを追加できる優秀なライブラリということがわかりました。以下のエントリーで画像に付与されているジオタグを抽出する方法を紹介しているので、興味のある方はぜひ読んでみてください。

www.gis-py.com

本日は以上です。