Digikam/GSoC2010/ReverseGeocoding

From KDE Community Wiki

Reverse geocoding will be implemented for the new version of the GPSSync plugin as part of GSOC by Gabriel Voicu, mentored by Michael G. Hansen.

Short description

The idea of reverse geocoding is that when the coordinates on earth of an image are known, the application retrieves the associated human readable location: City, street, country, etc. and stores this information in the image. The location names can be stored in the images as new tags, allowing the user to easily search for all pictures he took in a country, city or even street.

Use Cases

Let's say you are a user who wants to have all his photos geotagged. Of course, you can take them one by one and add geotag them manually. But what happens when you have thousands of photos? The solution comes from the Reverse Geocoding widget (which can be found in Geolocation widget) that does the job for you with just some clicks.

But how will this widget do the job? Well, first you need to set some parameters.Don't worry, you will have to set them only once if you're happy with them.

Firstly, you need to select the service that will provide your data. The choices are: Open Street Map or Geonames.org. You should try each of them, because they provide different results on some areas.

After you select all this, you should select the language, because you may want to have special characters in the retrieved data.

The tag tree from the center of the widget will be the place where all the fun will take place. I will make a step-by-step tutorial, to show how to work with it. At first, here is the widget, with the tag tree located in the center:

Let's say you want to add your new geotags as childs of "Places" tag, so you right-click it and a menu appears.

Before I explain what does each menu element, I should tell you how this works: when you select an address element tag from the menu, a control tag(coloured with red) appears as a child of parent tag. This way, when applying the reverse geocoding service, it will know where to add the new geotags. Don't worry about the control tags, because they will not be added as tags to your host application(here digiKam).

Now, let's get back to menu elements. The menu elements gives you the possibility to select what control tags will you want to add. So, you will have country tag, county tag, city tag... or you can click "Add all address elements" and all control tags(each containing a different address element) will be added, sorted by scale(country is bigger than city).

Up there, I clicked the "Add all address elements" menu item and all control tags added properly below the "Places" tag. Now, it's time to retrieve some data. Select you images in the lower-left list (I've selected all) and click "Apply reverse geocoding" button. The data will be added guided by the control tags:

Ok, now you have the intermediate tags(coloured in green). I called them intermediate because they exist as much as Geolocation widget is open. To add them proper to host application and metadata, you must click the "Apply" button. You will notice that the intermediate tags haven't dissapeard. This is good, because they will help you in case you want to geotag some other photos before you close Geolocation widget.


You will also have an option to select whether your tags will be saved in each image XMP metadata. I've chosen only XMP because IPTC doesn't provide support for special characters. To be more precise,IPTC uses ASCII encoding, while XMP uses UTF-8 encoding.

Where is the code?

All code can be found in the kipi-plugins/digikam gsoc branch. Reverse geocoding is implemented in the gpssync kipi plugin.

Backends

OpenStreetMap Nominatim

OSM Nominatim

  • Marble already has integration for this service
  • Address elements returned, if they exist:
    • country
    • state
    • state district
    • county
    • city
    • city district
    • town
    • village
    • hamlet
    • street

Geonames.org

geonames.org

  • Provides both reverse geocoding and elevation information
  • It has to services implemented here:
    • "Find nearby place name" which provides:
      • country
      • place name
    • "Find address" is only for USA and retrieves:
      • local administration 2
      • local administration 1
      • place name

Storing information

Inside the image

The textual location descriptions can be stored as tags and in the dedicated location fields provided by XMP and IPTC. However, there are some competing tags which store the same information.

Digikam allows the user to choose whether he wants to have data written to his image files or not. We may want to add a host property to the kipi interface to automatically respect these settings.

In Digikam's database

For now, have a look at the document outlining database changes for the GSOC projects. Possible additions to the existing tags:

  • Coordinates of the tag.
  • Possibly introduce multi-language tags.

