可视化你的足迹
可视化你的足迹 数据可视化可以让读者以一种轻松的方式来消费数据,人类大脑在处理图形的速度是处理文本的66,000倍,这也是人们常常说的一图胜千言。在本文中,我们通过将日常中很容易收集到的数据,通过一系列的处理,并最终展现在地图上。这仅仅是GIS的一个很简单场景,但是我们可以看到,当空间数据和地图结合在一起时,可以在可视化上得到很好的效果,读者可以很容易从中获取信息。 我们在本文中会制作一个这样的地图,图中灰色的线是城市中的道路,小六边形表示照片拍摄地。颜色表示当时当地拍摄照片的密度,红色表示密集,黄色为稀疏。可以看到,我的活动区域主要集中在左下角,那是公司所在地和我的住处,:) 要展现数据,首先需要采集数据,不过这些已经在日常生活中被不自觉的被记录下来了: 数据来源 如果你开启了iPhone相机中的定位功能,拍照的时候,iPhone会自动把当前的地理信息写入到图片的元数据中,这样我们就可以使用这些数据来做进一步的分析了。 我在去年学习OpenLayers的时候已经玩过一些简单的足迹可视化,另外还有一篇全球地震信息的可视化,但是仅仅是展示矢量信息,并没有深入,而且都是一些前端的JavaScript的代码。最近又在重新整理之前的GIS知识,重新把这个作为例子来练手。当然,这次会涉及一些地图编辑,空间计算的内容。 我的照片一般都通过Mac自带的Photos管理(前身iPhoto),手机里照片会定期同步上去。老版本的iPhoto用的是XML文件来存储照片的EXIF数据,新的Photos的实现里,数据被存储在了好几个SQLite数据库文件中,不过问题不大,我们只需要写一点Ruby代码就可以将数据转化为标准格式,这里使用GeoJSON,GeoJSON既可以方便人类阅读,也可以很方便的导入到PostGIS或者直接在客户端展现。 实现步骤 我们现在要绘制照片拍摄的密度图,大概需要这样一些步骤: 抽取照片的EXIF信息(经度,纬度,创建时间等) 编写脚本将抽取出来的信息转换成通用格式(GeoJSON) 使用QGIS将这些点的集合导入为图层 插入一些由六边形组成的图层(设置合适的大小) 计算落在各个多边形中的点的个数,并生成新的图层heatmap 使用MapServer来渲染基本地图 数据抽取 Mac上的Photos会将照片的元数据存储在一个SQLite3格式的数据库中,文件名为Library.apdb,通常位于这个位置~/Pictures/Photos\ Library.photoslibrary/Database/apdb/Library.apdb。这个文件可以通过SQLite3的客户端直接打开,不过由于可能有其他进程(Mac自己的)打开了该文件,所以会有锁文件,你可能需要先将这个文件拷贝到另外一个位置。 然后将表RKVersion中的部分信息导出即可,SQLite内置了很方便的导出功能,通过它提供的shell客户端sqlite3,将信息导出到csv文件中: sqlite> .mode csv sqlite> .headers on sqlite> .output places-ive-been.csv sqlite> select datetime(imageDate+978307200, 'unixepoch', 'localtime') as imageDate, exifLatitude, exifLongitude from RKVersion where exifLatitude and exiflongitude; sqlite> .output stdout 注意这里的日期,苹果的日期偏移和其他公司不同,始于2001年1月1日,所以要在imageDate之后加上这个base值,然后将文件以.csv的格式导出到places-ive-been.csv中,该文件包含3列:时间,纬度,精度。 imageDate,exifLatitude,exifLongitude "2012-10-25 16:34:01",34.19216667,108.87316667 "2012-10-28 14:45:53",35.1795,109.9275 "2012-10-28 14:45:45",35.1795,109.9275 "2012-10-25 16:34:04",34.19216667,108.87316667 "2012-10-19 23:01:05",34.19833333,108.86733333 ... 转换为GeoJSON 方便以后的转换起见,我们将这个文件转换成GeoJSON(其实很多客户端工具可以支持CSV的导入,不过GeoJSON更为标准一些)。 require 'csv' require 'json' lines = CSV....