• Python(pyexiv2)修改照片(证件照)的拍摄日期


    介绍

    手机或者相机拍摄的照片都会有拍摄日期,特别在某些特殊的APP上上传证件照时,都会有一个日期检查,并要求上传6个月之内的照片。那如何修改照片上的拍摄日期呢?

    很多方法就是说在Windows系统上选中图片右键、选择属性、点击详细信息、最后修改拍摄日期,如下:
    在这里插入图片描述
    通过这种方式修改后,再去APP上上传照片发现还是上传失败,这说明修改并没有成功。

    我们换一种图片查看器,即XnView MP,打开图片后,选择编辑->属性->EXIF,可以发现拍摄时间并没有变,如下:
    在这里插入图片描述
    我们也可以继续查看IPTC-IIM和XMP属性,如下:
    在这里插入图片描述
    在这里插入图片描述
    对于EXIF、IPTC、XMP三者属性的区别,我们可以查看CSDN博客:python 修改、读取图片元数据

    EXIF:通常被数码相机在拍摄照片时自动添加,比如相机型号、镜头、曝光、图片尺寸等信息。
    IPTC:比如图片标题、关键字、说明、作者、版权等信息。
    XMP:由Adobe公司制定标准,以XML格式保存。用PhotoShop等Adobe公司的软件制作的图片通常会携带这种信息。

    那如何修改这些信息呢
    本文源码参考于:python 修改、读取图片元数据

    修改照片元数据

    环境安装

    我们使用Python中pyexiv2来修改这些照片元数据
    安装pyexiv2:

    pip install pyexiv2
    
    • 1

    查看和修改EXIF

    from pyexiv2 import Image
    
    img = Image('./weihuang.jpg')
    print(img.read_exif())
    
    • 1
    • 2
    • 3
    • 4

    打印结果:

    {'Exif.Image.ImageWidth': '5472', 
    'Exif.Image.ImageLength': '3648', 
    'Exif.Image.BitsPerSample': '8 8 8', 
    'Exif.Image.PhotometricInterpretation': '2', 
    'Exif.Image.Make': 'Canon', 
    'Exif.Image.Model': 'Canon EOS 6D', 
    'Exif.Image.Orientation': '1', 
    'Exif.Image.SamplesPerPixel': '3', 
    'Exif.Image.XResolution': '720000/10000', 
    'Exif.Image.YResolution': '720000/10000', 
    'Exif.Image.ResolutionUnit': '2', 
    'Exif.Image.Software': 'Adobe Photoshop CC 2017 (Windows)', 
    'Exif.Image.DateTime': '2021:07:26 18:57:55', 
    'Exif.Image.YCbCrPositioning': '2', 
    'Exif.Image.ExifTag': '304', 
    'Exif.Photo.ExposureTime': '1/125', 
    'Exif.Photo.FNumber': '5/1', 
    'Exif.Photo.ExposureProgram': '1', 
    'Exif.Photo.ISOSpeedRatings': '250', 
    'Exif.Photo.SensitivityType': '2', 
    'Exif.Photo.RecommendedExposureIndex': '250', 
    'Exif.Photo.ExifVersion': '48 50 51 48', 
    'Exif.Photo.DateTimeOriginal': '2021:07:26 19:15:47', 
    'Exif.Photo.DateTimeDigitized': '2021:07:26 19:15:47', 
    'Exif.Photo.ComponentsConfiguration': '1 2 3 0', 
    'Exif.Photo.ShutterSpeedValue': '458752/65536', 
    'Exif.Photo.ApertureValue': '303104/65536', 
    'Exif.Photo.ExposureBiasValue': '0/1', 
    'Exif.Photo.MaxApertureValue': '175/100', 
    'Exif.Photo.MeteringMode': '3', 
    'Exif.Photo.Flash': '16', 
    'Exif.Photo.FocalLength': '50/1', 
    'Exif.Photo.UserComment': '', 
    'Exif.Photo.SubSecTime': '04', 
    'Exif.Photo.SubSecTimeOriginal': '04', 
    'Exif.Photo.SubSecTimeDigitized': '04', 
    'Exif.Photo.FlashpixVersion': '48 49 48 48', 
    'Exif.Photo.ColorSpace': '1', 
    'Exif.Photo.PixelXDimension': '1933', 
    'Exif.Photo.PixelYDimension': '2705', 
    'Exif.Photo.InteroperabilityTag': '1216', 
    'Exif.Iop.InteroperabilityIndex': 'R98', 
    'Exif.Iop.InteroperabilityVersion': '48 49 48 48', 
    'Exif.Photo.FocalPlaneXResolution': '5472000/1436', 
    'Exif.Photo.FocalPlaneYResolution': '3648000/956', 
    'Exif.Photo.FocalPlaneResolutionUnit': '2', 
    'Exif.Photo.CustomRendered': '0', 
    'Exif.Photo.ExposureMode': '1', 
    'Exif.Photo.WhiteBalance': '1', 
    'Exif.Photo.SceneCaptureType': '0', 
    'Exif.Photo.CameraOwnerName': '', 
    'Exif.Photo.BodySerialNumber': '268021002586', 
    'Exif.Photo.LensSpecification': '50/1 50/1 0/1 0/1', 
    'Exif.Photo.LensModel': 'EF50mm f/1.8 STM', 
    'Exif.Photo.LensSerialNumber': '00001d49f8', 
    'Exif.Image.GPSTag': '1248', 
    'Exif.GPSInfo.GPSVersionID': '2 3 0 0', 
    'Exif.Thumbnail.Compression': '6', 
    'Exif.Thumbnail.XResolution': '72/1', 
    'Exif.Thumbnail.YResolution': '72/1', 
    'Exif.Thumbnail.ResolutionUnit': '2', 
    'Exif.Thumbnail.JPEGInterchangeFormat': '1362', 
    'Exif.Thumbnail.JPEGInterchangeFormatLength': '3257'}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    我们可以发现,程序返回了照片很多的EXIF信息,我们也不用去管全部,只需要找到里面有关时间的几个信息就行,如下:

    {'Exif.Image.DateTime': '2021:07:26 18:57:55', 
    'Exif.Photo.DateTimeOriginal': '2021:07:26 19:15:47', 
    'Exif.Photo.DateTimeDigitized': '2021:07:26 19:15:47'}
    
    • 1
    • 2
    • 3

    我们可以发现跟时间有关的信息有三条,我们仅修改这三条信息即可,修改方法如下:

    # 构建一个字典
    # 字典里面放对应的这三个键和对应的想要的时间,如下:
    exif_dict = {'Exif.Image.DateTime': '2022:05:25 18:57:55', 
                'Exif.Photo.DateTimeOriginal': '2022:05:25 19:15:47', 
                'Exif.Photo.DateTimeDigitized': '2022:05:25 19:15:47'}
    # 修改EXIF数据
    img.modify_exif(exif_dict)
    # 打印新的EXIF数据
    print(img.read_exif())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    查看和修改IPTC

    print(img.read_iptc())
    
    • 1

    打印结果:

    {'Iptc.Envelope.CharacterSet': '\x1b%G', 
    'Iptc.Application2.RecordVersion': '0', 
    'Iptc.Application2.DateCreated': '2021-07-26', 
    'Iptc.Application2.TimeCreated': '19:15:47+00:00'}
    
    • 1
    • 2
    • 3
    • 4

    我们可以发现有时间有关的只有一条,修改方法如下:

    # 构建一个字典
    iptc_dict = {'Iptc.Application2.DateCreated': '2022-05-25'}
    # 修改IPTC数据
    img.modify_iptc(iptc_dict)
    # 打印新的IPTC数据
    print(img.read_iptc())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    查看和修改XMP

    print(img.read_xmp())
    
    • 1

    打印结果:

    {'Xmp.xmp.Rating': '0', 
    'Xmp.xmp.ModifyDate': '2021-07-26T18:57:55+08:00', 
    'Xmp.xmp.CreateDate': '2021-07-26T19:15:47', 
    'Xmp.xmp.MetadataDate': '2021-07-26T18:57:55+08:00', 
    'Xmp.aux.SerialNumber': '268021002586', 
    'Xmp.aux.LensInfo': '50/1 50/1 0/0 0/0', 
    'Xmp.aux.Lens': 'EF50mm f/1.8 STM', 
    'Xmp.aux.LensID': '4156', 
    'Xmp.aux.LensSerialNumber': '00001d49f8', 
    'Xmp.aux.ImageNumber': '0', 
    'Xmp.aux.ApproximateFocusDistance': '167/100', 
    'Xmp.aux.FlashCompensation': '0/1', 
    'Xmp.aux.Firmware': '1.1.6', 
    'Xmp.photoshop.DateCreated': '2021-07-26T19:15:47.004', 
    'Xmp.photoshop.ColorMode': '3', 
    'Xmp.photoshop.ICCProfile': 'sRGB IEC61966-2.1', 
    'Xmp.xmpMM.DocumentID': 'adobe:docid:photoshop:409d8ef2-ee00-11eb-9975-95b945bcd28b', 
    'Xmp.xmpMM.InstanceID': 'xmp.iid:ea31ee64-8669-4f48-addf-e41f938f5f1d', 
    'Xmp.xmpMM.OriginalDocumentID': 'C36BB424AD4C7607F523A9056D9B87C5', 
    'Xmp.xmpMM.History': 'type="Seq"', 
    'Xmp.xmpMM.History[1]': 'type="Struct"', 
    'Xmp.xmpMM.History[1]/stEvt:action': 'saved', 
    'Xmp.xmpMM.History[1]/stEvt:instanceID': 'xmp.iid:3ab464dc-15f3-f943-b2af-7d96614a879d', 
    'Xmp.xmpMM.History[1]/stEvt:when': '2021-07-26T18:57:55+08:00', 
    'Xmp.xmpMM.History[1]/stEvt:softwareAgent': 'Adobe Photoshop CC 2017 (Windows)', 
    'Xmp.xmpMM.History[1]/stEvt:changed': '/', 
    'Xmp.xmpMM.History[2]': 'type="Struct"', 
    'Xmp.xmpMM.History[2]/stEvt:action': 'saved', 
    'Xmp.xmpMM.History[2]/stEvt:instanceID': 'xmp.iid:ea31ee64-8669-4f48-addf-e41f938f5f1d', 
    'Xmp.xmpMM.History[2]/stEvt:when': '2021-07-26T18:57:55+08:00', 
    'Xmp.xmpMM.History[2]/stEvt:softwareAgent': 'Adobe Photoshop CC 2017 (Windows)', 
    'Xmp.xmpMM.History[2]/stEvt:changed': '/', 
    'Xmp.dc.format': 'image/jpeg'}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    跟时间相关的有:

    {'Xmp.xmp.ModifyDate': '2021-07-26T18:57:55+08:00', 
    'Xmp.xmp.CreateDate': '2021-07-26T19:15:47', 
    'Xmp.xmp.MetadataDate': '2021-07-26T18:57:55+08:00', 
    'Xmp.photoshop.DateCreated': '2021-07-26T19:15:47.004', 
    'Xmp.xmpMM.History[1]/stEvt:when': '2021-07-26T18:57:55+08:00', 
    'Xmp.xmpMM.History[2]/stEvt:when': '2021-07-26T18:57:55+08:00'}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    修改方法如下:

    # 构建一个字典
    xmp_dict = {'Xmp.xmp.ModifyDate': '2022-05-25T18:57:55+08:00', 
                'Xmp.xmp.CreateDate': '2022-05-25T19:15:47', 
                'Xmp.xmp.MetadataDate': '2022-05-25T18:57:55+08:00', 
                'Xmp.photoshop.DateCreated': '2022-05-25T19:15:47.004', 
                'Xmp.xmpMM.History[1]/stEvt:when': '2022-05-25T18:57:55+08:00', 
                'Xmp.xmpMM.History[2]/stEvt:when': '2022-05-25T18:57:55+08:00'}
    # 修改XMP数据
    img.modify_xmp(xmp_dict)
    # 打印新的XMP数据
    print(img.read_xmp())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    总结

    通过以上方式我们再用XnView MP去查看图片的元数据就会发现所有元数据的时间信息都发现了改变,再上传也成功了

    本文主要的代码如下:

    # 导入pyexiv2包
    from pyexiv2 import Image
    # 读取图片
    img = Image('./weihuang.jpg')
    # 打印EXIF、IPTC、XMP信息
    print(img.read_exif())
    print(img.read_iptc())
    print(img.read_xmp())
    # 用字典记录目标时间信息
    exif_dict = {'Exif.Image.DateTime': '2022:05:25 18:57:55', 
                'Exif.Photo.DateTimeOriginal': '2022:05:25 19:15:47', 
                'Exif.Photo.DateTimeDigitized': '2022:05:25 19:15:47'}
    iptc_dict = {'Iptc.Application2.DateCreated': '2022-05-25'}
    xmp_dict = {'Xmp.xmp.ModifyDate': '2022-05-25T18:57:55+08:00', 
                'Xmp.xmp.CreateDate': '2022-05-25T19:15:47', 
                'Xmp.xmp.MetadataDate': '2022-05-25T18:57:55+08:00', 
                'Xmp.photoshop.DateCreated': '2022-05-25T19:15:47.004', 
                'Xmp.xmpMM.History[1]/stEvt:when': '2022-05-25T18:57:55+08:00', 
                'Xmp.xmpMM.History[2]/stEvt:when': '2022-05-25T18:57:55+08:00'}
    # 修改EXIF、IPTC、XMP信息
    img.modify_exif(exif_dict)
    img.modify_iptc(iptc_dict)
    img.modify_xmp(xmp_dict)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
  • 相关阅读:
    基于深度学习的Deepfake检测综述
    断点是什么,断点有哪几种类型?
    C++11相较于C++98 标准新增内容:包装器
    Playwright+Python+Pytest:基础方法二次封装简化及链式调用
    手记:把代码上传到Gitee等远程仓库的过程记录及常见问题
    MCE | 癌相关基因 ALK 参与胖瘦调节
    Java中的集合类
    去中心化数字身份(DID)的灵魂绑定
    Linux文件操作命令总结
    麻了,这让人绝望的大事务提交
  • 原文地址:https://blog.csdn.net/qq_33757398/article/details/124962767