
2GIS以数据准确性为荣。 在每个城市的每个工作日,我们的专家都会遍及整个区域,以修复地图上的所有更改-新房屋,道路甚至小路。 他们还收集并在上面贴上道路标志,以帮助正确地建立道路和步行路线。 在本文中,我将告诉您我们决定如何帮助制图师并开始自动收集路标。
斐济是什么,为什么有迹象
斐济是我们为GIS专家开发的地图编辑器。 这是一个经典的客户端-服务器应用程序。 该中心上已经有几篇文章:在其中谈论斐济:
之前如何收集标志
斐济具有收集和更新标志的特殊操作模式。 在此模式下,映射器可以打开DVR录制的视频。 视频本身显示在单独的窗口中,其轨迹显示在地图上。 标记显示当前位置。

视频顶部会应用一个网格-它使您可以确定到标志的距离。 一旦字符变为像元大小,制图人员就会暂停并创建字符。 此时,我们知道当前位置以及到标志的距离,因此我们将其向前移动并将其绘制到链接上。 我们术语中的链接是路段的示意图。 每个字符都有自己的数字代码,其制图员会在一个特殊字段中输入。
如果已经输入了字符,则将其加载到字符编辑器中。 制图人员检查视频,并在必要时使用相同的数字代码进行更改。 或者,如果符号正确,则将其标记为已更新。
当然,此方法需要制图师观看每个视频-然后还要花时间输入每个字符。 此外,还不能准确确定地图上标志的位置:我们只是从当前位置偏离了由网格确定的距离,然后将结果点绘制到最近的道路。 结果,可能在必要的地方没有(甚至根本没有)精确地创建标志。 这意味着制图师还必须将他移动到正确的位置,这也浪费了他的时间。 此外,视频可能根本没有任何标志,但制图师仍然被迫观看视频。 当然,该程序允许您提高视频速度,但是在任何情况下的时间成本都将超过零。 因此,我们决定使此过程自动化。
现在如何收集
我们仍然需要注册商视频。 但是现在,制图师无需查看每个文件,只需选择所需的文件,然后按“下载”按钮即可。 之后,他可以做其他事情-视频将被处理,并且路标将出现在地图上。 将特别指出各种可疑案件。 因此,制图师所要做的就是检查这些情况并纠正它们。
建筑学

为了从视频中获取具有必需属性的必需类的对象,我们编写了一些服务。
第一个是VideoPreprocessingService-这是视频文件的上传位置。 该服务将文件发送到存储库,在数据库中进行记录,并创建处理任务。 您需要从视频中剪切特定频率的帧,从轨道中为其选择GPS点,然后将结果发送到“帧处理”服务。
前两个任务不是由服务本身执行,而是由Worker执行。 这样做是为了方便您更改这些工作人员的数量。 如果需要的话,从而提高生产率。
FrameProcessingService会自行保存所有接收到的帧和点。 他还将帧上传到队列。 它是由我们的机器学习专家共同编写的一项服务读取的。 他认出交通标志。 当然,FrameProcessingService会从此服务读取响应-这些是字符代码(如果它们在框架上)以及在其中刻有该字符的矩形。 知道矩形的大小,我们就可以知道到标志的距离。 并且处理完视频中的所有帧后,他将它们发送到我们的地图服务器。
地图服务器是系统中最重要的部分。 客户从他那里收到我们存储的所有数据(
图块除外 )。 他保存此数据并执行所有业务逻辑。
一般说明
我们的地图数据是地理对象。 地理对象是几何(即,对象在空间中的位置)和一组属性。 我们将它们存储在数据库中并对其进行操作。 但是从FrameProcessingService中,我们仅获得标志代码,识别标志的点的坐标,框架本身以及该框架上的标志蒙版。 因此,我们需要将此数据集转换为地理对象。 每个地理对象都属于某个类。 每种类型的路标都是单独的类别。 我们可以很容易地从签名代码中获得它。 从符号代码中,我们可以获得特定于此类的属性。 例如,我们收到了代码3_24_60。 3_24-表示这是一个速度限制(交通规则中的标志3.24)。 必须为这些字符指定限制值。 他告诉我们代码的第三部分-此处为60 km / h。
因此,定义了地理对象类,其属性也是特定的。 看来您已经可以创建一个地理对象。 但这还为时过早。 首先,每个标志都有一个“ Direction”(方向)属性,该属性指示该标志在哪个方向上起作用。 其次,我们仍然没有此地理对象的几何。 我们有一个看到标志的地方。 因此,标志本身与我们之间有一段距离。 此外,其几何形状还会影响Direction属性的值。

