当前位置: 首页 > news >正文

深入解析 KMZ 文件的处理与可视化:从数据提取到地图展示项目实战

文章目录

      • 1. KMZ 文件与 KML 文件简介
        • 1.1 KMZ 文件
        • 1.2 KML 文件
      • 2. Python 环境配置与依赖安装
      • 3. 代码实现详解
        • 3.1 查找 KMZ 文件
        • 3.2 解压 KMZ 文件
        • 3.3 解析 KML 文件
        • 3.4 可视化 KMZ 数据
      • 4. 项目实战
        • 4.1. 数据采集
        • 4.2. 项目完整代码
      • 5. 项目运行与结果展示
      • 6. 总结与展望

在处理地理空间数据时,KMZ 文件是一种常见的格式,用于存储地图和地理信息数据。KMZ 文件是 KML 文件的压缩版本,其中 KML(Keyhole Markup Language)用于描述地理数据的格式。本文将详细介绍如何使用 Python 处理 KMZ 文件,提取其中的地理数据,并将其可视化到地图上。本文的核心代码将涉及文件的解压、KML 文件的解析、GPS 数据的提取以及如何使用 Folium 库将数据展示到地图上。

1. KMZ 文件与 KML 文件简介

1.1 KMZ 文件

KMZ 文件是 KML 文件的压缩版本,通常用于存储 Google Earth 或 Google Maps 中使用的地理信息数据。KMZ 文件可以包含一个或多个 KML 文件以及其他资源文件(如图片、图标等)。KML 文件是基于 XML 的格式,用于描述地理数据的标记、路径、区域等信息。

1.2 KML 文件

KML 文件由 XML 构成,用于存储地理数据,如地点标记、线条、区域、图像叠加等。KML 的基本结构包括:

  • Placemark:标记点
  • Point:点类型
  • LineString:线条
  • Polygon:多边形
  • TimeStamp:时间戳

2. Python 环境配置与依赖安装

在开始之前,确保你的 Python 环境中已经安装了以下依赖:

  • folium:用于地图可视化
  • xml.etree.ElementTree:用于解析 XML 文件
  • zipfile:用于解压 KMZ 文件
  • glob:用于文件路径匹配

可以使用以下命令安装所需的库:

pip install folium

3. 代码实现详解

3.1 查找 KMZ 文件
import os
import globdef find_kmz_files(directory):# 使用 glob 模块查找指定目录下的所有 .kmz 文件kmz_files = glob.glob(os.path.join(directory, '*.kmz'))return kmz_files
  • 功能:遍历指定目录,查找所有以 .kmz 结尾的文件。
  • 实现:使用 glob 模块和通配符模式来匹配所有 KMZ 文件。
3.2 解压 KMZ 文件
import zipfiledef extract_kml_from_kmz(kmz_file_path):# 解压 KMZ 文件with zipfile.ZipFile(kmz_file_path, 'r') as kmz:# 查找 KML 文件kml_files = [name for name in kmz.namelist() if name.lower().endswith('.kml')]if kml_files:kml_file_path = kml_files[0]kmz.extract(kml_file_path, os.path.dirname(kmz_file_path))return os.path.join(os.path.dirname(kmz_file_path), kml_file_path)return None
  • 功能:解压 KMZ 文件,并提取其中的 KML 文件。
  • 实现:使用 zipfile 模块打开 KMZ 文件,查找并解压 KML 文件。
