TLC
TLC

Reputation: 33

How to extract jpg EXIF metadata from a folder in chronological order

I am currently writing a script to extract EXIF GPS data from a folder of jpg images. I am using os.scandir to extract the entries from the folder but from my understanding os.scandir opens the files in an arbitrary way. I need the images to be opened in chronological order by filename. Below is my current code which works as intended however it does not open the images in the correct order. The files within my image folder are named chronologically like so: "IMG_0097, IMG_0098" etc.

#!/usr/bin/python

import os, exif, folium

def convert_lat(coordinates, ref):
    latCoords = coordinates[0] + coordinates[1] / 60 + coordinates[2] / 3600
    if ref == 'W' or ref == 'S':
        latCoords = -latCoords
    return latCoords

coordList=[]
map = folium.Map(location=[51.50197125069916, -0.14000860301423912], zoom_start = 16)

from exif import Image
with os.scandir('gps/') as entries:
    try:
        for entry in entries:   
            img_path = 'gps/'+entry.name
            with open (img_path, 'rb') as src:
                img = Image(src)            
                if img.has_exif:
                    latCoords = (convert_lat(img.gps_latitude, img.gps_latitude_ref))
                    longCoords = (convert_lat(img.gps_longitude, img.gps_longitude_ref))
                    coord = [latCoords, longCoords]
                    coordList.append(coord)
                    folium.Marker(coord, popup=str(coord)).add_to(map)
                    folium.PolyLine(coordList, color =" red", weight=2.5, opacity=1).add_to(map)
                    print(img_path)
                    print(coord)
                else:
                    print (src.name,'has no EXIF information')
    except:
        print(img_path)
        print("error occured")

map.save(outfile='/home/jamesdean/Desktop/Python scripts/map.html')
print ("Map generated successfully")

Upvotes: 1

Views: 459

Answers (2)

Pedro Maia
Pedro Maia

Reputation: 2732

You can sort a list using the built-in sorted function, Paul made an interesting point and simply sorting without any arguments will work just as fine:

a = ["IMG_0097.jpg", "IMG_0085.jpg", "IMG_0043.jpg", "IMG_0098.jpg", "IMG_0099.jpg", "IMG_0100.jpg"] 
sorted_list = sorted(a)
print(sorted_list)

Output:

['IMG_0043.jpg', 'IMG_0085.jpg', 'IMG_0097.jpg', 'IMG_0098.jpg', 'IMG_0099.jpg', 'IMG_0100.jpg']

In your case you can do:

for entry in sorted(entries):

Upvotes: 0

Paul M.
Paul M.

Reputation: 10809

I would say ditch os.scandir and take advantage of more modern features the standard library has to offer:

from pathlib import Path
from operator import attrgetter

# assuming there is a folder named "gps" in the current working directory...
for path in sorted(Path("gps").glob("*.jpg"), key=attrgetter("stem")):
    print(path) # do something with the current path

The from operator import attrgetter and key=attrgetter("stem") are a bit redundant, but I'm just being explicit about what attribute I would like to use for determining the sorted order. In this case, the "stem" attribute of a path refers to just the name of the file as a string. For example, if the current path has a filename (including extension) of "IMG_0097.jpg", then path.stem would be "IMG_0097". Like I said, the stem is a string, so your paths will be sorted in lexicographical order. You don't need to do any conversion to integers, because your filenames already include leading zeroes, so lexicographical ordering should work just fine.

Upvotes: 2

Related Questions