在这里,我们将做一点题外话。 当然,我们有公路网。 它由各个链接组成。 每个链接都是一行。 在图的第一部分,我们刚刚绘制了两个链接。 箭头表示绘制方向,即 左侧是从下至上绘制的,右侧是从上至下绘制的。
每个链接都包含有关您可以沿哪个方向移动的信息。 移动方向是一个单独的属性;它不等于渲染方向。 此属性告诉我们相对于绘图方向,您可以沿着链接沿哪个方向移动。 在该图的第二部分,两个链接对此属性具有相同的值,而在第三个图中,两个链接具有相反的值。
这与标志有什么关系? 因此,我们从下往上沿着链接移动,我们看到了某种迹象。 因此,在左侧链接上,标志的方向为“仅笔直”,在右侧为“仅背面”,即 与第三图中的链接相同。 一切在这里都变得很简单,但这是因为我们的链接是单向的。 实际上,大量的链接是双边的,即 它们的方向具有“双向”的含义。 而且标志总是指向一个方向,我们需要了解哪个方向。
地图匹配
在开始在地图上放置标志之前,我们需要了解当录制视频时我们行驶的道路。 GPS数据不足以实现这一点:通常会误认为数十米。 此外,地图仍是计划,可能也与实际地形不符。 例如,在宽阔的多车道道路上。
这将立即解决许多问题:
- 在这些道路上已经可以创建标志,因此我们可以对其进行更改(如果有);
- 其中一些标志可能未出现在视频中,我们可以找到这些标志-并给它们加上特殊标签;
- 当我们看到一些公认的标志时,我们可以了解我们所走的路,这反过来又可以帮助我们将该标志放置在地图上的正确位置。
演算法
我们使用的算法非常简单。 关于哈布雷的
文章已有描述。 一般而言,这听起来像是:我们有一条选定的道路,将GPS点距轨道最接近其终点。 关于这一点,我们评估了连接我们道路的道路-也就是说,我们评估了该点指向该特定道路的可能性。 每条道路都获得分数,选择分数最高的道路。 重复直到曲目结束。
在此过程中,我们对该算法做了一些补充。 该算法没有考虑道路连接的方向,因此我们要做的第一件事就是开始考虑它们:现在,如果连接是单向的,我们就知道应该沿着该方向移动。 如果此方向与链接的方向不一致,我们将丢弃此链接。
最初,在我们看来这已经足够了,最初的测试证实了这一点。 但是随后我们开始检查在居民区中录制的视频,结果发现一切并不那么乐观。 事实是,我们在道路上都有很高的数据准确性。 因此,我们已将所有季内车道绘制到最小的细节。 另一方面-正如我所说,GPS可能不是非常准确,甚至不是很准确。 而且,如果您走在高楼大厦周围的道路上,那么赛道上的各个点可能会非常强烈地离开。 曾经发生过这些点移向20多米的情况。 结果,事实证明很多地方都靠近我们未走过的道路。 此类轨迹缩小的结果是此图:

常识告诉我们,这种道路上几乎没有路标,因此没有特别的理由在那儿收集它们。 因此,在大多数情况下,汽车极有可能沿着主要街道行驶。 因此,对于季度内的车道,我们实行了罚款。 罚款是指沿道路的点数减少。 结果,解决了季内车道的问题-当我们不沿着它们行驶时它们并没有消失,而即使它们很好,当我们真正沿着它们行驶时,它们仍然是最佳选择,然后我们选择它们。
在那之后,结果已经非常好了。 在我们看来,地图匹配已经结束。 但是麻烦来了,他们没有等待。 突然之间,突然发现有些情况是另一条道路从这条道路上分叉出来,并且行驶非常顺畅。 至少在一段时间内,分支路也可以与我们的路平行,这使一切变得更糟。 同时,我提醒您,GPS轨迹几乎永远不会位于我们所链接的链接的顶部,它稍微偏离了它的某些侧面。 当然,由于所有这些,该算法开始坚持这些分支。 因此,充其量,我们收到了一些实际上没有经过的链接。 而且在最坏的情况下-他们在赛道上坐错了位置。

因此,我们提出了对道路的其他评估。 我们选择相对于我们选择链接的点的GPS轨迹的上一个和下一个点。 而且我们看到这些点的方位角与沿着此链接的移动方位角相差不大。 如果相差很大,我们会对此链接进行罚款。
结果,我们得到了适合自己的结果,尽管有时仍然会出现一些小错误(有时可以选择一个我们没有经过的额外链接)。 但是它们非常罕见,因此对我们而言并不重要。
字符排列
现在,我们有一组要行驶的道路连接以及一组带有标志的车架。 以及有关该帧上哪个字符的信息,还可以从轨道上的哪个点获得该帧和该字符的蒙版(描述此帧上字符的矩形)。 因此,您可以在地图上放置这些标志。
第一步是获取其他信息,这将有助于我们将标牌放置在正确的位置:
- 方位角标志。 如果标记恰好位于帧的中心,则它与GPS点的方位角重合。 如果符号未居中,则为点的方位角+框架中心与符号之间的角度。 我们已经有了GPS点的方位角,并且可以计算框架中心与符号之间的角度,因为 我们知道标志遮罩在框架上的位置,并且知道录制视频的视角。
- 从GPS点到标记的距离。 我们可以计算出来,因为 我们知道标志蒙版的大小,帧的分辨率以及视频录制的视角。
现在,您可以直接转到标牌的安装。 因为 轨迹上的点并不总是(但实际上永远不会)位于道路链接上,首先,我们需要将我们的标志检测点放在链接上。 我们这样做如下:
- 在轨道所在的道路中,我们仅保留那些在我们的GPS点周围穿过某种缓冲区的道路;
- 我们计算到每条选定道路的距离,并根据其增加量对其进行排序;
- 我们上路,计算GPS点在其上的投影;
- 我们沿着这条路的这一点获得了前进的方向。
- 如果这条道路上的项目4的方向不可接受,那么我们返回项目3并沿着那条路行驶;
- 如果方向是可接受的,则停止。
现在,我们有了在设置GPS点时所经过的道路,以及该点在道路上的投影。 实际上,可能没有正确选择这条道路以及重点。 例如,在转弯时,很容易犯错误。

