代码复现(一):Active fire detection in Landsat-8 imagery: A large-scale dataset and a deep-learning study


  代码链接:Github

使用总结

1.文件目录结构

  以下是从Google Drive下载的完整文件夹,目录结构如下:

active-fire-detection
	- datasets:由已处理的256x256图像及火焰掩码组成,并不包含生成数据集的原始Landsat-8图像,仅包含已处理过的patches
		- continents:数据按大洲进行了划分
		- manually_annotated:手动注释的数据集
	- weights:保存卷积神经网络的权重
		- intersection:交集掩模训练得到的模型
			- unet_16f_2conv_762:保存模型文件model_unet_Intersection_final_weights.h5
			- unet_64f_2conv_10c:保存模型文件model_unet_Intersection_final_weights.h5
			- unet_64f_2conv_762:保存模型文件model_unet_Intersection_final_weights.h5
		- kumar-roy:kumar算法训练得到的模型
			- unet_16f_2conv_762:保存模型文件model_unet_kumar-roy_final_weights.h5
			- unet_64f_2conv_10c:保存模型文件model_unet_kumar-roy_final_weights.h5
			- unet_64f_2conv_762:保存模型文件model_unet_kumar-roy_final_weights.h5
		- murphy:murphy算法训练得到的模型
			- unet_16f_2conv_762:保存模型文件model_unet_murphy_final_weights.h5
			- unet_64f_2conv_10c:保存模型文件model_unet_murphy_final_weights.h5
			- unet_64f_2conv_762:保存模型文件model_unet_murphy_final_weights.h5
		- schroder:schroder算法训练得到的模型
			- unet_16f_2conv_762:保存模型文件model_unet_schroder_final_weights.h5
			- unet_64f_2conv_10c:保存模型文件model_unet_schroder_final_weights.h5
			- unet_64f_2conv_762:保存模型文件model_unet_schroder_final_weights.h5
		- voting:投票掩模训练得到的模型
			- unet_16f_2conv_762:保存模型文件model_unet_voting_final_weights.h5
			- unet_64f_2conv_10c:保存模型文件model_unet_voting_final_weights.h5
			- unet_64f_2conv_762:保存模型文件model_unet_voting_final_weights.h5

2.下载完整数据集/样本数据集

  涉及脚本:src/utils/download_dataset.pysrc/utils/unzip_patches.py

  • 1.使用download_dataset.py下载完整数据集的压缩文件到输出目录中,可自定义的常量:
    • DOWNLOAD_FULL_DATASET = True:选择下载完整数据集或样本数据集。
    • OUTPUT_DIR=r'D:\dataset':完整数据集压缩文件的输出目录。
    • REGIONS:自定义需要下载的大洲数据。
    • OUTPUT_SAMPLES:样本数据集压缩文件的输出目录。

在这里插入图片描述
此处设置DOWNLOAD_FULL_DATASET = TrueOUTPUT_DIR=r'D:\dataset',下载后得到:
在这里插入图片描述
文件目录如下:

South_America.zip
- z001054.zip
- z001054_masks.zip
- z001054_masks_derivates.zip
- ... ...
  • 2.使用src/utils/unzip_patches.py压缩文件,可自定义常量:
    • FULL_DATASET=True:设置解压完整数据集或样本数据集。
    • 完整数据集相关常量:
      • FULL_DATASET_ZIPS_PATH:完整数据集压缩路径。
      • FULL_DATASET_UNZIP_PATH:完整数据集解压路径。
    • 样本数据集相关常量:
      • SAMPLES_ZIP_PATH:样本数据集压缩路径。
      • IMAGES_PATH:样本数据集图片保存路径。
      • MASKS_PATH:样本数据集掩模保存路径。
      • MANUAL_ANNOTATIONS_PATH:手动注释数据保存路径。
          当前设置:
  • FULL_DATASET_ZIPS_PATH = 'D:\dataset'
  • FULL_DATASET_UNZIP_PATH = 'D:\dataset\South_America-unzip'

在这里插入图片描述
解压成功后输出:
在这里插入图片描述
得到解压文件目录如下:

- South_America-unzip
	- images
		- patches:11875张图像,格式为tif
	- masks
		- intersection:交集掩模,格式为tif
		- patches:三种算法生成的掩模文件,格式为tif
		- voting:投票掩模,格式为tif

注意:

  • 1.FULL_DATASET_ZIPS_PATH应设为压缩文件上级目录路径,如,若压缩文件South_America.zip路径为D:\dataset\South_America.zip,则应设为FULL_DATASET_ZIPS_PATH = 'D:\dataset'
  • 2.FULL_DATASET_UNZIP_PATH相应地可设为FULL_DATASET_UNZIP_PATH = 'D:\dataset\South_America-unzip'
  • 3.上述路径均采用\,且不带r

3.下载手动注释数据集

  手动注释案例:
在这里插入图片描述  

4.获取对应的模型

  以下是src

5.下载模型权重

  使用脚本src/utils/download_weights.pysrc/utils/unzip_download_weights.py

  • 1.使用脚本src/utils/download_weights.py下载权重压缩包,可自定义常量如下:
    • OUTPUT_DIR = '../../weights/':权重压缩包输出目录。
    • WEIGHT_FILES:自行选择数据集对应的模型,包括votingschroedermurphykumar-royintersection

此处设置OUTPUT_DIR = D:\weights进行下载,得到压缩文件目录如下:

- voting.zip
	- unet_16f_2conv_762:model_unet_Voting_final_weights.h5
	- unet_64f_2conv_10c:model_unet_Voting_final_weights.h5
	- unet_64f_2conv_762:model_unet_Voting_final_weights.h5
- schroeder.zip
	- unet_16f_2conv_762:model_unet_Schroeder_final_weights.h5
	- unet_64f_2conv_10c:model_unet_Schroeder_final_weights.h5
	- unet_64f_2conv_762:model_unet_Schroeder_final_weights.h5
- murphy.zip
	- unet_16f_2conv_762:model_unet_Murphy_final_weights.h5
	- unet_64f_2conv_10c:model_unet_Murphy_final_weights.h5
	- unet_64f_2conv_762:model_unet_Murphy_final_weights.h5
- kumar-roy.zip
	- unet_16f_2conv_762:model_unet_Kumar-Roy_final_weights.h5
	- unet_64f_2conv_10c:model_unet_Kumar-Roy_final_weights.h5
	- unet_64f_2conv_762:model_unet_Kumar-Roy_final_weights.h5
- intersection.zip
	- unet_16f_2conv_762:model_unet_Intersection_final_weights.h5
	- unet_64f_2conv_10c:model_unet_Intersection_final_weights.h5
	- unet_64f_2conv_762:model_unet_Intersection_final_weights.h5

在这里插入图片描述

  • 2.使用脚本src/utils/unzip_download_weights.py解压权重压缩包到trainmanual_annotations/cnn_compare目录下(不会解压缩到weights下)。可自定义常量如下:
    • ZIPED_WEIGHTS_DIR = '../../weights':指定权重压缩包目录。
    • UNZIP_TO_TRAIN = True:是否将文件解压缩到训练目录。
    • TRAIN_DIR = '../train/':训练目录路径。
    • UNZIP_TO_MANUAL_ANNOTATNIOS_CNN = True:是否将文件解压缩到手动注释评估目录。
    • UNZIP_TO_MANUAL_ANNOTATIONS_CNN = '../manual_annotations/cnn_compare':手动注释评估目录路径

此处设置:

ZIPED_WEIGHTS_DIR = 'D:\weights'
UNZIP_TO_TRAIN = True
TRAIN_DIR = 'D:\\train'#'D:\train'会报错
UNZIP_TO_MANUAL_ANNOTATNIOS_CNN = False
UNZIP_TO_MANUAL_ANNOTATIONS_CNN = None

在这里插入图片描述
得到目录D:\train

- voting
	- unet_16f_2conv_762
		- train_output:model_unet_Voting_final_weights.h5
	- unet_64f_2conv_10c
		- train_output:model_unet_Voting_final_weights.h5
	- unet_64f_2conv_762
		- train_output:model_unet_Voting_final_weights.h5
- schroeder
	- unet_16f_2conv_762
		- train_output:model_unet_Schroeder_final_weights.h5
	- unet_64f_2conv_10c
		- train_output:model_unet_Schroeder_final_weights.h5
	- unet_64f_2conv_762
		- train_output:model_unet_Schroeder_final_weights.h5
- murphy
	- unet_16f_2conv_762
		- train_output:model_unet_Murphy_final_weights.h5
	- unet_64f_2conv_10c
		- train_output:model_unet_Murphy_final_weights.h5
	- unet_64f_2conv_762
		- train_output:model_unet_Murphy_final_weights.h5
- kumar-roy
	- unet_16f_2conv_762
		- train_output:model_unet_Kumar-Roy_final_weights.h5
	- unet_64f_2conv_10c
		- train_output:model_unet_Kumar-Roy_final_weights.h5
	- unet_64f_2conv_762
		- train_output:model_unet_Kumar-Roy_final_weights.h5
- intersection
	- unet_16f_2conv_762
		- train_output:model_unet_Intersection_final_weights.h5
	- unet_64f_2conv_10c
		- train_output:model_unet_Intersection_final_weights.h5
	- unet_64f_2conv_762
		- train_output:model_unet_Intersection_final_weights.h5

6.查看/重新生成训练、测试、验证数据集CSV文件

  训练网络前需将数据集分为训练、测试、验证共三个数据子集,在github中每个模型用于训练、测试、验证的样本(包括图像及掩码)均由对应模型路径下的CSV文件给出。例如,使用intersection(交集数据集)训练的unet_16f_2conv_762模型对应的数据集路径src/train/kumar-roy/unet_16f_2conv_762/dataset
在这里插入图片描述

  • images_masks.csv:所有图像及掩模的tif文件名。
  • images_train.csvmasks_train.csv:训练集图像及掩模的tif文件名。
  • images_test.csvmasks_test.csv:测试集图像及掩模的tif文件名。
  • images_val.csvmasks_val.csv:验证集图像及掩模的tif文件名。

  研究中使用CSV文件保存图像、掩模的文件名来划分数据集。也可使用脚本src/utils/split_dataset.py来创建新的训练集、测试集、验证集进行模型训练,即,创建新的CSV文件。split_dataset.py可设置常量如下:

  • MASK_ALGORITHM = 'Kumar-Roy':使用的掩模算法名称,可选SchroederMurphyKumar-RoyIntersectionVoting
    • 生成src/train/kumar-roy/unet_*模型:使用Kumar-Roy
    • 生成src/train/murphy/unet_*模型:使用Murphy
    • 生成src/train/schroeder/unet_*模型:使用Schroeder
  • IMAGES_PATH='../../dataset/images/patches/':图像patches路径。
  • MASKS_PATH='../../dataset/masks/patches/':掩模路径。
  • OUTPUT_FOLDER='../../dataset/':新数据集输出目录。
  • TRAIN_RATIOVALIDATION_RATIOTEST_RATIO:设置训练、验证、测试数据的占比。

