使用Python检索图像描述(不通过PIL或exifread返回EXIF数据)

3

我想获取一个 .jpg 图像的描述。它会显示在Mac OSx信息(cmd + i)窗口中。

Mac OS Info

我想读取“描述”(德语中的“Beschreibung”)字段。试用PIL和exifread都没有成功。

我可以获取这些EXIF标签,但它们不包括描述或关键词。

Key: Image ImageWidth
Key: Image ImageLength
Key: Image Compression
Key: Image Make
Key: Image Model
Key: Image XResolution
Key: Image YResolution
Key: Image PlanarConfiguration
Key: Image ResolutionUnit
Key: Image Software
Key: Image DateTime
Key: Image YCbCrPositioning
Key: Image ExifOffset
Key: Thumbnail Compression
Key: Thumbnail Orientation
Key: Thumbnail XResolution
Key: Thumbnail YResolution
Key: Thumbnail ResolutionUnit
Key: Thumbnail DateTime
Key: Thumbnail JPEGInterchangeFormat
Key: Thumbnail JPEGInterchangeFormatLength
Key: EXIF ExposureTime
Key: EXIF FNumber
Key: EXIF ExposureProgram
Key: EXIF ISOSpeedRatings
Key: EXIF SensitivityType
Key: EXIF ExifVersion
Key: EXIF DateTimeOriginal
Key: EXIF DateTimeDigitized
Key: EXIF ComponentsConfiguration
Key: EXIF ShutterSpeedValue
Key: EXIF ApertureValue
Key: EXIF ExposureBiasValue
Key: EXIF MaxApertureValue
Key: EXIF MeteringMode
Key: EXIF LightSource
Key: EXIF Flash
Key: EXIF FocalLength
Key: EXIF SubSecTimeOriginal
Key: EXIF SubSecTimeDigitized
Key: EXIF ColorSpace
Key: EXIF ExifImageWidth
Key: EXIF ExifImageLength
Key: EXIF FocalPlaneXResolution
Key: EXIF FocalPlaneYResolution
Key: EXIF FocalPlaneResolutionUnit
Key: EXIF SensingMethod
Key: EXIF FileSource
Key: EXIF SceneType
Key: EXIF CVAPattern
Key: EXIF CustomRendered
Key: EXIF ExposureMode
Key: EXIF WhiteBalance
Key: EXIF DigitalZoomRatio
Key: EXIF FocalLengthIn35mmFilm
Key: EXIF SceneCaptureType
Key: EXIF GainControl
Key: EXIF Contrast
Key: EXIF Saturation
Key: EXIF Sharpness
Key: EXIF SubjectDistanceRange
Key: EXIF BodySerialNumber
Key: EXIF LensSpecification
Key: EXIF LensModel

我假设这些字段不是EXIF数据?为了获取描述,我需要查找什么内容?


你在exif数据中找到了描述字段在哪里? - DapperDuck
@DapperDuck,我无法通过PIL或exif读取在exif数据中找到它。因此,我需要找到它隐藏的位置... - moritz
3个回答

3

感谢@Mark Serchell的答案,我发现描述中没有EXIF数据,而是IPTC数据(exiftool显示所有字段)。

在Python中,我现在可以使用IPTCInfo3:https://pypi.org/project/IPTCInfo3/ 并通过以下方式提取描述:

info = IPTCInfo('img.jpg')
info['caption/abstract']

这将打印:

b'Gel\xe4ndewagen auf den Salzformationen im Salzsee Ass-Ale in der Danakil-Senke, Danakil-Senke, Hamed Ela, Wollo, \xc4thiopien, Afrika

1
这个答案可以帮助未来查看此问题的用户。请将其标记为已接受的答案! - DapperDuck
1
感谢您与 Stack Overflow 社区分享您的发现。请继续接受您自己的答案并获得积分 :-) - Mark Setchell

1

通常情况下,元数据可能隐藏在多个位置,并且有一些技巧可以用来查找它。我将在我的答案的不同部分写几句话。


您所需的数据可能在文件的 "扩展属性"xattr 中。如果您在终端中运行以下命令,就可以看到它们:
ls -l image.jpg

-rw-r--r--@ 1 mark  staff  214557  2 Jan 15:47 image.jpg

