Zeichen von oben: Wie wir Kartographen vor unnötiger Arbeit und roten Augen retteten

Bild

2GIS ist stolz auf seine Datengenauigkeit. An jedem Arbeitstag in jeder Stadt gehen unsere Experten durch ganze Gebiete, um alle Änderungen auf der Karte zu korrigieren - neue Häuser, Straßen und sogar Wege. Außerdem sammeln sie Straßenschilder und bringen sie an, um Straßen- und Fußwege richtig zu bauen. In diesem Artikel werde ich Ihnen erzählen, wie wir beschlossen haben, Kartographen zu helfen, und automatisch mit dem Sammeln von Verkehrszeichen begonnen haben.

Was ist Fidschi und warum gibt es Zeichen?


Fidschi ist ein Karteneditor, den wir für unsere GIS-Spezialisten entwickeln. Dies ist eine klassische Client-Server-Anwendung. Es gibt bereits mehrere Artikel über den Hub: In denen wir über Fidschi sprechen:


Wie man vorher Schilder sammelt


Fidschi verfügt über eine spezielle Betriebsart zum Sammeln und Aktualisieren von Zeichen. In diesem Modus kann der Mapper das vom DVR aufgenommene Video öffnen. Das Video selbst wird in einem separaten Fenster angezeigt und seine Spur wird auf der Karte angezeigt. Die Markierung zeigt die aktuelle Position an.

Bild

Über dem Video wird ein Raster angebracht, mit dem Sie den Abstand zum Schild bestimmen können. Sobald der Charakter die Größe einer Zelle hat, hält der Kartograf an und erstellt den Charakter. In diesem Moment kennen wir die aktuelle Position und den Abstand zum Schild, also bewegen wir es vorwärts und zeichnen es auf den Link. Der Link in unserer Terminologie ist eine schematische Darstellung eines Straßenabschnitts. Jedes Zeichen hat seinen eigenen numerischen Code, sein Kartograf gibt ein spezielles Feld ein.

Wenn wir bereits ein Zeichen eingegeben haben, laden wir es in den Zeicheneditor. Der Kartograf überprüft das Video und nimmt bei Bedarf Änderungen mit denselben numerischen Codes vor. Wenn das Zeichen korrekt ist, wird es als aktualisiert markiert.

Bei dieser Methode muss der Kartograf natürlich jedes Video anzeigen - und dann auch Zeit für die Eingabe der einzelnen Zeichen aufwenden. Außerdem wird die Position des Zeichens auf der Karte nicht genau bestimmt: Wir weichen einfach von der aktuellen Position um eine Entfernung ab, die durch das Raster bestimmt wird, und zeichnen dann den resultierenden Punkt auf die nächste Straße. Infolgedessen werden Zeichen möglicherweise nicht genau dort (oder gar nicht) erstellt, wo dies erforderlich ist. Dies bedeutet, dass der Kartograf ihn auch an den richtigen Ort bringen muss, was auch seine Zeit in Anspruch nimmt. Außerdem hat das Video möglicherweise überhaupt keine Anzeichen, aber der Kartograf ist immer noch gezwungen, es anzusehen. Natürlich können Sie mit dem Programm die Geschwindigkeit des Videos erhöhen, aber die Zeitkosten betragen in jedem Fall mehr als null. Aus diesem Grund haben wir uns entschlossen, diesen Prozess zu automatisieren.

So sammeln Sie jetzt


Wir brauchen noch Registrar-Videos. Aber jetzt wählt der Kartograf nicht mehr die einzelnen Dateien aus, sondern drückt einfach auf die Schaltfläche "Herunterladen". Danach kann er andere Dinge tun - das Video wird verarbeitet und Verkehrszeichen erscheinen auf der Karte. Verschiedene zweifelhafte Fälle werden speziell erwähnt. Daher muss der Kartograf diese Fälle nur noch durchgehen und korrigieren.

Architektur


Bild

Um Objekte der erforderlichen Klassen mit den erforderlichen Attributen aus dem Video zu erhalten, haben wir mehrere Dienste geschrieben.

Der erste ist VideoPreprocessingService - hier wird die Videodatei hochgeladen. Der Dienst sendet die Datei an das Repository, zeichnet sie in der Datenbank auf und erstellt Aufgaben für die Verarbeitung. Sie müssen Frames aus dem Video mit einer bestimmten Frequenz ausschneiden, GPS-Punkte für sie aus der Spur für sie auswählen und das Ergebnis an den Frames Processing-Dienst senden.