执行脚本后可生成images_masks.csvimages_*.csvmasks_*.csv文件,代表完成了新的数据集(包含了训练、测试、验证集)。

7.训练模型

  以使用kumar-roy数据集训练unet_16f_2conv_762为例,需使用脚本src/train/kumar-roy/unet_16f_2conv_762/train.py

import os
import warnings
warnings.filterwarnings("ignore")
import glob
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split
import tensorflow as tf
from keras.backend.tensorflow_backend import set_session
import keras
from keras.optimizers import *
from keras.callbacks import ModelCheckpoint, EarlyStopping
from tensorflow.python.keras import backend as K
from generator import *
from models import *
from metrics import *
from plot_history import plot_history
import sys
import pandas as pd
from tqdm import tqdm
from keras.preprocessing.image import ImageDataGenerator

#是否绘制训练和验证的图表
PLOT_HISTORY = True 

#指出所用的掩模算法,包括Schoeder、Murphy、Kumar-Roy
MASK_ALGORITHM = 'Kumar-Roy'
#滤波器、通道数目
N_FILTERS = 16
N_CHANNELS = 3
#模型训练超参数
EPOCHS = 50
BATCH_SIZE = 64
IMAGE_SIZE = (256, 256)
#指定使用unet模型
MODEL_NAME = 'unet'

RANDOM_STATE = 42
#图像和掩模的路径
IMAGES_PATH = '../../../../dataset/images/patches/'
MASKS_PATH = '../../../../dataset/masks/patches/'
#数据集中images_masks.csv的位置
IMAGES_DATAFRAME = './dataset/images_masks.csv'
#训练结果输出目录
OUTPUT_DIR = './train_output/'
#线程数
WORKERS = 4
#与EarlyStopping回调函数相关的参数,若训练过程中验证集上的损失在连续多少个epoch中没有改善,则训练会提前终止,依次防止过拟合。
EARLY_STOP_PATIENCE = 5 
#检查点保存的周期,ModelCheckpoint回调函数会按照这个参数定义的时间间隔保存模型的权重。
CHECKPOINT_PERIOD = 5
#保存模型权重的文件名模板,可以根据模型名称、掩模算法和epoch数生成唯一的文件名。模板中的双大括号{{epoch:02d}}会被实际的epoch数替换,格式化为两位数字。
CHECKPOINT_MODEL_NAME = 'checkpoint-{}-{}-epoch_{{epoch:02d}}.hdf5'.format(MODEL_NAME, MASK_ALGORITHM)
#设置训练开始的初始轮次,若大于0则表示训练不是从第一轮开始,而是从INITIAL_EPOCH指定的轮数恢复训练。
INITIAL_EPOCH = 0
RESTART_FROM_CHECKPOINT = None
#INITIAL_EPOCH>0表示希望从检查点开始恢复训练
if INITIAL_EPOCH > 0:
    RESTART_FROM_CHECKPOINT = os.path.join(OUTPUT_DIR, 'checkpoint-{}-{}-epoch_{:02d}.hdf5'.format(MODEL_NAME, MASK_ALGORITHM, INITIAL_EPOCH))


#最终权重文件名称
FINAL_WEIGHTS_OUTPUT = 'model_{}_{}_final_weights.h5'.format(MODEL_NAME, MASK_ALGORITHM)

CUDA_DEVICE = 1

if not os.path.exists(OUTPUT_DIR):
    os.makedirs(OUTPUT_DIR)
#设置CUDA设备及TensorFlow会话
os.environ["CUDA_VISIBLE_DEVICES"] = str(CUDA_DEVICE)
try:
    config = tf.compat.v1.ConfigProto()
    config.gpu_options.allow_growth = True
    sess = tf.compat.v1.Session(config=config)
    K.set_session(sess)
except:
    pass

try:
    np.random.bit_generator = np.random._bit_generator
except:
    pass

df = pd.read_csv(IMAGES_DATAFRAME, header=None, names=['images', 'masks'])

images_df = df[ ['images'] ]
masks_df = df[ ['masks'] ]
#获取训练、验证和测试数据集的CSV文件,这些文件中保存了图像patch/掩模文件对应的文件名,可通过x_train['images']/y_train['masks']获取
x_train = pd.read_csv('./dataset/images_train.csv')
y_train = pd.read_csv('./dataset/masks_train.csv')
x_val = pd.read_csv('./dataset/images_val.csv')
y_val = pd.read_csv('./dataset/masks_val.csv')
x_test = pd.read_csv('./dataset/images_test.csv')
y_test = pd.read_csv('./dataset/masks_test.csv')


