代码之家  ›  专栏  ›  技术社区  ›  K.Mulier

如何在Windows 11上使用Python从.heic图像文件中提取元数据?

  •  0
  • K.Mulier  · 技术社区  · 2 年前

    我在Windows 11上运行Python 3.10。我需要从中提取元数据 .heic 图像文件。以下是我所尝试的:

    1.ExifRead

    我试过了 ExifRead (参见 https://pypi.org/project/ExifRead/ )但失败了:

    >>> import exifread
    >>> f = open("path/to/img.heic", 'rb')
    >>> tags = exifread.process_file(f)
    Traceback (most recent call last):
      File "C:\Python310\lib\site-packages\exifread\heic.py", line 171, in get_parser
        return defs[box.name]
    KeyError: 'hdlr'
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "C:\Python310\lib\site-packages\exifread\__init__.py", line 137, in process_file
        offset, endian, fake_exif = _determine_type(fh)
      File "C:\Python310\lib\site-packages\exifread\__init__.py", line 109, in _determine_type
        offset, endian = heic.find_exif()
      File "C:\Python310\lib\site-packages\exifread\heic.py", line 268, in find_exif
        meta = self.expect_parse('meta')
      File "C:\Python310\lib\site-packages\exifread\heic.py", line 159, in expect_parse
        return self.parse_box(box)
      File "C:\Python310\lib\site-packages\exifread\heic.py", line 177, in parse_box
        probe(box)
      File "C:\Python310\lib\site-packages\exifread\heic.py", line 195, in _parse_meta
        psub = self.get_parser(box)
      File "C:\Python310\lib\site-packages\exifread\heic.py", line 173, in get_parser
        raise NoParser(box.name) from err
    exifread.heic.NoParser: hdlr
    

    2.皮海夫

    我尝试安装 pyheif 模块,但没有Windows版本。

    3.枕头

    我试着用 pillow 模块(aka PIL ):

    >>> from PIL import Image
    >>> img = Image.open("path/to/img.HEIC")
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "C:\Python310\lib\site-packages\PIL\Image.py", line 3280, in open
        raise UnidentifiedImageError(msg)
    PIL.UnidentifiedImageError: cannot identify image file 'C:/Backup/Pictures_2023/IMG_0620.HEIC'
    
    0 回复  |  直到 2 年前
        1
  •  1
  •   K.Mulier    2 年前

    我找到了一种在Windows 11上提取Python 3.10元数据的方法:

    import subprocess
    
    def get_photo_metadata(filepath):
        filepath = filepath.replace('/', '\\')
        filepath = filepath.replace('\\', '\\\\')
        cmd = f'cmd.exe /c wmic datafile "{filepath}" list full'
        output = subprocess.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            shell=True,
        ).communicate()[0]
        output_utf = output.decode('utf-8', errors='ignore')
        return output_utf
    
    print(
        get_photo_metadata("path/to/img.HEIC")
    )
    

    此打印:

    AccessMask=1507775
    Archive=TRUE
    Caption=C:\Backup\Pictures_2023\CHINA\202308_b\IMG_0620.HEIC
    Compressed=FALSE
    CompressionMethod=
    CreationClassName=CIM_LogicalFile
    CreationDate=20230817080632.333836+120
    CSCreationClassName=Win32_ComputerSystem
    CSName=SKIKK-2022
    Description=C:\Backup\Pictures_2023\CHINA\202308_b\IMG_0620.HEIC
    Drive=c:
    EightDotThreeFileName=c:\backup\pictures_2023\china\202308_b\img_06~3.hei
    Encrypted=FALSE
    EncryptionMethod=
    Extension=HEIC
    FileName=IMG_0620
    FileSize=1823601
    FileType=HEIC File
    FSCreationClassName=Win32_FileSystem
    FSName=NTFS
    Hidden=FALSE
    InstallDate=20230817080632.333836+120
    InUseCount=
    LastAccessed=20230904163653.526369+120
    LastModified=20230808123918.000000+120
    Manufacturer=
    Name=C:\Backup\Pictures_2023\CHINA\202308_b\IMG_0620.HEIC
    Path=\backup\pictures_2023\china\202308_b\
    Readable=TRUE
    Status=OK
    System=FALSE
    Version=
    Writeable=TRUE
    

    注: 我制作了以下脚本来从照片中提取日期:

    import subprocess
    import re
    import datetime
    
    p = re.compile(r'(20\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)\.(\d*)')
    
    def get_photo_dates(filepath) -> datetime.datetime:
        filepath = filepath.replace('/', '\\')
        filepath = filepath.replace('\\', '\\\\')
        cmd = f'cmd.exe /c wmic datafile "{filepath}" list full'
        output = subprocess.Popen(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            shell=True,
        ).communicate()[0]
        output_utf = output.decode('utf-8', errors='ignore')
        dates = []
        for m in p.finditer(output_utf):
            dates.append(
                datetime.datetime(
                    year        = int(m.group(1)),
                    month       = int(m.group(2)),
                    day         = int(m.group(3)),
                    hour        = int(m.group(4)),
                    minute      = int(m.group(5)),
                    second      = int(m.group(6)),
                    microsecond = int(m.group(7)),
                )
            )
        return sorted(dates)
    
        2
  •  1
  •   James    2 年前

    我也一直在努力解决这个问题。Exiftool运行良好,但只支持windows(我正在拼命寻找一种与操作系统无关的替代方案,可以从requirements.txt轻松安装)。

    Anyhoo,给你:

    import exiftool               # Install PyExifTool
    exiftool_path = os.path.abspath("./exiftool.exe")
    os.environ['EXIFTOOL_PATH'] = exiftool_path
    
    def get_metadata(files):
        metadata = []
        with exiftool.ExifToolHelper() as et:
            metadata = et.get_metadata(files)
            return metadata
    

    下载&;根据重命名exiftool https://exiftool.org/install.html 但是,与其把它放在windows文件夹中,不如把它放与脚本相同的文件夹中。我的导入语句处理了“PATH”的内容。

    'files'变量可以是路径,也可以是路径列表(用于处理批处理)。它返回一个字典列表——每个文件一个。

        3
  •  0
  •   Jeff    2 年前

    显然,降级到exifread 2.x也解决了这个问题。请点击此处查看评论: https://github.com/ianare/exif-py/issues/184#issuecomment-1856296220vn

    推荐文章