3.3 解析 KML 文件
import xml.etree.ElementTree as ETdef parse_kml(kml_file_path):gps_data = []tree = ET.parse(kml_file_path)root = tree.getroot()# KML 的 XML namespacenamespace = {'kml': 'http://earth.google.com/kml/2.2'}print(f"Root element: {root.tag}")# 查找所有 Placemark 元素for placemark in root.findall('.//kml:Placemark', namespace):coordinates = placemark.find('.//kml:Point/kml:coordinates', namespace)if coordinates is not None:coords = coordinates.text.strip().split(',')if len(coords) >= 3:try:longitude = float(coords[0])latitude = float(coords[1])altitude = float(coords[2])gps_data.append({'latitude': latitude,'longitude': longitude,'altitude': altitude})except ValueError as e:print(f"Error parsing coordinates: {e}")return gps_data
  • 功能:解析 KML 文件,提取 GPS 数据(经纬度和高度)。
  • 实现:使用 xml.etree.ElementTree 解析 XML 格式的 KML 文件,通过查找 Placemark 元素和 coordinates 元素来获取地理数据。
3.4 可视化 KMZ 数据
import folium
from folium.features import CustomIcondef visualize_multiple_kmz_data(kmz_data_list):if not kmz_data_list:print("No GPS data available to visualize.")return# 计算所有经纬度的平均值,作为地图的中心all_latitudes = []all_longitudes = []for kmz_data in kmz_data_list:latitudes = [data['latitude'] for data in kmz_data['gps_data']]longitudes = [data['longitude'] for data in kmz_data['gps_data']]all_latitudes.extend(latitudes)all_longitudes.extend(longitudes)avg_latitude = sum(all_latitudes) / len(all_latitudes)avg_longitude = sum(all_longitudes) / len(all_longitudes)map_center = [avg_latitude, avg_longitude]gps_map = folium.Map(location=map_center, zoom_start=14, tiles='OpenStreetMap')folium.TileLayer(tiles='https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',name='Google Satellite',attr='© Google').add_to(gps_map)folium.LayerControl().add_to(gps_map)# 为每个 KMZ 文件使用不同的颜色colors = ['red', 'blue', 'green', 'purple', 'orange', 'darkred', 'lightred', 'beige', 'darkblue', 'darkgreen', 'cadetblue', 'darkpurple', 'white', 'pink', 'lightblue', 'lightgreen', 'gray', 'black', 'lightgray']for idx, kmz_data in enumerate(kmz_data_list):color = colors[idx % len(colors)]for data in kmz_data['gps_data']:folium.CircleMarker([data['latitude'], data['longitude']],radius=0.5,  # 半径大小color=color,  # 边框颜色fill=True,fill_color=color,  # 填充颜色fill_opacity=0.8).add_to(gps_map)# 绘制路径线并添加箭头for i in range(1, len(kmz_data['gps_data'])):start_point = kmz_data['gps_data'][i-1]end_point = kmz_data['gps_data'][i]# 绘制线条folium.PolyLine(locations=[(start_point['latitude'], start_point['longitude']),(end_point['latitude'], end_point['longitude'])],color=color,weight=2).add_to(gps_map)# 添加箭头folium.Marker(location=[(start_point['latitude'] + end_point['latitude']) / 2,(start_point['longitude'] + end_point['longitude']) / 2],icon=CustomIcon('https://upload.wikimedia.org/wikipedia/commons/e/e5/Black_triangle_pointing_right.svg',icon_size=(10, 10), icon_anchor=(5, 5))).add_to(gps_map)gps_map.save('multiple_kmz_map.html')print("GPS map saved as 'multiple_kmz_map.html'.")
  • 功能:将多个 KMZ 文件的数据可视化到一个地图上,使用不同的颜色表示不同的 KMZ 文件。
  • 实现
    • 计算所有点的平均经纬度作为地图的中心。
    • 使用 folium.Map 创建地图,并添加地图图层。
    • 对每个 KMZ 文件使用不同的颜色,并将其 GPS 数据以 CircleMarker 的形式添加到地图上。

绘制路径线,并在路径中添加箭头指示方向。

4. 项目实战

4.1. 数据采集

两个kmz文件:
在这里插入图片描述
其中一个kmz文件解压,会看到有一个kml文件:
在这里插入图片描述
kml文件打开,会看到一些关键信息,以下是部分信息截图:
在这里插入图片描述