Miscellaneous

  • Terminology: Make sure we use a consistent name for reverse geotagging which is easily understandable to the user.
  • In order to display a tree of tags, we need to add a function to the kipi interface to read the tags from the host application.
  • Use solid to detect whether we have a network connection. If KDE thinks there is no network, warn the user, but always let him override it. Relevant code can be found in KGPG (search for networkUp): keysmanager.cpp

What if the user wants to store his tags as

  • Countries
    • Germany
    • England
  • Cities
    • Cologne
    • London

TODO Reverse Geocoding

Job Status
RG backend
Looking at http://wiki.openstreetmap.org/wiki/Nominatim they seem to want us to limit the number of simultaneous connections to 1! DONE
OSM also wants us to include a user agent string, which contains a contact address, possibly [email protected]. Maybe you can find out how to set the user agent on KIO::Job? DONE
Investigate what happens on errors, like when the connection to the server fails or the connection times out. How do we react and make sure we report the error to the user? DONE
We should merge requests for the same coordinates. Have a look at the altitude backend again as a guide. Try to make it in a way that when a request has already been sent to the backend, the new request should still be merged in. DONE
Move MakeTagString into a common header file which is included by both the GUI and the test. DONE
Make backend-rg.h independent of gpsreversegeocodingwidget.h DONE
UI
Entering of the tag destination: Think of how the input should be formatted (My Tags/{Country} of similar) and write code that creates the resulting tag names (best done in a test-case outside the UI first, see existing tests directory on how to create tests). DONE
We need to store the settings made in the RG widget UI. Look at the correlation widget to see how it's done. DONE
Finally, we need to decide whether we want to modify the tags in digikam to contain coordinates. Have a look at the database page and think about how it could be done. Try to continue with the following points until a decision is made.
We need to store the tags in the GPSImageItems und the corresponding undo/redo structures. Decide on how to store the tags in the gpsimageitems and in the undo/redo structures, the implement it. We also have to think about where to store whether the user wants XMP/IPTC updated. DONE
Finally, we need to store the tags in the images. There is a function in GPSImageItem that updates the images, and needs to be modified. DONE
Maybe display an invitation to donate to OSM/geonames?
General
Add correct licensing information to all files DONE
Review digikam coding guidelines and apply them to the code DONE

To be done later:

  • Add an option to set which tags in a hierarchy should be applied to an image. For example, in 'Places/Germany/Monheim', one may not want 'Places' to be a tag for an image. But in 'Holidays/Spain/Barcelona', 'Holidays' may be wanted as a tag.

Improved Map Search

The mouse modes definitons found in libkmap:

  • Pan Mode = Map can be panned and zoomed. All the existing thumbnails are displayed on the map. When the user clicks on a thumbnail nothing happens.
  • Selection Mode = The selection is made by drawing a rectangle on the map. The thumbnails outside the selection aren't displayed anymore on the map. The selection rectangle from the last search is displayed on the map when the user is not in Pan Mode. To remove the current selection, the "Remove current selection" button must be pressed.
  • Zooming Mode = When the user clicks a group of thumbnails, the map is zoomed until it fits to display the most of them.
  • Filter Mode = When the user clicks a group of thumbnails/a thumbnail, the rest of thumbnails on the map dissapear. To remove the current filter, the "Remove current filter" button must be pressed.
  • Select Thumbnail Mode = When a selection is made, the user can select the images in the central view by clicking on the thumbnails on the map.

TODO Before 2.0