#根据csv文件生成训练集图像及对应掩模的完整路径列表
images_train = [ os.path.join(IMAGES_PATH, image) for image in x_train['images'] ]
masks_train = [ os.path.join(MASKS_PATH, mask) for mask in y_train['masks'] ]
#根据csv文件生成验证集图像及对应掩模的完整路径列表
images_validation = [ os.path.join(IMAGES_PATH, image) for image in x_val['images'] ]
masks_validation = [ os.path.join(MASKS_PATH, mask) for mask in y_val['masks'] ]
#使用列表,创建训练和验证数据的数据加载器(类似DataLoader)
train_generator = generator_from_lists(images_train, masks_train, batch_size=BATCH_SIZE, random_state=RANDOM_STATE, image_mode="762")
validation_generator = generator_from_lists(images_validation, masks_validation, batch_size=BATCH_SIZE, random_state=RANDOM_STATE, image_mode="762")
#传入模型参数以获取模型
model = get_model(MODEL_NAME, input_height=IMAGE_SIZE[0], input_width=IMAGE_SIZE[1], n_filters=N_FILTERS, n_channels=N_CHANNELS)
#编译模型,使用Adam优化器和二元交叉熵损失函数
model.compile(optimizer = Adam(), loss = 'binary_crossentropy', metrics = ['accuracy'])
#打印模型摘要
model.summary()
#定义早期停止和模型检查点
es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=EARLY_STOP_PATIENCE)
checkpoint = ModelCheckpoint(os.path.join(OUTPUT_DIR, CHECKPOINT_MODEL_NAME), monitor='loss', verbose=1,
save_best_only=True, mode='auto', period=CHECKPOINT_PERIOD)

#若初始轮次大于0,则加载对应轮次的模型参数
if INITIAL_EPOCH > 0:
    model.load_weights(RESTART_FROM_CHECKPOINT)
#训练模型
print('Training using {}...'.format(MASK_ALGORITHM))
history = model.fit_generator(
    train_generator,
    steps_per_epoch=len(images_train) // BATCH_SIZE,
    validation_data=validation_generator,
    validation_steps=len(images_validation) // BATCH_SIZE,
    callbacks=[checkpoint, es],
    epochs=EPOCHS,
    workers=WORKERS,
    initial_epoch=INITIAL_EPOCH
)
print('Train finished!')

#保存模型及权重
print('Saving weights')
model_weights_output = os.path.join(OUTPUT_DIR, FINAL_WEIGHTS_OUTPUT)
model.save_weights(model_weights_output)
print("Weights Saved: {}".format(model_weights_output))

#PLOT_HISTORY为True,则绘制训练和验证的图表
if PLOT_HISTORY:
    plot_history(history, OUTPUT_DIR)

src

landsat

create_masks

  处理Landsat 8卫星图像数据,检测图像中的火点,并生成火点掩模。

  • GC_L8 = 'https://storage.googleapis.com/gcp-public-data-landsat/LC08/01/':Landsat 8数据的Google Cloud存储路径。
  • MTL_EXTENSION:元数据文件的扩展名。
  • IN_DIR = r'../../dataset/images/tif_images/':输入目录。
  • OUT_DIR = r'../../dataset/masks/':输出目录。
  • getMTLParameters(MTL):解析元数据文件(MTL)并返回文件相关参数。
  • get_bounds(width,height,transform):计算图像的边界,返回包含图像边界像素的元组(left, bottom, right, top)
  • get_extent(dataset)
  • getReflectance(band, add_band, mult_band, sun_elevation):计算反射率并根据太阳高度角进行图像校正。
  • get_saturation(BQA):检测饱和像素。
  • save_masks(out_dir, image_name, profile, fire_mask, reference):保存火点掩模文件。
  • get_split(fileIMG,out_path):将图像分割成小块(256x256)。
  • 以下是Schroeder、Kumar-Roy、Murphy三种算法的实现:
    • Schroeder算法:
      • Seq1(bands, r75, diff75):Schroeder方程1。
      • Seq2 (bands):Schroeder方程2。
      • Seq3 (r75, diff75):Schroeder方程3。
      • Seq4and5 (bands, r75, unamb_fires, potential_fires, water):Schroeder方程4、5。
      • Seq6 (bands):Schroeder方程6。
      • Seq7_8_9 (bands):Schroeder方程7、8、9。
    • Kumar算法:
      • Geq12(bands):Kumar-Roy方程12。
      • Geq13 (bands, eq12_mask):Kumar-Roy方程13。
      • Geq14 (bands):Kumar-Roy方程14。
      • Geq15(bands):Kumar-Roy方程15。
      • Geq16 (bands):Kumar-Roy方程16。
      • pixelVal(p7,ef,ep,ew):辅助函数。
      • Geq8and9 (bands, valid, unamb_fires, potential_fires, water):- ---- Kumar-Roy方程8和9。
    • Murphy算法:
      • Meq2 (bands):Murphy方程2。
      • Meq3 (bands):Murphy方程3。
  • getFireMaskGOLI (bands):Kumar-Roy火点检测的函数,返回生成的掩模图像。
  • getFireMaskMurphy (bands, saturated):Murphy火点检测的函数,返回生成的掩模图像。
  • getFireMaskSchroeder (bands):Schroeder火点检测的函数,返回生成的掩模图像。
  • processImage (in_dir, out_dir, image_name, Aref, Mref, SE, sat):读取图像、获取元数据、执行火点检测和保存结果。共包含包括输入输出目录、图像名称、辐射定标系数、反射率定标系数、太阳高度角和饱和像素掩模共七个参数。
    • 1.打开指定路径的图像文件,并获取其元数据,并读取1-7波段的数据。
    • 2.对读取的波段数据计算反射率,并根据太阳高度角进行校正。
    • 3.分别使用三种算法计算图像掩模,并使用save_masks保存掩模,同时将掩模图像分割为256x256大小,并保存在patches目录下。
  • 执行部分:
    • 1.循环遍历BQA图像文件,提取图像名称。
    • 2.读取BQA图像文件,获取饱和像素掩模。
    • 3.从AWS获取元数据文件并解析参数。
    • 4.调用processImage函数处理图像,包括读取图像、执行火点检测和保存结果。

