Animated Aquarell Karte für Radtour / Rennen Videos

9 Schritt:Schritt 1: Beginnend mit Python, Einlesen von Daten Schritt 2: Umgang mit dem Tile Nummernschema Schritt 3: Die Bestimmung, die zum Download Fliesen, basierend auf Spuren Grenzen Schritt 4: Laden Sie die Fliesen Schritt 5: Seriendruck Fliesen in ein Bild einfügen Schritt 6: Ziehen Sie den Pfad Schritt 7: Mit den Funktionen Schritt 8: Mit dem Pfad als Maske Schritt 9: Animieren der Pfad

Animated Aquarell Karte für Radtour / Rennen Videos
Einführung
Ich habe immer aufzeichnen GPS Spuren meines Zyklus Expeditionen sowie oft die Aufnahme von Videos, so dass, wenn ich irgendwo interessant I, beides zu verbinden, wenn ich wieder nach Hause wollen. Nachdem wir auf Staubblatt der wunderschönen Aquarellkarten , wusste ich, dass ich die fehlende Zutat gefunden. Meine Prozess jetzt ist zweifach, ich ein Python-Skript, um die Karte abrufen und zeichnen Sie die GPS-Spur zu einem Bild, dann überlagern I und animieren die Bilder in einem Video-Editor. Ich habe versucht, eine Anleitung, die einfach, für den Anfänger Python-Programmierer als auch den Anfänger-Video-Editor folgen zu schreiben.

Der Python-Code ist auf jeden Fall nicht das stromlinienförmige, denn ich habe auf Lesbarkeit fokussiert und Schneiden der Prozess in diskreten Schritten, wenn Sie wissen, wie es gemacht wird, wird es sehr einfach, um es Ihren eigenen Bedürfnissen modifizieren. Alles ist unter Verwendung von Standard-Modulen durchgeführt.

Wenn Sie bereits wissen, wie man ein Kartenbild und eine Spur Bild zu erzeugen, dann springen Sie mit Schritt 8 (oder wenn Sie nur wollen das komplette Skript, Kopf zum vorherigen Schritt)

Zulassung
Alle von der Software, die ich verwendet, ist frei / Open-Source. Die Karten von Staubblatt sind unter Lizenz Creative Commons. Bitte nicht missbrauchen sie tun, indem Sie versuchen, die ganze Welt bei maximalem Zoom herunterladen. Offensichtlich du brauchst, um entsprechend zu lizenzieren Video, kontaktieren Staubblatt , bevor Sie sie im Handel.

Verwendete Software
Endomondo (für die Aufzeichnung von GPS-Tracks) Scripting: Python Text Editor Image Editor: GIMP Video Editing: Kdenlive (Kann jemand eine gute kostenlose Windows-Option, die unterstützt die Maskierung empfehlen?) Beispiel

Animated GPS Trace Demo von Jason Suter auf Vimeo .

