python – Crear un video a partir de un track (GPX/KML) usando imagenes de Google Street View

Estoy intentando crear un video a partir de un track en formato GPX o KML a partir de las imágenes de Google Street view.

Quisiera hacerlo sin tener que usar la API de Google ya que necesitas su KEY y esta limitado su uso.

Es por ello que he encontrado una manera de hacerlo, usando esta url:

https://www.google.com/maps/@?api=1&map_action=pano&viewpoint={},{}&heading={}&pitch=0

Si introduzco los datos de las coordenadas de una ubicación, puedo conseguir generar un JPG con esa imágen.

Mi problema es que cuando quiero que sean varios puntos, entonces no consigo hacerlo.

He intentado ver si a través del control de pagina cargada lo puedo hacer, pero solo lo hace con el último punto que le envío.

Alguna idea de como hacerlo?

from PyQt5.QtWidgets import QWidget, QApplication,QMainWindow,QFileDialog
from PyQt5.QtWidgets import QLineEdit, QVBoxLayout, QHBoxLayout,QSplitter,QPushButton
from PyQt5.QtCore import QUrl,QRect,QRectF
from PyQt5.QtGui import QIcon

from PyQt5.QtWebEngineWidgets import QWebEngineView,QWebEngineProfile,QWebEngineSettings
import sys
import time


