Saturday, June 30, 2012

Using a scanned map for digitizing in Potlatch2 for OpenStreetMap

I had a map that I wanted to use as an online base layer for adding features to OpenStreetMap using a Windows machine. I was successful in doing so using all open source tools and lots of trial and error.

Here's how I did it.

  1. I scanned my map using my flatbed scanner. I have an HP 6500A Plus. I scanned it in at 300 dpi and saved it as a TIFF file.
  2. Now I needed to GeoReference the TIFF file. For this I used QGIS Desktop. You can download it for free. The best way to install it is with the OSGeo4W Installer which can be found here:  http://trac.osgeo.org/osgeo4w/. The projection of my scanned map was UTM 10 NAD83 aka EPSG:26910 so I set the Coordinate Reference System (CRS) to  26910  under Settings => Project Properties and checked the "Enable 'on the fly' CRS transformation". For reference sakes I loaded some layers from a WMS for the area my map was in. The WMS I used was from DataBC Geographic Services. I used the 'Quick Base' WMS. The WMS URL for this can be found at:  http://www.data.gov.bc.ca/dbc/geo/wms/index.page. In QGIS I added all the 'Base Layers' and 'Transportation'  layers that were available from the WMS.  Next, I enabled the Georeferencer GDAL plugin and fired it up. It runs in a separate window. I loaded my TIFF file in the Georeferencer GDAL plugin window. Now I setup the tool under Settings => Transformation Settings. I set my Output raster and set my Target SRS to the known projection of my map. In my case it was 26910. I also checked Load in QGIS when done. Next I used the 'Add Point' tool to pick points on my map that I knew were in the WMS I loaded. My favourite points are road intersections. Once I added a point to the map in the Georeferencer I then clicked the 'From map canvas' button which switches screens back to the QGIS main window. I then found the same point in the WMS and clicked which autopopulated the X and Y values in the Georeference window. I did this for about 4 points and then hit the Green play button which 'start[s] Georeferencing'.
  3. I now had a georeferenced TIFF but, in its original projection. In order for it to be used efficiently as a base layer I wanted to eliminate on the fly transformation so I reprojected the TIFF into the the projection my final product would be in, Google Spherical Mercator aka EPSG:900913. I used the GDAL Tools plugin and under Raster => Projections => Warp (Reproject). Again I set the Output filename and the Target SRS to 900913.
  4. After reprojecting the TIFF I needed a WMS that served it via HTTP. This is easily accomplished using QGIS Server which I installed using the same OSGeo4W: http://trac.osgeo.org/osgeo4w/. I followed the tutorial here:  http://hub.qgis.org/projects/quantum-gis/wiki/QGIS_Server_Tutorial#Windows. One thing missing from this tutorial was picking the Fast CGI package when choosing packages to install and then fcgi works fine and you don't need to change the c:/osgeo4w/httpd.d/httpd_qgis.conf. After following the tutorial I had a WMS up and running.
  5. I tested my WMS using OpenLayers. I swapped out an example WMS for my own using this example: view-source:http://dev.openlayers.org/releases/OpenLayers-2.11/examples/lite.html. I just swapped out the url for the one from the tutorial. You can check a WMS with QGIS as well. If you want to see the call that's being made you can check the C:\OSGeo4W\apache\logs\access.log.
  6. Now that I had a WMS that I knew worked I needed to convert in into a Tile Mapping Service so it could be consumed by OpenStreetMap Potlatch2. I would accomplish this by adding TileCache to the mix. I downloaded the package from here:  http://tilecache.org/. I unzipped it into C:\OSGeo4W\apps\tilecache. I then set up the folder the same way qgis was set up; with C:\OSGeo4W\httpd.d\httpd_tilecache.conf with the following contents:

    Alias /tilecache/ C:\OSGeo4W/apps/tilecache/

    <Directory "C:\OSGeo4W/apps/tilecache/">
      SetHandler cgi-script
      Options ExecCGI
      Order allow,deny
      Allow from all

    </Directory>

    I also installed a separate instance of Python27 to run TileCache. Thus I needed to update my C:\OSGeo4W\apps\tilecache\tilecache.cgi to reflect this, putting the following line in the first line:#!C:/Python24/python.exe -u
  7. With a Tile Mapping Service in place I now needed to set up a TMS layer that consumed my WMS. This is where the magic happens. In the C:\OSGeo4W\apps\tilecache\tilecache.cfg I added the following entry:

    [omg_bg]type=WMS
    url=http://localhost:8080/qgis/qgis_mapserv.fcgi.exe?map=C:/gis/project/omg_bg.qgs
    extension=png
    layers=omg_bg
    bbox=-20037508.34,-20037508.34,20037508.34,20037508.34
    maxResolution=156543.0339
    srs=EPSG:900913

    tms_type=google
  8. I was now able to log into OpenStreetMap.org and add a background under Background => Edit => Add. I gave it the name ogm_bg and the URL http://localhost:8080/tilecache/tilecache.cgi/1.0.0/omg_bg/$z/$x/$y.png
Voila! I was now able to digitize the features from my scanned map and add them to OpenStreetMap.

1 comment:

Unknown said...

hey matt, i've done similar things to use custom maps in my gps map program (mappero) on my n900.

it's awesome for layering mountain biking trail maps over google maps.

my procedure for that is as follows.
1. save pdf of map to png
2. make background of png transparent
3. load png into map cruncher (microsoft windows eww)
4. create tiles from map cruncher
5. use a web server/php script to serve up the microsoft tiles as google maps tiles

i have also used other tools to get maps into mappero.
- mapproxy to convert wms tiles to google maps
- gdal_merge to merge a bunch of maps into one large map
- gdalwarp to convert projection
- gdal2tiles to create tiles from an image
- maptiler (gui wrapper to gdal2tiles)

i used the gdal tools to merge vancouver island backroad mapbook maps (pngs from a cd) into one large image, then warp to the proper projection, then chop up into tiles. i'm sure i wrote a script or instructions on how i did this but i can't find them at the momemnt.