downloader

  从Google Cloud Storage下载Landsat 8卫星图像数据,并将它们保存到本地目录。

  • GC_L8 = 'https://storage.googleapis.com/gcp-public-data-landsat/LC08/01/':Google Cloud Storage的Landsat 8数据路径。
  • MTL_EXTENSION = '_MTL.txt':元数据文件的扩展名。
  • ext = '.TIF':图像文件的扩展名。
  • IN_DIR = r'../../dataset/':输入目录。
  • OUT_DIR = r'../../dataset/images/tif_images/':输出目录。
  • csv:包含产品ID的CSV文件。

在这里插入图片描述

  • 执行流程:
    • 1.读取CSV文件中的卫星图像产品ID。
    • 2.循环遍历每个产品ID,对于每个产品ID:
      • 记录开始时间、检查日志文件是否存在,如果不存在,则执行下载操作。
      • 下载BQA图像和所有波段图像,更新元数据并保存图像。
      • 记录日志信息,记录结束时间并打印处理时间。

manual_annotations

evaluate_v1

  评估多个火点检测算法的性能。它计算了各种统计指标,如Jaccard指数、F1分数、像素精度和混淆矩阵。

train

intersection

unet_16f_2conv_762
dataset

  保存训练、测试、验证的图像及其掩模对应的tif文件名。
在这里插入图片描述

train_output

  保存训练好的模型(.h5文件)。

evaluate_v1

  评估火灾检测模型的性能。通过加载真实标签和预测结果,计算各种统计指标,如Jaccard指数、F1分数、像素精度和混淆矩阵。

generate_images_csv

  读取图像和掩模文件,生成一个包含图像和对应掩模文件名的CSV文件,并使用这些文件名来分割数据集为训练集、验证集和测试集。这些生成的数据集使用CSV文件格式保存在dataset目录下。
  此模块生成了dataset下的images_train'masks_trainimages_valmasks_valimages_testmasks_test文件。

generator

  定义线程安全的generator_from_lists(),函数声明如下:

@threadsafe_generator
def generator_from_lists(images_path, masks_path, batch_size=32, shuffle = True, random_state=None, image_mode='10bands')

输入图像patches路径、图像掩模路径,生成一个包含图像及对应掩模数据的列表,当列表长度达到batch_size大小时,生成一个数据批次并清空列表。

inference

  使用预训练的深度学习模型对测试集进行推断,并保存推断结果。

models

  定义了FCN(全连接神经网络)和几个不同版本的unet模型。

  • 全卷积神经网络模型(FCN):
FCN(nClasses, input_height=128, input_width=128, n_filters = 16, dropout = 0.1, batchnorm = True)
  • UNet模型
def get_unet(nClasses, input_height=256, input_width=256, n_filters = 16, dropout = 0.1, batchnorm = True, n_channels=10):
  • 通用卷积函数
def conv2d_block(input_tensor, n_filters, kernel_size = 3, batchnorm = True)
  • 较小的UNet模型
def get_unet_small1(nClasses, input_height=128, input_width=128, n_filters = 16, dropout = 0.1, batchnorm = True, n_channels=3)
  • 更小的UNet模型
def get_unet_small2(nClasses, input_height=128, input_width=128, n_filters = 16, dropout = 0.1, batchnorm = True, n_channels=3)
  • get_model():传入参数,并根据模型名传入相应参数、创建模型对象并返回。
def get_model(model_name, nClasses=1, input_height=128, input_width=128, n_filters = 16, dropout = 0.1, batchnorm = True, n_channels=10)
plot_history

  绘制训练历史的准确性和损失图,用于可视化深度学习模型训练过程中的性能。

def plot_history(history, out_dir)
  • history:模型训练过程中记录的历史对象,包含训练和验证的准确性和损失数据。
  • out_dir:保存绘图的输出目录。
train

  UNet模型的完整深度学习训练流程,使用了TensorFlow和Keras库进行训练。

import os
import warnings
warnings.filterwarnings("ignore")
import glob
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import train_test_split
import tensorflow as tf
from keras.backend.tensorflow_backend import set_session
import keras
# from keras import optimizers
from keras.optimizers import *
from keras.callbacks import ModelCheckpoint, EarlyStopping
from tensorflow.python.keras import backend as K
from generator import *
from models import *
from metrics import *
from plot_history import plot_history
import sys
import pandas as pd
from tqdm import tqdm
from keras.preprocessing.image import ImageDataGenerator

#是否绘制训练和验证的图表
PLOT_HISTORY = True 

#定义使用的掩模算法名称,可选:Schoeder、Murphy、Kumar-Roy、交集掩模、投票掩模
MASK_ALGORITHM = 'Intersection'
#滤波器、通道数目
N_FILTERS = 16
N_CHANNELS = 3
#定义模型训练超参数
EPOCHS = 50
BATCH_SIZE = 64
IMAGE_SIZE = (256, 256)
#指定使用unet模型
MODEL_NAME = 'unet'

RANDOM_STATE = 42
#图像和掩模的路径
IMAGES_PATH = '../../../../dataset/images/patches/'
MASKS_PATH = '../../../../dataset/masks/intersection/'
#输出目录
OUTPUT_DIR = './train_output/'
#线程数
WORKERS = 4
#与EarlyStopping回调函数相关的参数,若训练过程中验证集上的损失在连续多少个epoch中没有改善,则训练会提前终止,依次防止过拟合。
EARLY_STOP_PATIENCE = 5 
#检查点保存的周期,ModelCheckpoint回调函数会按照这个参数定义的时间间隔保存模型的权重。
CHECKPOINT_PERIOD = 5
#保存模型权重的文件名模板,可以根据模型名称、掩模算法和epoch数生成唯一的文件名。模板中的双大括号{{epoch:02d}}会被实际的epoch数替换,格式化为两位数字。
CHECKPOINT_MODEL_NAME = 'checkpoint-{}-{}-epoch_{{epoch:02d}}.hdf5'.format(MODEL_NAME, MASK_ALGORITHM)

