<jupyter_start><jupyter_text>常规赛：遥感影像地块分割实战>比赛页面传送门：[ 常规赛：遥感影像地块分割](https://aistudio.baidu.com/aistudio/competition/detail/63)>欢迎参加 [飞桨领航团实战速成营](https://aistudio.baidu.com/aistudio/education/group/info/16606)  赛题介绍本赛题由 2020 CCF BDCI 遥感影像地块分割 初赛赛题改编而来。遥感影像地块分割, 旨在对遥感影像进行像素级内容解析，对遥感影像中感兴趣的类别进行提取和分类，在城乡规划、防汛救灾等领域具有很高的实用价值，在工业界也受到了广泛关注。现有的遥感影像地块分割数据处理方法局限于特定的场景和特定的数据来源，且精度无法满足需求。因此在实际应用中，仍然大量依赖于人工处理，需要消耗大量的人力、物力、财力。本赛题旨在衡量遥感影像地块分割模型在多个类别（如建筑、道路、林地等）上的效果，利用人工智能技术，对多来源、多场景的异构遥感影像数据进行充分挖掘，打造高效、实用的算法，提高遥感影像的分析提取能力。 赛题任务 本赛题旨在对遥感影像进行像素级内容解析，并对遥感影像中感兴趣的类别进行提取和分类，以衡量遥感影像地块分割模型在多个类别（如建筑、道路、林地等）上的效果。 数据说明本赛题提供了多个地区已脱敏的遥感影像数据，各参赛选手可以基于这些数据构建自己的地块分割模型。 赛题任务本赛题旨在对遥感影像进行像素级内容解析，并对遥感影像中感兴趣的类别进行提取和分类，以衡量遥感影像地块分割模型在多个类别（如建筑、道路、林地等）上的效果。 训练数据集样例图片及其标注如下图所示：![](https://ai-studio-static-online.cdn.bcebos.com/fb7d813b0bb0449e9c49d5587d591af5e1e6fc5ba94544b6bbbf8ee3d19c4c25)训练数据集文件名称：train_and_label.zip包含2个子文件，分别为：训练数据集（原始图片）文件、训练数据集（标注图片）文件，详细介绍如下：训练数据集（原始图片）文件名称：img_train包含66,653张分辨率为2m/pixel，尺寸为256 * 256的JPG图片，每张图片的名称形如T000123.jpg。训练数据集（标注图片）文件名称：lab_train包含66,653张分辨率为2m/pixel，尺寸为256 * 256的PNG图片，每张图片的名称形如T000123.png。备注： 全部PNG图片共包括4种分类，像素值分别为0、1、2、3。此外，像素值255为未标注区域，表示对应区域的所属类别并不确定，在评测中也不会考虑这部分区域。测试数据集测试数据集文件名称：img_test.zip，详细介绍如下：包含4,609张分辨率为2m/pixel，尺寸为256 * 256的JPG图片，文件名称形如123.jpg。 提交内容及格式* 以zip压缩包形式提交结果文件，文件命名为 result.zip；* zip压缩包中的图片格式必须为单通道PNG；* PNG文件数需要与测试数据集中的文件数相同，且zip压缩包文件名需要与测试数据集中的文件名一一对应；* 单通道PNG图片中的像素值必须介于0~3之间，像素值不能为255。如果存在未标注区域，评测系统会自动忽略对应区域的提交结果。 提交示例提交文件命名为：result.zip，zip文件的组织方式如下所示：>主目录                                                                        >├── 1.png         每个结果文件命名为：测试数据集图片名称+.png                      >├── 2.png                                                              >├── 3.png                                                    >├── ...                                                         备注： 主目录中必须包含与测试数据集相同数目、名称相对应的单通道PNG图片，且每张单通道PNG图片中的像素值必须介于0~3之间，像素值不能为255。![](https://ai-studio-static-online.cdn.bcebos.com/e7ca4bdb7c594d928f900c817abc60c471c50b1fce7a4cc4b8ff360ecc721596)  第一步 环境配置<jupyter_code>!pip install paddlex -i https://mirror.baidu.com/pypi/simple
!pip install imgaug -i https://mirror.baidu.com/pypi/simple
# 设置使用0号GPU卡（如无GPU，执行此代码后仍然会使用CPU训练模型）
import matplotlib
import os
import paddlex as pdx

os.environ['CUDA_VISIBLE_DEVICES'] = '0'

import numpy as np
from paddlex.seg import transforms
import imgaug.augmenters as iaa

from tqdm import tqdm
import cv2<jupyter_output><empty_output><jupyter_text>第二步 解压数据集解压数据集并读取信息<jupyter_code>!unzip -q data/data77571/train_and_label.zip
!unzip -q data/data77571/img_test.zip
import numpy as np

datas = []
image_base = 'img_train'   # 训练集原图路径
annos_base = 'lab_train'   # 训练集标签路径

# 读取原图文件名
ids_ = [v.split('.')[0] for v in os.listdir(image_base)]

# 将训练集的图像集和标签路径写入datas中
for id_ in ids_:
    img_pt0 = os.path.join(image_base, '{}.jpg'.format(id_))
    img_pt1 = os.path.join(annos_base, '{}.png'.format(id_))
    datas.append((img_pt0.replace('/home/aistudio', ''), img_pt1.replace('/home/aistudio', '')))
    if os.path.exists(img_pt0) and os.path.exists(img_pt1):
        pass
    else:
        raise "path invalid!"

# 打印datas的长度和具体存储例子
print('total:', len(datas))
print(datas[0][0])
print(datas[0][1])
print(datas[0][:])
import numpy as np

# 四类标签，这里用处不大，比赛评测是以0、1、2、3类来对比评测的
labels = ['0', '1', '2',  '3']

# 将labels写入标签文件
with open('labels.txt', 'w') as f:
    for v in labels:
        f.write(v+'\n')

# 随机打乱datas
np.random.seed(5)
np.random.shuffle(datas)

# 验证集与训练集的划分，0.10表示10%为训练集，90%为训练集
split_num = int(0.10*len(datas))

# 划分训练集和验证集
train_data = datas[:-split_num]
valid_data = datas[-split_num:]

# 写入训练集list
with open('train_list.txt', 'w') as f:
    for img, lbl in train_data:
        f.write(img + ' ' + lbl + '\n')

# 写入验证集list
with open('valid_list.txt', 'w') as f:
    for img, lbl in valid_data:
        f.write(img + ' ' + lbl + '\n')

# 打印训练集和测试集大小
print('train:', len(train_data))
print('valid:', len(valid_data))<jupyter_output>train: 59987
valid: 6665<jupyter_text>数据预处理<jupyter_code>from paddlex.seg import transforms
import imgaug.augmenters as iaa

# 定义训练和验证时的transforms
train_transforms = transforms.Compose([
    transforms.RandomHorizontalFlip(),
    transforms.Resize(target_size=300),
    transforms.RandomPaddingCrop(crop_size=256),
    transforms.RandomBlur(prob=0.1),
    transforms.RandomRotate(rotate_range=15),
    # transforms.RandomDistort(brightness_range=0.5),
    transforms.Normalize()
])
eval_transforms = transforms.Compose([
    transforms.Resize(256),
    transforms.Normalize()
])<jupyter_output><empty_output><jupyter_text>读取语义 分割任务数据集<jupyter_code>data_dir = './'

# 定义训练和验证数据集
train_dataset = pdx.datasets.SegDataset(
    data_dir=data_dir,                # 数据集路径
    file_list='train_list.txt',       # 训练集图片文件list路径
    label_list='labels.txt',          # 训练集标签文件list路径
    transforms=train_transforms,      # train_transforms
    shuffle=True)                     # 数据集是否打乱
    
eval_dataset = pdx.datasets.SegDataset(
    data_dir=data_dir,                # 数据集路径
    file_list='valid_list.txt',       # 验证集图片文件list路径
    label_list='labels.txt',          # 验证集标签文件list路径
    transforms=eval_transforms)       # eval_transforms<jupyter_output>2021-04-15 17:07:17 [INFO]	59987 samples in file train_list.txt
2021-04-15 17:07:17 [INFO]	6665 samples in file valid_list.txt<jupyter_text>模型训练利用paddlex.seg.DeepLabv3p 构建 DeepLabv3p分割器。<jupyter_code># 分割类别数
num_classes = len(train_dataset.labels)

# 构建DeepLabv3p分割器
model = pdx.seg.DeepLabv3p(
    num_classes=num_classes,  backbone='Xception65', use_bce_loss=False
)

# 模型训练
model.train(
    num_epochs=50,                 # 训练迭代轮数
    train_dataset=train_dataset,  # 训练集读取
    train_batch_size=16,           # 训练时批处理图片数
    eval_dataset=eval_dataset,    # 验证集读取
    learning_rate=0.002,         # 学习率
    save_interval_epochs=1,       # 保存模型间隔轮次  
    save_dir='output',    # 模型保存路径
    log_interval_steps=1000,       # 日志打印间隔
    pretrain_weights='output/best_model')  #加载预训练模型<jupyter_output>/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/layers/math_op_patch.py:298: UserWarning: /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddlex/cv/nets/xception.py:316
The behavior of expression A + B has been unified with elementwise_add(X, Y, axis=-1) from Paddle 2.0. If your code works well in the older versions but crashes in this version, try to use elementwise_add(X, Y, axis=0) instead of A + B. This transitional warning will be dropped in the future.
  op_type, op_type, EXPRESSION_MAP[method_name]))
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/layers/math_op_patch.py:298: UserWarning: /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddlex/cv/nets/segmentation/model_utils/loss.py:74
The behavior of expression A * B has been unified with elementwise_mul(X, Y, axis=-1) from Paddle 2.0. If your code works well in the older versions but crashes in this version, try to use eleme[...]<jupyter_text>模型评估<jupyter_code># 加载模型
model = pdx.load_model('./output/best_model')