因此,在继续之前,您需要确保我们没有记错。 或者,如果您输入有误,请用正确的道路替换道路,并在上面投影。 为此,请选择与我们的道路相连的道路,并根据距离和方位角对其进行评估。 结果,我们得到最适合给定点的道路,并在其上构建投影。
现在我们的GPS点已经拉到道路上了,我们可以计算出标志相对于道路的位置。 为此,请从该点构建一个矢量,该矢量的长度等于与符号方位角一致的方向上与符号的距离。 之后,我们尝试将标牌拉到轨道所在的道路之一上。 在这种情况下,我们会考虑道路的方向和标志的方向,这是针对通过标志的方位角的每条道路计算的。
在这一阶段,可能发现没有合适的道路。 例如,由于标志的方向在这些道路上是不可接受的(即,它们是单向的)。 在这种情况下,此标志位于我们未通过的相邻道路上,这意味着我们根本不会创建它。
现在我们有了在道路上绘制的路标的坐标,它仍然需要验证路标的设置是否正确,因为有时我们会犯错。 为此,我们可以通过将该距离与通过框架获得的到标志的距离进行比较,并在一定假设的基础上,验证标志与原始GPS点的距离不是太远。 还要检查标记是否不在GPS点后面。 如果验证成功,我们将获得道路上路标的坐标及其方向,这意味着我们的地理对象具有几何形状和所有必要的属性。 您可以继续保存它。
合并标志
实际上,现在进行保护还为时过早。 事实是,除了某些特殊情况外,每个标志都可以从几个框架中看到,当标志在框架的某些部分隐藏在任何障碍物之后,例如卡车后面。
从这些框架的每一个中,我们得到一个用于标志的地理对象,它们具有相同的属性,并且位于大约相同的位置。 这意味着我们只需要保留其中一个即可。 另外,如果该符号不是新的,则我们已经在数据库中拥有它,这意味着我们需要将其标记为已更新,而不是创建新的地理对象。
为此,我们在自己之间以及与现有对象之间进行新地理对象的合并。
首先,我们在行驶的链接上获得了已经创建的所有标志。 我们向他们添加从帧中识别出的所有字符。
我们需要对它们做些什么:我们需要从它们的类,属性和几何形状中了解,这些地理对象的某些集合是相同的符号。 如果此集中有一个现有的地理对象,则仅保留它并注意它已被更新。 如果集合仅包含新的地理对象,则仅保留其中一个。
我们分四个步骤进行操作:
- 按类别对地理对象进行分组;
- 在步骤1的每个组中,我们通过属性获得组;
- 对于步骤2中的每个组,我们按几何形状收集组;
- 如果步骤3中的组中存在一个现有标志,则仅保留它(如果有多个,则将其全部保留),如果组中没有现有标志,则保留中间的一个标志。
在那之后,我们拥有了可以最终保存的所需数量的字符。

当然,结果可能是我们有某种标志,但我们在视频中没有认出它。 在这种情况下,该符号将不会更新。 不幸的是,我们不能确定这个迹象也不再存在,因为 录制视频时可能会被某种障碍所掩盖。 因此,我们不会立即删除此标志,而是在视频中将其标记为丢失。 如果在其他一些视频上可以看到该标志,那么我们只需从其上删除该标志并进行更新即可。 如果他仍然不可见-制图师将不得不处理这个标志。 如果确实没有更多内容,则将其删除。
即时计划
从小路的迹象
视频中的标志不仅来自我们行驶的道路,还来自侧向道路:这些道路可能是穿越我们的道路或与我们相邻的道路。 反之亦然-分支出我们的道路。 甚至可能是与我们平行的道路。 区分这些道路上的标志与我们需要的标志是非常困难的。 毕竟,它们经常靠近我们的道路。
为了解决该问题,我们计划在链接上放置符号时使用许多语义规则。 例如,在高速公路上不太可能达到5 km / h的速度限制,但很有可能会在加油站的入口处。
跟踪标志
有时我们不保留标志,有时反之亦然-我们保留不需要合并的标志。 因此,我们计划逐帧跟踪字符-以便甚至在将它们转变为地理对象之前就可以识别不同帧上的相同字符。 并结合使用这些知识。
结论
当前版本实质上是beta。 因此,这是不完美的。 我们将在不久的将来解决一些问题。 有些问题仍不清楚如何解决。
而且有些通常不太可能使用算法解决。例如,GPS轨道的质量可能很差。或图像和轨道不同步的视频-只有通过观看才能理解。总的来说,任务比我们最初预期的要复杂得多。我们拥有解决各种问题的广阔领域。因此,我们将决定。当然,要告诉我们是否偶然发现了一些有趣的东西。