class Video_Google_Street(QMainWindow):
    def __init__(self):
        super().__init__()
        self.showMaximized()
        
        # Create GUI
        self.centralwidget = QWidget(self)
        self.layoutWidget = QWidget(self.centralwidget)
        self.horizontalLayout = QVBoxLayout(self.centralwidget)
        self.web_view=QWebEngineView(self.layoutWidget)
        self.file_Gpx = QPushButton(self.layoutWidget)
        self.file_Gpx.setText('GPX')
        self.pb_fixed_point = QPushButton(self.layoutWidget)
        self.pb_fixed_point.setText('Fixed Point')
        self.pb_list_points = QPushButton(self.layoutWidget)
        self.pb_list_points.setText('List of Points')
        
        self.setCentralWidget(self.centralwidget)
        self.horizontalLayout.addWidget(self.web_view)
        self.horizontalLayout.addWidget(self.file_Gpx )
        self.horizontalLayout.addWidget(self.pb_fixed_point)
        self.horizontalLayout.addWidget(self.pb_list_points)
        
        # Create Slots
        # Slot when page is loaded
        self.web_view.loadProgress.connect(self.webLoading)
        self.file_Gpx.clicked.connect(self.select_track)
        self.pb_fixed_point.clicked.connect(self.fixed_point)
        self.pb_list_points.clicked.connect(self.list_points)
        
        self.loaded=0 # For control how many times Google Street give page loaded. Give 4 or 6 times
                
    def webLoading(self,event):
        if event==100: # For control how many times Google Street give page loaded. Give 4 or 6 times
            self.loaded+=1
            print(self.loaded)
            if self.loaded==6: # When give 6 loaded pages, then I grab the image
                height=self.web_view.page().contentsSize().height()
                width=self.web_view.page().contentsSize().width()
                self.web_view.grab(QRect(0,0,width,height)).save(self.file_name_jpg, b'JPG')
                self.loaded=0 # Restart Counter
    
    def fixed_point(self):
        # For test one fixed point
        page='https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=42.2410144284368,0.965725583955646&heading=186.20048419497363&pitch=0'
        url = QUrl(page)        
        self.file_name_jpg='c:/temp/jpg/Fixed_Point.jpg'
        self.web_view.page().load(url)
        
    def list_points(self):
        # For test a list of points
        points=((42.2410144284368, 0.965725583955646), (42.2409574314952, 0.965720470994711), (42.240896243602, 0.965715777128935), (42.2408291045576, 0.965709993615747), (42.2407593671232, 0.965707311406732), (42.240682002157, 0.965706137940288), (42.2406058106571, 0.965705132111907), (42.2405290324241, 0.965702198445797), (42.2404542658478, 0.96570186316967), (42.2403736319393, 0.965694990009069), (42.2402878012508, 0.965689290314913), (42.2402046527714, 0.965683842077851), (42.2401182353497, 0.965680154040456), (42.2400250285864, 0.965676885098219), (42.2399284690619, 0.965670766308904), (42.239836268127, 0.965669928118587), (42.2397397086024, 0.965669760480523), (42.2396446578205, 0.965668670833111), (42.2395426500589, 0.965667329728603), (42.2394416481256, 0.965666742995381), (42.2393352817744, 0.965665988624096), (42.239225897938, 0.965662971138954), (42.2391161788255, 0.965662384405732), (42.2390032745898, 0.965660456568003), (42.238890286535, 0.965660959482193), (42.2387754544616, 0.965657522901893), (42.2386588621885, 0.965651236474514), (42.2385448683053, 0.965645201504231), (42.2384282760322, 0.965633047744632), (42.2383137792349, 0.965623240917921), (42.2381979413331, 0.965607399120927), (42.2380880545825, 0.965586444362998), (42.2379776649177, 0.965560711920261), (42.2378623299301, 0.965525507926941), (42.2377466596663, 0.965477395802736), (42.2376317437738, 0.965427858754992), (42.2375180851668, 0.965373795479536), (42.2374019119889, 0.965305985882878), (42.2372817993164, 0.965243289247155), (42.2371708229184, 0.965186543762684), (42.2370388079435, 0.965118734166026), (42.2369178570807, 0.965059977024794), (42.2367867641151, 0.965002393350005), (42.2366627119482, 0.964955454692245), (42.2365273442119, 0.964910443872213), (42.2363934852183, 0.96487800590694), (42.2362439520657, 0.964843891561031), (42.2360911499709, 0.964822098612785), (42.235938096419, 0.964814722537994), (42.2357739787549, 0.96481841057539), (42.2356092743576, 0.964833246544003), (42.2354392055422, 0.964861242100596), (42.235277434811, 0.96489611081779), (42.2350895125419, 0.964943552389741), (42.2349150013179, 0.964991580694914), (42.2347342036664, 0.965042291209102), (42.2345569264144, 0.965098952874541), (42.2343808226287, 0.965155195444822), (42.2342006955296, 0.965212108567357))
        self.file_name='List_Of_Points____' # Name used to save capture in JPG file
        self.load_street_view(points)
        
    def select_track(self):
        # For test with a GPX or KML file
        #self.file_name_gpx='c:/temp/jpg/GRMN6969.gpx'
        self.file_name_gpx,_ = QFileDialog.getOpenFileName(self, 'Selecciona Fichero Track','c:/' , 'TRACK (*.gpx *.kml)')
        self.read_track(self.file_name_gpx)

    def read_track(self, file_name):
        # Read a KML or GPX and convert in a list of points
        from xml.dom import minidom

        if file_name:
            points=()
            doc = minidom.parse(file_name)
            if file_name(-3:).upper()=='KML':
                coordinates = doc.getElementsByTagName('coordinates')(0).firstChild.data
                for element in coordinates.split():
                    lat=float(element.split(',')(0))
                    lon=float(element.split(',')(1))
                    points.append((lat,lon))
                    
            elif file_name(-3:).upper()=='GPX':
                track = doc.getElementsByTagName("trkpt")
                for punto in track:
                    lat=float(punto.getAttribute("lat"))
                    lon=float(punto.getAttribute("lon"))
                    points.append((lat,lon))
                    
            self.load_street_view(points)        
        
    def load_street_view(self, points):
        # Read a list of points and
        # Load a web page of Street view
        
        for position in range(len(points)):
            lat=points(position)(0)
            lon=points(position)(1)
            if not position==len(points)-1: # If it's the last point i can't calculate bearing
                bearing=self.cal_bearing(lat,lon,points(position+1)(0),points(position+1)(1))
                
            self.file_name_jpg=self.file_name(:-4)+"_"+str(position).zfill(5)+'.jpg'
            page=('https://www.google.com/maps/@?api=1&map_action=pano&viewpoint={},{}&heading={}&pitch=0').format(str(lat),str(lon),bearing)
            url = QUrl(page)   
            self.loaded=0 
            self.web_view.page().load(url)  
        
    def cal_bearing(self,lat1,lon1,lat2,lon2):
        """ Calculate bearing between two coordinates """
        from math import sin, cos, sqrt, atan2, radians, degrees 
        lat1 = radians(lat1) 
        lon1 = radians(lon1) 
        lat2 = radians(lat2) 
        lon2 = radians(lon2) 
        dLon = lon2 - lon1
        y = sin(dLon) * cos(lat2)
        x = cos(lat1)* sin(lat2) - sin(lat1)*cos(lat2)*cos(dLon)
        initial_bearing = atan2(x, y)
        # Now we have the initial bearing but math.atan2 return values
        # from -180° to + 180° which is not what we want for a compass bearing
        # The solution is to normalize the initial bearing as shown below
        initial_bearing = degrees(initial_bearing)
        compass_bearing = (initial_bearing + 360) % 360
        compass_bearing -=80 # I don't know why, but I have to correct with -80
        return compass_bearing
        
if __name__ == '__main__':
    app = QApplication(sys.argv)
    win = Video_Google_Street()
    win.show()
    sys.exit(app.exec_())