Background: Geotagging in Flickr

As you learned in Chapter 1, geotagging in Flickr started with people using tags (specifically, geotagged and geo:lon, geo:lat) to associate a latitude and longitude with a given photo. This way of geotagging was very popular. Lots of people started creating geotagged photos. Moreover, programs arose to both display geotagged photos (such as GMiF and Geobloggers) and create geotagged photos.

This approach (what I refer here as old-style geotagging), as cool as it was, was a hack. Flickr moved to institutionalize geotagging, into what I refer to as new-style geotagging. First, Flickr created the framework of machine tags to clean up the clutter. Clearly, there was a desire for developers (spurred on by serving users) to add extra metadata to Flickr photos. The result was that data meant for machine consumption was pushed into tags, which were geared more for people manually sticking in descriptions. Flickr decided to take tags of the following form and make them into machine tags:

namespace:predicate=value

For example, the geo:lat= and geo:lon= tags have become machine tags. This means they are not displayed by default in the UI. Rather, a user needs to click the “Show machine tags” link to see these machine tags. (The thinking is that machine tags weren’t really for human consumption—so why display them?)

Let’s consider a geotagged photo that we already looked at in Chapter 1 (“Campanile in the Fog”):

http://flickr.com/photos/raymondyee/18389540/

You can see the relevant geotags under Tags by clicking “Show machine tags” to reveal this:

geo:lon=-122.257704
geo:lat=37.8721
      

You can use the Flickr API to get at these regular and machine tags. Remember that Flickr geotagging was based originally on the geotagged tag and tags of the form geo:lon=[LONGITUDE] and geo:lat=[LATITUDE] that became machine tags. For example, to use the Flickr API to look up the tags for the photo whose ID is 18389540, you issue the following HTTP GET request:

http://api.flickr.com/services/rest/?method=flickr.tags.getListPhoto&api_key={api_key}&photo_id=18389540
      

whose response is as follows:

<?xml version="1.0" encoding="utf-8" ?>
<rsp stat="ok">
  <photo id="18389540">
    <tags>
      <tag id="29475-18389540-11787" author="48600101146@N01"
           authorname="Raymond Yee" raw="campanile" machine_tag="0">campanile</tag>
      <tag id="29475-18389540-1700" author="48600101146@N01"
           authorname="Raymond Yee" raw="geotagged" machine_tag="0">geotagged</tag>
      <tag id="29475-18389540-10860922" author="48600101146@N01"
           authorname="Raymond Yee" raw="geo:lon=-122.257704"
           machine_tag="1">geo:lon=122257704</tag>
      <tag id="29475-18389540-10860930" author="48600101146@N01"
           authorname="Raymond Yee" raw="geo:lat=37.8721"
           machine_tag="1">geo:lat=378721</tag>
      <tag id="29475-18389540-88988" author="48600101146@N01"
           authorname="Raymond Yee" raw="UC Berkeley"
           machine_tag="0">ucberkeley</tag>
      <tag id="29475-18389540-9233381" author="48600101146@N01"
           authorname="Raymond Yee" raw="mashupguide"
           machine_tag="0">mashupguide</tag>
    </tags>
  </photo>
</rsp>
      
[Note]Note

You might wonder why you get machine tags for latitude and longitude since using geo:lat and geo:lon has been superceded. I’m showing this technique for historic interest and also because it’s still used by older pieces of software (such as the Google Maps in Flickr Greasemonkey script that uses old-­style geotagging).

With new-­style geotagging, support for geotagging was built into the core of Flickr (geo-information became a first-­class citizen of the Flickr data world). Each photo can optionally be associated with a location (that is, a latitude and longitude) and permissions about who can see this location.

There are some major advantages of the new-­style geotagging:

By setting a location, you give a photo a latitude, longitude, and accuracy (1–16): world level equals 1, country equals approximately 3, and street equals approximately 16. The default accuracy is 16. Permissions are the values for four parameters: is_public, is_contact, is_friend, and is_family (0 or 1). (See Chapter 2 for a discussion of the permission system in Flickr.) There are five methods under flickr.photos.geo: getting, setting, deleting the location of a given photo (flickr.photos.geo.getLocation, flickr.photos.geo.setLocation, and flickr.photos.geo.? removeLocation), and getting and setting the permission (flickr.photos.geo.getPerms and flickr.photos.geo.getPerms).

You’ll notice that for the following, in addition to using the old-­style geotagging in the example photo, I am also using the new-­style geotagging:

http://flickr.com/photos/raymondyee/18389540/

Since this photo is public, anyone can use flickr.photos.geo.getLocation to access the photo’s latitude and longitude. (All the other geo.* methods require authorization.) Let’s use the API to get the location. Issue an HTTP GET request on this:

http://api.flickr.com/services/rest/?method=flickr.photos.geo.getLocation&api_key={api_key}&photo_id=18389540
      

You will get the following:

<?xml version="1.0" encoding="utf-8" ?>
<rsp stat="ok">
  <photo id="18389540">
    <location latitude="37.8721" longitude="-122.257704" accuracy="16">
      <locality>Oakland</locality>
      <county>Alameda</county>
      <region>California</region>
      <country>United States</country>
    </location>
  </photo>
</rsp>
      

For the other methods, it’s easier to demonstrate using a Flickr API kit that helps you with the Flickr authentication process (which is covered in detail in Chapter 6). I’ll now display some code to show how to use Python to manipulate a photo’s location and geopermission. Here, flickr.client is an authenticated instance of the Flickr client using Beej’s Python Flickr API (http://flickrapi.sourceforge.net/).

Let’s retrieve the location of the photo:

>>> rsp = flickr.client.photos_geo_getLocation(photo_id=18389540)

Now let’s remove the location of the photo:

>>> rsp = flickr.client.photos_geo_removeLocation(photo_id=18389540)

Let’s write the location back to the photo:

>>> rsp = flickr.client.photos_geo_setLocation(photo_id=18389540,lat=37.8721,lon=-122.257704,accuracy=16)

In addition to reading and writing the location and geopermissions of an individual photo, you can use the Flickr API to search for photos that have an associated location. You do so by using the flickr.photos.search method (the one to which you were introduced in Chapter 6), documented here:

http://www.flickr.com/services/api/flickr.photos.search.html

To do a search for geotagged photos, you add the search parameters of the following form:

bbox=lon0,lat0,lon1,lat1

Here lon0,lat0 and lon1,lat1 are the longitude and latitude of the southwest and northeast corners of the bounding box, respectively. Note that you can also use the accuracy parameter to specify the minimum accuracy level you demand of the specified locations.

Let’s consider the example of searching for photos around Berkeley in a bounding box with the following parameters:

SW:  37.81778516606761, -122.34374999999999
NE:  37.92619056937629, -122.17208862304686
      

The following will get the first page of all the publicly available geotagged photos in Flickr, including photos of all accuracies (with this call, you can get at the total number of such photos):

http://api.flickr.com/services/rest/?api_key={api_key}&method=flickr.photos.search&bbox=-180%2C-90%2C180%2C90&min_upload_date=820483200&accuracy=1
      

You can get the first page of photos with a bounding box around the UC Berkeley campus:

http://api.flickr.com/services/rest/?api_key={api_key}&method=flickr.photos.search&bbox=-122.34374999999999%2C+37.81778516606761%2C+-122.17208862304686%2C+37.92619056937629&min_upload_date=820483200&accuracy=1
      

The Flickr API doesn’t like unqualified searches for geotagged photos. That is, you can’t just, say, search for photos in a certain bounding box—you need to use at least one other search parameter to reduce the strain on the Flickr database caused by unqualified searches. Here I’m using the min_upload_date parameter to convince Flickr to give some results.