#设置训练开始的初始轮次,若大于0则表示训练不是从第一轮开始,而是从INITIAL_EPOCH指定的轮数恢复训练。
INITIAL_EPOCH = 0
#存储检查点文件的路径,如果设置了从检查点恢复训练,这个变量将被用来加载之前保存的模型权重。
RESTART_FROM_CHECKPOINT = None
#INITIAL_EPOCH>0表示希望从检查点开始恢复训练
if INITIAL_EPOCH > 0:
	#构建检查点文件完整路径,即,将输出目录、模型名称、掩模算法和初始epoch数组合成文件名来加载模型权重
    RESTART_FROM_CHECKPOINT = os.path.join(OUTPUT_DIR, 'checkpoint-{}-{}-epoch_{:02d}.hdf5'.format(MODEL_NAME, MASK_ALGORITHM, INITIAL_EPOCH))

#最终权重文件名称
FINAL_WEIGHTS_OUTPUT = 'model_{}_{}_final_weights.h5'.format(MODEL_NAME, MASK_ALGORITHM)

CUDA_DEVICE = 1

if not os.path.exists(OUTPUT_DIR):
    os.makedirs(OUTPUT_DIR)
#设置CUDA设备及TensorFlow会话
os.environ["CUDA_VISIBLE_DEVICES"] = str(CUDA_DEVICE)
try:
    config = tf.compat.v1.ConfigProto()
    config.gpu_options.allow_growth = True
    sess = tf.compat.v1.Session(config=config)
    K.set_session(sess)
except:
    pass
#设置Numpy随机数生成器
try:
    np.random.bit_generator = np.random._bit_generator
except:
    pass=
#获取训练、验证和测试数据集的CSV文件,这些文件中保存了图像patch/掩模文件对应的文件名,可通过x_train['images']/y_train['masks']获取
x_train = pd.read_csv('./dataset/images_train.csv')
y_train = pd.read_csv('./dataset/masks_train.csv')
x_val = pd.read_csv('./dataset/images_val.csv')
y_val = pd.read_csv('./dataset/masks_val.csv')
x_test = pd.read_csv('./dataset/images_test.csv')
y_test = pd.read_csv('./dataset/masks_test.csv')

#根据csv文件生成训练集图像及对应掩模的完整路径列表
images_train = [ os.path.join(IMAGES_PATH, image) for image in x_train['images'] ]
masks_train = [ os.path.join(MASKS_PATH, mask) for mask in y_train['masks'] ]
#根据csv文件生成验证集图像及对应掩模的完整路径列表
images_validation = [ os.path.join(IMAGES_PATH, image) for image in x_val['images'] ]
masks_validation = [ os.path.join(MASKS_PATH, mask) for mask in y_val['masks'] ]
#使用列表,创建训练和验证数据的数据加载器(类似DataLoader)
train_generator = generator_from_lists(images_train, masks_train, batch_size=BATCH_SIZE, random_state=RANDOM_STATE, image_mode="762")
validation_generator = generator_from_lists(images_validation, masks_validation, batch_size=BATCH_SIZE, random_state=RANDOM_STATE, image_mode="762")
#获取模型
model = get_model(MODEL_NAME, input_height=IMAGE_SIZE[0], input_width=IMAGE_SIZE[1], n_filters=N_FILTERS, n_channels=N_CHANNELS)
#编译模型,使用Adam优化器和二元交叉熵损失函数
model.compile(optimizer = Adam(), loss = 'binary_crossentropy', metrics = ['accuracy'])
#打印模型摘要
model.summary()
#定义早期停止和模型检查点
es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=EARLY_STOP_PATIENCE)
checkpoint = ModelCheckpoint(os.path.join(OUTPUT_DIR, CHECKPOINT_MODEL_NAME), monitor='loss', verbose=1,
save_best_only=True, mode='auto', period=CHECKPOINT_PERIOD)

#若初始轮次大于0,则加载对应轮次的模型参数
if INITIAL_EPOCH > 0:
    model.load_weights(RESTART_FROM_CHECKPOINT)
#训练模型
print('Training using {}...'.format(MASK_ALGORITHM))
history = model.fit_generator(
    train_generator,
    steps_per_epoch=len(images_train) // BATCH_SIZE,
    validation_data=validation_generator,
    validation_steps=len(images_validation) // BATCH_SIZE,
    callbacks=[checkpoint, es],
    epochs=EPOCHS,
    workers=WORKERS,
    initial_epoch=INITIAL_EPOCH
)
print('Train finished!')

#保存模型及权重
print('Saving weights')
model_weights_output = os.path.join(OUTPUT_DIR, FINAL_WEIGHTS_OUTPUT)
model.save_weights(model_weights_output)
print("Weights Saved: {}".format(model_weights_output))

#PLOT_HISTORY为True,则绘制训练和验证的图表
if PLOT_HISTORY:
    plot_history(history, OUTPUT_DIR)

流程包括:

  • 数据准备
  • 模型构建并训练
  • 早期停止
  • 检查点保存
  • 结果绘图
metrics

  计算了两个评估图像分割模型性能的指标,包括Dice系数、像素精度。

