本文目录导读:

我来详细说明如何使用Pillow(PIL)读取图片的EXIF信息。
基础读取方法
from PIL import Image
# 打开图片
img = Image.open('example.jpg')
# 获取EXIF信息
exif_data = img._getexif()
if exif_data:
print("EXIF信息:")
for tag_id, value in exif_data.items():
print(f"Tag {tag_id}: {value}")
else:
print("该图片没有EXIF信息")
使用EXIF标签名称读取
from PIL import Image
from PIL.ExifTags import TAGS
def get_exif_info(image_path):
"""获取图片的EXIF信息,使用可读的标签名称"""
img = Image.open(image_path)
exif_data = img._getexif()
if not exif_data:
print("没有EXIF信息")
return None
exif_info = {}
for tag_id, value in exif_data.items():
# 获取标签名称
tag_name = TAGS.get(tag_id, tag_id)
exif_info[tag_name] = value
return exif_info
# 使用示例
image_path = 'photo.jpg'
exif_info = get_exif_info(image_path)
if exif_info:
for key, value in exif_info.items():
print(f"{key}: {value}")
读取常用EXIF信息
from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS
def get_common_exif_info(image_path):
"""获取常用的EXIF信息"""
img = Image.open(image_path)
exif_data = img._getexif()
if not exif_data:
return {}
info = {}
for tag_id, value in exif_data.items():
tag_name = TAGS.get(tag_id, tag_id)
# 提取常用信息
if tag_name == "Make": # 相机制造商
info['camera_make'] = value
elif tag_name == "Model": # 相机型号
info['camera_model'] = value
elif tag_name == "DateTime": # 拍摄时间
info['datetime'] = value
elif tag_name == "ExifImageWidth": # 图片宽度
info['width'] = value
elif tag_name == "ExifImageLength": # 图片高度
info['height'] = value
elif tag_name == "ISOSpeedRatings": # ISO值
info['iso'] = value
elif tag_name == "FNumber": # 光圈值
info['aperture'] = float(value)
elif tag_name == "ExposureTime": # 曝光时间
info['exposure_time'] = str(value)
elif tag_name == "FocalLength": # 焦距
info['focal_length'] = float(value)
elif tag_name == "GPSInfo": # GPS信息
gps_info = {}
for gps_tag_id, gps_value in value.items():
gps_tag_name = GPSTAGS.get(gps_tag_id, gps_tag_id)
gps_info[gps_tag_name] = gps_value
info['gps_info'] = gps_info
return info
# 使用示例
info = get_common_exif_info('photo.jpg')
print("常用EXIF信息:")
for key, value in info.items():
print(f"{key}: {value}")
读取GPS位置信息
from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS
def get_gps_coordinates(image_path):
"""从EXIF中提取GPS坐标"""
def convert_to_degrees(value):
"""将GPS坐标格式转换为十进制度数"""
d, m, s = value
return d + (m / 60.0) + (s / 3600.0)
img = Image.open(image_path)
exif_data = img._getexif()
if not exif_data:
return None
gps_info = {}
for tag_id, value in exif_data.items():
tag_name = TAGS.get(tag_id, tag_id)
if tag_name == "GPSInfo":
for gps_tag_id, gps_value in value.items():
gps_tag_name = GPSTAGS.get(gps_tag_id, gps_tag_id)
gps_info[gps_tag_name] = gps_value
if not gps_info:
return None
# 提取经纬度
try:
lat = convert_to_degrees(gps_info.get('GPSLatitude', [0, 0, 0]))
lon = convert_to_degrees(gps_info.get('GPSLongitude', [0, 0, 0]))
# 处理南北纬和东西经
if gps_info.get('GPSLatitudeRef') == 'S':
lat = -lat
if gps_info.get('GPSLongitudeRef') == 'W':
lon = -lon
return {'latitude': lat, 'longitude': lon}
except:
return None
# 使用示例
coordinates = get_gps_coordinates('photo.jpg')
if coordinates:
print(f"纬度: {coordinates['latitude']}")
print(f"经度: {coordinates['longitude']}")
print(f"Google Maps: https://maps.google.com/?q={coordinates['latitude']},{coordinates['longitude']}")
完整的EXIF读取工具类
from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS
from datetime import datetime
class ExifReader:
"""EXIF信息读取器"""
def __init__(self, image_path):
self.image_path = image_path
self.exif_data = self._load_exif()
def _load_exif(self):
"""加载EXIF数据"""
try:
img = Image.open(self.image_path)
return img._getexif()
except:
return None
def get_raw_exif(self):
"""获取原始EXIF数据"""
if not self.exif_data:
return {}
return {TAGS.get(tag_id, tag_id): value
for tag_id, value in self.exif_data.items()}
def get_camera_info(self):
"""获取相机信息"""
if not self.exif_data:
return {}
camera_info = {}
for tag_id, value in self.exif_data.items():
tag_name = TAGS.get(tag_id, tag_id)
if tag_name in ['Make', 'Model', 'Software']:
camera_info[tag_name] = value
return camera_info
def get_photo_settings(self):
"""获取拍摄设置"""
if not self.exif_data:
return {}
settings = {}
for tag_id, value in self.exif_data.items():
tag_name = TAGS.get(tag_id, tag_id)
if tag_name in ['ISOSpeedRatings', 'FNumber',
'ExposureTime', 'FocalLength', 'Flash']:
settings[tag_name] = value
# 格式化的曝光时间
if 'ExposureTime' in settings:
exp_time = settings['ExposureTime']
if isinstance(exp_time, tuple) and len(exp_time) == 2:
settings['ExposureTime_str'] = f"{exp_time[0]}/{exp_time[1]}s"
return settings
def get_datetime(self):
"""获取拍摄时间"""
if not self.exif_data:
return None
for tag_id, value in self.exif_data.items():
tag_name = TAGS.get(tag_id, tag_id)
if tag_name == 'DateTime':
return value
return None
def has_gps(self):
"""检查是否有GPS信息"""
if not self.exif_data:
return False
for tag_id in self.exif_data:
tag_name = TAGS.get(tag_id, tag_id)
if tag_name == 'GPSInfo':
return True
return False
# 使用示例
reader = ExifReader('photo.jpg')
print("=== 相机信息 ===")
print(reader.get_camera_info())
print("\n=== 拍摄设置 ===")
print(reader.get_photo_settings())
print("\n=== 拍摄时间 ===")
print(reader.get_datetime())
print("\n=== 是否有GPS信息 ===")
print(reader.has_gps())
批量处理多个图片
import os
from PIL import Image
from PIL.ExifTags import TAGS
def batch_extract_exif(folder_path, output_file='exif_info.txt'):
"""批量提取文件夹中所有图片的EXIF信息"""
results = []
for filename in os.listdir(folder_path):
if filename.lower().endswith(('.jpg', '.jpeg', '.tiff', '.tif')):
file_path = os.path.join(folder_path, filename)
try:
img = Image.open(file_path)
exif_data = img._getexif()
if exif_data:
info = {'filename': filename}
for tag_id, value in exif_data.items():
tag_name = TAGS.get(tag_id, tag_id)
if tag_name in ['Make', 'Model', 'DateTime']:
info[tag_name] = value
results.append(info)
else:
results.append({'filename': filename, 'exif': 'No EXIF data'})
except Exception as e:
results.append({'filename': filename, 'error': str(e)})
# 保存到文件
with open(output_file, 'w', encoding='utf-8') as f:
for result in results:
f.write(f"文件: {result.get('filename', 'Unknown')}\n")
for key, value in result.items():
if key != 'filename':
f.write(f" {key}: {value}\n")
f.write("\n")
print(f"已将结果保存到 {output_file}")
return results
# 使用示例
batch_extract_exif('./photos/', 'exif_analysis.txt')
注意事项
- 图片格式支持:JPG、TIFF等格式支持EXIF,PNG、GIF等不支持
- 隐私问题:EXIF可能包含位置信息,分享图片时注意隐私
- 处理错误:有些图片可能损坏或没有EXIF数据,需要适当处理
- 编码问题:某些EXIF信息可能包含非ASCII字符
这些示例涵盖了大部分常见的EXIF读取需求,你可以根据具体场景选择合适的实现方式。