1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

A-kunひとりAdvent Calendar 2024

Day 8

Web上からアップロードした画像のメタデータをサーバー側で取得する方法

Last updated at Posted at 2024-12-08

はじめまして、H-kunと申します。
A-kun ひとり Advent Calender 8日目です。
今回の話題は、Web上からアップロードした画像の撮影時刻・GPS情報を取得する方法について、解説します。

やったこと

下記がExif情報を取得するモジュールです。exif_utils.pyとして保存します。

import streamlit as st
from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS

def get_exif_data(image):
    """Extract Exif data from an image."""
    exif_data = {}
    info = image._getexif()
    if info:
        for tag, value in info.items():
            tag_name = TAGS.get(tag, tag)
            exif_data[tag_name] = value
    return exif_data

def get_geotagging(exif_data):
    """Extract GPS data from Exif."""
    if "GPSInfo" not in exif_data:
        return None
    
    gps_data = {}
    for tag, value in exif_data["GPSInfo"].items():
        tag_name = GPSTAGS.get(tag, tag)
        gps_data[tag_name] = value
    return gps_data

def get_decimal_coordinates(gps_data):
    """Convert GPS coordinates to decimal format."""
    def convert_to_decimal(coord, ref):
        degrees, minutes, seconds = coord
        decimal = degrees + (minutes / 60.0) + (seconds / 3600.0)
        if ref in ['S', 'W']:
            decimal = -decimal
        return decimal

    if gps_data:
        latitude = gps_data.get("GPSLatitude")
        latitude_ref = gps_data.get("GPSLatitudeRef")
        longitude = gps_data.get("GPSLongitude")
        longitude_ref = gps_data.get("GPSLongitudeRef")

        if latitude and latitude_ref and longitude and longitude_ref:
            return (
                convert_to_decimal(latitude, latitude_ref),
                convert_to_decimal(longitude, longitude_ref)
            )
    return None

def display_exif_info(uploaded_file):
    """Process and display Exif info from an uploaded image."""
    image = Image.open(uploaded_file)
    exif_data = get_exif_data(image)

    # 撮影時刻を取得
    datetime = exif_data.get("DateTimeOriginal", "情報なし")
    st.write(f"撮影時刻: {datetime}")

    # GPS情報を取得
    gps_data = get_geotagging(exif_data)
    if gps_data:
        coordinates = get_decimal_coordinates(gps_data)
        if coordinates:
            st.write(f"緯度: {coordinates[0]}")
            st.write(f"経度: {coordinates[1]}")
        else:
            st.write("GPS情報が見つかりませんでした。")
    else:
        st.write("GPS情報が見つかりませんでした。")

これをstreamlitで公開するコードが、下記になります。

# FILE: view.py
import streamlit as st
from exif_utils import display_exif_info

# Streamlitアプリの構築
st.title("Exif情報取得アプリ")
st.write("画像をアップロードして、Exif情報を確認してください。")

uploaded_file = st.file_uploader("画像をアップロードしてください", type=["jpg", "jpeg", "png"])

if uploaded_file:
    display_exif_info(uploaded_file)

Exifデータが取得できるか確認

確認したところ、条件によってはブラウザ側でExif情報が削除されてしまうことがわかりました。

動作検証端末

iPhone XR (iOS 17.6.1)

  • Chrome 121.0.6167.66 -> OK
  • Safari -> OK

Android (Android 15)

  • Chrome 131.0.6778.104 -> NG

(代替策)Google Formを利用する

いくつか試してみたところ、Google Formを利用することで、Exif情報がついたままま画像のアップロードが可能であることがわかりました。
そこで、アップロードされた画像をGoogleDriveの特定のフォルダに保存し、定期的にそのフォルダの内容を監視することで、Exif情報を取得することができると考えられます。これはまた次回の課題としたいと思います。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?