如何用Python批量为文件夹内JPG图片添加GPS元数据?
批量给JPG图片写入GPS元数据的修正方案
原代码核心问题
- 重复读取CSV文件,冗余低效
- GPS格式不符合
exif库要求(必须是度分秒元组,而非DataFrame对象) - 仅处理单张图片,未实现批量逻辑
- 修改后未保存图片,无实际效果
- 变量名拼写错误:
gps_longitute→gps_longitude
修正后完整代码
import glob import pandas as pd from exif import Image def decimal_to_dms(decimal): """把十进制经纬度转成EXIF标准要求的度分秒元组""" degrees = int(decimal) minutes = int((decimal - degrees) * 60) seconds = (decimal - degrees - minutes/60) * 3600 return (degrees, minutes, round(seconds, 4)) # 一次性读取CSV,避免重复IO操作 # 假设CSV列顺序为:文件名, 其他列, 纬度, 经度(根据实际情况调整列索引) df = pd.read_csv('reference.csv', delimiter='\\s+', quotechar='"') # 将文件名设为索引,快速匹配图片与GPS数据 df.set_index(df.columns[0], inplace=True) # 获取当前目录下所有JPG文件 image_paths = glob.glob("*.jpg") for img_path in image_paths: # 提取纯文件名(去掉路径)用于匹配CSV记录 img_name = img_path.split("\\")[-1] if "\\" in img_path else img_path # 跳过CSV中无对应记录的图片 if img_name not in df.index: print(f"跳过:CSV中无{img_name}的GPS信息") continue try: # 必须以二进制模式读取图片,否则无法解析EXIF with open(img_path, 'rb') as img_file: img = Image(img_file) # 从CSV获取十进制经纬度,转成度分秒格式 lat = df.loc[img_name, df.columns[2]] # 第3列(索引2)为纬度,按需调整 lon = df.loc[img_name, df.columns[3]] # 第4列(索引3)为经度,按需调整 img.gps_latitude = decimal_to_dms(lat) img.gps_longitude = decimal_to_dms(lon) # 必须设置南北纬/东西经方向,否则GPS信息不被识别 img.gps_latitude_ref = "N" if lat >= 0 else "S" img.gps_longitude_ref = "E" if lon >= 0 else "W" # 以二进制模式保存修改后的图片(可修改文件名避免覆盖原文件) with open(img_path, 'wb') as img_file: img_file.write(img.get_file()) print(f"成功写入:{img_name}") except Exception as e: print(f"处理{img_name}失败:{str(e)}")
关键修改说明
- CSV读取优化:仅读取一次CSV,用文件名做索引,大幅提升匹配效率
- 经纬度格式转换:EXIF标准强制要求GPS用度分秒格式,通过
decimal_to_dms函数完成十进制到度分秒的转换 - 批量逻辑实现:遍历所有JPG文件,自动匹配CSV中的对应记录
- 正确读写模式:必须用二进制(
rb/wb)读写图片,否则会损坏文件或无法解析EXIF - GPS方向补全:添加
gps_latitude_ref和gps_longitude_ref(N/S/E/W),缺失的话GPS信息无法被设备识别 - 异常处理:捕获图片损坏、CSV列索引错误等问题,避免程序崩溃
- 拼写修正:修复了
gps_longitute的拼写错误
提示:如果你的CSV有明确列名(比如
filename、latitude),建议把代码中的列索引(如df.columns[2])换成对应的列名,比如'latitude',这样更不易出错。
内容的提问来源于stack exchange,提问作者Katerkaskade
相关产品推荐
相关产品推荐