unet_64f_2conv_10c
unet_64f_2conv_762

utils

convert_patch_to_3channels_image

  从TIF图像中读取特定波段,处理和归一化图像数据,并保存为 PNG 格式。

  • IMAGE:要读取的TIF图像路径。
  • OUTPUT_DIR:输出图像的目录。
  • OUTPUT_IMAGE_NAME:保存的图像文件名。
  • MAX_PIXEL_VALUE:定义最大像素值,用于归一化图像数据。这里的最大值是 65535,表示 16 位图像。
  • get_img_762bands(path):接受图像路径,读取TIF的7、6、2波段并归一化处理。D:\ActiveFireData\active-fire-detection\datasets\continents\patches_and_masks\Africa下有相应图片可提取,注意,不应从_masks_masks_derivates中提取,二者是掩膜二值图像,没有波段可提取。
  • 剩余部分代码:创建输出目录OUTPUT_DIR、将归一化后的像素转换到0~255,并转为PNG格式。

copy_trained_weights_to_manual_annotations_evaluation

  遍历指定的训练目录,找到每个算法和架构的最终权重文件,并将它们复制到手动注释的 CNN 评估目录下的对应位置。

  • TRAINING_DIR:训练数据目录。

count_fire_pixels

  读取指定路径下的掩模图像,计算图像中火灾像素的数目,并打印结果。

  • MASK_NAME:掩模图像名称。
  • MASK_PATH:掩膜图像路径。
  • PATCHES_PATTERN:若MASK_NAME不以tifTIF结尾,则加上PATCHES_PATTERN
  • get_mask_arr(path):读取掩模图像,并将其转换为一维的像素数组。
  • main
    • 给图像名称加上后缀名,得到image_name
    • 查找MASK_PATH下所有匹配image_name的图像路径,并返回一个列表images_path
    • 打印掩模名称和找到的图像总数。
    • 获取掩膜对应的一维像素数组,计算火灾像素的数目。

crop_manual_annotations

  从输入目录中读取图像和相关的掩模及注释,使用 get_split 函数将这些文件分割成补丁(patches,指分割后的256x256图像),并保存到指定的输出目录。

  • INPUT_ANNOTATION_SCENE_DIR:手工标注的文件目录。
  • OUTPUT_ANNOTATION_PATCHES:输出图像和掩模的目录。
  • create_folder(folder_path):检查指定文件夹是否存在。
  • split_images(input_dir, output_dir):接受输入目录、输出目录作为参数,分割图像。
  • main:定义图像文件目录images_dir、掩模文件目录masks_dir、手动标注文件目录manual_annotation_dir,定于输出图像块目录output_images_diroutput_masks_dir输出掩模目录、output_manual_annotation_dir手工注释补丁目录。调用split_images(),分别处理图像、掩模和手动注释目录,将其分割并保存到对应的输出目录。

download_dataset.py

  从Google Drive下载完整或部分数据集,patches,指分割后的256x256图像。文件夹结构如下:
在这里插入图片描述
可在REGIONS常量中注释掉不需要的部分来选择性下载某些区域的数据集,以节省空间。

  • DOWNLOAD_FULL_DARASET=True:布尔变量,
    • True:下载完整数据集。
    • False:只下载样本数据。
  • OUTPUT_DIR:下载文件输出目录。
  • BASE_URL = 'https://drive.google.com/uc?id={}':Google Drive文件下载的URL模板。
  • REGIONS:不同地区的名称及其对应的 Google Drive 文件 ID。
  • SUBSET_SAMPLES:样本数据的Google Drive文件ID。
  • OUT_PUT_SAMPLES:样本文件下载的输出目录。
  • download_file(file_id, output):接收文件ID和输出路径,打印下载信息并下载文件。
  • main
    • DOWNLOAD_FULL_DARASET=True:遍历REGIONS中的所有区域,并为之构建zip文件夹、下载文件。
    • DOWNLOAD_FULL_DARASET=False:下载样本数据。

download_manual_annotations

  从Google Drive下载手动标注的图像到本地目录,可选择下载手动标注的图像(patches,指分割后的256x256图像)或用于生成这些patches的完整场景图像。手动标注的图像(patches,指分割后的256x256图像)的文件夹位置为:
在这里插入图片描述
用于生成这些patches的完整场景图像位置为:
在这里插入图片描述

  • OUTPUT_DIR:输出目录。
  • DOWNLOAD_SCENES:决定是否下载原始场景或图像块。
  • BASE_URL:Google Drive的基本下载链接格式,其中,{}会被替换为文件ID。
  • PATCHES:保存patches文件的Google Drive ID。
  • SCENES:保存scenes文件Google Drive ID。
  • download_file(file_id, output):根据文件ID和输出路径下载文件,并输出下载的URL。
  • download_files(files):以文件夹路径作为参数,遍历其中的所有文件名,下载对应的ZIP文件。
  • main:创建输出目录、根据DOWNLOAD_SCENES来决定下载scenes文件或patches文件。

download_weights

  下载对应模型的参数,在Google Drive中,这些模型参数存储在:
在这里插入图片描述
代码中使用字典WEIGHT_FILES记录了基本的Google Drive URL,其中,download_file()用于下载指定文件,main程序中遍历权重文件列表,将文件下载到指定目录。

