Förderjahr 2016 / Projekt Call #11 / ProjektID: 1983 / Projekt: Prometheus
Extracting Latitude/Longitude from Images
Nowadays images from photo cameras including those in smart phones often come with a lot of useful metadata.
Fortunately there already exists an extensive and widely used Java library called metadata-extractor and a Clojure wrapper for it called exif-processor that we can use to extract this information.
Add [io.joshmiller/exif-processor "0.2.0"]
to your :dependencies
in project.clj
.
First we require exif-processor.core
and clojure.edn
on the top of our file as we will be using them later
(ns exifdemo.core (:require [haversine.core :as haversine] [exif-processor.core :as exif] [clojure.edn :as edn]))
The geolocation information we get from the library is in a format that looks like this:
50° 49' 8.59"
These are coordinates represented as a string containing degrees, minutes and seconds. Since we want to convert them to decimal degrees later we can use a regular expression to extract the numbers from the string and use edn
to parse the numbers we've extracted.
; a regular expression pattern that we can use to extract numbers from a string (def numbers-pattern #"[0-9]+[.]?[0-9]*") ; turns coordinate information represented as string "50° 49' 8.59" into numbers for degrees, minutes and seconds (50 49 8.59) (defn parse-coordinate [s] (map edn/read-string (re-seq numbers-pattern s))) ; here we access the metadata of the image file, fetch its latitude and longitude and parse the coordinates ; you can use exif/exif-for-url to fetch an image from a URL instead of from the file system (let [metadata (exif/exif-for-filename "/Users/tosh/Downloads/harbor-gps.jpg") latitude (parse-coordinate (get metadata "GPS Latitude")) longitude (parse-coordinate (get metadata "GPS Longitude"))] (def latlng [latitude longitude]))
Now we just need to convert our coordinates to decimal form.
; helper function to convert degrees, minutes and seconds to decimal coordinates (defn dms-to-decimal [degrees minutes seconds] (+ degrees (/ minutes 60) (/ seconds 3600))) {:latitude (apply dms-to-decimal (first latlng)) :longitude (apply dms-to-decimal (second latlng))}
Further reading
https://en.wikipedia.org/wiki/Exif
https://github.com/drewnoakes/metadata-extractor-images/wiki (sample images)
https://github.com/drewnoakes/metadata-extractor/wiki/SampleOutput (sample output)