# 模型评估
model.evaluate(eval_dataset, batch_size=16, epoch_id=None, return_details=False)<jupyter_output>/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/fluid/layers/math_op_patch.py:298: UserWarning: /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddlex/cv/nets/xception.py:316
The behavior of expression A + B has been unified with elementwise_add(X, Y, axis=-1) from Paddle 2.0. If your code works well in the older versions but crashes in this version, try to use elementwise_add(X, Y, axis=0) instead of A + B. This transitional warning will be dropped in the future.
  op_type, op_type, EXPRESSION_MAP[method_name]))<jupyter_text>模型预测<jupyter_code>from tqdm import tqdm
import cv2

test_base = 'img_testA/'    # 测试集路径
out_base = 'result/'        # 预测结果保存路径

# 是否存在结果保存路径，如不存在，则创建该路径
if not os.path.exists(out_base):
    os.makedirs(out_base)

# 模型预测并保存预测图片
for im in tqdm(os.listdir(test_base)):
    if not im.endswith('.jpg'):
        continue
    pt = test_base + im
    result = model.predict(pt)
    cv2.imwrite(out_base+im.replace('jpg', 'png'), result['label_map'])<jupyter_output>100%|██████████| 4608/4608 [01:25<00:00, 53.92it/s]
{'fraction_non_alphanumeric': 0.1197533791795115, 'fraction_numerical': 0.0445814560113825, 'mean_word_length': 4.050898203592815, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 31, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 9, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '575348', 'license': 'Apache-2.0', 'n_tokens_mistral': 4446, 'n_tokens_neox': 4547, 'n_words': 477, 'path': '1809354.ipynb', 'repo_name': 'ITerydh/paddle', 'size': '8434'}