You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python的OpenCV编辑图片时如何保留EXIF数据?

解决裁剪图片后保留EXIF数据的问题

嗨,这个问题我之前也踩过坑——OpenCV的cv2.imwrite确实不会自动帮你保留原始图片的EXIF元数据,得咱们手动做一下数据迁移。下面给你两种实用的解决方案,直接修改你的代码就能用:

方案一:用Pillow(推荐,更通用)

Pillow是Python处理图片的常用工具,它能轻松读取和写入EXIF数据。咱们只需要在代码里加几步,提取原始图片的EXIF,再在保存裁剪图时把数据写回去就行。

步骤1:安装Pillow

先确保你本地装了这个库:

pip install pillow

步骤2:修改你的代码

我把关键改动标出来了,直接替换原代码就行:

from imutils import face_utils
import imutils
import numpy as np
import collections
import dlib
import cv2
import glob
import os
from PIL import Image  # 新增:导入Pillow库

detector = dlib.get_frontal_face_detector()
PREDICTOR_PATH = "shape_predictor_68_face_landmarks.dat"
predictor = dlib.shape_predictor(PREDICTOR_PATH)

def face_remap(shape):
    remapped_image = cv2.convexHull(shape)
    return remapped_image

def faceCrop(imagePattern):
    imgList=glob.glob(imagePattern)
    if len(imgList)<=0:
        print ('No Images Found')
        return
    for img in imgList:
        # 新增:用Pillow读取原始图片的EXIF数据
        pil_origin_img = Image.open(img)
        exif_data = pil_origin_img.getexif()
        
        # 原有的OpenCV人脸裁剪逻辑保持不变
        image = cv2.imread(img)
        image = imutils.resize(image, width=500)
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        out_face = np.zeros_like(image)
        rects = detector(gray, 1)
        for (i, rect) in enumerate(rects):
            shape = predictor(gray, rect)
            shape = face_utils.shape_to_np(shape)
            remapped_shape = np.zeros_like(shape)
            feature_mask = np.zeros((image.shape[0], image.shape[1]))
            remapped_shape = face_remap(shape)
            cv2.fillConvexPoly(feature_mask, remapped_shape[0:27], 1)
            feature_mask = feature_mask.astype(np.bool)
            out_face[feature_mask] = image[feature_mask]
        
        # 关键改动:用Pillow保存裁剪图并写入EXIF
        # OpenCV是BGR格式,要转成Pillow的RGB格式
        out_face_rgb = cv2.cvtColor(out_face, cv2.COLOR_BGR2RGB)
        pil_crop_img = Image.fromarray(out_face_rgb)
        fname,ext=os.path.splitext(img)
        # 保存时传入之前提取的EXIF数据
        pil_crop_img.save(fname+'_crop'+ext, exif=exif_data)
        print ('Listo \n')

faceCrop('/Users/alejandroramirez/Documents/imagenes nuevas/2/*.JPG')

方案二:用piexif库(专注EXIF处理)

如果你只想单独处理EXIF,不想依赖Pillow的其他功能,可以用piexif这个专门操作EXIF的库:

步骤1:安装piexif

pip install piexif

步骤2:修改代码

核心逻辑是先读原始EXIF,用OpenCV保存裁剪图后,再把EXIF写入新文件:

# 新增导入piexif
import piexif

# 在循环处理图片的部分:
for img in imgList:
    # 读取原始图片的EXIF字典
    exif_dict = piexif.load(img)
    
    # 原有的OpenCV人脸裁剪逻辑不变...
    
    # 先用cv2保存裁剪后的图片
    fname,ext=os.path.splitext(img)
    crop_path = fname+'_crop'+ext
    cv2.imwrite(crop_path, out_face)
    # 把EXIF数据写入裁剪后的图片
    piexif.insert(piexif.dump(exif_dict), crop_path)
    print ('Listo \n')

小提醒

  • 有些EXIF标签(比如图片尺寸、分辨率)是和原始图片绑定的,裁剪后尺寸变了,这类标签可能需要手动调整,但拍摄时间、相机型号、GPS信息这类核心元数据都能直接保留。
  • 如果你的图片是PNG格式,要注意PNG对EXIF的支持有限,建议保存为JPG格式来确保元数据完整。

内容的提问来源于stack exchange,提问作者Alejandro Ramirez Baez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:02:21