Schritt 1: Beginnend mit Python, Einlesen von Daten

  1. Erstellen Sie das Script
    Erstens, stellen Sie sicher, dass Sie Python, indem Sie "python" in einem Befehlszeilenfenster installiert ist. Wenn nicht, fahren Sie hier . Ich habe das Skript mit Version 2.7.1 getestet

    Erstellen Sie einen Projektordner ein Make eine neue Textdatei in ihr, die Ihr Skript sein wird, rief ich mein "overlay.py". Öffnen Sie die Datei mit einem Texteditor wie gedit (Ubuntu) oder Notepad ++ (Windows). Regelmäßige Notizbuch wird auch funktionieren, aber Sie werden keine Syntax-Highlighting zu haben.

    Importieren Sie die Daten

    Unser erstes Ziel ist es, die GPS-Spur als eine einfache Liste von Lat, Lon Paare importieren. Es gibt eine Reihe von Formaten für die Speicherung von GPS-Spuren, aber ich werde nur mit kommagetrennten Werten (CSV) und GPS eXchange Format (GPX), denn es gibt eine Vielzahl von Werkzeugen, um fast jedem Format auf jede andere (konvertieren befassen GPSVisualiser , mein Lieblings-Online-Konverter).

    Eine CSV-Datei kann dann leicht gelesen werden, um eine Python-Liste mit dem folgenden einfachen Funktion, die Verwendung von Python gebaut in "csv" Modul macht.

     def traceImportCSV (fname):
    
     CSV-Import
     Spuren = []
     für Lat, Lon in csv.reader (open (fname, 'r')):
     trace.append ([float (lat), Schwimmer (lon)])
     Rück trace
    
    Die meisten Websites / Geräte haben die Möglichkeit, Strecken als GPX (wie Endomondo Exportfunktion) zu speichern, so dass, wenn wir in eine GPX-Datei zu lesen direkt, das wäre praktisch. Der folgende Code liest die Datei Zeile für Zeile und reguläre Ausdrücke verwendet, um Text, der sagt "lat =" oder "lon =" und ruft, was nicht-Whitespace-Zeichen zwischen den folgenden Anführungszeichen fallen sehen.

    Wenn beide in einer Zeile gefunden wird, dann, dass Lat, Lon Paar in die Liste aufgenommen. Zur Vereinfachung der einzige ungewöhnliche Bedingung, die ich behandelt wird mit lat, lon erscheinen als lon, lat statt. Wenn die Flaggen auf verschiedenen Linien, oder die Datei enthält Elemente, die nicht Punkte zu verfolgen sind, kann seltsame Ergebnisse entstehen.
     def traceImportGPX (fname):
    
     import re
     Spuren = []
    
     für Zeile in open (fname, 'r'):
     matchLat = re.search (r '. * lat = \ "(\ s *) \". * "Zeile)
     matchLon = re.search (r '. * lon = \ "(\ s *) \". * "Zeile)
     wenn matchLat = None und matchLon = None!:
     lat = matchLat.group (1)
     lon = matchLon.group (1)
     trace.append ([float (lat), Schwimmer (lon)])
    
     Rück trace 
    

Schritt 2: Umgang mit dem Tile Nummernschema

  1. Animated Aquarell Karte für Radtour / Rennen Videos
    Wie bei den meisten Web-basierte Karten, wird das Bild, das Sie auf dem Bildschirm sehen, der von Dutzenden von Fliesen, die aus den Kartenserver im Web-Browser abgerufen und angeordnet sind. Die abgerufenen Fliesen werden von den geographischen Koordinaten sowie der Zoomfaktor bestimmt. Damit wir eine schöne große Karte, die die ganze GPS-Route umfasst die Erstellung, müssen wir alle relevanten Fliesen an einer geeigneten Zoom abrufen und richtig anordnen.

    Die Fliesen Namenskonvention ist in der Tiefe beschrieben hier . Mit Hilfe dieser Definition werden die folgenden Funktionen definiert, von lat konvertieren, lon, um x, y und umgekehrt.

     ### Funktion nach lat zu kacheln x / y-Wert umzuwandeln, lon ### Grad
     def deg2num (lat_deg, lon_deg, Zoom):
    
     lat_rad = math.radians (lat_deg)
     n = 2,0 ** Zoom
     xtile = int ((lon_deg + 180,0) / 360,0 * n)
     ytile = int ((1,0 - math.log (Math.tan (lat_rad) + (1 / math.cos (lat_rad))) / Math.PI) / 2,0 * n)
     return (xtile, ytile)
    
     ### Funktion zur xy Fliese NW Ecke der Fliese zu konvertieren ###
     def num2deg (xtile, ytile, Zoom):
    
     n = 2,0 ** Zoom
     lon_deg = xtile / n * 360,0-180,0
     lat_rad = Math.atan (math.sinh (math.pi * (1 - 2 * ytile / n)))
     lat_deg = math.degrees (lat_rad)
     return (lat_deg, lon_deg)
    
    

Schritt 3: Die Bestimmung, die zum Download Fliesen, basierend auf Spuren Grenzen

  1. Animated Aquarell Karte für Radtour / Rennen Videos
    Um zu wissen, welche zum Abrufen Fliesen, müssen wir die Grenzen unserer GPS-Spur zu bestimmen. Seit Breite (West - Ost) im Bereich von -180 bis 180 und Länge (Süd - Nord) liegt im Bereich von -90 bis 90, der Norden und Osten Grenzen der Spur entsprechen der maximalen Länge und Breite auf. Die Süd- und Westgrenzen entsprechen den Minimalwerten der Breite und Länge auf.

    Die folgende Funktion transponiert die Liste der Lat, Lon Paare, effektiv die Erstellung einer Liste von Breitengraden und eine Liste der Längengrade, so dass es einfach ist, die minimalen und maximalen Wert eines jeden zu erhalten.

    Sobald die Spuren Grenzen bekannt sind, können wir die zuvor definierten Funktion die x, y-Werte der Fliesen an jeder Ecke zu bestimmen.
     ### Funktion zu verfolgen boundries bekommen ###
     def traceBoundaries (Trace):
    
         #transpose 2d Liste so, dass wir eine Reihe von Lats und eine Reihe von Lons
     lat = zip (* trace) [0]
     lon = zip (* trace) [1]
    
     Rückkehr {"Nord": max (lat), "Süd": min (lat), "Osten": max (lon), "West": min (lon)} Da wir jetzt eine Methode zur Bestimmung der Grenzen der GPS-Spur in Lat, Lon Koordinaten und in Abhängigkeit zu den lat konvertieren, koordiniert lon um x, y-Fliesen Zahlen ist es eine einfache Sache, die Palette der Fliesen zu bestimmen, die für eine bestimmte Zoomstufe heruntergeladen werden.  Die Fliesen werden mit 0,0 oben links (Nord-West) Ecke nummeriert, so dass der NW Grenze entspricht der linken oberen Fliese und der SE Grenze entspricht der unten rechts Fliese. 
     ### Bestimmen Fliesenserie gegebenen Grenzen und Zoom ###
     def determineTileRange (Grenzen, Zoom):
     Xmax, Ymin = deg2num (Grenzen ["nördlich"], Grenzen ["Osten"], Zoom)
     Xmin, Ymax = deg2num (Grenzen ["südlich"], Grenzen ["westen"], Zoom)
     Rückkehr {"xMin": Xmin, "xMax": Xmax, "yMin": Ymin "yMax": Ymax}
    

Schritt 4: Laden Sie die Fliesen

  1. Die Fliesen sind von Stamen der Kartenserver (oder welch auch immer andere Karte Sie verwenden) mit der URL http://tile.stamen.com/watercolor/ZOOM/X/Y.jpg verfügbar

    Durch die Verwendung von Python "os.path" Tool können wir das Skript cross-kompatibel zwischen Windows und Linux-Systeme. Nach einer einfachen Dateiprüfung, um festzustellen, ob wir heruntergeladen haben, dass insbesondere Fliesen in der Vergangenheit setzen wir Pythons "urllib" Modul, um das Bild abzurufen und sie in ein lokales Verzeichnis mit dem gleichen Aufbau wie der Web-Server.

    Es ist erwähnenswert, dass die Verlängerung der Aquarell Kartenkacheln ist ".jpg" was ungewöhnlich ist, Karten sind in der Regel als ".png" gespeichert, da ihre begrenzte Palette und scharfen Kanten sind besser komprimiert auf diese Weise.

     ### Nehmen Sie eine Fliesenserie und laden Sie sie (wenn nicht lokal vorhanden) ###
    
     def getTiles (xyRange, Zoom):
    
     #set acive Verzeichnis derjenigen des Skripts
     CURRENTDIR = os.curdir
     tileDir = os.path.join (CURRENTDIR, "Kacheln")
         #define die Kachel-Server
     tileServerUrl = "http://tile.stamen.com/watercolor/"
    
     #create eine vollständige Liste von x und y-Koordinaten zum Download
     xRange = range (xyRange ["xMin"], xyRange ["xMax"] + 1)
     YRange = range (xyRange ["yMin"], xyRange ["yMax"] + 1)
    
     für x in xRange:
     für y in YRange:
     #define den Dateinamen
     tileFileName = str (y) + ". jpg"
    
     #define den lokalen Pfad als auch den vollständigen Pfad zu den lokalen und Remote-Dateien
     localPath = os.path.join (tileDir, str (Zoom), str (x))
     localfile = os.path.join (localPath, tileFileName)
     Remote = tileServerUrl + str (Zoom) + "/" + str (x) + "/" + str (y) + ". jpg"
    
     #check, wenn die Datei lokal vorhanden
     wenn nicht os.path.isfile (localfile):
     print "Abrufen" + Remote
     #if lokale Verzeichnis noch nicht existiert, erstellen Sie es
     wenn nicht os.path.isdir (localPath):
     os.makedirs (localPath)
     #retrieve die Datei vom Server und speichern Sie es
     urllib.urlretrieve (Remote, localfile)
    

Schritt 5: Seriendruck Fliesen in ein Bild einfügen

  1. Animated Aquarell Karte für Radtour / Rennen Videos

    Animated Aquarell Karte für Radtour / Rennen Videos

    Animated Aquarell Karte für Radtour / Rennen Videos

    Jetzt, da wir alle Kartenkacheln lokal gespeichert ist es eine einfache Aufgabe zu automatisieren Verschmelzung sie alle zu einem Bild. Dies ist der Punkt, wenn Sie werden froh sein, dass Sie Scripting sind die Lösung anstatt zu versuchen, es von Hand machen.

    Python zeigt einige grundlegende Bildbearbeitungswerkzeuge, die wir nutzen werden. Die Kachelgröße wird innerhalb der Funktion als 256x256 welche so etwas wie ein Standard, aber es lohnt sich bestätigt, wenn Sie Fliesen aus einer anderen Quelle verwenden, definiert.

    Einfach Schleife durch den erforderlichen Bereich der Fliesen, Lesen in jeder Kachel und es in das Bild einfügen. Seit den Befehl "Einfügen" Orte der oberen linken Ecke des Bildes an den angegebenen Koordinaten, wird jede Kachel auf platziert werden (X * tileSize, Y * tileSize), wobei X, Y im Bereich von null bis Anzahl der Kacheln in X- oder Y-Richtung .
     ### Fliesen zu einem Bild zusammenführen ###
     def mergeTiles (xyRange, Zoom, Dateiname):
     Import Bild
     tileSize = 256
     tileDir = os.path.join (os.curdir, "Kacheln", str (Zoom))
    
     out = Image.new ("RGB", ((xyRange ["xMax"] - xyRange ["xMin"] + 1) * tileSize, (xyRange ["yMax"] - xyRange ["yMin"] + 1) * tileSize ))
    
     IMX = 0;
     für x in range (xyRange ["xMin"], xyRange ["xMax"] + 1):
     imy = 0
     für y in Reichweite (xyRange ["yMin"], xyRange ["yMax"] + 1):
     tileFile = os.path.join (tileDir, str (x), str (y) + ". jpg")
     tile = Image.open (tileFile)
     out.paste (Fliesen, (IMX, imy))
     imy + = tileSize
     IMX + = tileSize
    
     out.save (os.path.join (os.curdir, Dateiname))
    

Schritt 6: Ziehen Sie den Pfad

  1. Animated Aquarell Karte für Radtour / Rennen Videos

    Animated Aquarell Karte für Radtour / Rennen Videos

    Animated Aquarell Karte für Radtour / Rennen Videos

    Der letzte Schritt in dem GPS-Verfahren ist, um die Bahn auf einem Bild von der gleichen Größe wie der Karte zu zeichnen.

    Ziehen der Bahn erfordert, dass wir konvertieren GPS-Koordinaten, um etwas, das wir auf die x, y-Koordinaten eines Bildes beziehen. Da das Bild, das wir erzeugt wird, auf der Mercator-Projektion basiert, jede horizontale / vertikale Linie in es hat eine zugeordnete Breite oder Länge.

    Subtrahieren der Lat, Lon von der nordwestlichen Ecke von jedem Koordinaten effektiv macht die Nordwest koordinieren korrelieren mit Pixel (0,0).

    Die Werte müssen dann geändert werden, so dass eine Koordinate auf der Südwestecke korreliert mit der (X-Auflösung, Y Auflösung) Pixel. Dazu bestimmen wir die Lat, Lon des Punktes (bezogen auf die Nordwest-Ecke) als Prozentsatz des Bildes Lat, Lon Bereich und multiplizieren Sie die Auflösung in dieser Richtung. Der Lat, Lon Bereich ist einfach (North Grenze - Süd-Grenze, East Rand - West Grenze).
     ### Zeichnen Bild Pfad ###
    
     def drawTraceMask (trace, xresolution, YResolution, traceBoundaries, Zoom, Dateiname):
     Import Bild
     Import ImageDraw
    
     # Holen XY Anzahl von NW und SE Ecke Fliesen
     xy_nw = deg2num (traceBoundaries ["nördlich"], traceBoundaries ["westen"], Zoom)
     xy_se = deg2num (traceBoundaries ["südlich"], traceBoundaries ["Osten"], Zoom)
    
     # Bekommen Lat, Lon von Ecken
     # (Da die Funktion den NW-Ecke einer Fliese,
     # Wir brauchen Lat, Lon von X + 1, Y + 1 für die SE Ecke)
     NW = num2deg (xy_nw [0], xy_nw [1], Zoom)
     SE = num2deg (xy_se [0] + 1, xy_se [1] + 1, Zoom)
    
     # Die Bildgrenzen sind eigentlich anders, weil
     # Sie die Grenzen der Kacheln sind, nicht die Spur
     # Definieren die neuen Grenzen
    
     mapBoundaries = {}
     mapBoundaries ["nördlich"] = NW [0]
     mapBoundaries ["südlich"] = SE [0]
     mapBoundaries ["westlich"] = NW [1]
     mapBoundaries ["östlich"] = SE [1]
    
     # Offset um sicherzustellen, dass NW Ecke ist 0,0
     latOffset = - (mapBoundaries ["nördlich"])
     latDivisor = mapBoundaries ["nördlich"] - mapBoundaries ["südlich"]
     lonOffset = - (mapBoundaries ["westen"])
     lonDivisor = mapBoundaries ["Osten"] - mapBoundaries ["westen"]
    
     out = Image.new ("RGB" (xresolution, YResolution))
     Unentschieden = ImageDraw.Draw (out)
    
     FirstRun = True
     für Lat, Lon in Spur:
     # Convert genullt Lat, Lon in x, y-Koordinaten
     # Dies wird Korrektur für Nordhalbkugel müssen
     x = abs (int (xresolution * ((lon + lonOffset) / lonDivisor)))
     y = abs (int (YResolution * ((lat + latOffset) / latDivisor)))
     wenn FirstRun:
     FirstRun = false
     sonst:
     draw.line ((x, y, xPrev, yPrev) einzutragen, füllen = "white", width = 10)
     xPrev = x
     yPrev = y
     del Unentschieden
    
     out.save (os.path.join (os.curdir, Dateiname))
    

Schritt 7: Mit den Funktionen

  1. Alles, was übrig bleibt, ist, die Funktionen, die wir definiert haben. Ich habe das Skript beendet und befestigt.
     # Parameter definieren
     zoom = 12
     trace = traceImportCSV ("test_trace_4.csv")
    
     # Bestimmen die Grenzen der Spur
     boundaries_trace = traceBoundaries (Trace)
    
     # Bestimmen xy Zahl von Randfliesen
     tileRange = determineTileRange (boundaries_trace, Zoom)
    
     # Zählzahl von Fliesen in x- und y-Richtung
     xtiles = tileRange ["xMax"] - tileRange ["xMin"]
     ytiles = tileRange ["yMax"] - tileRange ["yMin"]
     numTiles = xtiles * ytiles
    
     # Download Fliesen bei Bedarf vor Ort nicht verfügbar
     getTiles (tileRange, Zoom)
    
     # Verschmelzen Fliesen in OneImage
     mergeTiles (tileRange, Zoom, "output-map.jpg")
    
     # Zeichnen den Weg
     # Hinweis: der Bereich, in "tilerange" bezieht sich auf die nordwestlichen Ecke, aber unser Bild erstreckt sich auf Block weiter
     drawTraceMask (Trace, 256 * (xtiles + 1), 256 * (ytiles + 1), boundaries_trace, Zoom, "output-mask.jpg")
    

Schritt 8: Mit dem Pfad als Maske

  1. Animated Aquarell Karte für Radtour / Rennen Videos

    Animated Aquarell Karte für Radtour / Rennen Videos

    Jetzt, da wir ein Bild der Karte und ein Bild des GPS Spur von genau der gleichen Größe, können wir die beiden zu überlagern und das Bild oder Video, das wir wollten.

    Der flexibelste Weg, um die Trace-Bild zu verwenden ist als eine Maske. Wenn ein Schwarz-Weiß-Bild auf ein Bild als Maske angewendet die schwarzen Bereiche werden transparent und die weißen Teile undurchsichtig. Auftragen der Schwarzweiss-Bild Pfad zu einer festen Farbschicht als Maske wird in einem Pfad dieser Farbe führen.

    Die Schwarz-Weiß-Maske kann geändert werden, wie gewünscht, öffnete ich den Pfad in GIMP, die ausgewählt weißes Feld mit dem Zauberstab und wuchs dann schrumpfte die Auswahl, um in allen Lücken zu füllen, danach habe ich eine kleine Menge des "Ölgemälde angewendet "auswählen, um die Kanten leicht verwischen und erzielen Sie einen Blick, die mehr im Einklang mit der Aquarell Thema war.

Schritt 9: Animieren der Pfad

  1. Animated Aquarell Karte für Radtour / Rennen Videos

    Animated Aquarell Karte für Radtour / Rennen Videos

    Animated Aquarell Karte für Radtour / Rennen Videos

    Animated Aquarell Karte für Radtour / Rennen Videos

    Alle voll ausgestatteten Video-Editor sollte in der Lage, das Maskenbild in der gleichen Weise, dass man verwendet sie in GIMP / Photoshop zu verwenden. Der einzige Unterschied in der Videobearbeitung ist, dass Sie uns eine zusätzliche Maske, die im Laufe der Zeit bewegt sich und enthüllt mehr von der GPS-Spur festlegen möchten.

    Dies ist ein kurzer Überblick darüber, wie die Wirkung in der freien und Open Source zu erreichen Kdenlive , werden die gleichen Konzepte anwendbar (aber wahrscheinlich einfacher zu implementieren) werden in Adobe Premier, Sony Vegas usw.

    Da bin ich mit Kdenlive, die alle Arten von bizarren Eigenheiten hat, finde ich es einfacher, eine Version des Bildes, die gerade die rote Spur auf einem transparenten Hintergrund ist (unter Verwendung von PNG-Format, weil es unterstützt Transparenz) zu speichern. Bei der Verwendung von Bildern mit Transparenz in Kdenlive stellen Sie sicher, dass die "transparent background" Flag in die Eigenschaften des Clips überprüft.

    Einmal war ich mit meinen beiden Bilder glücklich ich brachte sie in Kdenlive und legte sie auf zwei Videoebenen, der einen mit dem Pfad über dem man mit der Karte.

    Der "rotoscoping" Effekt verwendet, um eine Schicht-Maske, die in der Umgebung mit der Zeit bewegt werden kann zu machen. Fügen Sie zunächst "Rotoscoping", um den Effekt Baum des Wegs Clip, dann zeichnen Sie ein Polygon in Ihrem Projekt-Fenster (wie in den Bildern zu sehen ist). Wenn der "alpha-Betrieb" des Rotoscoping Wirkung auf "Subtrahieren" dann alles innerhalb des Polygons unsichtbar. Durch Änderung der Form des Polygons in verschiedenen Keyframes gesamten Clip die rotoscoping Maske kann hergestellt werden, bewegen und zeigen mehr von der Spur.

    Da die rotoscoping Wirkung nur auf die Maskierungsschicht, muss ein "Verbund" Übergang zwischen den beiden Schichten, damit der Effekt angewendet sichtbar sein werden.

    Rotoscoping in Kdenlive ist vollständig erklärt hier

    Beispiel

    Animated GPS Trace Demo von Jason Suter auf Vimeo .