Extracting EXIF (Meta)Data From Images With Python
This tutorial is the first part of a series where different aspects of programming with Python are explained, using Python and public libraries to make useful tools.
Repository
https://github.com/ianare/exif-py
What will I learn
- Install ExifRead
- What is EXIF data
- Extract EXIF data from images
- Process EXIF data
- Analyse images
Requirements
- Python3.6
- ExifRead
Difficulty
- basic
Tutorial
Setup
Download the files from Github. There are 6 files. The code is contained in exif.py
the other 5 files are images which can be used to test the code on. exif.py
takes 1 argument which is the filename for the image. In addition, the argument analysis
is used to perform a model analysis on all the images.
Run scripts as following:
> python exif.py 1.jpg
Install ExifRead
Installation of the required package is recommended using the PyPI package manager.
pip install exifread
What is EXIF data
Also referred to as metadata
. When taking a photo the device stores a lot of additional information inside the image file. Information like the datetime
and location
or more specific data like theISO
, aperture
and focal length
. This information can be used by photographers when comparing images to see which settings worked best, learning from other photographers by looking at which settings they used or data analysis.
(Right click->get info (for Mac))
Extract EXIF data from images
Processing the image with exifread.process_image()
returns a dictionary containing all the EXIF
data.
def process_image(filename):
# Open image file for reading (binary mode)
f = open(filename, 'rb')
# Return Exif tags
tags = exifread.process_file(f)
return tags
Quite a lot of information can be stored which also adds to the image file size. Photographer can choice to omitEXIF
data to to save on bandwidth or to keep information about their ways of working private.
{
'Image Make': (0x010F) ASCII = SONY @ 110,
'Image Model': (0x0110) ASCII = ILCE - 7 M3 @ 116,
'Image XResolution': (0x011A) Ratio = 240 @ 126,
'Image YResolution': (0x011B) Ratio = 240 @ 134,
'Image ResolutionUnit': (0x0128) Short = Pixels / Inch @ 66,
.
.
.
}
Process EXIF data
Photographers often share the main settings used for capturing a photo and what gear was used. For this example the data will be extracted from the the image and put into a html table
for easy sharing. The same works for applying the code on a downloaded image from the web, learning more how the image was taken. The code can easily be adjusted depending on which data is needed.
def create_table(tags):
# extract required data
brand = tags['Image Make']
model = tags['Image Model']
date = tags['Image DateTime']
shutterspeed = tags['EXIF ExposureTime']
focallength = tags['EXIF FocalLength']
aperture = tags['EXIF FNumber']
iso = tags['EXIF ISOSpeedRatings']
lens = tags['EXIF LensModel']
# generate a htlm table
print('<table>')
print(f'<tr><td>Settings</td><td><b>ISO {iso} {focallength} ' +
f' mm f/{aperture} {shutterspeed} sec </b></td></tr>')
print(f'<tr><td>Camera</td><td><b>{brand} {model}</b></td></tr>')
print(f'<tr><td>Lens</td><td><b>{lens}</b></td></tr>')
print(f'<tr><td>Date</td><td><b>{date}</b></td></tr>')
print('</table>')
Analyse images
Imagine having a batch of images and you want to know which camera was used the most often. By looping through all the images, creating keys for unique camera models
with a value indicating their frequency
this can be easily answered.
def perform_analysis():
# Empty dict
camera_models = {}
# Loop through images 1-5.jpg
for image_num in range(1, 6):
filename = f'{image_num}.jpg'
# Extract str from the IfdTag
model = str(process_image(filename)['Image Model'])
# Fill dict with unique models and increase frequency
if model in camera_models:
camera_models[model] += 1
else:
camera_models[model] = 1
print(camera_models)
Running the code
Five photos come with the code, running exif.py
on the first three of them shows how useful EXIF
data is when working with different cameras and different lenses.
python exif.py 1.jpg
Settings | ISO 100 192 mm f/11 3/5 sec |
Camera | SONY ILCE-7M3 |
Lens | FE 70-200mm F4 G OSS |
Date | 2018:07:04 20:56:11 |
python exif.py 2.jpg
Settings | ISO 3200 50 mm f/16/5 1/60 sec |
Camera | NIKON CORPORATION NIKON D7500 |
Lens | 50.0 mm f/1.8 |
Date | 2017:12:17 17:24:47 |
python exif.py 3.jpg
Settings | ISO 100 32 mm f/25 13 sec |
Camera | NIKON CORPORATION NIKON D3400 |
Lens | 18.0-140.0 mm f/3.5-5.6 |
Date | 2018:05:11 01:46:48 |
Using the argument analysis
will perform the analysis, looping over all the images and counting which model
camera was used with what frequency
.
python exif.py analysis
{'ILCE-7M3': 3, 'NIKON D7500': 1, 'NIKON D3400': 1}
The code for this tutorial can be found on Github!
This tutorial was written by @juliank.
Hi! Seems
exif
now become like a standard de'facto for inserting and extracting metadata from image file. Curious if it can insert or extract metadata from.gif
?There is also technique called steganography which can hide information like text or image inside the original image, what do you think if using that instead of exif? (by the way I hid some image in my steemit profile picture xD)
Hey @drsensor
Here's a tip for your valuable feedback! @Utopian-io loves and incentivises informative comments.
Contributing on Utopian
Learn how to contribute on our website.
Want to chat? Join us on Discord https://discord.gg/h52nFrV.
Vote for Utopian Witness!
Nice, I've used
exifread
in Python to extract JPEG metadata such as the timestamp and GPS coordinates of the photo. IIRC, I tried scikit-image, but it was overkill and much less straightforward.Nice! I also found exifread very straightforward to work with. Do not know about scikit-image, did not have to look further as this worked quite well ;p
I tried downloading images from an url in python and extracting the EXIF data from the downloaded image, but could not get this to work. For some reason the EXIF data got omitted, while downloading the image manually did make it work.
Hmm. I feel like it should be possible to extract EXIF metadata from an image URL. The
exifread.process_file
source code seems to expect a bytestream file-like object. If you're usingrequests
, did you try wrappingresponse.content
inio.BytesIO
before passing it toexifread.process_file
?I did not, will look into at a later time. Thanks for the tip
Thanks a lot for your hard work.
I'm not your best student, but your post are very useful for me for approach to python and the steem blockchain.
and also exif and a lot more, of course... !!
;-)
Regards.
Hey @steempytutorials
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!
Want to chat? Join us on Discord https://discord.gg/h52nFrV.
Vote for Utopian Witness!
Thank you for your contribution.
The tutorial is basic however it is interesting.
Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.
To view those questions and the relevant answers related to your post, click here.
Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]
Отличная статья. Мне очень понравилось. Удачи Вам и Любви
Excellent article. I really liked it. Good luck to you and Love.
Thats is amazing ☺
how to work this project
Nicely done @steempytutorials. Although am curious to know if the PyPI package could be available to be installed on Qpython for mobile. It would be a really valuable package while trying to write code on the go.
Do you know a way to get at the exif data for cr2 raw files?