2017-09-20 2 views
1

Ich habe zwei Python-Skripte (eher Fragmente) von einem ehemaligen Kollegen geerbt. Der Code soll ein Bild mit hoher Auflösung (png) in zoombare Kacheln (slippy-map) konvertieren, die von Leaflet.js im goographischen Koordinatenraum (lat/long) verwendet werden können.Python Slippy-map Tile Generation

Ich bin kein Python (oder GIS) Typ, ich kämpfe darum, dass sie richtig funktionieren. Ich kann nicht feststellen, ob das Problem mein Mangel an Wissen oder der Code ist ...

Dieses erste Skript funktioniert wie erwartet und produziert fünf Bilddateien mit progressiv niedriger Auflösung, abgeleitet aus dem Eingabebild (myImgMaxRez.png). Ich glaube, das wird als "Bildpyramide" bezeichnet. Die Abmessungen jedes z [1..5] .png sind teilbar durch 256.

from skimage import io 
from skimage import transform 
import skimage 

z1 = io.imread("myImgMaxRez.png", as_grey=True) 
io.imsave("z1.png",skimage.img_as_uint(z1)) 

z2 = transform.pyramid_reduce(z1) 
io.imsave("z2.png",skimage.img_as_uint(z2)) 

z3 = transform.pyramid_reduce(z2) 
io.imsave("z3.png",skimage.img_as_uint(z3)) 

z4 = transform.pyramid_reduce(z3) 
io.imsave("z4.png",skimage.img_as_uint(z4)) 

z5 = transform.pyramid_reduce(z4) 
io.imsave("z5.png",skimage.img_as_uint(z5)) 

Das nächste Skript die slippy-Kartenkacheln zu erzeugen, wirft ein Typ-Umwandlungsfehler (float int).

import math 
import os 
from skimage import io 

def createTiles(xStart, yStart, zoom, theData): 
    ncols = theData.shape[1]/256 
    nrows = theData.shape[0]/256 
    print(nrows, ncols) 
    topDir = "%d" % (zoom) 
    os.mkdir(topDir) 
    for i in range(0, ncols): 
     theDir = topDir + "/%d" % (i+xStart) 
     print (theDir) 
     os.mkdir(theDir) 
     for j in range(0, nrows): 
      theFile = topDir + "/%d/%d.png" % (i + xStart, j + yStart) 
      print (theFile) 
      io.imsave(theFile, theData[j*256:(j+1)*256, i*256(i+1)*256]) 

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) 

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) 

# Take center point of interest (MCK). Since z tile is 4x3 go 1 tile up and 2 left 
startZoom = 18 
centerLoc = deg2num(43.533942709166325, -96.71487003564836, startZoom) 
startCol = centerLoc[0] 
startRow = centerLoc[1] 

# Now get lat/long of upper left tile corner 
geoCoord = num2deg(startCol, startRow, startZoom) 

loc = deg2num(geoCoord[0], geoCoord[1],18) 
# EDIT: reading the .png thanks to JH comment below 
z1 = io.imread("z1.png", as_grey=True) 
createTiles(loc[0], loc[1], 18, z1) 

loc = deg2num(geoCoord[0], geoCoord[1],19) 
# EDIT: reading the .png thanks to JH comment below 
z2 = io.imread("z2.png", as_grey=True) 
createTiles(loc[0], loc[1], 19, z2) 

loc = deg2num(geoCoord[0], geoCoord[1],20) 
# EDIT: reading the .png thanks to JH comment below 
z3 = io.imread("z3.png", as_grey=True) 
createTiles(loc[0], loc[1], 20, z3) 

loc = deg2num(geoCoord[0], geoCoord[1],21) 
# EDIT: reading the .png thanks to JH comment below 
z4 = io.imread("z4.png", as_grey=True) 
createTiles(loc[0], loc[1], 21, z4) 

loc = deg2num(geoCoord[0], geoCoord[1],22) 
# EDIT: reading the .png thanks to JH comment below 
z5 = io.imread("z5.png", as_grey=True) 
createTiles(loc[0], loc[1], 22, z5) 

CreateTiles() ist ein Fehler in Zeilen wirft for i in range(0, ncols):TypeError: float object cannot be interpreted as an integer sagen ... Interessanterweise schafft es das erste Unterverzeichnis 18/ vor dem Fehler zu werfen. Ich habe erneut die Abmessungen des z [1..5] bestätigt .png sind Potenzen von 2 (oder Vielfachen von 256).

Warum habe ich diesen Fehler beim Konvertieren von Float in Integer?

Antwort

0

Es stellte sich heraus, dass es sich um ein Problem mit der Python-Version handelte. Wenn in 2.7 das Ergebnis einer Division xx.0 ist, ist es ein int. In Python 3.x ist es ein Float. Also 512/256 = 2 in Python 2.7 und es ist = 2.0 in Python 3.x.

Durch die Umwandlung der Ergebnisse der Division in ein INT konnte ich es zum Laufen bringen.

ncols = int(theData.shape[1]/256) 
nrows = int(theData.shape[0]/256) 
1

z1 ging aus dem Geltungsbereich, wenn das erste Skript beendet wurde, so dass es für das zweite Skript nicht verfügbar ist. Sie müssen einen Weg finden, um es, z. kurz bevor der Aufruf von createTiles() ausgeführt wird:

z1 = io.imread("z1.png", as_grey=True) 

Diese Skripts sind schlecht strukturiert. Es ist sinnvoll, import s auf oberster Ebene zu halten (kein Einzug), aber es wäre gut, die anderen Anweisungen in eigene Funktionen zu verschieben. Zumindest sollten sie unter sein:

if __name__ == '__main__': 

diese Weise erhalten Sie eine Chance, ein Script-Funktionen von einem anderen Skript wiederverwenden zu können, stehen, wie Sie können import ohne Nebenwirkungen.

+0

Vielen Dank dafür. Der erste Teil war sehr hilfreich ... fühlt sich an, als wäre ich einer Lösung nahe, aber noch nicht da. Nochmals vielen Dank für Ihre Hilfe und Bereitschaft, dies zu betrachten ... – Colin