Die ersten beiden Aufgaben werden nicht vom Dienst selbst ausgeführt, sondern vom Mitarbeiter. Dies geschieht, damit Sie die Anzahl dieser Mitarbeiter leicht ändern können. Dies erhöht die Produktivität, wenn ein solcher Bedarf besteht.

FrameProcessingService speichert sich alle empfangenen Frames und Punkte. Er lädt auch Frames in die Warteschlange hoch. Es wird von einem Service gelesen, der von unseren Experten für maschinelles Lernen verfasst wurde. Er erkennt Verkehrszeichen. Natürlich liest FrameProcessingService die Antworten dieses Dienstes - dies sind die Zeichencodes, sofern sie sich im Frame befinden, und die Rechtecke, in die dieses Zeichen eingeschrieben ist. Wenn wir die Größe des Rechtecks ​​kennen, verstehen wir den Abstand zum Zeichen. Und wenn alle Bilder aus dem Video verarbeitet sind, sendet er sie an unseren Kartenserver.

Der Kartenserver ist der wichtigste Teil des Systems. Kunden erhalten von ihm alle Daten, die wir speichern ( außer Kacheln ). Er speichert diese Daten und führt die gesamte Geschäftslogik aus.

Allgemeine Beschreibung


Unsere Kartendaten sind Geoobjekte. Ein Geoobjekt ist eine Geometrie (dh die Position eines Objekts im Raum) und eine Reihe von Attributen. Wir speichern sie in der Datenbank und bearbeiten sie. Von FrameProcessingService erhalten wir jedoch nur den Zeichencode, die Koordinaten des Punkts, von dem aus das Zeichen erkannt wurde, den Rahmen selbst und die Zeichenmaske auf diesem Rahmen. Wir müssen diesen Datensatz also in ein Geoobjekt verwandeln. Jedes Geoobjekt gehört zu einer Klasse. Jede Art von Verkehrszeichen ist eine separate Klasse. Wir können es leicht aus dem Zeichencode erhalten. Aus dem Vorzeichencode können wir Attribute erhalten, die für diese Klasse spezifisch sind. Zum Beispiel haben wir den Code 3_24_60 erhalten. 3_24 - sagt, dass dies eine Geschwindigkeitsbegrenzung ist (Zeichen 3.24 in den Verkehrsregeln). Der Einschränkungswert muss für diese Zeichen angegeben werden. Er sagt uns den dritten Teil des Codes - hier sind es 60 km / h.

Die Geo-Objektklasse ist also definiert, und ihre Attribute sind ebenfalls spezifisch. Es scheint, dass Sie bereits ein Geo-Objekt erstellen können. Aber es ist zu früh. Erstens hat jedes Zeichen ein Attribut „Richtung“, das angibt, in welche Richtung das Zeichen wirkt. Zweitens haben wir noch keine Geometrie für dieses Geoobjekt. Wir haben einen Punkt, von dem aus wir ein Zeichen gesehen haben. Das Schild selbst ist also in einiger Entfernung von uns. Darüber hinaus wirkt sich seine Geometrie auf den Wert des Direction-Attributs aus.

Bild

Hier machen wir einen kleinen Exkurs. Natürlich haben wir ein Straßennetz. Es besteht aus einzelnen Links. Jeder Link ist eine Linie. Im ersten Teil der Abbildung haben wir gerade zwei Links gezeichnet. Die Pfeile zeigen die Richtung, in die sie gezeichnet wurden, d.h. Die linke wurde von unten nach oben und die rechte von oben nach unten gezeichnet.

Jeder Link enthält Informationen darüber, in welche Richtung Sie sich bewegen können. Die Bewegungsrichtung ist ein separates Attribut und entspricht nicht der Renderrichtung. Dieses Attribut gibt an, in welche Richtung Sie sich relativ zur Zeichenrichtung entlang des Links bewegen können. Im zweiten Teil der Abbildung haben beide Links den gleichen Wert für dieses Attribut und in der dritten Abbildung entgegengesetzte Werte.