任何带有"扩展属性"的文件,在其权限之后都会有@。然后,您可以使用以下命令查看扩展属性:

ls -@l image.jpg

-rw-r--r--@ 1 mark  staff  2219100  3 Jan 18:07 image.jpg
    com.apple.lastuseddate#PS        16 
    com.apple.quarantine         22 

查看带有 man xattr 的手册页面。
数据可能在您的文件的EXIF部分中。处理EXIF数据的最佳工具是exiftool,请尝试以下命令:
exiftool -v -v image.jpg 

您可以使用HomebrewmacOS上安装exiftool,具体命令如下:
brew install exiftool

当你在Mac上创建文件时,苹果会进行各种索引,因此数据可能在元数据数据库中。你可以像这样使用mdls进行检查:

mdls image.jpg

样例输出

_kMDItemDisplayNameWithExtensions      = "image.jpg"
kMDItemAcquisitionMake                 = "Apple"
kMDItemAcquisitionModel                = "iPhone 4"
kMDItemAltitude                        = 1.128681019549616
kMDItemAperture                        = 2.970853573907009
kMDItemBitsPerSample                   = 32
kMDItemColorSpace                      = "RGB"
kMDItemContentCreationDate             = 2013-03-09 08:59:50 +0000
kMDItemContentCreationDate_Ranking     = 2013-03-09 00:00:00 +0000
kMDItemContentModificationDate         = 2013-03-09 08:59:50 +0000
kMDItemContentModificationDate_Ranking = 2013-03-09 00:00:00 +0000
kMDItemContentType                     = "public.jpeg"
kMDItemContentTypeTree                 = (
    "public.jpeg",
    "public.image",
    "public.data",
    "public.item",
    "public.content"
)
kMDItemCreator                         = "6.1.2"
kMDItemDateAdded                       = 2021-01-03 18:07:34 +0000
kMDItemDateAdded_Ranking               = 2021-01-03 00:00:00 +0000
kMDItemDisplayName                     = "image.jpg"
kMDItemDocumentIdentifier              = 0
kMDItemEXIFVersion                     = "2.2.1"
kMDItemExposureMode                    = 0
kMDItemExposureProgram                 = 2
kMDItemExposureTimeSeconds             = 0.001094091903719912
kMDItemFlashOnOff                      = 0
kMDItemFNumber                         = 2.8
kMDItemFocalLength                     = 3.85
kMDItemFocalLength35mm                 = 35
kMDItemFSContentChangeDate             = 2021-01-03 18:07:34 +0000
kMDItemFSCreationDate                  = 2021-01-03 18:07:34 +0000
kMDItemFSCreatorCode                   = ""
kMDItemFSFinderFlags                   = 0
kMDItemFSHasCustomIcon                 = (null)
kMDItemFSInvisible                     = 0
kMDItemFSIsExtensionHidden             = 0
kMDItemFSIsStationery                  = (null)
kMDItemFSLabel                         = 0
kMDItemFSName                          = "image.jpg"
kMDItemFSNodeCount                     = (null)
kMDItemFSOwnerGroupID                  = 20
kMDItemFSOwnerUserID                   = 501
kMDItemFSSize                          = 2219100
kMDItemFSTypeCode                      = ""
kMDItemGPSDateStamp                    = "2013:03:09"
kMDItemHasAlphaChannel                 = 0
kMDItemImageDirection                  = 324.4435483870968
kMDItemInterestingDate_Ranking         = 2019-08-27 00:00:00 +0000
kMDItemISOSpeed                        = 80
kMDItemKind                            = "JPEG image"
kMDItemLastUsedDate                    = 2019-08-27 14:26:14 +0000
kMDItemLastUsedDate_Ranking            = 2019-08-27 00:00:00 +0000
kMDItemLatitude                        = 20.84433333333333
kMDItemLogicalSize                     = 2219100
kMDItemLongitude                       = 107.091
kMDItemMeteringMode                    = 5
kMDItemOrientation                     = 0
kMDItemPhysicalSize                    = 2220032
kMDItemPixelCount                      = 5018112
kMDItemPixelHeight                     = 1936
kMDItemPixelWidth                      = 2592
kMDItemProfileName                     = "sRGB IEC61966-2.1"
kMDItemRedEyeOnOff                     = 0
kMDItemResolutionHeightDPI             = 72
kMDItemResolutionWidthDPI              = 72
kMDItemTimestamp                       = "01:59:48"
kMDItemUseCount                        = 1
kMDItemUsedDates                       = (
    "2019-08-26 23:00:00 +0000"
)
kMDItemWhiteBalance                    = 0

