Python Slippy-map 平铺生成

标签 python leaflet scikit-image

我从一位前同事那里继承了两个 Python 脚本(更像是片段)。该代码应该将高分辨率图像 (png) 转换为可供 slippy-map 使用的可缩放图 block ( Leaflet.js )在地理坐标空间(纬度/经度)中。

我不是 Python(或 GIS)人员,我正在努力让它们正常工作。我无法确定问题是我缺乏知识还是代码......

第一个脚本按预期工作,生成五个分辨率逐渐降低的图像文件,这些图像文件源自输入图像 (myImgMaxRez.png)。我相信这被称为“图像金字塔”。每个 z[1..5].png 的尺寸可以被 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))

生成滑动 map 图 block 的下一个脚本会抛出类型转换错误(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() 在 for i in range(0, ncols): 行上抛出错误,提示 TypeError: float object can beterpreted as an integer...有趣的是,它在抛出错误之前创建了第一个子目录 18/。我再次确认了 z[1..5].png 的尺寸是 2 的幂(或 256 的倍数)。

为什么我在将 float 转换为整数时出现此错误?

最佳答案

当第一个脚本终止时,

z1 超出了范围,因此它对第二个脚本不可用。您需要找到一种方法来传递它,例如在调用 createTiles() 之前,您可以这样做:

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

这些脚本的结构很差。将 import 保持在顶层(无缩进)是有意义的,但最好将其他语句移至它们自己的函数中。至少他们应该是这样的:

if __name__ == '__main__':

这样,您就有机会使一个脚本能够重用另一个脚本中的函数,因为您可以导入而不会产生副作用。

关于Python Slippy-map 平铺生成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46327791/

相关文章:

python - 将 URL 从数据库传递到 webdriver 时出错

python - 如何在 sympy 中使用 Lambdify 和 IndexedBase 计算导数

javascript - 如何锁定 Leaflet map 中的缩放级别?

python - 平滑一个凹凸不平的圆圈

python - 为什么 SciKit 的分水岭功能太慢?

python - 如何在Elasticsearch DSL(elasticsearch-dsl-py)中使用存储桶,指标或管道用于多层聚合

python - 暴力破解python

javascript - 传单中带有 geoJson 文件的 Font Awesome 图标

javascript - div 中无法选择的文本到可选择的传单

python - 将 PIL.Image 转换为 skimage