如何使用 Python 将 TIFF 和 Shapefile 叠加并保存为 JPG

文摘   2024-10-20 23:13   广东  
今晚来简单地写一写公众号~~~

最近你们是不是在本公众号看到这个视频。
之前买了个服务器,这个视频是通过写代码在linux上自动下载卫星影像自动合成的卫星影像来源于himawari8

我只是想把每天的himawari8卫星图都合成为一个视频,记录下来每天我们的亚洲上空,看云卷云舒。

这个视频还可以进一步改进,加载shp文件,把边界也画到视频。

本文将介绍如何使用 Python 中的 GDAL 库、PIL 库,实现将 TIFF 格式的栅格图像和 Shapefile 矢量数据叠加并保存为 JPG 格式。

在这里,我把TIFF 和 Shapefile 叠加并保存为 JPG的python代码放出来。
如下:

import osfrom osgeo import ogr, gdal, osrfrom PIL import Image, ImageDraw, ImageFont
def transform_point(point, inv_geo_transform): """将地理坐标转换为像素坐标""" pixel_x = int(inv_geo_transform[0] + inv_geo_transform[1] * point[0] + inv_geo_transform[2] * point[1]) pixel_y = int(inv_geo_transform[3] + inv_geo_transform[4] * point[0] + inv_geo_transform[5] * point[1]) return pixel_x, pixel_y
def draw_geometry(geom, draw, inv_geo_transform): """根据几何类型绘制相应的线""" geom_type = geom.GetGeometryName()
if geom_type == 'LINESTRING' or geom_type == 'LINEARRING': points = geom.GetPoints() pixel_points = [transform_point(point, inv_geo_transform) for point in points] draw.line(pixel_points, fill=(255, 0, 0), width=5) # 红色线条,宽度5像素
elif geom_type == 'MULTILINESTRING': # MULTILINESTRING 是多个 LINESTRING 的组合 for i in range(geom.GetGeometryCount()): sub_geom = geom.GetGeometryRef(i) draw_geometry(sub_geom, draw, inv_geo_transform)
def draw_shapefile_on_image(shp_file, jpg_image, reference_ds): """将线矢量文件的几何形状绘制到图像上""" # 获取参考栅格的地理变换 geo_transform = reference_ds.GetGeoTransform() inv_geo_transform = gdal.InvGeoTransform(geo_transform)
# 打开Shapefile shapefile = ogr.Open(shp_file) layer = shapefile.GetLayer()
# 创建一个ImageDraw对象 draw = ImageDraw.Draw(jpg_image)
# 遍历所有几何对象并将它们绘制到图像上 for feature in layer: geom = feature.GetGeometryRef() draw_geometry(geom, draw, inv_geo_transform)
def process_image(tiffile, shpfile, outpath): # 打开TIF文件 tif_image = Image.open(tiffile)
# 提取日期和时间部分 filename = os.path.basename(tiffile) # 获取文件名 timestamp = filename[0:16] # 假设文件名前面部分为日期时间,如09_22_16_50 timestamp = timestamp.split('_') timestamp = "{}-{}-{} {}:{}".format(timestamp[0], timestamp[1], timestamp[2], timestamp[3], timestamp[4])
# 转换为JPEG jpg_image = tif_image.convert('RGB')
# 在JPEG上打印文本 draw = ImageDraw.Draw(jpg_image) font = ImageFont.truetype('cmr10.ttf', size=200) # 选择合适的字体和大小 text_position = (2400, 200) # 文本位置,可以根据需要调整 draw.text(text_position, timestamp, fill=(255, 255, 255), font=font) # 白色文本
# 使用GDAL打开TIF文件作为参考栅格 reference_ds = gdal.Open(tiffile)
# 将Shapefile边界绘制到图像上 draw_shapefile_on_image(shpfile, jpg_image, reference_ds)
# 保存JPEG jpg_image.save(outpath, 'JPEG') print(f"图像已保存为 {outpath}")

if __name__ == '__main__': # 文件路径 tiffile = "/home/ubuntu/code/h8/2024-10-20/06-00/2024_10_20_06_00_clip.tif" shpfile = "/home/ubuntu/code/himawari8/shp/边界线_省级_九段线.shp" outpath = "/home/ubuntu/code/h8/2024-10-20/06-00/2024_10_20_06_00_clip.jpg"

process_image(tiffile, shpfile, outpath)

实现流程

  1. 读取 TIFF 栅格数据:通过 Pillow 打开 TIFF 图像并转换为 RGB 格式,以便可以进一步操作。

  2. 读取 Shapefile 矢量数据:使用 OGR 读取 Shapefile 文件,提取线矢量数据的几何形状。

  3. 将矢量边界绘制到栅格图像上:通过 ImageDraw 对象在栅格图像上绘制线条。

  4. 添加时间戳信息:根据 TIFF 文件名提取时间信息,并将其绘制到图像上。

  5. 保存为 JPEG:将叠加结果保存为 JPEG 格式。



结果如下:
北京时间7


北京时8


视频如下:


为什么今天的视频有早上的6点到九点半,原因是我的服务器的存储空间满了,我又没写自动清除之前不要的数据的功能,导致9点半之后的数据没有自动下载。


下一步计划是

1自动清除不要的数据。

2将视频自动上传到b站、抖音。

3将图片进行24小时实时直播。


今天先写到里了。


往期文章回顾

避免 Python 中 GDAL/OGR 绑定导致的崩溃

从原图中提取GPS信息并创建Shapefile(第5版)| 把文件名字写入shp、txt

这么多年下来,我确实是没处理过modis影像 | hdf格式转为tif格式

为什么我经常使用python,原因在于Python 是地理信息系统(GIS)和遥感领域的热门编程语言。

在Ubuntu 24.04系统上安装Rust编程语言环境

从原图中提取GPS信息并创建Shapefile(第四版)允许文件夹里同时存在原图、非原图




remote sensing
一个专注于测绘、地信、遥感的公众号
 最新文章