台风路径可视化 | 强台风“天兔”移动轨迹图(Chiikawa版)
前言
大家好!最近,2024年第25号台风天兔引起了网友们的广泛关注,因为它有一个特别的名字——“ウサギ”(Usagi),直译过来就是“兔子”。其本义是指天兔星座。
由于这个名字与《Chiikawa》漫画中的可爱角色“乌萨奇”(Usagi)同名,网友们亲切地称其为“乌萨奇台风”。这不仅增加了台风话题的趣味性,也让许多人对这次台风产生了更多的关注。
为了更好地理解和展示这次台风的路径,我们决定用 Python 可视化台风“天兔”的路径,并且用《Chiikawa》漫画中的乌萨奇头像作为台风图标,为数据可视化增添一些趣味性。让我们一起动手吧
项目目标
我们的目标是:
收集台风“天兔”的历史路径数据。 使用 Python 的 Matplotlib 和 cartopy 工具包绘制台风路径图。 将《Chiikawa》漫画中的角色“乌萨奇”头像用作台风图标,让地图更加生动有趣。 将乌萨奇头像的图片进行抠图处理 通过本文档,帮助大家掌握使用 Python 进行地理信息数据可视化的基础方法。
数据准备
首先,我们需要收集台风“天兔”的路径数据。这些数据通常可以从气象网站或相关机构提供的公开数据集中获得。数据应包含日期、时间、经度、纬度等关键信息。博主通过爬虫在中央气象台的数据中爬取了数据并放置到project文件夹下
如何爬取则去看看往期文章
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from PIL import Image
import numpy as np
# 读取 Excel 文件
file_path = '/home/mw/project/2024_TY2425.xlsx'
data = pd.read_excel(file_path)
# 查看数据前几行
print(data.head())
tc_num name_cn name_en dateUTC dateCST vmax grade lat \
0 2425 天兔 USAGI 202411111800 202411120200 18 热带风暴 12.8
1 2425 天兔 USAGI 202411112100 202411120500 18 热带风暴 13.0
2 2425 天兔 USAGI 202411120000 202411120800 18 热带风暴 13.2
3 2425 天兔 USAGI 202411120300 202411121100 25 强热带风暴 13.9
4 2425 天兔 USAGI 202411120600 202411121400 25 强热带风暴 14.0
lon mslp attr
0 135.0 998 analysis
1 134.5 998 analysis
2 134.1 998 analysis
3 132.6 985 analysis
4 132.0 985 analysis
绘制台风路径
我们将使用 Python 中的 Matplotlib 库与cartopy进行可视化
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import urllib.request
import cartopy.crs as ccrs
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
from meteva.base.tool.plot_tools import add_china_map_2basemap
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
from cartopy.feature import NaturalEarthFeature
lons = data['lon'].values
lats = data['lat'].values
# 定义绘图范围(可以根据实际需要调整)
lon_min, lon_max = min(lons) - 5, max(lons) + 5
lat_min, lat_max = min(lats) - 5, max(lats) + 5
# 创建一个新的图形
fig = plt.figure(figsize=(12,10))
ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
plt.rcParams.update({'font.size': 16})
# 设置绘图范围
ax.set_extent([lon_min, lon_max, lat_min, lat_max], crs=ccrs.PlateCarree())
# 添加经纬度刻度
ax.set_xticks(np.arange(lon_min, lon_max+1, 5), crs=ccrs.PlateCarree())
ax.set_yticks(np.arange(lat_min, lat_max+1, 5), crs=ccrs.PlateCarree())
ax.xaxis.set_major_formatter(LongitudeFormatter())
ax.yaxis.set_major_formatter(LatitudeFormatter())
# 绘制路径
ax.plot(lons, lats, marker='o', linestyle='-', color='red')
# 设置标题和轴标签
ax.set_title('台风路径')
ax.set_xlabel('经度')
ax.set_ylabel('纬度')
# 下载并加载头像图片
avatar_url = 'https://c-ssl.duitang.com/uploads/blog/202402/09/JOSqvMj5SWDxxeJ.jpeg'
with urllib.request.urlopen(avatar_url) as url:
avatar_image = Image.open(url)
avatar_array = np.array(avatar_image)
# 每隔五个点绘制一个乌萨奇头像
for i in range(len(lons)):
if i % 5 == 0: # 每隔五个点绘制一次
imagebox = OffsetImage(avatar_array, zoom=0.05)
ab = AnnotationBbox(imagebox, (lons[i], lats[i]), frameon=False)
ax.add_artist(ab)
# 显示网格
ax.grid(True)
# 添加中国地图
add_china_map_2basemap(ax, name="nation", edgecolor='k', lw=0.5, encoding='gbk', grid0=None) # "国界"
land = NaturalEarthFeature('physical', 'land', '10m', edgecolor='face', facecolor='lightgreen')
ocean = NaturalEarthFeature('physical', 'ocean', '10m', edgecolor='face', facecolor='lightblue')
ax.add_feature(land)
ax.add_feature(ocean)
# 调整布局以适应图像
plt.tight_layout()
# 显示图形
plt.show()
头像图片边缘在图中还是稍显违和,那么无敌的Python一定有抠图库
安装抠图库rembg
!pip install rembg -i https://pypi.mirrors.ustc.edu.cn/simple/
拷贝预训练模型
由于训练模型下载缓慢,博主将其上传为数据集
!cp /home/mw/input/rembg2522/u2net.onnx /home/mw/.u2net/
开始抠图
核心代码
from rembg import remove
input_path = '/home/mw/project/usagi.jpeg'
output_path = 'output.png'
with open(input_path, 'rb') as i:
with open(output_path, 'wb') as o:
input = i.read()
output = remove(input)
o.write(output)
from PIL import Image
from rembg import remove
from IPython.display import display
input_path = '/home/mw/project/usagi.jpeg'
output_path = 'output.png'
comparison_path = 'comparison.png'
# 读取原始图片
with open(input_path, 'rb') as i:
input_data = i.read()
# 执行抠图操作
output_data = remove(input_data)
# 将处理后的数据写入到输出文件
with open(output_path, 'wb') as o:
o.write(output_data)
# 加载原始图片和处理后的图片
input_image = Image.open(input_path)
output_image = Image.open(output_path)
# 创建一个新图像,宽度是两个图像宽度之和,高度取两者中的最大值
width = input_image.width + output_image.width
height = max(input_image.height, output_image.height)
comparison_image = Image.new('RGB', (width, height))
# 将原始图片粘贴到左侧
comparison_image.paste(input_image, (0, 0))
# 将处理后的图片粘贴到右侧
comparison_image.paste(output_image, (input_image.width, 0))
# 保存对比图片
comparison_image.save(comparison_path)
# 在 Jupyter Notebook 中显示图片
display(comparison_image)
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import urllib.request
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
from cartopy.feature import NaturalEarthFeature
# 定义绘图范围(可以根据实际需要调整)
lon_min, lon_max = min(lons) - 5, max(lons) + 5
lat_min, lat_max = min(lats) - 5, max(lats) + 5
# 创建一个新的图形
fig = plt.figure(figsize=(12,10))
ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
plt.rcParams.update({'font.size': 16})
# 设置绘图范围
ax.set_extent([lon_min, lon_max, lat_min, lat_max], crs=ccrs.PlateCarree())
# 添加经纬度刻度
ax.set_xticks(np.arange(lon_min, lon_max+1, 5), crs=ccrs.PlateCarree())
ax.set_yticks(np.arange(lat_min, lat_max+1, 5), crs=ccrs.PlateCarree())
ax.xaxis.set_major_formatter(LongitudeFormatter())
ax.yaxis.set_major_formatter(LatitudeFormatter())
# 绘制路径
plt.plot(lons, lats, marker='o', linestyle='-', color='red')
# 设置标题和轴标签
plt.title('台风路径')
plt.xlabel('经度')
plt.ylabel('纬度')
avatar_image = Image.open('/home/mw/project/output.png')
avatar_array = np.array(avatar_image)
# 每隔五个点绘制一个乌萨奇头像
for i in range(len(lons)):
if i % 5 == 0: # 每隔五个点绘制一次
imagebox = OffsetImage(avatar_array, zoom=0.04)
ab = AnnotationBbox(imagebox, (lons[i], lats[i]), frameon=False)
ax.add_artist(ab)
# 显示网格
ax.grid(True)
# 添加中国地图
add_china_map_2basemap(ax, name="nation", edgecolor='k', lw=0.5, encoding='gbk', grid0=None) # "国界"
land = NaturalEarthFeature('physical', 'land', '10m', edgecolor='face', facecolor='lightgreen')
ocean = NaturalEarthFeature('physical', 'ocean', '10m', edgecolor='face', facecolor='lightblue')
ax.add_feature(land)
ax.add_feature(ocean)
# 调整布局以适应图像
plt.tight_layout()
# 显示图形
plt.show()
小结
通过本文的介绍,我们不仅学会了如何使用 Python 的 Matplotlib 和cartopy库来绘制地图和台风路径,还学会了如何将外部图像(如《Chiikawa》漫画中的乌萨奇头像)添加到地图中,让地图更加生动有趣。
另外还学习了如何使用Python进行抠图
这种方法不仅适用于台风路径的展示,还可以应用于其他需要地理信息可视化的场景。希望这篇文章能激发你对数据可视化领域的兴趣。