Creating a photo key map and table with R

A complicated approach to make a simple map.

mapping
R
Author
Published

March 6, 2021

A simple table of photos with a corresponding photo key map is a common type of figure for many different planning documents and reports. Typically, making this type of map can be a bit tedious: pulling a base map into Adobe Illustrator (or another graphics editor), marking the location of each photo on the map, and hoping you don’t get anything mixed up.

This post illustrates a reproducible process for making this style of map using R. Using the coordinates embedded in the photo metadata, you can make a map and then combine the map with an table showing each photo alongside a short description pulled from the embedded title or description. At the end, I show how you can use the same approach using photos from Flickr.

Check your photo metadata at the start

Get started by checking the location metadata attached to your photographs. By default, every photo you take with your cell phone saves your location when you took the photo to the Exif metadata attached to the image file. The accuracy of coordinates attached to photographs varies but you can you can check and update the location associated with the photograph using the OSX Photos app or a dedicated utility like GeoTag for OSX or GeoSetter for Windows.

I also used the Photos app to add a brief description to each image (as the title for each photo). You could also add titles or modify coordinates for one or more images after importing the image exif metadata by modifying the data frame.

Read the Exif metadata from photos with exiftoolr

Once you have a folder of photos with locations and descriptions, you want to use the exiftoolr package to import the image metadata. Josh OBrien describes this package as a wrapper around ExifTool “a comprehensive open source utility for reading, writing and editing meta information in a wide variety of files.” You can use the exiftoolr::install_exiftool function to install ExifTool (if you don’t have it installed already).

For this example, I am using five photographs of Baltimore’s Ellwood Park neighborhood. I added titles to each image in the Photos app then exported them to the jpg subfolder I created in the image folder for this post. The following code shows how to use purrr::map_dfr to import selected metadata for each image, sort the images by longitude, and then number the images in order.

Make a photo table with gt

Now that we have the metadata for all of the images in a data frame, I can use gt to display the images and descriptions in a simple HTML table.

gt currently supports image columns created using local images, web images, or images created with ggplot. The example for the local_image helper function in the gt documentation is a bit unclear but I found a helpful example from a user on Stackoverflow that I adapted below.

I want the numbers in the table to match the style I plan to use for the key map so I am using the html helper function from gt to stack the number on a FontAwesome circle icon.

Description # Photo
Tres Amigas / Three Friends (2015; Pablo Machioli, Edgar Reyes, and area youth, muralists) Jefferson Street and N. Decker Street 1
Rowhouses, 3100 block of McElderry Street (north side) 2
Rowhouses, 411-415 N. Ellwood Avenue 3
Rowhouses, 400 block of N. Robinson Street (east side) 4
Formstone-covered backs of rowhouses, 300 block of Loney Lane (west side) 5

One caution: this approach only works with images that have a consistent orientation and aspect ratio so mixing images with a mix portrait and landscape orientations will result in distorted images.

Make a key map with sf and snapbox

Next, I can put the images onto a map. The first step to making the map is to convert the data frame containing the image Exif data into a simple features (sf) object and then transform the sf object to use a projected coordinate reference system (CRS).

I’m transform the data to a projected CRS so I can use the adjust_bbox function from my own mapbaltimore package to define the map area. This function returns a bounding box that contains all of the photo locations with a little extra space (fifty meters) around the edges and a set aspect ratio (4 by 3).

The next step is to make the map base layer using the layer_mapbox function from the maplayer package. For this to work, you need to a Mapbox API key to pass to the function or to save it to your local environment using mapboxapi::mb_access_token().1

Now I can mark the location of each photograph with the corresponding number on top of the base map. Sorting by latitude or longitude before numbering the images is one easy way to make the number placement predictable.2

There are other ways to label the key map. For example, I could use the the exif data again to show where direction I was facing when I took each photo and use the geom_label_repel from the ggrepel package to offset the location of the numbers.

The offset numbers could definitely be appropriate if you have image locations clustered too close together but the combined effect with the directional arrows looks too busy. I decided to stick with the simple approach for this example.

Combine the key map and photo table

The last step is to combine the photo table and the key map into a single combined figure. I used the ggplot_image function to insert the image in lieu of a subtitle for the table.

Making a key map and table with images from Flickr

This same process works well with photographs from Flickr—again provided that those photos have a location and have titles that you can use as the description in your image table.

To start, I took the code I used to make the map and the table and turned into two functions: make_key_map and make_flickr_key_table.

Getting the photos from Flickr requires both the FlickrAPI package3 and a Flickr API key. You can save the key to the local environment with Sys.setenv(FLICKR_ACCESS_TOKEN = "x") (again substituting your own API key for x). I’m using the getPhotoSearch function to pull images from the Baltimore Heritage Flickr account tagged with the Eager Park, Ellwood Park, or McElderry Park neighborhood names.

Next I convert the data frame of Flickr photos into a sf object. I’m randomly selecting 5 photos from the three neighborhoods making sure only to select landscape oriented images with an associated location.

Finally, I call the make_flickr_key_table function on the sf object. I didn’t include the Font Awesome icons for the numbers in this version of the table but it still looks good to me.

Reuse

Citation

BibTeX citation:
@online{pousson2021,
  author = {Pousson, Eli},
  title = {Creating a Photo Key Map and Table with {R}},
  date = {2021-03-06},
  url = {https://elipousson.github.io/posts/2021-03-06-creating-a-key-map-for-photographs-with-r},
  langid = {en}
}
For attribution, please cite this work as:
Pousson, Eli. 2021. “Creating a Photo Key Map and Table with R.” March 6, 2021. https://elipousson.github.io/posts/2021-03-06-creating-a-key-map-for-photographs-with-r.