HOOOS

Python图片自动整理:图像处理与地理信息库推荐

0 16 图片整理小能手 Python图像处理地理信息
Apple

想要用Python脚本自动整理你下载的图片,按照拍摄时间和地点分类?这绝对是个好主意!下面我将为你推荐一些非常实用的图像处理库和地理信息库,并提供一些代码示例,帮你快速上手。

1. 图像处理库:PIL/Pillow

首先,我们需要一个强大的图像处理库来读取图片的元数据。PIL (Python Imaging Library) 是一个非常流行的选择,但官方已经停止维护。不过,它的一个分支 Pillow 继承了 PIL 的所有功能,并且更加活跃,强烈推荐使用 Pillow。

安装 Pillow

pip install Pillow

使用 Pillow 读取图片元数据(EXIF信息)

EXIF (Exchangeable Image File Format) 信息包含了照片的拍摄时间、相机型号、光圈、ISO等各种元数据。很多手机和相机都会在照片中写入 EXIF 信息。

from PIL import Image
from PIL.ExifTags import TAGS

def get_exif_data(image_path):
    """从图片中提取EXIF信息"""
    image = Image.open(image_path)
    exif_data = {}
    info = image._getexif()
    if info:
        for tag, value in info.items():
            decoded = TAGS.get(tag, tag)
            exif_data[decoded] = value
    return exif_data

# 示例
image_path = "your_image.jpg"  # 替换成你的图片路径
exif_data = get_exif_data(image_path)

if exif_data:
    for tag, value in exif_data.items():
        print(f"{tag}: {value}")
else:
    print("No EXIF data found.")

解释:

  • Image.open(image_path):打开图片。
  • image._getexif():获取 EXIF 信息,返回一个字典。
  • TAGS.get(tag, tag):将 EXIF 信息的数字标签转换为可读的字符串标签。

获取拍摄时间

通常,拍摄时间存储在 DateTimeOriginal 标签中。

def get_image_date(image_path):
    """从图片中提取拍摄时间"""
    exif_data = get_exif_data(image_path)
    if exif_data and 'DateTimeOriginal' in exif_data:
        return exif_data['DateTimeOriginal']
    else:
        return None

# 示例
image_path = "your_image.jpg"  # 替换成你的图片路径
date_time = get_image_date(image_path)
if date_time:
    print(f"拍摄时间: {date_time}")
else:
    print("未找到拍摄时间信息")

2. 地理信息库:geopy

如果你的照片包含 GPS 信息,你可以使用 geopy 库来获取地理位置的详细信息,例如城市、国家等。

安装 geopy

pip install geopy

从 EXIF 中提取 GPS 信息

GPS 信息通常以经纬度坐标的形式存储在 EXIF 中,需要进行转换。

from geopy.geocoders import Nominatim

def get_decimal_from_dms(dms, ref):
    """将度分秒格式的GPS坐标转换为十进制格式"""
    degrees = dms[0][0] / dms[0][1]
    minutes = dms[1][0] / dms[1][1]
    seconds = dms[2][0] / dms[2][1]

    if ref in ('S', 'W'):
        degrees = -degrees
        minutes = -minutes
        seconds = -seconds

    return degrees + minutes / 60 + seconds / 3600

def get_coordinates(image_path):
    """从图片中提取GPS坐标"""
    exif_data = get_exif_data(image_path)
    if exif_data:
        lat = None
        lon = None
        if 'GPSInfo' in exif_data:
            gps_info = exif_data['GPSInfo']
            
            lat_dms = gps_info.get(2)
            lat_ref = gps_info.get(1)
            lon_dms = gps_info.get(4)
            lon_ref = gps_info.get(3)

            if lat_dms and lat_ref and lon_dms and lon_ref:
                latitude = get_decimal_from_dms(lat_dms, lat_ref)
                longitude = get_decimal_from_dms(lon_dms, lon_ref)

                return latitude, longitude
    return None, None


def get_location_from_coordinates(latitude, longitude):
    """根据经纬度获取地理位置信息"""
    geolocator = Nominatim(user_agent="image_organizer") #  user_agent是必须的
    try:
        location = geolocator.reverse((latitude, longitude), timeout=10)
        return location.address
    except Exception as e:
        print(f"Error getting location: {e}")
        return None

# 示例
image_path = "your_image.jpg"  # 替换成你的图片路径
latitude, longitude = get_coordinates(image_path)

if latitude and longitude:
    print(f"Latitude: {latitude}, Longitude: {longitude}")
    location = get_location_from_coordinates(latitude, longitude)
    if location:
        print(f"Location: {location}")
    else:
        print("无法获取详细位置信息")
else:
    print("未找到GPS信息")

解释:

  • get_decimal_from_dms:将 EXIF 中度分秒格式的 GPS 坐标转换为十进制格式。
  • Nominatim(user_agent="image_organizer"):初始化一个 Nominatim 地理编码器。user_agent 参数是必须的,用于标识你的应用程序。
  • geolocator.reverse((latitude, longitude), timeout=10):根据经纬度获取地理位置信息。timeout 参数设置超时时间,防止请求卡住。

3. 文件操作和目录管理:os 和 shutil

最后,我们需要使用 osshutil 模块来创建目录和移动文件。

import os
import shutil

def organize_images(image_dir, dest_dir):
    """整理图片,按时间和地点分类"""
    for filename in os.listdir(image_dir):
        if filename.endswith(('.jpg', '.jpeg', '.png', '.gif')):
            image_path = os.path.join(image_dir, filename)
            
            # 获取拍摄时间
            date_time = get_image_date(image_path)
            if date_time:
                date_dir = date_time[:7].replace(":", "-") # 使用年月作为目录名,例如:2023-10
            else:
                date_dir = "UnknownDate"  # 如果没有拍摄时间,放到 UnknownDate 目录
            
            # 获取地理位置
            latitude, longitude = get_coordinates(image_path)
            if latitude and longitude:
                location = get_location_from_coordinates(latitude, longitude)
                if location:
                    location_dir = location.split(',')[0] # 使用城市名作为目录名
                else:
                    location_dir = "UnknownLocation" # 如果无法获取详细位置,放到 UnknownLocation 目录
            else:
                location_dir = "UnknownLocation"

            # 创建目标目录
            target_dir = os.path.join(dest_dir, date_dir, location_dir)
            os.makedirs(target_dir, exist_ok=True)

            # 移动文件
            target_path = os.path.join(target_dir, filename)
            shutil.move(image_path, target_path)
            print(f"Moved {filename} to {target_path}")

# 示例
image_dir = "/path/to/your/images"  # 替换成你的图片目录
dest_dir = "/path/to/your/organized/images" # 替换成你的目标目录
organize_images(image_dir, dest_dir)

解释:

  • os.listdir(image_dir):列出指定目录下的所有文件和目录。
  • filename.endswith(('.jpg', '.jpeg', '.png', '.gif')):检查文件名是否以指定的图片格式结尾。
  • os.path.join(image_dir, filename):将目录和文件名组合成完整的文件路径。
  • os.makedirs(target_dir, exist_ok=True):创建目标目录。exist_ok=True 表示如果目录已存在,不会抛出异常。
  • shutil.move(image_path, target_path):移动文件。

注意事项

  • EXIF 信息并非所有图片都有。 有些图片可能缺少 EXIF 信息,或者 EXIF 信息不完整。你需要处理这些情况,例如将缺少信息的图片放到一个单独的目录中。
  • 地理位置信息的准确性取决于照片的 GPS 信息。 有些照片可能没有 GPS 信息,或者 GPS 信息不准确。
  • geopy 库需要访问网络才能获取地理位置信息。 确保你的脚本在运行时可以访问网络。
  • user_agent 参数在 Nominatim 中是必须的。 你需要提供一个能够标识你的应用程序的字符串。
  • 异常处理非常重要。 在实际使用中,你需要添加更多的异常处理代码,以处理各种可能出现的问题。
  • 目录结构可以根据你的需求进行调整。 例如,你可以使用年/月/日作为目录结构,或者使用国家/城市/景点作为目录结构。

总结

使用 Python 自动整理图片可以大大提高你的效率。通过结合 Pillow、geopy、os 和 shutil 模块,你可以轻松地根据拍摄时间和地点对图片进行分类和整理。希望这些信息能帮助你构建自己的图片整理脚本!

点评评价

captcha
健康