You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Matplotlib网格计数图导出KML后显示异常,求可行解决方案

问题描述

我已成功生成可正常显示的Matplotlib网格计数图,但将其导出为KML格式后,使用Google Earth打开时网格计数无法正确显示(相关截图已附上)。请问是否可以通过KML格式正确展示网格计数?

实现代码

import geopandas as gpd
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import shapely
import contextily as cx
import simplekml
from operator import itemgetter

df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/Nuclear%20Waste%20Sites%20on%20American%20Campuses.csv')

gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df.lon, df.lat))
gdf.crs = "EPSG:4326"

fig = plt.figure(1)
ax = fig.add_axes([0,0,1,1])
ax.axis('off')

plt.axis('off')
border1 = plt.axis()

#if False:
#    plt.show()
#else:
#    pngName = 'Overlay.png'
#    fig.savefig(pngName, facecolor=fig.get_facecolor(), transparent=False)

# total area for the grid
#xmin, ymin, xmax, ymax = gdf.total_bounds

bounds = gdf.geometry.apply(lambda x: x.bounds).tolist()
xmin, ymin, xmax, ymax = min(bounds, key=itemgetter(0))[0], min(bounds, key=itemgetter(1))[1], max(bounds, key=itemgetter(2))[2], max(bounds, key=itemgetter(3))[3]

# how many cells across and down
n_cells = 10
cell_size = (xmax-xmin)/n_cells

# projection of the grid
#crs = "+proj=sinu +lon_0=0 +x_0=0 +y_0=0 +a=6371007.181 +b=6371007.181 +units=m +no_defs"

# create the cells in a loop
grid_cells = []
for x0 in np.arange(xmin, xmax+cell_size, cell_size ):
    for y0 in np.arange(ymin, ymax+cell_size, cell_size):
        # bounds
        x1 = x0-cell_size
        y1 = y0+cell_size
        grid_cells.append(shapely.geometry.box(x0, y0, x1, y1))
        
cell = gpd.GeoDataFrame(grid_cells, columns = ['geometry'], crs = 'EPSG:4326')

merged = gpd.sjoin(gdf, cell, how='left', predicate='within')

# make a simple count variable that we can sum
merged['gridCount'] = 1

# Compute stats per grid cell -- aggregate fires to grid cells with dissolve
dissolve = merged.dissolve(by = 'index_right', aggfunc = 'count')

# put this into cell
cell.loc[dissolve.index, 'gridCount'] = dissolve['gridCount'].values

ax = cell.plot(column = 'gridCount', 
               figsize = (12, 8), 
               cmap = 'viridis_r', 
               vmax = 1000,
               alpha = 0.5,
               edgecolor = 'grey')
   
cx.add_basemap(ax, zoom = 8, crs = 'EPSG:4326')

pngName = 'Overlay.png'
plt.axis('off')
plt.savefig(pngName, facecolor=fig.get_facecolor(), transparent=False)

bottomleft  = xmin,ymin
bottomright = xmax,ymin
topright    = xmax,ymax
topleft     = xmin,ymax

kml = simplekml.Kml()
ground = kml.newgroundoverlay(name='GroundOverlay')
ground.icon.href = pngName
ground.gxlatlonquad.coords =[bottomleft, bottomright, topright, topleft]
kml.save("GroundOverlay.kml")
解决方案

可以通过KML正确展示网格计数,当前图片叠加方案失效的核心原因是投影匹配误差和Google Earth对栅格叠加的渲染限制,推荐两种可靠实现方式:

方式1:直接导出矢量网格到KML

放弃图片叠加,将带计数属性的网格矢量数据直接导出,Google Earth可原生渲染矢量并支持点击查看计数,无变形问题:

# 方法A:用geopandas直接导出(需libkml依赖)
cell.to_file("grid_count.kml", driver="KML")

# 方法B:用simplekml手动构建带样式的网格(兼容无libkml环境)
kml = simplekml.Kml()
cmap = plt.get_cmap('viridis_r')

for idx, row in cell.iterrows():
    count = row.get('gridCount', 0)
    # 归一化计数并转换为KML支持的AARRGGBB颜色格式
    norm_count = min(count / 1000, 1)
    rgba = cmap(norm_count)
    kml_color = simplekml.Color.rgb(int(rgba[0]*255), int(rgba[1]*255), int(rgba[2]*255), int(rgba[3]*255))
    
    # 创建多边形网格
    poly = kml.newpolygon(name=f"网格{idx} | 计数:{count}")
    poly.outerboundaryis.coords = list(row.geometry.exterior.coords)
    # 设置填充色和边框
    poly.style.polystyle.color = kml_color
    poly.style.polystyle.outline = 1

kml.save("grid_count_vector.kml")

方式2:修复图片叠加的投影匹配问题

若坚持用图片叠加,需解决两个关键问题:

  1. 清除图片空白边:原代码保存图片时会生成额外空白,导致和地理边界错位:
# 替换原图片保存代码
plt.gca().set_aspect('equal', adjustable='box')
plt.savefig(pngName, bbox_inches='tight', pad_inches=0, transparent=True)
  1. 修正KML坐标顺序:Google Earth的gx:LatLonQuad要求坐标按左下角→右下角→右上角→左上角→左下角闭合,确保无拉伸:
# 修复坐标顺序并添加闭合点
ground.gxlatlonquad.coords = [bottomleft, bottomright, topright, topleft, bottomleft]
ground.gxlatlonquad.rotation = 0  # 强制无旋转

注意事项

  • 矢量方案比图片叠加更可靠,支持交互且无投影变形;
  • 图片叠加必须严格保证图片宽高比与地理区域经纬度跨度比一致,否则会出现拉伸;
  • 全程使用EPSG:4326(WGS84)投影,Google Earth原生支持该投影,避免使用其他投影导致匹配误差。

内容的提问来源于stack exchange,提问作者Chopin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 03:17:17