728x90
반응형

사진 속에는 우리가 눈으로 볼 수 없는 다양한 메타데이터가 포함되어 있습니다. 특히 스마트폰이나 GPS 기능이 있는 카메라로 촬영한 사진에는 GPS 정보가 포함될 수 있습니다. 이번 포스팅에서는 파이썬을 사용해 이미지에서 GPS 정보를 추출하는 방법을 소개합니다.


준비물

이 작업을 위해 두 가지 라이브러리가 필요합니다: PillowExifRead. 아래 명령어를 사용하여 설치할 수 있습니다.


Pillow

Pillow는 Python의 강력한 이미지 처리 라이브러리로, 이미지 파일을 열고, 읽고, 저장하며 다양한 변환 작업(예: 크기 조정, 포맷 변환 등)을 수행할 수 있습니다.

이 포스팅에서는 이미지를 열고 EXIF 메타데이터를 추출하기 위해 사용됩니다. 직관적이고 간단한 API 덕분에 이미지 처리에 널리 활용됩니다.


ExifRead

ExifRead는 이미지의 EXIF 메타데이터를 분석하는 데 특화된 라이브러리입니다. GPS 정보와 같은 세부 데이터를 효율적으로 읽고, 해석하는 기능을 제공합니다.

Pillow만으로도 EXIF 데이터를 읽을 수 있지만, ExifRead는 특히 GPS 데이터를 더 세밀하고 직관적으로 다룰 수 있도록 설계되어 있습니다.

 

pip install Pillow ExifRead

코드 구현

다음은 파이썬으로 이미지의 GPS 정보를 추출하는 코드입니다.

1. 이미지의 EXIF 데이터 읽기

from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS

def get_exif_data(image_path):
    """이미지에서 Exif 데이터를 추출합니다."""
    try:
        image = Image.open(image_path)
        exif_data = image._getexif()
        
        if not exif_data:
            return None
        
        exif = {}
        for tag, value in exif_data.items():
            tag_name = TAGS.get(tag, tag)  # 태그를 사람이 읽을 수 있는 이름으로 변환
            exif[tag_name] = value
        
        return exif
    except Exception as e:
        print(f"Error reading EXIF data: {e}")
        return None
  • Image.open(image_path): Pillow를 사용해 이미지를 엽니다.
  • image._getexif(): 이미지의 EXIF 데이터를 추출합니다.
  • TAGS.get(tag, tag): EXIF 태그 번호를 사람이 읽을 수 있는 이름으로 변환합니다.
728x90

2. GPS 정보 추출

def get_geotagging(exif_data):
    """Exif 데이터에서 GPS 정보를 추출합니다."""
    if not exif_data or "GPSInfo" not in exif_data:
        return None
    
    gps_info = exif_data["GPSInfo"]
    geotags = {}
    
    for key, val in gps_info.items():
        tag_name = GPSTAGS.get(key, key)  # GPS 태그 이름 변환
        geotags[tag_name] = val
    
    return geotags
  • exif_data["GPSInfo"]: EXIF 데이터에서 GPS 정보를 포함하는 부분만 추출합니다.
  • GPSTAGS.get(key, key): GPS 태그 번호를 사람이 읽을 수 있는 이름으로 변환합니다.

3. GPS 데이터를 도(degree)로 변환

def convert_to_degrees(value):
    """GPS 좌표 값을 도(degree)로 변환합니다."""
    d, m, s = value  # degree, minute, second 형식
    return d + (m / 60.0) + (s / 3600.0)

EXIF 데이터에서 GPS 좌표는 (degree, minute, second) 형식으로 저장됩니다. 이를 십진수 형식으로 변환하는 함수입니다.


4. 위도와 경도 계산

def get_coordinates(geotags):
    """GPS 정보에서 위도와 경도를 추출합니다."""
    if not geotags:
        return None
    
    lat = geotags.get("GPSLatitude")
    lat_ref = geotags.get("GPSLatitudeRef")
    lon = geotags.get("GPSLongitude")
    lon_ref = geotags.get("GPSLongitudeRef")
    
    if not lat or not lon or not lat_ref or not lon_ref:
        return None
    
    lat = convert_to_degrees(lat)
    if lat_ref != "N":
        lat = -lat
    
    lon = convert_to_degrees(lon)
    if lon_ref != "E":
        lon = -lon
    
    return lat, lon

 

  • GPSLatitude****, ********GPSLongitude: 위도와 경도 정보를 가져옵니다.
  • GPSLatitudeRef****, ********GPSLongitudeRef: 위도/경도의 북(N)/남(S), 동(E)/서(W) 방향을 확인합니다. 방향이 남(S) 또는 서(W)일 경우 음수로 변환합니다.

전체 코드

위의 함수들을 조합하면, 이미지에서 GPS 정보를 추출하는 전체 코드는 다음과 같습니다:

from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS

def get_exif_data(image_path):
    try:
        image = Image.open(image_path)
        exif_data = image._getexif()
        if not exif_data:
            return None
        exif = {TAGS.get(tag, tag): value for tag, value in exif_data.items()}
        return exif
    except Exception as e:
        print(f"Error reading EXIF data: {e}")
        return None

def get_geotagging(exif_data):
    if not exif_data or "GPSInfo" not in exif_data:
        return None
    gps_info = exif_data["GPSInfo"]
    geotags = {GPSTAGS.get(key, key): val for key, val in gps_info.items()}
    return geotags

def convert_to_degrees(value):
    d, m, s = value
    return d + (m / 60.0) + (s / 3600.0)

def get_coordinates(geotags):
    if not geotags:
        return None
    lat = geotags.get("GPSLatitude")
    lat_ref = geotags.get("GPSLatitudeRef")
    lon = geotags.get("GPSLongitude")
    lon_ref = geotags.get("GPSLongitudeRef")
    if not lat or not lon or not lat_ref or not lon_ref:
        return None
    lat = convert_to_degrees(lat)
    if lat_ref != "N":
        lat = -lat
    lon = convert_to_degrees(lon)
    if lon_ref != "E":
        lon = -lon
    return lat, lon

# 사용 예제
image_path = "example.jpg"  # 이미지 경로
exif_data = get_exif_data(image_path)
geotags = get_geotagging(exif_data)

if geotags:
    coordinates = get_coordinates(geotags)
    if coordinates:
        print(f"GPS Coordinates: {coordinates}")
    else:
        print("GPS 정보가 없습니다.")
else:
    print("Exif에 GPS 정보가 없습니다.")

결과

사진에 GPS 정보가 포함되어 있다면, 위 코드를 실행하면 다음과 같은 출력 결과를 얻을 수 있습니다:

GPS Coordinates: (37.7749, -122.4194)

 

이 결과는 위도(latitude)와 경도(longitude)를 나타냅니다. 예를 들어, 37.7749, -122.4194는 샌프란시스코의 좌표입니다.


주의사항

  1. GPS 정보 유무: 모든 이미지에 GPS 정보가 포함되어 있지는 않습니다. 스마트폰이나 GPS 기능이 있는 카메라로 촬영된 사진만 GPS 정보를 포함할 가능성이 높습니다.
  2. EXIF 제거 여부: 일부 소셜 미디어나 편집 프로그램은 이미지를 저장할 때 EXIF 데이터를 제거할 수 있습니다.
  3. 라이브러리 버전: 최신 버전의 Pillow를 사용하는 것을 권장합니다.
728x90
반응형

+ Recent posts