聚合国内IT技术精华文章,分享IT技术精华,帮助IT从业人士成长

基于照片地理位置的产品设计

2021-11-20 09:08 浏览: 3299167 次 我要评论(0 条) 字号:

当前智能手机的默认相机应用大部分是支持将用户的地理位置信息写入照片的Exif信息中。有了照片+经纬度就可以产生有趣的应用。

Google Panoramio

Panoramio是Google推出的一项基于地理位置图片分享的网站,任何人都可以把自己的照片与全世界分享,当然你还可以将自己的照片分享到谷歌地球。

你可以通过Panoramio探索世界,也可以与他人分享世界风景。Panoramio的宗旨是让Google地球的用户凭借观看其他用户的摄影作品对特定的区域更加地了解。

Google宣布Panoramio于2016年11月4日结束营运,在Google Earth则可以访问Panoramio的照片至2018年1月。

Flickr Map

flickr map是有个类似Panoramio的服务,主要也是在地图上呈现标记点位置的图片。

马蜂窝的地理相册

马蜂窝使用经纬度+照片的主要场景是想让用户快速地找到想要分享的照片/视频。:

  • 根据目的地和时间,对用户相册进行聚合、排序
  • 基于某个地理位置信息和给定范围,在用户相册中搜索给定范围的照/视频

相关功能点:

  • 笔记,以图片、视频为主要呈现形式。用户发布笔记的第一个环节就是从相册中选择需要发布的照片/视频,在新版 App 中,基于地理相册服务结合马蜂窝自有目的地数据,对用户相册进行按照地点维度的聚合分类,并且按照片/视频的创建时间由近及远的排序,提升用户选择发布效率。
  • 足迹,帮助马蜂窝用户以自动同步或手动点选去过的国家和地区这种更简易的方式记录旅行。在「我的足迹」中有一个场景,会鼓励用户对去过的但还没有发布笔记的地点发布笔记。此时地理相册服务可以帮助用户发布相册中以指定地点为圆心,给定半径范围内的所有照片。

马蜂窝的具体实现方案

由于用户手机中会存放大量的照片,且大部分照片的拍摄距离较近。所以没有必要对用户手机里的每一张照片都进行位置解析。可以通过经纬度将拍摄距离较近的照片进行聚类。然后取经纬度中心点进行解析。

经纬度聚类

经纬度聚类的方法可以采用空间索引算法,如GeohashUber H3Google S2。马蜂窝最终采用的是Google S2。其选型时只考虑了Geohash和Google S2。

Geohash的主要弱点是其填充曲线是Z 阶曲线。Z 阶曲线有一个比较严重的问题,就是它的突变性。在每个 Z 字母的拐角,都有可能出现顺序的突变,导致搜索临近点的精确度较差,不能满足业务场景对精确度的要求。

S2 算法采用正方体投影的方式将地球展开,然后利用希尔伯特分形曲线将展开后的二维地球进行填充,完成了对三位地球的降维和分形,从而得到空间坐标点与希尔伯特分形曲线的函数关系,即将球面经纬度坐标转换成球面 xyz 坐标,再转换成正方体投影面上的坐标,最后变换成修正后的坐标在坐标系变换,映射到 [0,2^30^-1] 区间,最后一步就是把坐标系上的点都映射到希尔伯特曲线上。最终,映射到希尔伯特曲线上的点成为 Cell ID,即是空间坐标点的索引。

S2 的最大的优势在于精度高。Geohash 有 12 级,从 5000km 到 3.7cm,中间每一级的变化比较大。有时候可能选择上一级会大很多,选择下一级又会小一些。而 S2 有 30 级,从 0.7cm² 到 85,000,000km²,中间每一级的变化都比较平缓,接近于 4 次方的曲线。所以选择精度时不会出现 Geohash 选择困难的问题。

地理相册服务的功能实现

马蜂窝App 地理相册服务主要基于相册索引数据操作、用户相册扫描、相册索引服务和相册地点分类计算四大模块实现:

相册索引数据操作模块

相册位置信息的索引采用数据库作为存储介质,将用户照片信息以及通过 S2 算法计算出来的 Cell ID 存储到数据库当中。其中,考量存储的数量和对搜索和聚合经度的要求,存储了从 Level4~Level16 经度级别的 Cell ID。

相册索引数据操作模块,由数据库(DB)和数据库操作层(DAO)组成。数据表的设计见下图:

数据库操作层(DAO)封装了数据插入、删除、查询等基本操作的 API。

用户相册扫描模块

用户相册扫描模块基于 iOS 原生提供的相册查询的 API,将用户相册的数据与本地数据库中存储的照片数据进行对比,提取出新增照片数据和用户已经删除的照片。

备注:用户已经发表过的照片是否需要标识?

相册索引服务模块