Component Job Status
Unknown Size hint of GPS properties tab too wide, workaround implemented: Move KComboBox into a new line. FOR NOW
KMap A border of 0.001 around the images is better now, and should be sufficient for most cases
Digikam and KMap Make the map and the marker models to proper react to setActive function test again
Digikam Make the unfiltered thumbnails displayed transparently when the filtering happens inside a selection later
KMap Save the current mouse mode to the settings.
Digikam Check whether the last active gps search album is properly restored after a restart: Selection rectangle, selection in the search list, display of the thumbnails on the map and in the center view. Started GV
Digikam GPSSearch: Add a "sticky" button or KMap configuration menu item. When sticky is not set, the map can move to show the currently selected search region rectangle.
Digikam GPS Properties tab: Also add a "sticky" button/menu entry. When it is not set, the map should center on the images displayed on the map. PARTIALLY
Digikam Center map view: Also add a "sticky" button/menu entry. When it is not set, the map should also center on the displayed images.
KMap Check whether the zoom levels of Google Maps and Marble are roughly the same when switching between the two backends.
Digikam/KMap Zooming into a group of thumbnails does not work in the properties tab. Started GV
GPSSync Add a way to cancel RG. When calling slotSetUIEnabled, a pointer and a slot can be given which will be called when the cancel button is clicked.
GPSSync test_gpsrgparsing fails
GPSSync RG: New action: Remove all spacers
GPSSync RG: Model: Handle removal of tags in the source model. SimpleTreeModel first needs to be updated to support removal of items.
GPSSync Handle threads properly when closing while a thread is running, for example when GPX files are being loaded.
KMap The Marble people are implementing a new 'geodetic search rectangle' - find out what that means and port the code over to libkmap for now if appropriate.
KMap Try again to make panning work when clicking on thumbnails in Google Maps.
KMap Implement the new sort-best-items-on-adding idea.
GPSSync Search: options for language selection if appropriate.
GPSSync Search: restrict the search to the visible map area.
GPSSync Search: cancel and progress
GPSSync Search: pressing 'enter' in the search text field triggers both the search and the apply button
GPSSync Add a configuration dialog, like in digikam maybe. STARTED
GPSSync Configuration: Options for units: speed, coordinates, height
GPSSync Find out whether KDE has settings for selecting KM/H vs. miles/hour and make this the default for the speed. Same for the height.
GPSSync Configuration: Whether non-coordinate data should be cleared when markers are moved.

TODO Later versions

Component Job Status
GPSSync Support for loading KML files.

DONE

Component Job Status
GPSSync Remove the settings tab. DONE
Digikam Also enable marker modes for the gpssearch? DONE
Digikam Also enable marker modes for the center map. DONE
KMap Switching from Marble to Google Maps does not keep rectangle selection mode FIXED
Digikam Coordinates/altitude not shown in GPS properties tab sometimes. FIXED
Digikam Mouse text "Remove the filtered image" indicates that images will be deleted, but we only remove the filtering. FIXED
KMap KHTML shows some JavaScript errors in the digikam status bar when clicking around in the gps search. FIXED
Digikam Modify GPS properties tab to only show altitude if there is one. FIXED
KMap When no mouse mode buttons are shown, the control widget ends with a separator. FIXED
KMap Put our definitions for the mouse modes into the wiki, because we will need them for the sprint when we talk about the UI with the others. FIXED
KMap Do not hide the selection rectangle when the user switches to pan mode FIXED
All Look through the code once more, there are still some places where digikam coding guidelines are not strictly followed, like "if(" or "for(" instead of "if (" and "for (", or spaces in empty lines. FIXED
Digikam Save the map settings for the map view in the center. FIXED
KMap Replace the B button with an "image" icon, for the E button use one of the markers as an icon. FIXED
Digikam/KMap GPS properties tab: Make it possible to show markers instead of images, but find a way to disable moving of those markers for now. For this, the ModelHelper should not return the movable flag, and the flags should also be returned by the MarkerTiler, so that the kmap backends can check whether markers should be movable or not. Also, rename the enableEditMode function to enableMarkerMode or something, since the availability of "editing=moving" is managed by the model flags. DONE
GPSSync Add license to rg-google-maps backend and/or move it out of the main directory. FIXED
- Remove the gsoc-geocoding folder from SVN if it is no longer needed. FIXED
GPSSync Configuration: Option to have two map views at the same time, with a horizontal or a vertical splitter. Useful when the user wants to look at Google Maps and OSM at the same time, or see the pictures closely and from far away at the same time. Plus, we need to use the model-view for something cool ;-) DONE
KMap Use GeoCoordinate::Pair instead of QList<qreal> to emit the search rectangle coordinates DONE