其他
万丈高楼平地起——基于飞桨PaddleGAN与PaddleRS实现建筑物样本扩充工具
项目背景与意义
Pix2Pix 模型简介
数据处理与代码实现
图1:Pix2Pix[3]模型在各场景下图像重建效果
将 Label(一般是图像熵较低的数据)输入生成器 G,输出重建后的图像 Image-fake。在 Image-fake 与 Image-Gt 间计算 L1 损失并优化,以缩小两幅图像间的逐像素差距。
将 Image-fake 与 Label、Image-Gt 与 Label 分别组成图像对并输入判别器 D,判别器 D 输出 Image-fake 或 Image-Gt 为真实图像的概率。使用 Image-fake、Image-Gt、Label 以及判别器 D 的输出计算 GAN 损失并优化,使生成器 G 生成图像的分布逼近真实影像的分布。GAN 损失的公式为:
图2:Pix2Pix[3]网络的训练、预测过程
图3:数据集内容展示
图4:建筑物实例级别擦除,构建训练样本
使用 GDAL 库读取矢量数据; 遍历每条矢量数据,根据第 i 个建筑物 Bi 坐标提取其周围的遥感影像块(尺寸为512*512),将其采样为栅格图,得到 Gt; 将 Gt 中目标建筑物 Bi 范围内像素值设置为(0,0,0)。
遍历切片后的二值化标注,使用 OpenCV 查找标注中的白色多边形; 对多边形进行筛选,删除面积过小的区域或位于图像边界处的区域; 以每一个多边形区域 Ci 作为一个实例,将与二值化标注对应的遥感影像 Image 作为 Gt,Ci 范围内像素设置为(0,0,0),得到 Label。
图5:数据集切片效果展示
"""
获取文件路径, 文件名, 后缀名
:param fileUrl:
:return:
"""
filepath, tmpfilename = os.path.split(fileUrl)
shotname, extension = os.path.splitext(tmpfilename)
return filepath, shotname, extension
def gan_img(img_path, lab_path, save_dir, vis=False):
lab = cv2.imread(lab_path, -1)
img = cv2.imread(img_path, -1)
contours, hierarchy = cv2.findContours(lab, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):
# 计算面积,太小的去掉
area = cv2.contourArea(contours[i])
if area < 200:
continue
# 接边的建筑物去掉,仅保留轮廓完整的建筑物
if 0 in contours[i]:
continue
# 外接矩形框,没有方向角
x, y, w, h = cv2.boundingRect(contours[i])
# 可视化,调试用
if vis == True:
img_to_draw = img.copy()
cv2.drawContours(img_to_draw, contours, i, (0, 0, 0), thickness=-1)
cv2.rectangle(img_to_draw, (x, y), (x + w, y + h), (0, 255, 0), 2)
# cv2.rectangle(img_to_draw, (x - 5, y - 5), (x + w + 10, y + h + 10), (0, 255, 0), 2)
cv2.imshow("img_to_draw", img_to_draw)
cv2.waitKey(0)
# 每一个对象绘制一张图
os.makedirs(save_dir, exist_ok=True)
img_to_save = img.copy()
# (0, 0, 0)作为标记,需要生成建筑的部分
cv2.drawContours(img_to_save, contours, i, (0, 0, 0), thickness=-1)
# axis=0 按垂直方向,axis=1 按水平方向,左侧为目标图像,右侧为Label
img_dataset = np.concatenate((img, img_to_save), axis=1)
f, s, e = get_filePath_fileName_fileExt(img_path)
os.makedirs(os.path.join(save_dir, "pairs"), exist_ok=True)
cv2.imwrite(os.path.join(save_dir, "pairs", s + "_" + str(i) + ".jpg"), img_dataset)
os.makedirs(os.path.join(save_dir, "img"), exist_ok=True)
os.makedirs(os.path.join(save_dir, "lab"), exist_ok=True)
!python -u PaddleGAN/tools/main.py --config-file work/pix2pix_buildings.yaml
# 中断后重新开始
# !python -u PaddleGAN/tools/main.py --config-file work/pix2pix_buildings.yaml --resume output_d
定义模型; 读取预训练权重; 数据处理(transformer 中的方法与参数)。
g_net = UnetGenerator(3, 3, 8, 64, 'batch', False) #注释:参数在配置文件中
weight_path = "./work/epoch_200_weight.pdparams"
state_dicts = load(weight_path)['netG']
state_dicts = load(weight_path)['netG'] #注释:权重文件中包含了G与D的参数,这里是关键
g_net.set_state_dict(state_dicts)
g_net.eval()
transform = T.Compose([
T.Transpose(),
T.Normalize([127.5, 127.5, 127.5], [127.5, 127.5, 127.5])
]) #注释:参数在配置文件中test部分
!cp ./work/predict预测.py PaddleGAN/
!python PaddleGAN/predict预测.py
图7:训练结果展示
图8:异常结果展示
生成图像大部分与原图相同,L1 损失中包含大量冗余部分; 网络真正需要生成的区域较小,损失难以聚焦在这部分,而这个目标小区域才是我们真正需要的。
图9:优化后的训练数据集
图11:PaddleRS 架构图
图12:DRN[4]模型架构
图13:DRN[4]模型双重回归训练架构
import os
import glob
import paddle
import numpy as np
from PIL import Image
from paddlers.models.ppgan.apps.drn_predictor import DRNPredictor
from paddlers.models.ppgan.apps.lesrcnn_predictor import LESRCNNPredictor
from paddlers.models.ppgan.apps.realsr_predictor import RealSRPredictor
# 输出预测结果的文件夹
output = r'./Super_Resolution_out'
# 待输入的低分辨率影像位置
input_dir = r"./gan_low_solution_sample"
# 设置GPU为推理设备
paddle.device.set_device("gpu:0")
# 实例化
DRNpredictor = DRNPredictor(output)
LESRpredictor = LESRCNNPredictor(output)
RealSRpredictor = RealSRPredictor(output)
# 生成文件列表
list_images = glob.glob(input_dir + "/*.**g")
#遍历文件列表,模型推理
for filename in list_images:
DRNpredictor.run(filename) # 预测
LESRpredictor.run(filename)
RealSRpredictor.run(filename)
图14:超分辨率效果展示
总结与展望
本项目地址:
WHU Building Dataset/Satellite dataset Ⅱ(East Asia)数据集下载链接:
飞桨生成对抗网络开发套件 PaddleGAN github 地址:
飞桨高性能遥感影像处理开发套件 PaddleRS github 地址: