开发者日志
“今日回顾”、“过去与现在”和“护照印章”。
“今日回顾”、“过去与现在”和“护照印章”使用不同的技术:日历关联、空间分桶和 OCR。它们遵循相同的规则:找到有用的东西,解释它,并将最终决定权留给旅行者。
三种让过去重现的方法
大多数旅行软件针对下一次旅行进行优化。 Mapsake 也需要擅长让用户重温五、十或二十年前的旅行。
此更新增加了三种不同的路径,通往过去。 今日回忆 找到与日历的关联。 过去与现在 找到与地点的位置关联。 护照签证 保护一个物理文物,并将其用于改进地图。
它们遵循相同的设计原则:从用户已经拥有的数据开始,在设备上执行有趣的操作,并在任何推断可能不正确时请求确认。
此版本背后的理念是数据保留,但不是“发送更多通知”。 完整的地图集在创建新的原因来重新访问旧数据时才变得有用。 最好的原因是用户无需手动策划的真实连接。
“今日回顾”、“过去与现在”和“印章”都以不同的方式创建这些关联。这使得它们成为一个很好的测试,以确定 Mapsake 的不断增长的功能集是否可以共享照片加载、地点解析、渲染、导航和隐私规则,而不会合并成一个巨大的内存引擎。
“今日回顾”功能使用来自照片以外的日期。
最简单的实现方式是在当月和当天的照片库中搜索照片。Mapsake 更进一步,因为它认识到照片只是旅行证据的一种。
地图上的每个地点都可以包含来自手动输入、导入、航班和照片历史记录的停留天数。“今日回忆”将这些日期与缓存的元数据相结合,按年份分组,并按最具体的地点排序。 城市或机场可以成为记忆的重点,而其区域和国家/地区仍然是同一故事的一部分。
照片过滤会从主界面分离,因为即使查询很简单,大型库仍然很大。结果按最新顺序分组,并显示为安静的年度卡片。打开一个卡片会显示其图库以及指向相关地点故事的链接。
此外,对于没有数据的日子,还提供最近记忆的备用功能。如果7月的9没有数据,Mapsake可以指向最近的包含数据的日期,而不是显示空白页面。
日历匹配比表面上看起来更复杂。
“同一月份和日期” 听起来似乎是一个简单的谓词,直到时区和不完整的记录出现。照片的日期来自捕获的媒体,而手动和导入的位置日期可以表示一天,而不仅仅是确切的时刻。因此,此功能在日历组件中运行,而不是询问时间戳是否相差 365 天。
地点按最佳顺序排列。 如果地图知道一个地方的机场、城市、地区和国家,则机场或城市应作为卡片的标题; 将所有四个列为单独的回忆会夸大证据的一部分。 完整的层次结构作为地点标记可用,并有助于周围的故事。
照片模块使用 Mapsake 在导入过程中已经构建的元数据缓存。它不会每次打开 Profile 时都要求 PhotoKit 重新扫描整个库。每日过滤器在分离的任务中运行,然后界面接收一小部分资源引用,这些引用可以延迟加载。
第一个入口点位于 Atlas 中。 测试显示,即使在没有记忆的日子里,日历按钮也会使最重要的屏幕变得更拥挤。 将入口点移动到个人资料中,可以使其有条件地显示,自然地与其他个人功能配对,并且可以在不与地图控件冲突的情况下显示未读状态。
通知需要自己的路由机制。本地通知不会通过与普通通用链接相同的路径发送。Mapsake 将深度链接写入通知有效负载,在应用程序委托中捕获响应,并将其转发到其他深度链接使用的相同导航状态。可见功能是一个句子;可靠的点击需要整个路由。
提醒是明确的自愿选择。
“今日回顾”功能可以安排一个温和的通知,但仅在用户启用后才会发送。Mapsake 从本地数据准备即将到来的纪念日,并附加一个深度链接,以便点击通知可以打开正确的页面。
没有服务器决定哪个记忆重要,也没有照片需要离开设备才能使提醒功能正常工作。只有在今天确实有内容需要显示时,才会显示“个人资料”磁贴,并且会有一个小的未读指示器,打开后会消失。
通知副本可以总结超过一年的信息或多个地点,因为本地计算已经知道分组结果。提醒可能表明,旅行者在几年内曾在雷德蒙德、罗马和东京。
那个条件条目,在很大程度上是一个产品决策,而不是一个工程决策。一个永久的空卡会更频繁地宣传该功能,但如果该功能没有提供任何有用的信息,它会每天让“个人资料”变得更加嘈杂。
“Then & Now” 将位置视为共同的主题。
“Then & Now” 查找在相同位置附近拍摄的照片,至少相隔两年。 该实现使用紧凑的空间网格:过滤后的照片坐标放置在宽度约为 280 米的单元格中,每个单元格仅保留其最早和最新的照片。
持续时间足够长的单元格将成为候选对象。最长的持续时间排在最前面,附近的候选对象将被去重,因此一个广场不能填充整个列表。捆绑的地理信息库提供城市和国家/地区的标签。结果将被缓存,直到照片索引发生更改。
这有意不是图像相似性搜索。照片不必显示相同的构图或主题;那是 Constellations 的另一个任务。Then & Now 提出了一个更简单的问题:几年后您再次回到这个地方时,它是什么样子?
配对照片在正常的照片查看器中打开,并且可以通过与护照卡相同的渲染方式进行共享。原始文件保留在原始库中,而 Mapsake 仅保留查找配对所需的轻量级元数据。
为什么是 280 米和两年?
空间单元故意允许一定的误差。电话 GPS 可能会漂移,一个地标可能从广场的相反一侧拍照,并且较旧的相机可能具有不太精确的坐标。完全匹配坐标会错过许多有效的返回结果。城市级别的匹配会非常宽泛,从而将不相关的社区配对。
约280米是一个产品的阈值,而不是断言两张照片显示相同的物理位置。它询问的是,当图像并排显示时,结果是否足够接近,以至于会产生一种联系感。两年最长期限可以防止将旅行的第一天和最后一天视为长期的变化。
在扫描过程中,每个单元格仅保留最早和最新的照片。这使得内存使用量与已使用的单元格数量成比例,而不是总图像数量,并且自然地最大化了时间跨度。候选对然后按持续时间排序并进行空间去重,因此,即使某人周围有数百张照片,仍然可以看到各种各样的照片。
记忆化键遵循照片元数据生成和排除计数。导入新的库批次或从地图中删除照片,对会重新计算;重新打开屏幕而无需更改源,应用程序会重用结果。
第一次基准测试显示,Then & Now 也花费了大量时间在附近城市的信息查询中。 因为它使用共享的地理信息库,而不是特定于功能的反向地理编码器,因此加速导入和 Constellations 的地理索引工作也使这些标签变得更加便宜。 共享的基础设施带来共享的成功。
共享功能使用 Passport 管道。
“Then & Now” 需要一张包含年份、地点和时间跨度的两张照片的卡片。 构建新的导出器会重复轻量和暗模式的渲染、社交宽高比、图像预加载、照片保存以及系统共享表单。
而是,该对被包装为自定义 Passport 卡,并传递到现有的共享屏幕。源图像是预加载的,因为 SwiftUI 的 offscreen ImageRenderer 在最终渲染点是同步的。用户看到与地图和统计图相同的预览和目的地流程。
代码复用不仅仅是提高效率。它使共享行为更具可预测性:不会自动发布内容,导出的文件看起来与预览相同,并且应用相同的可访问性和颜色规则。
护照盖章需要帮助,而不是虚假的确定性。
真实的护照印章是 OCR 的难题。 它们可能褪色、旋转、叠加在背景图像上、使用多种语言书写,有时甚至直接印在彼此之上。 任何声称具有完美自动识别功能的扫描仪可能会向用户提供不准确的旅行数据。
Mapsake 使用 Apple 设备上的 Vision 框架提取可读的文本,然后对可能的匹配项进行排名。 IATA 机场代码是一个强烈的信号。国家/地区的两位字母代码、国家/地区名称、本地名称、城市、口岸或欧洲日期可以提供更多证据。本地语言机场名称有助于识别条目很可能是通过飞机,即使 OCR 无法识别单词的结尾。
匹配器会提供建议和首选地点链:国家/地区、地区、城市以及可用的机场。它绝不会自行做出猜测。审查屏幕始终允许另一种候选或完全手动选择。
这种谨慎的处理方式非常重要。一个错过的建议需要一次点击。一个自信但错误的建议会悄悄地破坏地图。
一个褪色的冰岛签证更改了匹配器。
一个真实的邮票使限制更加具体。机场文本应显示为 KEFLAVIKURFLUGVOLLUR,,但由于墨水模糊和换行符,Vision 认为它更接近。 KEFLAVIKURFLUGVOLI UR.。针对冰岛机场术语的完整单词检查失败,因此 Mapsake 既无法推断航班,也无法解析凯夫拉维克机场。
该修复不是针对单个护照的特殊情况。 现在,匹配器可以识别几个语言中常见机场单词的词干:对应于冰岛语、德语、西班牙语、葡萄牙语、荷兰语、斯堪的纳维亚语和其他语言中“机场”的片段。 即使是损坏的结尾也可以暗示入口方式并偏向机场。
添加了两个关于欧盟和申根地区的印章课程。 仅当它单独出现时,角落椭圆中的两个字母 ISO 国家/地区代码才有用; 将每个两个字母的单词视为国家/地区会产生荒谬的匹配。 欧洲的数字日期也需要在本地化感知的一般检测器有机会读取月份优先格式之前进行“日-月”解析。
门点解析对前缀具有容错性,原因相同。长本地语言复合词可能包含城市或机场名称,即使捆绑的地理信息库存储较短的英文形式。解析器尝试使用有意义的前缀片段,然后围绕确认的结果构建国家、地区、城市和机场链。
链条在保存之前会显示。选择特定的机场可以同时标记其城市、地区和国家,但每个推断的级别仍然可见且可编辑。UI 的设计围绕着强烈的建议,然后是人类的决策。
保留原始文物,而不是另一个副本。
护照印章记录存储元数据以及对原始照片的引用,而不是完整的图像字节。Mapsake 为印章墙创建一个小的可重现的缩略图,并在需要时加载原始图像。如果从 Photos 来源的原始图像被真正删除,则可以删除其孤立的印章,而不会假装该图像仍然存在。
句子中的“真正”一词很重要。有限的照片权限无法证明未看到的资产已被删除;它可能只是在允许的选择范围之外。如果库权限足够,并且本地或云标识符都无法解析,则才会删除邮票。不确定性会保留记录。
此基于参考的模型还可以使与 CloudKit 兼容的数据保持较小。 一个标记可以同步其国家/地区、日期、书籍、输入方法、页面、最喜欢的状态、注释和标识符,而无需尝试将护照照片存储在数据库行中。 256 像素的本地缩略图是缓存,而不是真实来源。
邮票可以整理到命名护照册中,标记为到达或出发,分配日期和入境方式,并按国家/地区查看。裁剪、校正、旋转和审查模糊工具可帮助您准备一个有用的图像,然后再共享国家/地区或大陆拼贴。
相同的流程也可以将护照身份页扫描到书中。机器可读区域解析可以提供结构化字段,而图像仍然是用户自己的库中的引用。
MRZ(机器可读区)识别会禁用语言校正。机器可读区是一系列字母、数字和尖括号;尝试使用光学字符识别 (OCR) 将其转换为自然语言,可以使其外观更易读,但会降低解析字段的准确性。出生地等打印字段使用单独的最佳努力方法,并且所有结果都以可编辑的格式显示。
相机和选择功能在识别之前共享裁剪和旋转步骤。 之后,添加了图像校正功能,包括倾斜校正旋钮、缩放和平移,以及用于模糊敏感信息的画笔。 编辑器在模糊画笔处于活动状态时禁用冲突的手势,然后根据用户的选择将编辑合并到原始图像中。
邮票画廊根据国家和大陆对文物进行分组,而不是仅仅按照护照书的顺序。点击展开的国家列表会显示单个邮票;可以筛选到达、出发和收藏夹;国家和大陆的标题可以通过 Passport 分享管道显示为拼贴画。国家仍然是有用的元数据,但在旅行地图册中,地理位置是更自然的浏览方式。
足够的技术,值得信赖。
这些功能使用三种不同的技术:日历关联、空间分块和光学字符识别 (OCR)。用户体验遵循相同的模式。
- 从现有本地数据派生候选条目。
- 将复杂的功能移出主界面。
- 解释发现了什么。
- 允许用户打开、更正、分享或忽略它。
这是我希望 Mapsake 拥有的智能。它应该使个人记录更容易被重新发现,而不会表现得好像一个算法比真正经历过生活的人更了解生活。
这些功能比其平静的表面暗示的包含更多的工程,但其中任何一项都不需要成为用户的作业。 当“今天”打开到正确的年份,“Then & Now” 显示出令人惊讶的回归,并且一个困难的印章提供了一个有用的候选者,而不会过度夸大确定性时,技术工作就成功了。