Wie hängt das mit Zeichen zusammen? Wir bewegen uns also von unten nach oben entlang der Links und sehen eine Art Zeichen. Auf dem linken Link hat das Schild also die Richtung "Nur gerade", auf der rechten Seite "Nur zurück", d. H. Gleich wie die Links in der dritten Abbildung. Hier ist alles einfach geworden, aber das liegt daran, dass unsere Links einseitig sind. In Wirklichkeit ist eine sehr große Anzahl von Verbindungen bilateral, d.h. Ihre Richtung hat die Bedeutung von "In beide Richtungen". Und das Zeichen ist immer in eine Richtung gerichtet, und wir müssen verstehen, in welche Richtung.

Kartenabgleich


Bevor wir beginnen, Schilder auf der Karte zu platzieren, müssen wir verstehen, auf welchen Straßen wir gefahren sind, als wir das Video aufgenommen haben. GPS-Daten reichen dafür nicht aus: Sie werden oft mit zehn Metern verwechselt. Darüber hinaus sind Karten immer noch Schemata und stimmen möglicherweise auch nicht mit dem realen Gelände überein. Zum Beispiel auf breiten mehrspurigen Straßen.

Dies wird eine Reihe von Problemen gleichzeitig lösen:

  • Auf diesen Straßen können bereits Schilder erstellt werden, sodass wir gegebenenfalls Änderungen daran vornehmen können.
  • Einige dieser Zeichen erscheinen möglicherweise nicht im Video, und wir können solche Zeichen finden - und sie mit einem speziellen Etikett versehen.
  • Wir können verstehen, auf welcher Straße wir uns befanden, als wir ein erkanntes Schild sahen, was uns wiederum hilft, dieses Schild an der richtigen Stelle auf der Karte zu platzieren.

Algorithmus


Der von uns verwendete Algorithmus ist ziemlich einfach. Es gibt bereits einen Artikel über Habré mit seiner Beschreibung. Im Allgemeinen klingt es so: Wir haben eine ausgewählte Straße, nehmen Sie den GPS-Punkt, der dem Ende am nächsten liegt, von der Strecke. Und in Bezug auf diesen Punkt bewerten wir die Straßen, die unseren Weg verbinden - das heißt, wir bewerten, wie wahrscheinlich es ist, dass sich unser Punkt auf diese bestimmte Straße bezieht. Jede Straße erhält Punkte, die mit den meisten Punkten wird ausgewählt. Wiederholen, bis der Track endet.

Dabei haben wir den Algorithmus mehrfach erweitert. Der Algorithmus berücksichtigte die Richtungen auf den Straßenverbindungen nicht. Als erstes haben wir begonnen, sie zu berücksichtigen: Wenn die Verbindung nur in eine Richtung verläuft, verstehen wir, in welche Richtung wir uns bewegen sollten. Und wenn diese Richtung nicht mit der Richtung des Links übereinstimmt, verwerfen wir diesen Link.

Anfangs schien es uns, dass dies ausreichen würde, und die ersten Tests bestätigten dies. Aber dann begannen wir, die in Wohnvierteln aufgenommenen Videos zu überprüfen, und alles stellte sich als nicht so rosig heraus. Tatsache ist, dass wir eine sehr hohe Datengenauigkeit haben, auch auf Straßen. Dementsprechend haben wir alle vierteljährlichen Einfahrten bis ins kleinste Detail gezeichnet. Auf der anderen Seite - wie gesagt - ist GPS möglicherweise nicht sehr genau oder sogar sehr ungenau. Und wenn Sie auf einer Straße fahren, um die sich hohe Gebäude befinden, können die Punkte auf der Strecke ziemlich stark abfahren. Früher bewegten sich die Punkte in Richtung mehr als 20 Meter. Infolgedessen stellt sich heraus, dass viele Punkte in der Nähe der Straßen liegen, auf denen wir nicht gefahren sind. Das Ergebnis des Schrumpfens solcher Spuren war dieses Bild:

Bild
Der gesunde Menschenverstand sagte uns, dass es auf solchen Straßen nur wenige Schilder gibt und es daher keinen besonderen Grund gibt, sie dort zu sammeln. Daher bewegte sich das Auto höchstwahrscheinlich in den meisten Fällen entlang der Hauptstraßen. Aus diesem Grund haben wir für Einfahrten innerhalb eines Quartals eine Geldstrafe eingeführt. Mit einer Geldstrafe meinen wir eine Verringerung der Anzahl der Punkte entlang der Straße. Infolgedessen wurde das Problem mit Einfahrten innerhalb eines Quartals behoben - sie kamen nicht heraus, als wir sie nicht befahren haben, und als wir sie wirklich befahren haben, haben sie sich trotz der Geldstrafe als die beste Option herausgestellt, und dann haben wir sie ausgewählt.

