Go program finds photos with nearby GPS coordinates
In the Hood

© Lead Image © Tatiana Venkova, 123RF.com
Every photo you take with your mobile phone stores the GPS location in the Exif data. A Go program was let loose on Mike Schilli's photo collection to locate shots taken within an area around a reference image.
Just recently, my favorite restaurant in San Francisco, Chow, shut down unexpectedly. On top of the traumatic experience of having to find a new eatery, I was overcome by the desire to find old photos of the place from the good old days on my mobile phone. But how? I sure didn't tag them, but who does, anyway? Having said that, every cell phone photo contains GPS information, and the phone's photo app can group the photos as dots on a map.
Of course, over the years, I had outsourced the photos to other media. Not to worry, my new favorite programming language, Go, comes with image processing routines, prompting me to browse my photo collection for photos taken in or near the restaurant.
To-Do
The Unix exiftool
tool finds the metadata of a JPG file in a flash, leaving social media users wondering what juicy bites of data they are giving to Facebook and company when they post them. In addition to the date and time, the altitude, and the direction of the camera, there are also GPS coordinates that record the exact location on the earth's surface where the picture was taken (Figure 1). Online guru Kevin Mitnick even reports that the authorities once tracked down a Bolivian drug lord, because he had published a vacation photo that still contained the metadata of his secret whereabouts [1].
Verbose Photos
Quite surprisingly, in the Exif section of the image file, metadata such as the latitude and longitude of a shot's location are by no means stored in a computer-friendly format. Instead, the mobile phone might put the string 122 deg 25' 46.82'' W
there under the GPS Longitude
tag and the letter W
for western longitude under the GPS Longitude Ref
tag.
To convert this string into something that can be used later to calculate distance from a reference point, you need to use a library function that converts 122 degrees, 25 angular minutes, and 46.82 angular seconds into floating-point format and negates the numerical value for the W
in western longitude, because only eastern longitudes are positive. The result is a value of -122.429672
for the longitude; based on this, along with the latitude, which is determined in a similar way, another library can then determine the geographical offset to the longitude and latitude of another image.
Now the distance between two points on the earth's surface, given as latitude and longitude, cannot be calculated quite as trivially as within a two-dimensional coordinate system. But if you quickly put on your old trigonometry hat from your school days, you can still work it out. The technical term for the curved distance is "orthodrome" ([2], Figure 2); it's a segment of the great circle on the (approximated) spherical surface of the earth, which is why the whole thing is also known as the "great circle distance." Thanks to the Internet, you don't even have to type this by hand, but can turn to a Go library like golang-geo
[3].

With these tools, whipping up an algorithm in the script shown today (Listing 1, [4]) is easy as pie. It accepts a reference image and a search path for the photo collection. It extracts the reference GPS coordinates from the former and then rummages through all the images in the photo collection one after another, comparing their GPS coordinates with the reference and reporting a hit if the distance to the reference image is below a preset minimum.
Listing 1
geosearch.go
Deep Sea Diver
The filepath.Walk
function from Go's core treasure trove plumbs into the depths of the files in the photo collection referenced as a directory no matter how deeply nested. The call in line 45 accepts a callback function (Visit()
defined in line 51). To ensure that this function has the GPS data of the reference image ready for comparisons, a structure of the type Walker
(defined as of line 14) gets created as its receiver, which is how Go ties functions to structs as objects.
First, lines 40 to 43 initialize a Walker
instance in w
by setting the refLat
and refLong
attributes of the GPS data to the values of the reference image, and then Walk()
in line 45 receives w.Visit
as a callback function. Since Visit()
in line 51 is defined with a receiver of the *Walker
type, as a result, the file system walker calls the Visit()
callback function for each file found, but passes the Walker
structure filled with the reference data to it each time, which means that Visit()
can conveniently pick up the location of the reference image in line 63 and use it to compute the offset distance.
The callback also uses a regular expression in line 53 to check whether the file just found also has a .jpg
suffix in its name; thanks to the "(?i)"
expression in the regex string, this also matches uppercase letters as in .JPG
. The somewhat strange MustCompile()
call for compiling the regular expression in line 53 is attributable to Go's strict error management. Every time a function gets called that could possibly go wrong, the program has to check if all systems are go, or an error has occurred, in which case it has to initiate rescue actions. Now, in theory, compiling a regular expression could go wrong (for example, if it contains illegal syntax), but with a static (and hopefully tested) string, this is impossible.
In this way, functions with a "must" in the name, like MustCompile()
for regular expressions, save the programmer from handling errors by internally aborting the program with a Panic()
if something goes wrong. By definition, the function itself does not return an error, because it only returns if everything actually works out.
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Direct Download
Read full article as PDF:
Price $2.95
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Find SysAdmin Jobs
News
-
Kubuntu Focus Announces XE Gen 2 Linux Laptop
Another Kubuntu-based laptop has arrived to be your next ultra-portable powerhouse with a Linux heart.
-
MNT Seeks Financial Backing for New Seven-Inch Linux Laptop
MNT Pocket Reform is a tiny laptop that is modular, upgradable, recyclable, reusable, and ships with Debian Linux.
-
Ubuntu Flatpak Remix Adds Flatpak Support Preinstalled
If you're looking for a version of Ubuntu that includes Flatpak support out of the box, there's one clear option.
-
Gnome 44 Release Candidate Now Available
The Gnome 44 release candidate has officially arrived and adds a few changes into the mix.
-
Flathub Vying to Become the Standard Linux App Store
If the Flathub team has any say in the matter, their product will become the default tool for installing Linux apps in 2023.
-
Debian 12 to Ship with KDE Plasma 5.27
The Debian development team has shifted to the latest version of KDE for their testing branch.
-
Planet Computers Launches ARM-based Linux Desktop PCs
The firm that originally released a line of mobile keyboards has taken a different direction and has developed a new line of out-of-the-box mini Linux desktop computers.
-
Ubuntu No Longer Shipping with Flatpak
In a move that probably won’t come as a shock to many, Ubuntu and all of its official spins will no longer ship with Flatpak installed.
-
openSUSE Leap 15.5 Beta Now Available
The final version of the Leap 15 series of openSUSE is available for beta testing and offers only new software versions.
-
Linux Kernel 6.2 Released with New Hardware Support
Find out what's new in the most recent release from Linus Torvalds and the Linux kernel team.