TIF转换到KMZ的教程
TIF转换到KMZ的教程
ytkzKML 和 KMZ 都是 Google 地球和其他地图程序中用于显示地理数据的文件格式。两者之间的主要区别在于,KML 是一种用于以 XML 格式存储地理数据的文件格式,而 KMZ 是一种压缩文件格式,包含一个或多个 KML 文件及其关联资源。
阅读本文,了解有关 KML 和 KMZ 的更多信息以及它们之间的区别。
什么是 KML?
KML(Keyhole 标记语言)是一种用于在三维空间中显示地理数据的文件格式,通常在 Google 地球等虚拟地球仪上显示。它是一种基于 XML 的语言,允许您构建和显示结构化地理信息。
例如,点由其纬度、经度和(可选)高度定义,并指示地图上的特定位置。地图上的线条和多边形描绘路径或区域,并由一组定义其形状的坐标定义。使用“扩展数据”元素,可以将名称、描述和 URL 等描述性信息链接到这些地理元素。
以下是 KML 的一些关键功能和组件 -
- 地理特征- KML 可以定义众多地理元素,例如点、线、多边形和 3D 模型。这些功能可以显示在虚拟地球上,您可以使用名称、描述和照片对其进行自定义。
- 样式- 在 KML 中,您还可以设置地理特征的样式。您可以更改线条的颜色和粗细,以及多边形的不透明度和纹理。这使您的数据更具视觉吸引力且易于理解。
- 叠加图像- 您还可以使用 KML 将图像叠加在地理数据之上。这非常适合添加上下文或视觉信息,例如卫星照片或历史地图。
- 基于时间的数据- KML 还允许基于时间的数据,因此您可以看到事物如何随时间变化。每个功能都可以分配一个时间段并按时间顺序显示。这可以用来描述天气模式、人口扩张或物品移动的变化。
- 网络链接- KML 还支持网络链接,即指向外部 KML 文件或互联网资源的链接。这使您能够创建不断更新的动态和交互式地图。要显示当前天气状况,您可以建立指向在线天气服务的网络链接。
KML 是一种复杂的文件格式,用于以结构化且具有视觉吸引力的方式创建和显示地理数据。 KML 经常用于环境监测、城市规划和旅游等应用,因为它支持不同的地理元素、风格选项、叠加图像、基于时间的数据和网络链接。
KMZ是什么?
KMZ(Keyhole 标记语言压缩)是一种压缩文件格式,用于存储地理数据,包括 KML 文件以及与其相关的资源,例如照片、图标和其他文件。 Keyhole Inc.(2004 年被 Google 收购)将其创建为一种在单个文件中捆绑和传输大量地理数据的机制。
KMZ 文件是通过将一个或多个 KML 文件及其相关资源压缩到一个扩展名为“.kmz”的文件中而形成的。压缩可以减小文件大小,从而更容易通过互联网共享和下载。当您在地图应用程序中打开 KMZ 文件时,KML 文件和关联资源将被提取并显示在地图上。
KMZ 文件可以包含与 KML 文件相同类型的地理数据,例如点、线、多边形和其他形状,以及描述性数据,例如名称、描述和 URL。区别在于,KMZ 文件包含显示数据所需的任何附带资源,例如图像和图标,从而形成一个可以轻松共享的独立包。
除了地理数据之外,KMZ 文件还可以包含样式、屏幕覆盖和网络链接等功能。样式允许您自定义地理数据的外观,而屏幕覆盖允许您在地图上显示图像或文本。其他 KML 或 KMZ 文件以及在线数据源可以通过网络链接引用。
总体而言,KMZ是一种实用且有效的打包和共享海量地理数据的方法,广泛应用于测绘、GIS和环境监测等一系列应用中。
KML 和 KMZ 之间的区别
下表强调了 KML 和 KMZ 之间的主要区别 -
特征 | 克米勒 | 克麦兹 |
---|---|---|
定义 | KML 是一种用于以 XML 格式存储地理数据的文件格式。 | KMZ 是一种压缩文件格式,包含一个或多个 KML 文件及其关联资源。 |
文件格式 | 它是一种基于 XML 的文件格式。 | 它是一种压缩 (Zip) 文件格式。 |
数据内容 | 地理数据 | 地理数据和资源 |
文件扩展名 | .kml | .kmz |
文件大小 | 由于包含资源,KML 文件大小较大。 | 由于压缩,KMZ 文件大小很小。 |
分享 | 在 KML 中,共享是通过电子邮件、文件共享平台或直接下载完成的。 | 在 KMZ 中,共享是通过电子邮件、文件共享平台或直接下载来完成的。 |
代表 | 锁孔标记语言 (KML) | 压缩锁孔标记语言 (KMZ) |
用法 | KML 用于存储地理数据。 | KMZ 文件用于打包 KML 文件并与关联资源共享。 |
20240516
KML(Keyhole Markup Language)和SHP(Shapefile)都是用于表示地理数据的文件格式,但它们在设计和应用上有一些差异。说KML是SHP的“更先进版本”可能并不完全准确,因为这两种格式各有其优点和适用场景。然而,KML在某些方面确实具有一些独特的优势,这些优势可能使其在某些应用中表现得更为“先进”。
以下是KML相对于SHP的一些优势:
- 跨平台兼容性:KML是一种基于XML的开放标准,因此它可以在各种操作系统和平台上使用,包括Web浏览器、移动设备和桌面应用程序。这使得KML成为一种非常灵活的地理数据格式,可以轻松地在不同的系统和应用程序之间共享和交换数据。
- 丰富的可视化功能:KML支持丰富的可视化功能,包括自定义图标、线条颜色、填充颜色、文本标签等。这使得KML可以创建出具有高度可定制性和吸引力的地图和地理可视化效果。
- 时间和动画支持:KML支持时间相关的地理信息,可以使用户展示地理位置随时间变化的动画效果。这对于描述历史轨迹、飞行路径等应用非常有用。
- 广泛的应用程序支持:KML是Google Earth和其他许多地理信息系统(GIS)应用程序的标准格式之一。这使得KML具有广泛的应用程序支持,并且可以与许多流行的GIS工具无缝集成。
相比之下,SHP格式在以下方面有一些限制:
- 封闭性:SHP是由ESRI公司开发的专有格式,因此其使用可能受到某些限制。例如,它可能不如KML那样易于在不同的系统和应用程序之间共享和交换数据。
- 可视化功能有限:虽然SHP格式支持基本的地理数据可视化,但它可能不如KML那样灵活和可定制。
- 应用程序支持有限:尽管SHP格式在GIS行业中广泛应用,但它可能不如KML那样受到广泛支持。某些GIS应用程序可能不支持SHP格式,或者可能需要额外的插件或驱动程序才能支持它。
那SHP格式可以转换到KML格式么?
答案是可以的,请看以下python代码。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2024/5/16 22:30
# @File : shp2kml.py
from osgeo import ogr
import os
def convert_to_kml(shapefile,outpath):
ds = ogr.Open(shapefile)
shape = ds.GetLayer(0)
attribute_names = []
ldefn = shape.GetLayerDefn()
for n in range(ldefn.GetFieldCount()):
fdefn = ldefn.GetFieldDefn(n)
attribute_names.append(fdefn.name)
boundary =''
placemark = ''
i = 1
for obj in shape:
placemark +='\n<Placemark id="ID_{}">' \
'\n<styleUrl>#m_ylw-pushpin</styleUrl>' \
'\n{}' \
'\n</Placemark>'.format(str(i),obj.GetGeometryRef().ExportToKML())
i+=1
constant = '<?xml version="1.0" encoding="UTF-8"?>' \
'<kml ' \
'xmlns="http://www.opengis.net/kml/2.2" ' \
'xmlns:atom="http://www.w3.org/2005/Atom" ' \
'xmlns:gx="http://www.google.com/kml/ext/2.2" ' \
'xmlns:kml="http://www.opengis.net/kml/2.2">' \
'<name>%s</name>' \
'\n<Document>' \
'\n<Style id="s_ylw-pushpin_hl"><IconStyle><scale>1.3</scale>' \
'\n<Icon><href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href></Icon>' \
'\n<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/></IconStyle>' \
'\n<LineStyle><color>ff0000ff</color><width>2</width></LineStyle>' \
'\n<PolyStyle><fill>0</fill></PolyStyle></Style>' \
'\n<StyleMap id="m_ylw-pushpin"><Pair><key>normal</key><styleUrl>#s_ylw-pushpin</styleUrl></Pair>' \
'\n<Pair><key>highlight</key><styleUrl>#s_ylw-pushpin_hl</styleUrl></Pair></StyleMap>' \
'\n<Style id="s_ylw-pushpin"><IconStyle><scale>1.1</scale>' \
'\n<Icon><href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href></Icon>' \
'\n<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/></IconStyle>' \
'\n<LineStyle><color>ff0000ff</color><width>2</width></LineStyle><PolyStyle><fill>0</fill>' \
'\n</PolyStyle></Style>'
end_tag = '</Document></kml>'
kml = ''.join([constant, placemark, end_tag])
# filler = '<Data name="{}"><value>{}</value></Data>'
# closing_tag = '</ExtendedData>'
# # constant + filler + closing + end_tag
# data = []
# for attribute in attribute_names:
# data.append(filler.format(attribute, obj.GetField(attribute)))
# data = ''.join(data)
filename = os.path.basename(shapefile).split('.')[0]
if not os.path.exists(outpath):
os.makedirs(outpath)
out_file = open(outpath+'\\'+filename+".kml", "w")
out_file.write(kml)
out_file.close()
if __name__ == '__main__':
shapefile = r"D:\11.shp"
outpath = r'D:\kml'
convert_to_kml(shapefile, outpath)
考虑到部分朋友可能不会编程,现在把以上代码打包为exe命令行程序,作为一个特定功能的小工具分享给大家。
pyinstaller -F -i favicon.png shp2kml.py
点要素kml在google earth 可视化
线要素kml在google earth 可视化
面要素kml在google earth 可视化
20240612 ChatGPT
使用Python将GeoTIFF转换为KMZ文件
在地理信息系统(GIS)领域,GeoTIFF是一种常见的栅格数据格式,而KMZ是Google Earth使用的压缩KML格式。本文将介绍如何使用Python将GeoTIFF文件转换为KMZ文件。具体实现中,我们将使用GDAL
库处理GeoTIFF文件,并利用Pillow
库生成PNG图片,最后通过zipfile
库将生成的KML和PNG文件打包成KMZ文件。
所需依赖库
首先,需要确保安装了以下Python库:
gdal
:用于读取和处理GeoTIFF文件。numpy
:用于数组操作和数据处理。Pillow
:用于图像处理。zipfile
:用于创建和管理ZIP文件。
pip install gdal numpy Pillow
实现步骤
1. 创建类tif2kmz
创建一个tif2kmz
类,它包含所有转换过程的步骤。
from zipfile import ZipFile
from osgeo import gdal
import codecs
import numpy as np
import PIL.Image as Image
class tif2kmz:
def __init__(self, tif_file, kmz_file):
self.tif_file = tif_file
self.kmz_file = kmz_file
2.获取GeoTIFF文件的属性
定义一个方法get_attribute
,用于获取GeoTIFF文件的地理属性,这些属性将在生成KML文件时使用。
def get_attribute(self):
ds = gdal.Open(self.tif_file, gdal.GA_ReadOnly)
gt = ds.GetGeoTransform()
self.east_longitude = gt[0]
self.west_longitude = self.east_longitude + (ds.RasterXSize * gt[1])
self.north_latitude = gt[3]
self.south_latitude = self.north_latitude + (ds.RasterYSize * gt[5])
3.图像线性拉伸
定义一个方法linear_stretch
,对图像数据进行线性拉伸,以增强图像对比度。
def linear_stretch(self, data, num=1):
data_8bit = data
data_8bit[data_8bit == -9999] = 0
d2 = np.percentile(data_8bit, num)
u98 = np.percentile(data_8bit, 100 - num)
maxout = 255
minout = 0
data_8bit_new = minout + ((data_8bit - d2) / (u98 - d2)) * (maxout - minout)
data_8bit_new[data_8bit_new < minout] = minout
data_8bit_new[data_8bit_new > maxout] = maxout
data_8bit_new = data_8bit_new.astype(np.int32)
return data_8bit_new
4.创建临时PNG文件
定义一个方法create_temp_png
,将GeoTIFF文件转换为PNG格式的图片。
def create_temp_png(self):
ds = gdal.Open(self.tif_file, gdal.GA_ReadOnly)
png_file = 'overlay.png'
data = ds.ReadAsArray()
z, x, y = data.shape
temp_arr = np.zeros(shape=(x, y, 3))
for i in range(3):
temp_arr[:, :, i] = self.linear_stretch(data[i, :, :], 2)
temp_arr = temp_arr.astype(np.uint8)
img = Image.fromarray(temp_arr)
img.save(png_file)
5. 创建KML文件
def create_kml(self):
self.get_attribute()
overlay_name = "KML overlay"
kml = (
'<?xml version="1.0" encoding="UTF-8"?>\n'
'<kml xmlns="http://www.opengis.net/kml/2.2">\n'
' <Folder>\n'
' <name>Ground Overlays</name>\n'
' <description>Examples of ground overlays</description>\n'
' <GroundOverlay>\n'
' <name>%s</name>\n'
' <Icon>\n'
' <href>overlay.png</href>\n'
' </Icon>\n'
' <LatLonBox>\n'
' <north>%f</north>\n'
' <south>%f</south>\n'
' <east>%f</east>\n'
' <west>%f</west>\n'
' </LatLonBox>\n'
' </GroundOverlay>\n'
' </Folder>\n'
'</kml>\n'
) % (overlay_name, self.north_latitude, self.south_latitude, self.east_longitude, self.west_longitude)
with codecs.open('overlay.kml', encoding='utf-8', mode='w+') as kmlFile:
kmlFile.write(kml)
6.创建KMZ文件
定义一个方法create_kmz
,将生成的KML文件和PNG文件压缩成KMZ文件。
def create_kmz(self):
self.create_temp_png()
self.create_kml()
with ZipFile(self.kmz_file, 'w') as zipObj:
zipObj.write('overlay.kml')
zipObj.write('overlay.png')
7. 主函数
最后,在主函数中实例化tif2kmz
类,并调用create_kmz
方法。
if __name__ == '__main__':
ql_image_filename = r'D:\test\DJI_20230410091240_0035.tif'
kml_output_filename = r'D:\test\DJI_20230410091240_0035.kmz'
tif2kmz = tif2kmz(ql_image_filename, kml_output_filename).create_kmz()
完整代码
from zipfile import ZipFile
from osgeo import gdal
import codecs
import numpy as np
import PIL.Image as Image
class tif2kmz:
def __init__(self, tif_file, kmz_file):
self.tif_file = tif_file
self.kmz_file = kmz_file
def get_arrtibute(self):
# 获取tif文件的属性, 用于生成kml文件
ds = gdal.Open(self.tif_file, gdal.GA_ReadOnly)
gt = ds.GetGeoTransform()
self.east_longitude = gt[0]
self.west_longitude = self.east_longitude + (ds.RasterXSize * gt[1])
self.north_latitude = gt[3]
self.south_latitude = self.north_latitude + (ds.RasterYSize * gt[5])
def linear_stretch(seld, data, num=1):
'''
@param data: 待拉伸的矩阵
@param num: 拉伸系数,一般为1-5
@return: 拉伸后的矩阵
'''
data_8bit = data
data_8bit[data_8bit == -9999] = 0
# 把数据中的nan转为某个具体数值,例如
# data_8bit[np.isnan(data_8bit)] = 0
d2 = np.percentile(data_8bit, num)
u98 = np.percentile(data_8bit, 100 - num)
maxout = 255
minout = 0
data_8bit_new = minout + ((data_8bit - d2) / (u98 - d2)) * (maxout - minout)
data_8bit_new[data_8bit_new < minout] = minout
data_8bit_new[data_8bit_new > maxout] = maxout
data_8bit_new = data_8bit_new.astype(np.int32)
return data_8bit_new
def create_temp_png(self):
ds = gdal.Open(self.tif_file, gdal.GA_ReadOnly)
png_file = 'overlay.png'
data = ds.ReadAsArray()
z,x,y = data.shape
temp_arr = np.zeros(shape=(x, y, 3))
for i in range(3):
temp_arr[:, :, i] = self.linear_stretch(data[i, :, :],2)
print(i)
temp_arr = temp_arr.astype(np.uint8)
img = Image.fromarray(temp_arr)
img.save(png_file)
def create_kml(self):
self.get_arrtibute()
overlay_name = "KML overlay"
kml = (
'<?xml version="1.0" encoding="UTF-8"?>\n'
'<kml xmlns="http://www.opengis.net/kml/2.2">\n'
' <Folder>\n'
' <name>Ground Overlays</name>\n'
' <description>Examples of ground overlays</description>\n'
' <GroundOverlay>\n'
' <name>%s</name>\n'
' <Icon>\n'
' <href>overlay.png</href>\n'
' </Icon>\n'
' <LatLonBox>\n'
' <north>%f</north>\n'
' <south>%f</south>\n'
' <east>%f</east>\n'
' <west>%f</west>\n'
' </LatLonBox>\n'
' </GroundOverlay>\n'
' </Folder>\n'
'</kml>\n'
) % (overlay_name, self.north_latitude, self.south_latitude, self.east_longitude, self.west_longitude)
with codecs.open('overlay.kml', encoding='utf-8', mode='w+') as kmlFile:
kmlFile.write(kml)
def create_kmz(self):
self.create_temp_png()
self.create_kml()
with ZipFile(self.kmz_file, 'w') as zipObj:
# zipObj.writestr(kml_output_filename, kml) # Add doc.kml entry
zipObj.write('overlay.kml')
zipObj.write('overlay.png')
if __name__ == '__main__':
ql_image_filename = r'D:\test\DJI_20230410091240_0035.tif'
kml_output_filename = r'D:\test\DJI_20230410091240_0035.kmz'
tif2kmz = tif2kmz(ql_image_filename, kml_output_filename).create_kmz()
代码解释
tif2kmz
类
这个类主要用于处理GeoTIFF文件并将其转换为KMZ文件。初始化方法接受两个参数:GeoTIFF文件路径和输出KMZ文件路径。
get_attribute
方法
该方法读取GeoTIFF文件并获取其地理位置信息。这些信息将用于生成KML文件,以便在Google Earth中正确显示图像。
linear_stretch
方法
该方法对图像数据进行线性拉伸,以增强对比度。线性拉伸是一种图像增强技术,通过将像素值映射到新的范围来提高图像的可见性。
create_temp_png
方法
该方法将GeoTIFF文件转换为PNG格式的图片。首先读取GeoTIFF文件中的数据,然后对每个通道(红、绿、蓝)应用线性拉伸,最后将处理后的数据保存为PNG文件。
create_kml
方法
该方法生成一个KML文件,该文件包含了PNG图片的地理位置信息。KML文件将描述PNG图片如何覆盖在地图上,以便在Google Earth中正确显示。
create_kmz
方法
该方法将生成的KML文件和PNG文件打包成KMZ文件。KMZ文件是KML文件的压缩版本,可以更方便地在Google Earth中使用。
主函数
主函数中,我们实例化tif2kmz
类并调用create_kmz
方法,将指定的GeoTIFF文件转换为KMZ文件。
总结
通过上述步骤,我们成功地将GeoTIFF文件转换为KMZ文件。这个过程利用了GDAL库读取GeoTIFF数据,Pillow库处理图像数据,以及zipfile库创建KMZ文件。这个转换过程可以帮助我们更方便地在Google Earth中查看和分析地理信息数据。
后续会把tif转为kzm的功能添加到大疆粗校正小工具里。
下一步计划是,去除无人机照片里的黑边。