你可以尝试一种老式的“暴力破解”方法。"strings"实用程序会在任何二进制文件中寻找类似文本的内容,因此您可以尝试提取任何看起来像一堆字母的东西,并搜索一个相对罕见的单词 - 在您的示例中,我会选择"Wollo",因此您可以执行以下操作以查看字符串"Wollo"是否实际存在于您的文件中 - 否则它可能在其他地方:
strings image.jpg | grep "Wollo"

谢谢,exiftool显示它是一个IPTCApplication记录。我之前在Python中查看exif数据,所以它没有显示出来,谢谢! - moritz

0

提取EXIF是最容易的部分。最困难的部分是解释它们并使它们适用于每个制造商和型号。有些制造商和型号缺少一些标签(例如,富士有LensMake和LensModel,而佳能只有LensModel)。简而言之,可能是这样的。

from PIL import Image
from math import pow
from PIL.ExifTags import TAGS
import datetime

def get_labeled_exif(exif):
    labeled = {}
    for (key, val) in exif.items():
        labeled[TAGS.get(key)] = val

    return labeled

def get_exif(filename):
    image = Image.open(filename)
    image.verify()
    return image._getexif()


def get_shutter_speed(shutter_speed):
    print("shutter_speed = {0}, type = {1}".format(
        shutter_speed, type(shutter_speed)))

    ss_val1 = 0.0
    ss_val2 = 0.0

    if type(shutter_speed) != type(list):
        ss_val1 = shutter_speed
        ss_val2 = 0

        ss = (str(ss_val1/1) + "s") if ss_val1 > 0 else str(ss_val1)+"s"

        return ss
    
    ss_val1 = float(shutter_speed[0])
    ss_val2 = float(shutter_speed[1])

    ss = ss_val1/ss_val2

    return str(round(1/pow(2, ss))) + \
        "s" if ss_val1 < 0 else "1/"+str(round(pow(2, ss)))

def get_aperture(aperture):
    print("aperture = {0}, type(aperture) = {1}".format(
        aperture, type(aperture)))
    ap_val1 = 0.0
    ap_val2 = 0.0

    if type(aperture) != type(list):
        ap = float(aperture)
    else:
        ap_val1 = float(aperture[0])
        ap_val2 = float(aperture[1])
        
        ap = ap_val1/ap_val2
    
    print("get_aperture:: ap_val1 = {0}, ap_val2 = {1}, aperture = {2}".format(ap_val1, ap_val2, ap))
    return "f/"+str(ap)

def get_exposure_mode(mode):
    if mode == 0:
        return "Auto"
    elif mode == 1:
        return "Manual"
    else:
        return "Auto Bracket"

def get_light_source(ls_val):
    if ls_val==10:
        return "Cloudy Weather"
    elif ls_val==13:
        return "Cool White Fluorescent"
    elif ls_val==1:
        return "Daylight"
    elif ls_val==12:
        return "Daylight Fluorescent"
    elif ls_val==13:
        return "Day White Fluorescent"
    elif ls_val==9:
        return "Fine Weather"
    elif ls_val==4:
        return "Flash"
    elif ls_val==2:
        return "Fluorescent"
    elif ls_val==11:
        return "Shade"
    elif ls_val==3:
        return "Tungsten (Incandescent Light)"
    elif ls_val==15:
        return "White Fluorescent"
    else:
        return "Other Light Source"