相册索引服务模块,是基于 S2 算法的相册服务的核心模块。模块功能如下:

  • 直接与数据模块交互,向使用者屏蔽数据层的数据操作细节,提供满足查询、搜索等需求的 API
  • 查询指定 Cell ID 下的照片资源
  • 查询指定 Level 下,相册照片索引后的Cell ID
  • 查询以指定坐标点为圆心、指定半径范围内的照片
  • 与用户相册扫描模块交互,获取新增照片和已经删除照片的数据,更新数据库内容,同时支持查询和通知更新状态

相册地点分类计算模块

相册地点分类计算模块是计算用户相册的地点分类结果的核心模块。该模块的主体功能如下:

  • 获取 S2 相册索引服务中的照片 Cell ID,作为参数上传至服务端,服务端根据地图服务提供的聚合接口,将 Cell ID 的聚合结果返回给服务端
  • 综合考量精确度和 Cell ID 的数据量,选取 Level12 的 Cell ID 作为请求服务端的 Cell ID 等级
  • 调用相册索引服务模块根据指定 Level 获取 Cell ID 的方法得到去重后的 Cell ID
  • 服务端返回的数据结构是 mdd_id(目的地 ID) 与 Cell ID 的一对多的映射关系
  • 利用本地 S2 相册索引服务中的照片 Cell ID,根据上一步服务端返回的分类数据进行分类
  • 缓存每次地点分类的计算结果

整体流程

相册索引服务模块会在 App 启动时更新服务,将本地数据与相册数据同步。当用户触发地点相册功能时,相册地点分类计算模块会先取出缓存在本地相册地点分类计算结果展现给用户,同时驱动相册索引服务更新。

在收到更新服务更新完毕的通知后,首先向相册请求 12Level 的全量去重的 Cell ID,然后将 Cell ID 上传服务端由服务端计算分类,最后结合相册索引服务的全量照片数据,计算照片的地点分类结果,缓存结果并渲染展现给用户。

地理相册服务的性能优化

获取相册增量照片

相册索引服务模块需要同步服务和用户相册的照片资源数据,找到新增数据,加入到服务数据库中。最初设计的获取新增数据方案如下:

  • 1 获取全量的用户相册的数据
  • 2 遍历用户照片,查询是否存在本地服务数据库中

但是这个方案应用到照片量较大的手机上时,获取新增照片的时延很高。排查后我们发现原因在于全量遍历用户相册时延很高,同时在遍历中频繁查询数据库也比较耗时。经过调研发现,iOS 的用户相册有「最近项目」的相册分类,该相册分类下的资源只按照添加顺序的倒序排列,即越新的照片越靠前。故将方案优化如下:

  • 1:从列表头部截取 100 条
  • 2:将该 100 条追加为新增照片
  • 3:判断该 100 条中的最后一条,即新增时间最晚的一条,查询是否存在于服务数据库中
    • 若不存在,继续1
    • 若存在,停止截取,从而得到新增照片

渐进计算相册照片的地点分类

相册地点分类计算模块在获得服务端返回的分类结果(mdd_id 与 Cell ID 列表的映射关系)后,根据结果对本地服务数据库中的照片进行分类。最初的方案如下:

  • 1:遍历结果列表,获得每个 mdd_id 映射的 Cell ID 列表
    • 遍历 Cell ID 列表,通过 Cell ID 向相册索引服务模块查询属于该 Cell ID 索引下的照片资源,从而获得该 mdd_id 对应的照片资源
    • 对该目的地下的照片按照创建时间倒序排序
  • 2:将所有目的地维度照片分类结果,按照每个结果集中照片最晚创建时间,即第一个照片的创建时间,进行倒序排序,获得按照地点维度和创建时间维度排序的地点相册的最终计算结果。

这样的方案导致在地点相册首次计算的时候,用户需要等待所有目的地下的结果计算完毕后才能展现给用户,同时需要多次按照创建时间排序,导致时延很高,冷启动下用户体验很差。

为此,马蜂窝做出了方案优化,减少排序次数,同时通过渐进加载的方式优化用户体验。主要思路是相册索引服务模块的数据库中,存储照片的创建时间可以通过 SQL 查询,按照创建时间倒序排列的所有照片资源,获取倒序排列的照片资源集合:

  • 1:每次从照片资源集合头部取 1000 条照片
    • 遍历每一张照片,根据照片的 Cell ID,从 mdd_id-Cell ID 映射表中查询所属的目的地, 判断照片目的地分类结果集中是否存在该目的地的照片资源分类集合
    • 存在,追加该照片
    • 创建该目的地的结果集,追加到照片目的地分类结果集中,并追加该照片
  • 2:将该 1000 张照片的分类结果渲染展现给用户
  • 3:计算完所有照片的分类,通知结束渲染,计算完毕。

以上方案,将全量的本地照片资源以 1000 张为一批次,进行渐进计算,同时渐进渲染,缩短了用户的等待时间;同时,依托关系型数据库的排序能力,减少排序次数,优化了性能。

参考链接:



网友评论已有0条评论, 我也要评论

发表评论

*

* (保密)

Ctrl+Enter 快捷回复