Extracting EXIF (Meta)Data From Images With Python

in #utopian-io6 years ago (edited)

banner.png

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.


Screenshot 2018-07-10 16.19.36.png
(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,
  .
  .
  .
}

Pastebin to the entire EXIF

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.


1.jpg

python exif.py 1.jpg

SettingsISO 100 192 mm f/11 3/5 sec
CameraSONY ILCE-7M3
LensFE 70-200mm F4 G OSS
Date2018:07:04 20:56:11

2.jpg

python exif.py 2.jpg

SettingsISO 3200 50 mm f/16/5 1/60 sec
CameraNIKON CORPORATION NIKON D7500
Lens50.0 mm f/1.8
Date2017:12:17 17:24:47

3.jpg

python exif.py 3.jpg

SettingsISO 100 32 mm f/25 13 sec
CameraNIKON CORPORATION NIKON D3400
Lens18.0-140.0 mm f/3.5-5.6
Date2018:05:11 01:46:48

Using the argument analysis will perform the analysis, looping over all the images and counting which modelcamera 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.

Sort:  

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 using requests, did you try wrapping response.content in io.BytesIO before passing it to exifread.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?

Coin Marketplace

STEEM 0.21
TRX 0.20
JST 0.033
BTC 97859.91
ETH 3296.28
USDT 1.00
SBD 3.01