def printFujifilmExif(labeled):
    shutter_speed = get_shutter_speed(labeled['ExposureTime'])

    aperture = get_aperture(labeled['FNumber'])

    format = "%Y:%m:%d %H:%M:%S"
    date_created = datetime.datetime.strptime(labeled['DateTimeOriginal'], format)

    exposure_mode = get_exposure_mode(labeled['ExposureMode'])
    light_source = get_light_source(
        labeled['LightSource'])  # LightSource for Fujifilm

    iso_value = labeled['ISOSpeedRatings']
    camera_make = labeled['Make']
    camera_model = labeled['Model']

    lens_make = labeled['LensMake']  # LensMake for Fujifilm
    lens_model = labeled['LensModel']  # LensModel for Fujifilm
    software = labeled['Software']

    print("\n\nPRINTING PROFILE FOR FUJIFILM***")
    print("Camera Make: {0}".format(camera_make))
    print("Camera Model: {0}".format(camera_model))
    print("Lens Make: {0}".format(lens_make))
    print("Lens Model: {0}".format(lens_model))
    print("Date taken: {0}".format(date_created))
    print("Aperture: {0}".format(aperture))
    print("Shutter speed: {0}".format(shutter_speed))
    print("ISO: {0}".format(iso_value))
    print("Exposure mode: {0}".format(exposure_mode))
    print("Light source: {0}".format(light_source))
    print("Softwawre = {0}".format(software))

def printExifInfo(file_name):
    exif = get_exif(file_name)
    labeled = get_labeled_exif(exif)
    print("EXIF: {0}\n\n".format(labeled))

    if labeled['Make'].upper()=="FUJIFILM":
        printFujifilmExif(labeled)
    else:
        printCanonExif(labeled)


print("****Printing Fujifilm profile****")
printExifInfo('DSCF3846_Lowres.jpg')

示例输出

打印富士胶片的设置信息:
EXIF:{'ResolutionUnit': 2, 'ExifOffset': 446, 'Make': 'FUJIFILM', 'Model': 'GFX 50S', 'Software': 'GIMP 2.10.18','DateTime': '2021:05:14 22:58:13','Copyright': '
', 'XResolution': 72.0, 'YResolution': 72.0, 'ExifVersion': b'0230','ShutterSpeedValue': 8.965784,'ApertureValue': 4.970854,'DateTimeOriginal': '2021:05:14 15:51:42','DateTimeDigitized':'2021:05:14 15:51:42','BrightnessValue': 9.94,'ExposureBiasValue': 0.0,'MaxApertureValue': 5.0,'MeteringMode': 5,'LightSource': 1,'Flash': 0,'FocalLength': 196.5,'ColorSpace': 1,'ExifImageWidth':7333,'FocalPlaneXResolution': 914.0,'FocalPlaneYResolution': 914.0,'ExifImageHeight': 5500,'FocalPlaneResolutionUnit': 3,'Sharpness': 0,'SubjectDistanceRange': 0,'SensingMethod': 2,'FileSource': b'\x03','ExposureTime': 0.002,'FNumber': 5.6,'SceneType': b'\x01','ExposureProgram': 1,'CustomRendered': 0,'ISOSpeedRatings': 100,'ExposureMode': 1,'SensitivityType': 1,'StandardOutputSensitivity': 100,'WhiteBalance': 1,'BodySerialNumber': '72012151','LensSpecification': (196.5, 196.5, 5.656854256854257, 5.656854256854257),'LensMake': 'FUJIFILM','LensModel': 'GF100-200mmF5.6 R LM OIS WR','LensSerialNumber': '88A10682','FocalLengthIn35mmFilm': 155,'SceneCaptureType': 0}
shutter_speed = 0.002,type = <class'PIL.TiffImagePlugin.IFDRational'> 快门速度不是一个列表。快门速度值:0.002,类型 <class'PIL.TiffImagePlugin.IFDRational'> get_shutter_speed :: ss_val1 = 0.002,ss = 1/500s 光圈值:5.6,类型(光圈)= <class'PIL.TiffImagePlugin.IFDRational'> get_aperture :: ap_val1 = 0.0,ap_val2 = 0.0,光圈 = 5.6
打印富士胶片的设置信息:
相机制造商:FUJIFILM 相机型号:GFX 50S 镜头制造商:FUJIFILM 镜头型号:GF100-200mmF5.6 R LM OIS WR 拍摄日期:2021年05月14日 光圈:f/5.6 快门速度:1/500s 感光度:100 曝光模式:手动 光源:日光 软件 = GIMP 2.10.18

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接