Skip to content

Extracting Latitude Longitude from Images

Thomas Schranz edited this page Aug 4, 2017 · 10 revisions

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)