地线

摘要

Land Lines 是一项实验性功能,可让您通过手势探索 Google 地球卫星图像。通过结合使用机器学习、数据优化和显卡功能,该实验可以在手机的网络浏览器上高效运行,而无需后端服务器。此会议可查看我们的开发过程以及我们曾尝试各种方法并最终得出结果。

https://g.co/LandLines

当 Data Arts 团队想探索一个地球图像数据集时,我非常高兴:这些图像很美,展示了各种不同类型的结构和纹理,包括人造和自然景观,我想知道如何连接这个数据集。我进行了各种初始实验,关注图片相似性,以及不同的过滤和整理方式。

t-sne 相似性布局
t-sne 相似性布局, 高分辨率 50 MB

大家一起来反复研究图像中美丽的主导线条。这些线路(高速公路、河流、山脉边缘和地块)很容易被发现,我们设计了几个项目来探索这些线路。作为一名艺术家,您可以用线条集合实现的美丽效果(例如 Cassandra C Jones 处理闪电)让我深受启发,很高兴能使用此数据集。

线条检测

最初的挑战之一是如何检测图像中的线条。您可以拿出一张描画纸,将其放在其中一张照片的打印件上,然后绘制眼睛看到的线条,但一般来说,用于寻找线条的计算机视觉算法在多种多样的图片中通常表现不佳。

我使用包含本地项目的项目绘制算法,从而开发了之前的搜索版本,为此,我们手动为要搜索的行添加了注释。在艺术作品上绘画很有趣,但从几十张图片变为数千张图片却非常繁琐。我想尝试让查找线的流程自动完成

利用这些航拍图,我尝试了传统的线检测算法(例如 openCv 的Canny 边缘检测算法),但发现它们给出的线段极不连续,或者如果阈值过于宽松,则会出现大量虚假线。此外,在不同图像集中获得良好结果的阈值也不同,我想要一种算法,以便在没有监督的情况下找到一致的理想线条。

我试用了各种线检测算法,包括最近的算法,例如 gPb (PDF),虽然这些算法产生了令人惊叹的结果,但每张图片需要几分钟的运行时间。最后,我最终确定了结构化林边缘检测,这是一种随 openCV 一起提供的算法。

有了良好的“线条图像”后,我仍然会遇到实际获取线条并彼此识别各线条的问题,即如何获取这些光栅数据并将其变为矢量。在研究计算机视觉问题时,我通常会研究 imageJ,这是一个基于 Java 的开源图像处理环境,科学家和研究人员都使用它,它拥有一个健康的插件生态系统。我找到了一款名为凸线检测的插件,该插件有助于获取强度图片并将其转换成一组线段。(顺便提一下,我还发现这个来自 Matlab 的边缘检测和标签代码也很有用)。

检测到线段的图片
包含检测到的线段的图片

无服务器

我还想看看是否有可能实现一个本质上无服务器的数据可视化应用,即在客户端执行匹配和连接的艰巨任务。我通常使用 openFrameworks,一个用于广告素材编码的 C++ 框架。除了偶尔使用的节点项目之外,我也没有做过很多服务器端编码。我想知道能否在客户端执行所有计算,并且仅使用服务器来提供 JSON 和图片数据。

对于绘图应用来说,匹配是一项非常繁重的操作。绘制线条时,我们需要从数以万计的线段中找到最接近的匹配项。为了计算一次画作与另一幅画的距离,我们使用了美元手势识别程序中的一个指标,该指标本身涉及很多距离计算。过去,我使用过线程和其他技巧,但为了让它在客户端设备(包括手机)上实时工作,我需要更好的东西。我研究了指标树来查找最近/最近的相邻点,并选定了制高点树JavaScript 实现)。制高点树基本上是基于一组数据和距离指标构建的,当您输入新的数据时,它会很快为您提供最接近的值的列表。第一次在手机上看到这份作品时 我瞬间被震惊了这种特殊制高点树实现的一大好处是,您可以在计算树后将其省去,并节省计算此树的成本。

最接近的结果 绘制的结果
制高点树的结果示例显示,绘制的输入位于右侧,最接近的结果位于左侧。

在没有服务器的情况下使其工作的另一个挑战是将数据加载到移动设备上 - 对于绘图,树状和线段数据超过 12 MB,并且图像非常大,我们希望体验快速且响应迅速,目标是尽量减小下载内容的大小。我们的解决方案是逐步加载数据。在绘图应用中,我们将制高点树数据集拆分为 5 块,当应用加载时,它仅加载第一个分块,然后每 10 秒在后台加载另一个数据块,从本质上讲,应用在使用的第一分钟内会变得越来越好。在拖动应用中,还努力缓存图片,以便在您拖动时,在后台加载新图片。

最后,我发现为这两个应用都创建一个预加载器比预期更困难,这样,数据加载的初始延迟是可以理解的。我对 jax 请求和 pixi.js 使用进度回调,检查异步加载的图片实际上已加载,并使用它来驱动预加载消息。

已连接的线路

对于拖动,我想根据在边缘检测中找到的线条创建无限的线条。第一步是从线条检测算法中过滤线条,并识别从一条边缘开始,在其他三条边缘中一条结束的长线条。

表示适合连接的线路已标为红色 表示适合连接的线路已标为红色
表示连接的有效线路已标为红色

有了一组长线(或使用更精确的术语,即多段线,即一系列相连的点)来连接这些线,我将这些线转换为一组角度变化。一般来说,您可以将多段线想象成一组点:点 a 与点 b 相连,点 b 又连接到点 c。不过,您可以将线条视为一组角度变化:前移并旋转一定程度,向前移动并旋转一定程度。要直观地理解这一点,不妨考虑一下弯线机,它接一根电线,在被挤出时执行旋转。绘制的形状来自旋转。

如果将直线视为角度变化而不是点,则更容易将多段线组合成一条不连续性更小的较大直线,而不是拼接点,实质上就是添加相对角度变化。如需添加线条,您需要取主线条的当前角度,然后加上要添加的线条的相对变化。

顺便说一句,我使用了这种将线条转换为一组角度变化的技术,以便用于艺术用途 - 您可以使绘图“展开”,类似于导线可以卷曲和展开。一些示例:onetwothree

通过计算角度,我们可以在拖动时调整线条 - 我们会计算主角与所要位置之间的偏离,并寻找一张有助于最有效地使线条朝正确方向的图片。就是要相对思考。

最后,我想说,这个项目真的很有趣。作为艺术家,被要求使用像这些图片一样美观的数据集令人兴奋。我很荣幸能与 Data Arts 团队联系。希望你 通过这个实验获得了愉快的实验体验!