一、数据简单解读
卫星图像最初来自:
https://www.goes-r.gov/spacesegment/abi.html
高级基线成像仪是GOES-R系列中用于对地球天气、海洋和环境进行成像的主要仪器。ABI用16个不同的光谱波段观察地球(上一代GOES只有<>个),包括两个可见光通道,四个近红外通道和十个红外通道。模型和工具使用这些不同的通道(波长)来指示地球表面或大气中的各种元素,例如树木,水,云,水分或烟雾。
使用双线性重采样对原始全盘图像进行重新投影以生成局部场景图像。 由于在时间背景下更容易识别尾迹,因此提供了一系列以 10 分钟为间隔的图像。 每个示例仅包含一个标记帧。
从我们的预印本中了解有关数据集的更多信息:
https://arxiv.org/abs/2304.02122
在每个由 {record_id} 命名的子目录中,提供了与单个示例相对应的 numpy .npy 格式的二进制文件:
band_{08-16}.npy:
大小为 H x W x T 的数组,其中 T = n_times_before + n_times_after + 1,表示序列中图像的数量。 标记帧之前和之后分别有 n_times_before 和 n_times_after 图像。 在我们的数据集中,所有示例的 n_times_before=4 和 n_times_after=3。 每个波段代表不同波长的红外通道,并根据校准参数转换为亮度温度。 文件名中的数字对应于 GOES-16 ABI 带编号。 ABI 频段的详细信息可在此处找到。
human_individual_masks.npy:
大小为 H x W x 1 x R 的数组。每个示例都由 R 个单独的人类标记器标记。 R 并非所有样本都相同。 带标签的掩模的值为 0 或 1,对应于 band_{08-16}.npy 中的第 (n_times_before+1) 个图像。 它们仅在训练集中可用。
human_pixel_masks.npy:
大小为 H x W x 1 的数组,包含二进制真实值。 如果一个像素被超过一半的标记者标记为轨迹像素,则在评估中将其视为轨迹像素。
{train/validation}_metadata.json:包含重现卫星图像的时间戳和投影参数。
二、可视化代码解读
import os
import numpy as np
from matplotlib import animation
import matplotlib.pyplot as plt
from IPython import display
import os:
导入用于操作操作系统功能的模块,例如文件和目录操作。
import numpy as np:
导入NumPy库并将其命名为np,用于处理数值计算和数组操作。
from matplotlib import animation:
导入matplotlib库中的animation模块,该模块用于创建动画效果。
import matplotlib.pyplot as plt:
导入matplotlib库中的pyplot模块,并将其命名为plt,用于绘制图形。
from IPython import display:
导入IPython库中的display模块,用于在IPython环境中显示图像和动画。
这段代码主要用于设置动画环境的基本组件。
BASE_DIR = '/kaggle/input/google-research-identify-contrails-reduce-global-warming/train'
N_TIMES_BEFORE = 4
record_id = '1704010292581573769'
with open(os.path.join(BASE_DIR, record_id, 'band_11.npy'), 'rb') as f:
band11 = np.load(f)
with open(os.path.join(BASE_DIR, record_id, 'band_14.npy'), 'rb') as f:
band14 = np.load(f)
with open(os.path.join(BASE_DIR, record_id, 'band_15.npy'), 'rb') as f:
band15 = np.load(f)
with open(os.path.join(BASE_DIR, record_id, 'human_pixel_masks.npy'), 'rb') as f:
human_pixel_mask = np.load(f)
with open(os.path.join(BASE_DIR, record_id, 'human_individual_masks.npy'), 'rb') as f:
human_individual_mask = np.load(f)
这段代码主要是加载一些数据文件,其中包括图像数据和遮罩数据。让我逐行解释:
BASE_DIR = '/kaggle/input/google-research-identify-contrails-reduce-global-warming/train':
这是一个目录路径,表示数据文件所在的基本目录。这段代码可能是在Kaggle环境中运行的,用于指定数据文件的路径。
N_TIMES_BEFORE = 4:
这个变量似乎表示一个时间点之前的次数。
record_id = '1704010292581573769':
这个变量存储了一个记录的唯一标识符,用于访问特定的数据文件。
使用with open(…)语句,代码打开并加载了一系列的NumPy数组文件(.npy格式):
- band11 = np.load(f): 加载名为’band_11.npy’的文件内容到变量band11中。
- band14 = np.load(f): 加载名为’band_14.npy’的文件内容到变量band14中。
- band15 = np.load(f): 加载名为’band_15.npy’的文件内容到变量band15中。
- human_pixel_mask = np.load(f): 加载名为’human_pixel_masks.npy’的文件内容到变量human_pixel_mask中。
- human_individual_mask = np.load(f): 加载名为’human_individual_masks.npy’的文件内容到变量human_individual_mask中。
将条带组合成假彩色图像:
为了在 GOES 中查看轨迹,我们使用“ash”配色方案。 这种配色方案最初是为观察大气中的火山灰而开发的,但也可用于观察薄卷云,包括凝结尾迹。 在此配色方案中,尾迹在图像中显示为深蓝色。
请注意,我们在这里使用由 Kulik 等人开发的灰配色方案的修改版本,它使用针对尾迹调整的略有不同的频带和范围。
Ash Color Scheme:
https://eumetrain.org/sites/default/files/2020-05/RGB_recipes.pdf
_T11_BOUNDS = (243, 303)
_CLOUD_TOP_TDIFF_BOUNDS = (-4, 5)
_TDIFF_BOUNDS = (-4, 2)
def normalize_range(data, bounds):
"""Maps data to the range [0, 1]."""
return (data - bounds[0]) / (bounds[1] - bounds[0])
r = normalize_range(band15 - band14, _TDIFF_BOUNDS)
g = normalize_range(band14 - band11, _CLOUD_TOP_TDIFF_BOUNDS)
b = normalize_range(band14, _T11_BOUNDS)
false_color = np.clip(np.stack([r, g, b], axis=2), 0, 1)
这段代码执行了一些数据处理操作,用于生成一张伪彩色图像。让我为您解释每一步:
-
_T11_BOUNDS = (243, 303):
这是一个包含两个值的元组,表示T11(可能是某种温度测量)的范围。 -
_CLOUD_TOP_TDIFF_BOUNDS = (-4, 5):
这是另一个包含两个值的元组,表示云顶温度差的范围。 -
_TDIFF_BOUNDS = (-4, 2):
这是一个包含两个值的元组,表示温度差的范围。 -
normalize_range(data, bounds):
这个函数将数据映射到范围[0, 1]。它通过减去范围下界,然后除以范围的范围来进行归一化。 -
r = normalize_range(band15 - band14, _TDIFF_BOUNDS):
计算 band15 - band14,然后使用 normalize_range 函数将其映射到 _TDIFF_BOUNDS 范围内,得到一个代表温度差的归一化数组。 -
g = normalize_range(band14 - band11, _CLOUD_TOP_TDIFF_BOUNDS):
计算 band14 - band11,然后使用 normalize_range 函数将其映射到 _CLOUD_TOP_TDIFF_BOUNDS 范围内,得到一个代表云顶温度差的归一化数组。 -
b = normalize_range(band14, _T11_BOUNDS):
使用 normalize_range 函数将 band14 映射到 _T11_BOUNDS 范围内,得到一个代表T11的归一化数组。 -
false_color = np.clip(np.stack([r, g, b], axis=2), 0, 1):
这行代码将 r、g 和 b 数组堆叠成一个三维数组,然后使用 np.clip 将数组中的值限制在 [0, 1] 范围内,生成了一个代表伪彩色图像的数组 false_color。
总之,这段代码将一些输入数据(可能是与温度测量相关的数据)进行处理和归一化,然后将处理后的数据组合成一个伪彩色图像。该图像的每个通道分别代表不同的物理量,并且已经映射到了0到1的范围内。这种伪彩色图像通常用于可视化多通道数据。
可视化代码:
img = false_color[..., N_TIMES_BEFORE]
plt.figure(figsize=(18, 6))
ax = plt.subplot(1, 3, 1)
ax.imshow(img)
ax.set_title('False color image')
ax = plt.subplot(1, 3, 2)
ax.imshow(human_pixel_mask, interpolation='none')
ax.set_title('Ground truth contrail mask')
ax = plt.subplot(1, 3, 3)
ax.imshow(img)
ax.imshow(human_pixel_mask, cmap='Reds', alpha=.4, interpolation='none')
ax.set_title('Contrail mask on false color image');
这段代码用于绘制图像和遮罩的可视化,包括伪彩色图像、人工像素遮罩和将遮罩叠加到伪彩色图像上。让我为您逐行解释:
img = false_color[…, N_TIMES_BEFORE]: 这一行代码从 false_color 数组中选择第 N_TIMES_BEFORE 个时间点的切片,表示为 img,然后使用这个切片绘制图像。
plt.figure(figsize=(18, 6)): 创建一个图像窗口,设置其大小为 (18, 6)。
创建三个子图,分别显示不同的图像和遮罩:
ax = plt.subplot(1, 3, 1): 创建一个子图,位置为 (1, 3, 1),表示一行三列中的第一个位置。
ax.imshow(img): 在该子图中显示 img,即伪彩色图像。
ax.set_title(‘False color image’): 设置子图标题为 ‘False color image’。
ax = plt.subplot(1, 3, 2): 创建第二个子图,位置为 (1, 3, 2)。
ax.imshow(human_pixel_mask, interpolation=‘none’): 在该子图中显示人工像素遮罩,interpolation=‘none’ 禁用插值。
ax.set_title(‘Ground truth contrail mask’): 设置子图标题为 ‘Ground truth contrail mask’。
ax = plt.subplot(1, 3, 3): 创建第三个子图,位置为 (1, 3, 3)。
ax.imshow(img): 在该子图中显示 img,即伪彩色图像。
ax.imshow(human_pixel_mask, cmap=‘Reds’, alpha=.4, interpolation=‘none’): 将人工像素遮罩以红色叠加在伪彩色图像上,alpha 参数控制透明度,interpolation=‘none’ 禁用插值。
ax.set_title(‘Contrail mask on false color image’): 设置子图标题为 ‘Contrail mask on false color image’。
这段代码通过三个子图将伪彩色图像、遮罩和叠加效果进行了可视化,可以更好地理解数据和分析结果。每个子图都有自己的标题和可视化设置。
n = human_individual_mask.shape[-1]
plt.figure(figsize=(16, 4))
for i in range(n):
plt.subplot(1, n, i+1)
plt.imshow(human_individual_mask[..., i], interpolation='none')
这段代码用于绘制一系列人工个体遮罩的可视化,将每个个体的遮罩以列的形式显示在一个大图中。让我为您逐行解释:
n = human_individual_mask.shape[-1]: 这行代码计算了 human_individual_mask 数组的最后一个维度的大小,即个体遮罩的数量。
plt.figure(figsize=(16, 4)): 创建一个图像窗口,设置其大小为 (16, 4)。
使用循环迭代遍历每个个体的遮罩,并在大图中以列的形式显示:
for i in range(n): 使用循环迭代 0 到 n-1。
plt.subplot(1, n, i+1): 创建一个子图,位置为 (1, n, i+1),表示一行 n 列中的第 i+1 位置。
plt.imshow(human_individual_mask[…, i], interpolation=‘none’): 在该子图中显示第 i 个个体的遮罩,禁用插值。
这段代码生成一个大图,其中每一列显示一个个体的遮罩。每个子图的标题和可视化设置都可以根据需要进行调整,以便更好地理解和分析个体遮罩的数据。
# Animation
fig = plt.figure(figsize=(6, 6))
im = plt.imshow(false_color[..., 0])
def draw(i):
im.set_array(false_color[..., i])
return [im]
anim = animation.FuncAnimation(
fig, draw, frames=false_color.shape[-1], interval=500, blit=True
)
plt.close()
display.HTML(anim.to_jshtml())
这段代码创建了一个动画,显示了伪彩色图像序列的逐帧变化。让我逐行为您解释:
fig = plt.figure(figsize=(6, 6)): 创建一个图像窗口,大小为 (6, 6)。
im = plt.imshow(false_color[…, 0]): 在图像窗口中显示 false_color 数组的第一帧,并将 imshow 返回的对象存储在变量 im 中。
def draw(i): …: 定义一个函数 draw,该函数接受一个参数 i,表示帧的索引。在每一帧,该函数将更新 im 的图像数据为 false_color 数组的第 i 帧。
anim = animation.FuncAnimation(…): 使用 animation.FuncAnimation 创建动画对象。参数包括:
fig: 图像窗口对象。
draw: 更新每一帧图像的函数。
frames=false_color.shape[-1]: 帧数,使用 false_color 数组的最后一个维度。
interval=500: 每帧之间的间隔时间,单位为毫秒。
blit=True: 设置为 True 表示使用渲染优化技术(需要支持)。
plt.close(): 关闭之前创建的图像窗口,以避免不必要的显示。
display.HTML(anim.to_jshtml()): 将动画对象转换为HTML格式,并在IPython环境中显示动画。
总之,这段代码创建了一个动画,展示了伪彩色图像序列的逐帧变化。动画将在IPython环境中以HTML格式显示。您可以根据需要调整动画的参数,例如帧数、间隔时间等。