4.2. 项目完整代码
import os
import glob
import folium
import zipfile
import xml.etree.ElementTree as ET
from folium.features import CustomIcondef find_kmz_files(directory):kmz_files = glob.glob(os.path.join(directory, '*.kmz'))return kmz_filesdef extract_kml_from_kmz(kmz_file_path):with zipfile.ZipFile(kmz_file_path, 'r') as kmz:kml_files = [name for name in kmz.namelist() if name.lower().endswith('.kml')]if kml_files:kml_file_path = kml_files[0]kmz.extract(kml_file_path, os.path.dirname(kmz_file_path))return os.path.join(os.path.dirname(kmz_file_path), kml_file_path)return Nonedef parse_kml(kml_file_path):gps_data = []tree = ET.parse(kml_file_path)root = tree.getroot()namespace = {'kml': 'http://earth.google.com/kml/2.2'}for placemark in root.findall('.//kml:Placemark', namespace):coordinates = placemark.find('.//kml:Point/kml:coordinates', namespace)if coordinates is not None:coords = coordinates.text.strip().split(',')if len(coords) >= 3:try:longitude = float(coords[0])latitude = float(coords[1])altitude = float(coords[2])gps_data.append({'latitude': latitude,'longitude': longitude,'altitude': altitude})except ValueError as e:print(f"Error parsing coordinates: {e}")return gps_datadef visualize_multiple_kmz_data(kmz_data_list):if not kmz_data_list:print("No GPS data available to visualize.")returnall_latitudes = []all_longitudes = []for kmz_data in kmz_data_list:latitudes = [data['latitude'] for data in kmz_data['gps_data']]longitudes = [data['longitude'] for data in kmz_data['gps_data']]all_latitudes.extend(latitudes)all_longitudes.extend(longitudes)avg_latitude = sum(all_latitudes) / len(all_latitudes)avg_longitude = sum(all_longitudes) / len(all_longitudes)map_center = [avg_latitude, avg_longitude]gps_map = folium.Map(location=map_center, zoom_start=14, tiles='OpenStreetMap')folium.TileLayer(tiles='https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}',name='Google Satellite',attr='© Google').add_to(gps_map)folium.LayerControl().add_to(gps_map)colors = ['red', 'blue', 'green', 'purple', 'orange', 'darkred', 'lightred', 'beige', 'darkblue', 'darkgreen', 'cadetblue', 'darkpurple', 'white', 'pink', 'lightblue', 'lightgreen', 'gray', 'black', 'lightgray']for idx, kmz_data in enumerate(kmz_data_list):color = colors[idx % len(colors)]for data in kmz_data['gps_data']:folium.CircleMarker([data['latitude'], data['longitude']],radius=0.5,color=color,fill=True,fill_color=color,fill_opacity=0.8).add_to(gps_map)for i in range(1, len(kmz_data['gps_data'])):start_point = kmz_data['gps_data'][i-1]end_point = kmz_data['gps_data'][i]folium.PolyLine(locations=[(start_point['latitude'], start_point['longitude']),(end_point['latitude'], end_point['longitude'])],color=color,weight=2).add_to(gps_map)folium.Marker(location=[(start_point['latitude'] + end_point['latitude']) / 2,(start_point['longitude'] + end_point['longitude']) / 2],icon=CustomIcon('https://upload.wikimedia.org/wikipedia/commons/e/e5/Black_triangle_pointing_right.svg',icon_size=(10, 10), icon_anchor=(5, 5))).add_to(gps_map)gps_map.save('multiple_kmz_map.html')print("GPS map saved as 'multiple_kmz_map.html'.")if __name__ == '__main__':directory_path = "F:\\notebookComputer\\20240723"kmz_files = find_kmz_files(directory_path)if kmz_files:kmz_data_list = []for kmz_file_path in kmz_files:kml_file_path = extract_kml_from_kmz(kmz_file_path)if kml_file_path:parsed_gps_data = parse_kml(kml_file_path)print(f"Parsed GPS data: {parsed_gps_data}")kmz_data_list.append({'file_name': os.path.basename(kmz_file_path),'gps_data': parsed_gps_data})if kmz_data_list:visualize_multiple_kmz_data(kmz_data_list)else:print("No GPS data available to visualize.")else:print(f"No .kmz files found in directory: {directory_path}")

