사진 속에는 우리가 눈으로 볼 수 없는 다양한 메타데이터가 포함되어 있습니다. 특히 스마트폰이나 GPS 기능이 있는 카메라로 촬영한 사진에는 GPS 정보가 포함될 수 있습니다. 이번 포스팅에서는 파이썬을 사용해 이미지에서 GPS 정보를 추출하는 방법을 소개합니다.
준비물
이 작업을 위해 두 가지 라이브러리가 필요합니다: Pillow와 ExifRead. 아래 명령어를 사용하여 설치할 수 있습니다.
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 태그 번호를 사람이 읽을 수 있는 이름으로 변환합니다.
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는 샌프란시스코의 좌표입니다.
주의사항
- GPS 정보 유무: 모든 이미지에 GPS 정보가 포함되어 있지는 않습니다. 스마트폰이나 GPS 기능이 있는 카메라로 촬영된 사진만 GPS 정보를 포함할 가능성이 높습니다.
- EXIF 제거 여부: 일부 소셜 미디어나 편집 프로그램은 이미지를 저장할 때 EXIF 데이터를 제거할 수 있습니다.
- 라이브러리 버전: 최신 버전의 Pillow를 사용하는 것을 권장합니다.