Danach waren die Ergebnisse bereits sehr gut. Und es schien uns, dass das Mapmatching vorbei war. Aber der Ärger kam, von wo aus sie nicht warteten. Ganz plötzlich stellte sich heraus, dass es Fälle gibt, in denen eine andere Straße von der Straße abzweigt, und dies sehr reibungslos. Und alles wurde durch die Tatsache verschärft, dass die Nebenstraße zumindest für einige Zeit auch parallel zu unserer verlaufen kann. Gleichzeitig erinnere ich Sie daran, dass sich der GPS-Track fast nie über den Verbindungen befindet, zu denen wir gereist sind. Er ist zu einer Seite leicht versetzt. Und dank alledem begann der Algorithmus natürlich, an diesen Zweigen festzuhalten. Aus diesem Grund haben wir bestenfalls mehrere Links erhalten, die wir nicht wirklich durchlaufen haben. Und im schlimmsten Fall saßen sie auf der Strecke ganz falsch.

Bild

Aus diesem Grund haben wir eine zusätzliche Bewertung der Straße vorgenommen. Wir nehmen den vorherigen und den nächsten Punkt der GPS-Spur relativ zu dem Punkt, von dem aus wir den Link ausgewählt haben. Und wir sehen, dass sich der Azimut an diesen Punkten nicht zu sehr vom Azimut der Bewegung entlang dieser Verbindung unterscheidet. Wenn es sehr unterschiedlich ist, wird dieser Link gut.

Als Ergebnis haben wir ein Ergebnis erhalten, das zu uns passt, obwohl manchmal immer noch kleine Fehler auftreten (manchmal kann ein zusätzlicher Link ausgewählt werden, den wir nicht durchlaufen haben). Aber sie sind ziemlich selten und daher für uns nicht kritisch.

Zeichenplatzierung


Jetzt haben wir eine Reihe von Straßenverbindungen, auf denen wir gefahren sind, und eine Reihe von Rahmen mit Schildern. Neben Informationen darüber, welches Zeichen sich in diesem Frame befindet, von welchem ​​Punkt auf der Spur dieser Frame und die Maske des Zeichens erhalten werden (ein Rechteck, das das Zeichen in diesem Frame beschreibt). Sie können diese Zeichen also auf der Karte platzieren.

Der erste Schritt besteht darin, zusätzliche Informationen zu erhalten, die uns helfen, das Schild an der richtigen Stelle anzubringen:

  1. Azimutzeichen. Befindet sich die Markierung genau in der Mitte des Rahmens, stimmt sie mit dem Azimut am GPS-Punkt überein. Wenn das Zeichen nicht zentriert ist, ist dies der Azimut am Punkt + der Winkel zwischen der Mitte des Rahmens und dem Zeichen. Wir haben bereits den Azimut des GPS-Punktes und können den Winkel zwischen der Mitte des Rahmens und dem Zeichen berechnen, weil Wir wissen, wo sich die Zeichenmaske auf dem Rahmen befindet, und wir kennen den Betrachtungswinkel, mit dem das Video aufgenommen wurde.
  2. Die Entfernung zur Markierung vom GPS-Punkt. Wir können es berechnen, weil Wir kennen die Größe der Zeichenmaske, die Auflösung des Rahmens und den Betrachtungswinkel, mit dem das Video aufgenommen wird.

Jetzt können Sie direkt zur Installation des Schildes gehen. Weil Punkte auf der Strecke liegen nicht immer (aber eigentlich nie) auf den Straßenverbindungen. Zuerst müssen wir unseren Schilderkennungspunkt auf die Verbindung setzen. Wir machen es wie folgt:

  1. Unter den Straßen, auf denen die Strecke lag, lassen wir nur diejenigen, die eine Art Puffer um unseren GPS-Punkt kreuzen.
  2. Wir berechnen die Entfernung zu jeder ausgewählten Straße und sortieren sie nach ihrer Zunahme.
  3. Wir nehmen die Straße, berechnen die Projektion des GPS-Punktes darauf;
  4. Wir bekommen die Richtung, mit der wir uns an diesem Punkt entlang dieser Straße bewegen;
  5. Wenn die Richtung von Punkt 4 auf dieser Straße nicht akzeptabel ist, kehren wir zu Punkt 3 zurück und nehmen dort die nächste Straße.
  6. Wenn die Richtung akzeptabel ist, stoppen Sie.

