使用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
相关产品推荐
相关产品推荐

