How can I extract metadata from an image using Python?
Use Pillow
, it's a fork of PIL that is still in active development, and supports python3. Here I use a dict generator to map the exif data to a dict
from PIL import Image, ExifTags
img = Image.open("/path/to/file.jpg")
exif = { ExifTags.TAGS[k]: v for k, v in img._getexif().items() if k in ExifTags.TAGS }
metadata = { ExifTags.TAGS[k]: v for k, v in img._getexif().items() if k in ExifTags.TAGS } builtins.AttributeError: 'NoneType' object has no attribute 'items'
–
Alcock img._getexif()
can return None
so need if img._getexif() else {}
at end of line –
Cabral There is couple of ways by which you can get the data from the file.
1. using Exif tool :
for Windows and mac: it is available at
ExifTool
for linux :
You can install ExifTool on Ubuntu using the apt utility
sudo apt install libimage-exiftool-perl
You can now run ExifTool anywhere in your terminal by typing exiftool. This is recommended approach to get the meta data as it gives more tags than any other way. It is a command line tool and to use it in Python user have to create a subprocess and pass the tool and image file path as an argument. Please refer the below code snippet to get the meta data using exif tool. (
infoDict = {} #Creating the dict to get the metadata tags
exifToolPath = 'D:/ExifTool/exifTool.exe' #for Windows user have to specify the Exif tool exe path for metadata extraction.
#For mac and linux user it is just
"""exifToolPath = exiftool"""
imgPath = 'D:/Images/12.jpg'
''' use Exif tool to get the metadata '''
process = subprocess.Popen([exifToolPath,imgPath],stdout=subprocess.PIPE, stderr=subprocess.STDOUT,universal_newlines=True)
''' get the tags in dict '''
for tag in process.stdout:
line = tag.strip().split(':')
infoDict[line[0].strip()] = line[-1].strip()
for k,v in infoDict.items():
print(k,':', v)
Metadata Result for below image:
Full Tag list is here:
""" ExifTool Version Number : 11.63
File Name : imgMeta.jpg
Directory : /Projects/ImageMetaData/Images
File Size : 32 kB
File Modification Date/Time : 30
File Access Date/Time : 30
File Creation Date/Time : 30
File Permissions : rw-rw-rw-
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
JFIF Version : 1.01
Exif Byte Order : Little-endian (Intel, II)
Make : Canon
Camera Model Name : Canon PowerShot S40
Orientation : Horizontal (normal)
X Resolution : 180
Y Resolution : 180
Resolution Unit : inches
Modify Date : 44
Y Cb Cr Positioning : Centered
Exposure Time : 1/500
F Number : 4.9
Exif Version : 0220
Date/Time Original : 44
Create Date : 44
Components Configuration : Y, Cb, Cr, -
Compressed Bits Per Pixel : 5
Shutter Speed Value : 1/501
Aperture Value : 5.0
Max Aperture Value : 2.8
Flash : Auto, Did not fire
Focal Length : 103.7 mm)
Macro Mode : Normal
Self Timer : Off
Quality : Superfine
Canon Flash Mode : Auto
Continuous Drive : Single
Focus Mode : Single
Record Mode : JPEG
Canon Image Size : Large
Easy Mode : Manual
Digital Zoom : None
Contrast : Normal
Saturation : Normal
Sharpness : 0
Camera ISO : 100
Metering Mode : Center-weighted average
Focus Range : Auto
AF Point : Center
Canon Exposure Mode : Program AE
Lens Type : n/a
Max Focal Length : 21.3125 mm
Min Focal Length : 7.09375 mm
Focal Units : 32/mm
Max Aperture : 5
Min Aperture : 8
Flash Activity : 0
Flash Bits : (none)
Focus Continuous : Single
AE Setting : Normal AE
Display Aperture : 4.9
Zoom Source Width : 2272
Zoom Target Width : 2272
Spot Metering Mode : AF Point
Focal Type : Zoom
Focal Plane X Size : 7.26 mm
Focal Plane Y Size : 5.46 mm
Auto ISO : 100
Base ISO : 100
Measured EV : 13.63
Target Aperture : 5
Target Exposure Time : 1/501
Exposure Compensation : 0
White Balance : Auto
Slow Shutter : Off
Shot Number In Continuous Burst : 0
Optical Zoom Code : 6
Flash Guide Number : 0
AF Points In Focus : Center
Flash Exposure Compensation : 0
Auto Exposure Bracketing : Off
AEB Bracket Value : 0
Control Mode : Camera Local Control
Focus Distance Upper : 7.82 m
Focus Distance Lower : 0 m
Bulb Duration : 0
Camera Type : Compact
Canon Image Type : PowerShot S40 JPEG
Canon Firmware Version : Firmware Version 1.10
File Number : 117-1771
Owner Name : Andreas Huggel
Canon Model ID : PowerShot S40
User Comment :
Flashpix Version : 0100
Color Space : sRGB
Exif Image Width : 2272
Exif Image Height : 1704
Interoperability Index : R98 - DCF basic file (sRGB)
Interoperability Version : 0100
Related Image Width : 2272
Related Image Height : 1704
Focal Plane X Resolution : 8114.285714
Focal Plane Y Resolution : 8114.285714
Focal Plane Resolution Unit : inches
Sensing Method : One-chip color area
File Source : Digital Camera
Custom Rendered : Normal
Exposure Mode : Auto
Digital Zoom Ratio : 1
Scene Capture Type : Standard
Compression : JPEG (old-style)
Thumbnail Offset : 2066
Thumbnail Length : 5448
Image Width : 480
Image Height : 360
Encoding Process : Baseline DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : 0 (2 2)
Drive Mode : Single-frame Shooting
ISO : 100
Lens : 34.5 - 103.7 mm)
Shooting Mode : Program AE
Aperture : 4.9
Image Size : 480x360
Lens ID : Unknown 7-21mm
Megapixels : 0.173
Scale Factor To 35 mm Equivalent : 4.9
Shutter Speed : 1/500
Thumbnail Image : (Binary data 5448 bytes, use -b option to extract)
Circle Of Confusion : 0.006 mm
Depth Of Field : 2.17 m (3.11 - 5.28 m)
Field Of View : 19.7 deg
Hyperfocal Distance : 15.02 m
Light Value : 13.6 """
2. using PIL package :
Refer any of the other post for this method. However the drawback of using this method is it doesn't works with all the images.
3. using hachoir package :
Similar to exif tool, it is also a command line tool except that it's a python package
and user can install it using pip install hachoir
. It can give metadata for most of the file formats but gives less information than Exif tool.
imgPath = 'D:/Images/12.jpg'
exeProcess = "hachoir-metadata"
process = subprocess.Popen([exeProcess,imgPath],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
universal_newlines=True)
for tag in process.stdout:
line = tag.strip().split(':')
infoDict[line[0].strip()] = line[-1].strip()
for k,v in infoDict.items():
print(k,':', v)
"""for same image : only 31 tags are identified by hachoir Method however Exif method is giving 131 tags """
Full tag list extracted by hachoir is below :
""" Metadata :
Image width : 480 pixels
Image height : 360 pixels
Image orientation : Horizontal (normal)
Bits/pixel : 24
Pixel format : YCbCr
Image DPI width : 72 DPI
Image DPI height : 72 DPI
Creation date : 44
Camera aperture : 2.97
Camera focal : 4.9
Camera exposure : 1/500
Camera model : Canon PowerShot S40
Camera manufacturer : Canon
Compression : JPEG (Baseline)
Thumbnail size : 5448 bytes
EXIF version : 0220
Date-time original : 44
Date-time digitized : 44
Compressed bits per pixel : 5
Shutter speed : 8.97
Aperture : 4.66
Exposure bias : 0
Focal length : 21.3
Flashpix version : 0100
Focal plane width : 8.11e+03
Focal plane height : 8.11e+03
Comment : 75%
Format version : JFIF 1.01
MIME type : image/jpeg
Endianness : Big endian
"""
png
images –
Winifield You can extract metadata with PIL Exif library for Python :
from PIL import Image
from PIL.ExifTags import TAGS
After you can pass the image file path to open the image and read data of corresponding exif tags :
# path to the image or video
imagename = "IMG_20220306_095310.jpg"
# read the image data using PIL
image = Image.open(imagename)
# extract EXIF data
exifdata = image.getexif()
# iterating over all EXIF data fields
for tag_id in exifdata:
# get the tag name, instead of human unreadable tag id
tag = TAGS.get(tag_id, tag_id)
data = exifdata.get(tag_id).decode("utf-16")
print(f"{tag:25}: {data}")
You can use following python code for this.
#!/bin/python
import os
import sys
from PIL import Image
from PIL.ExifTags import TAGS
image = sys.argv[1]
for (tag,value) in Image.open(image)._getexif().iteritems():
print '%s = %s' % (TAGS.get(tag), value)
some camera manufacturers add XMP data to images, and that data can be read easily with libxmp
(pip install python-xmp-toolkit).
I wrote a function to extract data from DJI drone images:
from libxmp.utils import file_to_dict
def read_xmp_data(image_path: Path):
xmp_dict = file_to_dict(str(image_path))
exif_dict = {}
dji_data = {}
# debug printout - helped me to find tag keywords in 'purl.org'
print(k)
for k in xmp_dict.keys():
if 'drone-dji' in k:
for element in xmp_dict[k]:
dji_data[element[0].replace('drone-dji:', '')] = element[1]
if 'exif' in k:
for element in xmp_dict[k]:
exif_dict[element[0].replace('exif:', '')] = element[1]
return dji_data, exif_dict
read_xmp_data("image.jpg")
A remark from editor: python-xmp-toolkit
was released in 2014 and it was archived by the owner on github Feb 20, 2023 (https://github.com/python-xmp-toolkit/python-xmp-toolkit). I used fstop
(on android) to tag images, geeqie
sees the Keywords. This solution is revealing them.
Thank you assaf-ge.
© 2022 - 2024 — McMap. All rights reserved.