Jetzt haben wir die Straße, die wir genommen haben, als wir den GPS-Punkt eingestellt haben, und die Projektion dieses Punktes auf unsere Straße. Tatsächlich kann diese Straße und damit der Punkt nicht richtig gewählt werden. Zum Beispiel ist es in Kurven sehr leicht, einen Fehler zu machen.

Bild

Bevor Sie fortfahren, müssen Sie daher sicherstellen, dass wir uns nicht irren. Wenn Sie einen Fehler machen, ersetzen Sie die Straße durch die richtige und erhalten Sie eine Projektion darauf. Nehmen Sie dazu die Straßen, die mit unserer Straße verbunden sind, und bewerten Sie sie nach Entfernung und Azimut. Als Ergebnis erhalten wir die Straße, die für einen bestimmten Punkt am besten geeignet ist, und konstruieren eine Projektion darauf.

Nachdem unser GPS-Punkt auf die Straße gezogen wurde, können wir die Position des Zeichens relativ dazu berechnen. Erstellen Sie dazu von diesem Punkt aus einen Vektor mit einer Länge, die dem Abstand zum Zeichen in der Richtung entspricht, die mit dem Zeichenazimut übereinstimmt. Danach versuchen wir, das Schild auf eine der Straßen zu ziehen, auf denen unsere Strecke stand. In diesem Fall berücksichtigen wir die Richtung der Straßen und die Richtung des Zeichens, die für jede Straße durch den Azimut des Zeichens berechnet wird.

Zu diesem Zeitpunkt könnte sich herausstellen, dass es keine geeignete Straße gab. Zum Beispiel aufgrund der Tatsache, dass das Schild eine Richtung hat, die auf diesen Straßen nicht akzeptabel ist (d. H. Sie sind in eine Richtung). In diesem Fall befindet sich dieses Schild an einer benachbarten Straße, an der wir nicht vorbeigefahren sind, was bedeutet, dass wir es einfach nicht erstellen werden.

Jetzt haben wir die Koordinate des Zeichens auf die Straße gezeichnet. Es bleibt zu überprüfen, ob es richtig eingestellt ist, da wir manchmal einen Fehler machen können. Zu diesem Zweck überprüfen wir, ob das Zeichen nicht zu weit vom ursprünglichen GPS-Punkt entfernt ist, indem wir diese Entfernung mit der Entfernung zu dem durch den Rahmen erhaltenen Zeichen vergleichen, wobei einige Annahmen getroffen werden. Stellen Sie außerdem sicher, dass sich die Markierung nicht hinter dem GPS-Punkt befindet. Wenn die Validierungen erfolgreich sind, haben wir die Koordinaten des Zeichens auf der Straße und seine Richtung erhalten, was bedeutet, dass unser Geoobjekt Geometrie und alle erforderlichen Attribute hat. Sie können fortfahren, um es zu speichern.

Zeichen zusammenführen


Tatsächlich ist es zu früh, um mit der Erhaltung fortzufahren. Tatsache ist, dass jedes Schild von mehreren Rahmen aus gesehen werden kann, mit Ausnahme einiger Sonderfälle, wenn das Schild hinter einem Hindernis, beispielsweise hinter einem LKW, auf einem Teil der Rahmen versteckt ist.

Von jedem dieser Frames haben wir ein Geo-Objekt für das Zeichen erhalten, sie haben dieselben Attribute und sie befinden sich ungefähr an derselben Stelle. Dies bedeutet, dass wir nur einen von ihnen verlassen müssen. Wenn dieses Zeichen nicht neu ist, haben wir es bereits in der Datenbank. Dies bedeutet, dass wir es als aktualisiert markieren und kein neues Geoobjekt erstellen müssen.

Dazu führen wir die Zusammenführung neuer Geo-Objekte zwischen uns und bestehenden durch.
Zunächst erhalten wir alle Zeichen, die wir bereits erstellt haben, auf den Links, auf denen wir gefahren sind. Zu ihnen fügen wir alle Zeichen hinzu, die wir aus den Frames erkannt haben.