5. 项目运行与结果展示

在代码执行完毕后,将会生成一个名为 multiple_kmz_map.html 的文件,该文件可以用浏览器打开以查看地图上的标记点和路径。地图将会显示所有 KMZ 文件中提取的 GPS 数据,每个文件的标记点使用不同的颜色表示。
multiple_kmz_map.html文件不好截图如下:
在这里插入图片描述
浏览器打开multiple_kmz_map.html文件效果图如下:
在这里插入图片描述

6. 总结与展望

本文详细介绍了如何使用 Python 处理 KMZ 文件,提取其中的 GPS 数据,并通过 Folium 库将其可视化。通过将 KMZ 文件中的地理数据转换为地图标记点和路径线,我们可以更直观地分析和展示地理数据。未来的工作可以包括支持更多的地理数据格式、添加更多的地图样式和功能、以及优化代码的性能和可读性。根据需求,文章可以继续扩展,以包含更多的技术细节、优化建议和实际应用场景的分析。

欢迎点赞|关注|收藏|评论,您的肯定是我创作的动力

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 计算几何 点乘 两点间距离 两向量夹角
  • C++ STL copy_backward, move_backward 用法
  • B3952 [GESP202403 一级] 小杨买书
  • python实现图像分割算法4
  • AI人工智能开发环境配置
  • 【人工智能】NLP入门指南:自然语言处理基础全解析
  • 计算机毕业设计选题推荐-学生作业管理系统-Java/Python项目实战
  • 工作纪实54-git使用ssh方式
  • 【第一章】软件测试人员的成长技能树:打造全方位的技能体系
  • PHP 表单处理基础
  • NVIDIA A100 和 H100 硬件架构学习
  • springboot集成RabbitMQ
  • 16进制转换-系统架构师(三十九)
  • 2023 RoboCom CAIP本科组决赛-RC-u3 兰州拉面派餐系统
  • vulhub:Apache解析漏洞CVE-2017-15715
  • [Vue CLI 3] 配置解析之 css.extract
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • Create React App 使用
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • Java程序员幽默爆笑锦集
  • js算法-归并排序(merge_sort)
  • JWT究竟是什么呢?
  • Mocha测试初探
  • oldjun 检测网站的经验
  • Promise初体验
  • spring boot 整合mybatis 无法输出sql的问题
  • 爱情 北京女病人
  • 百度地图API标注+时间轴组件
  • 坑!为什么View.startAnimation不起作用?
  • 目录与文件属性:编写ls
  • 爬虫模拟登陆 SegmentFault
  • 日剧·日综资源集合(建议收藏)
  • 使用agvtool更改app version/build
  • 小试R空间处理新库sf
  • 应用生命周期终极 DevOps 工具包
  • 中文输入法与React文本输入框的问题与解决方案
  • scrapy中间件源码分析及常用中间件大全
  • 阿里云重庆大学大数据训练营落地分享
  • #android不同版本废弃api,新api。
  • (2022 CVPR) Unbiased Teacher v2
  • (C)一些题4
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (SpringBoot)第七章:SpringBoot日志文件
  • (动手学习深度学习)第13章 计算机视觉---图像增广与微调
  • (力扣)1314.矩阵区域和
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (十三)Maven插件解析运行机制
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (转)【Hibernate总结系列】使用举例
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .FileZilla的使用和主动模式被动模式介绍
  • .NET 药厂业务系统 CPU爆高分析
  • .NET 依赖注入和配置系统
  • .net后端程序发布到nignx上,通过nginx访问