generate_nonfire_masks

  用于给patches(分割后的256x256图像)生成非火灾掩模(用0标记),并将其保存到输出目录下。

  • INPUT_PATCHES_DIR:patches(分割后的256x256图像)的路径。
  • OUTPUT_DIR:生成掩模的输出路径。
  • MASK_NOTATION:在patches文件名中加上’v1’,表明是该patch对应的掩模。
  • NON_FIRE_MASK:创建的256x256全零数组,作为非火灾掩模。
  • main:将INPUT_PATCHES_DIR下的所有patches,为其生成对应的非火灾掩模,该掩模文件名为原patch文件名中将_RT_替换为_RT_v1_得到。

make_masks

  通过组合三种手工算法生成的掩模(原始掩模)来生成新的掩模,组合方式包括并集、交集和投票。若某个算法的掩模不存在,则生成一个仅包含无关值(全零或其他默认值)的掩模。

  • MASKS_FOR_COMPLETE_SCENE=True:指示是否为整个图像生成掩膜。
  • MASKS_DIR:掩模路径。
  • MASKS_ALGORITHMS = ['Schroeder', 'Murphy', 'Kumar-Roy']:生成原始掩模的算法。
  • OUTPUT_DIR = '../../dataset/manual_annotations/scenes/masks/':输出目录。
  • OUTPUT_INTERSECTION = OUTPUT_DIR:设置交集掩模的输出目录。
  • OUTPUT_VOTING = OUTPUT_DIR:设置投票掩模的输出目录。
  • NUM_VOTINGS:投票阈值。
  • IMAGE_SIZE = (256, 256):图像大小。
  • load_masks_in_dataframe():加载掩模文件并返回dataframe数据,该数据中保存了原始图像对应的三种算法生成的掩模数据,可通过算法名直接获取对应的掩模。
  • make_intersection_masks(dataframes):通过与运算得到三种算法的交集掩模,并保存到输出目录。
  • make_voting_masks(dataframes):获取三种算法的投票掩模。
  • main:根据MASKS_FOR_COMPLETE_SCENE变量的值,决定计算整个原图像的掩模或是patches的掩模。之后计算交集掩模、投票掩模并保存到输出目录中。

masks_with_at_least_n_fire_pixels

  由用户指定阈值NUM_PIXELS(最小火灾像素的数目),打印超过该阈值的所有掩模路径,及掩模中火灾像素的数量。

purge_logs

  用于删除训练、推理和评估过程中生成的日志文件夹。

  • TRAIN_DIR:训练目录路径。
  • MANUAL_ANNOTATIONS_DIR:手动注释目录路径。
  • delete_log_from_algorithms(base_path):用于删除基于算法的日志。
  • delete_log_from_architecture(base_path):用于删除基于架构的日志。
  • delete_folder(folder_path):用于删除指定路径的文件夹。

split_dataset

  读取掩模图像,生成一个包含图像和对应掩模文件名的CSV文件,并使用这些文件名来分割数据集为训练集、验证集和测试集。

  • MASK_ALGORITHM = 'Kumar-Roy':使用的掩模算法名称。
  • IMAGES_PATH:图像patches路径。
  • MASKS_PATH:掩模路径。
  • OUTPUT_FOLDER:输出文件夹路径。
  • IMAGES_DATAFRAME:输出csv文件路径。
  • 执行流程:
    • 1.找出掩模算法对应的掩模文件。
    • 2.创建dataframe,将图像名及对应的掩模文件名存入csv文件中。
    • 3.读取CSV文件并划分为训练集、验证集和测试集,并保存为CSV文件。

transform_mask

  将掩模图像中的非零像素值设置为255(白色,代指火灾像素,即将图像转换为二值图像),然后将处理后的图像保存为PNG格式。

  • MASK_PATH:指定掩模图像路径。
  • OUTPUT_DIR:PNG图像保存路径。
  • OUTPUT_NAME:PNG图像文件名。

unzip_download_weights

  • ZIPED_WEIGHTS_DIR:模型权重文件路径。
  • TRAIN_DIR:训练目录路径。
  • UNZIP_TO_MANUAL_ANNOTATIONS_CNN:手动注释实现的CNN对照模型路径。
  • UNZIP_TO_TRAINUNZIP_TO_MANUAL_ANNOTATNIOS_CNN:是否将解压后的权重文件复制到训练目录和CNN对照模型目录。
  • create_folder(folder_path):指定路径,创建文件夹。
  • unzip_to_folder(input_zip, output_folder):将zip文件解压到指定文件夹。
  • 执行流程:
    • 1.将ZIPED_WEIGHTS_DIR下的压缩zip文件全部解压缩,并保存到临时目录。
    • 2.遍历临时目录中的每个算法对应的架构文件夹,构建权重文件的路径,并根据设置复制权重文件到目标目录。
    • 3.删除临时目录及其所有内容。

upzip_manual_annotations

  解压图像、手动注释和掩模的zip文件到相应的输出目录。

  • INPUT_DIROUTPUT_DIR:定义压缩文件目录和解压文件的保存路径。
  • UNZIP_SCENES:指示解压整个场景还是图像patch。
  • create_folder(folder_path):指定路径,创建文件夹。
  • unzip_to_folder(input_zip, output_folder):指定路径,解压文件夹。
  • 执行流程:
    • 1.根据UNZIP_SCENES解压整张图像或图像patch。
    • 2.调用unzip_to_folder将zip文件解压到输出目录。

unzip_patches

  • 执行流程:
    • 1.根据FULL_DATASET选择解压完整数据集或样本数据集。
    • 2.若解压完整数据集,则解压Landsat 压缩文件,并将patches文件解压到相应目录。
    • 3.若解压样本数据集,则使用临时目录解压,并重命名特定的掩模文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值