Was wir mit ihnen tun müssen: Wir müssen anhand ihrer Klassen, Attribute und Geometrien verstehen, dass einige dieser Geoobjekte dasselbe Zeichen sind. Wenn in diesem Satz ein Geoobjekt vorhanden ist, lassen Sie nur dieses und beachten Sie, dass es aktualisiert wurde. Wenn das Set nur neue Geo-Objekte enthält, lassen Sie nur eines davon übrig.

Wir machen das in vier Schritten:

  1. Gruppieren Sie Geoobjekte nach ihrer Klasse.
  2. In jeder Gruppe aus Schritt 1 erhalten wir Gruppen nach Attributen;
  3. Für jede Gruppe aus Schritt 2 sammeln wir die Gruppen nach Geometrie;
  4. Wenn in der Gruppe ab Schritt 3 ein Zeichen vorhanden ist, belassen wir nur dieses (wenn mehrere vorhanden sind, lassen wir sie alle), und wenn in der Gruppe keine Zeichen vorhanden sind, belassen wir das Zeichen in der Mitte.

Danach haben wir die gewünschte Anzahl von Zeichen, die endlich gespeichert werden können.

Bild

Natürlich kann sich herausstellen, dass wir eine Art Zeichen haben, aber wir haben es mit dem Video nicht erkannt. In diesem Fall wird dieses Symbol nicht aktualisiert. Leider können wir nicht sicher sein, dass dieses Schild auch nicht mehr am Boden ist, weil Es könnte nur durch ein Hindernis abgedeckt werden, während ein Video aufgenommen wird. Daher löschen wir dieses Zeichen nicht sofort, sondern markieren es im Video als fehlend. Wenn dieses Zeichen in einem anderen Video sichtbar ist, entfernen wir einfach diese Markierung und aktualisieren sie. Wenn er immer noch nicht sichtbar ist, muss sich der Kartograf mit diesem Zeichen befassen. Und löschen Sie es, wenn es wirklich nicht mehr ist.

Sofortige Pläne


Schilder von den Nebenstraßen


Das Video zeigt Schilder nicht nur von den Straßen, die wir fahren, sondern auch von den Nebenstraßen: Dies können Straßen sein, die unsere kreuzen oder an unsere angrenzen. Oder umgekehrt - Straßen, die von unseren abzweigen. Es können sogar Straßen sein, die parallel zu unseren verlaufen. Es ist sehr schwierig, die Schilder auf diesen Straßen von den Schildern zu unterscheiden, die wir brauchen. Schließlich sind sie oft in der Nähe unserer Straße.

Um das Problem zu lösen, planen wir, beim Platzieren eines Zeichens auf einem Link eine Reihe semantischer Regeln zu verwenden. Zum Beispiel ist es unwahrscheinlich, dass eine Geschwindigkeitsbegrenzung von 5 km / h auf der Autobahn liegt, aber sehr wahrscheinlich am Eingang zur Tankstelle.

Zeichen verfolgen


Manchmal halten wir keine Zeichen und manchmal umgekehrt - wir halten Zeichen, die nicht zusammengeführt werden müssen. Daher planen wir, Zeichen nach Frames zu verfolgen, um dasselbe Zeichen in verschiedenen Frames zu erkennen, noch bevor wir sie in Geoobjekte verwandeln. Und nutzen Sie dieses Wissen mit Merge.

Fazit


Die aktuelle Version ist im Wesentlichen Beta. Daher ist es unvollkommen. Es gibt Probleme, die wir in naher Zukunft lösen werden. Es gibt Probleme, deren Lösung noch unklar ist.Und es gibt solche, die im Allgemeinen wahrscheinlich nicht mit Algorithmen gelöst werden können. Beispielsweise können GPS-Tracks von sehr schlechter Qualität sein. Oder ein Video, bei dem Bild und Spur nicht synchron sind - und das kann man nur verstehen, wenn man es sich ansieht. Im Allgemeinen stellte sich heraus, dass die Aufgabe viel komplizierter war als ursprünglich erwartet.

Wir haben ein riesiges Feld für die Lösung verschiedener Probleme. Also werden wir uns entscheiden. Und natürlich, um zu sagen, ob wir auf etwas Interessantes stoßen.

Source: https://habr.com/ru/post/de457342/


All Articles