精华内容
下载资源
问答
  • 一、无人机遥感图像语义分割数据集UAVid UAVid数据集是用于针对城市场景的语义分割任务的UAV视频数据集。它具有几个特点: 语义分割 4K分辨率无人机视频 8种物体类别 街景环境 示例图像: 下载地址(支持...

    一、无人机遥感图像语义分割数据集UAVid

    UAVid数据集是用于针对城市场景的语义分割任务的UAV视频数据集。它具有几个特点:

    • 语义分割
    • 4K分辨率无人机视频
    • 8种物体类别
    • 街景环境

    示例图像:

    下载地址(支持百度网盘下载):https://uavid.nl/

    二、使用UAVid工具包(python)进行标签转换

    1. 下载数据集后,进入数据集中,将文件名进行修改并组织为以下形式,即将数据集上级目录名修改为UAVidDataset,将目录名uavid_train修改为train,其余也按照以下图片修改目录名

    2. 下载工具包

    # 首先进入到你的UAVidDataset路径下
    # 然后依次使用以下命令开始下载工具包并配置
    git clone https://github.com/YeLyuUT/UAVidToolKit.git
    cd UAVidToolKit
    python setup.py build_ext --inplace
     

    完成好后,你的文件组织形式应该为上图的格式。

    3. 标签转化

    在UAVidDataset文件下下使用以下命令

    python UAVidToolKit/prepareTrainIdFiles.py -s train/ -t labelimg/train/
    python UAVidToolKit/prepareTrainIdFiles.py -s valid/ -t labelimg/valid/

    如果顺利的话,文件夹结构为以下形式

    打开labelimg文件夹,里面由train和valid两个文件夹,分别存放的是训练集和验证集的标签图像,可以自行查看一下。

     

    三、编写DataLoader数据加载脚本(使用Pytorch)

    训练集和验证集的数据加载脚本,训练集采用了随机缩放、随机翻转、随机位置裁剪三种数据增强方式

    import torch
    import torch.utils.data
    
    import numpy as np
    import cv2
    import os
    
    train_dirs = ["seq1/", "seq2/", "seq3/", "seq4/", "seq5/", 
                  "seq6/", "seq7/", "seq8/", "seq9/", "seq10/",
                  "seq11/", "seq12/", "seq13/", "seq14/", "seq15/",
                  "seq31/", "seq32/", "seq33/", "seq34/", "seq35/"]
    val_dirs = ["sep16/", "seq17/", "seq18/","seq19/",
                "seq20/", "seq36/", "seq37/"]
    
    class DatasetTrain(torch.utils.data.Dataset):
        def __init__(self, uavid_data_path, uavid_meta_path):
            self.img_dir = uavid_data_path + "/train/"
            self.label_dir = uavid_meta_path + "/labelimg/train/"
    
            self.img_h = 2160
            self.img_w = 3840
    
            self.new_img_h = 1536
            self.new_img_w = 1536
    
            self.examples = []
            for train_dir in train_dirs:
                train_img_dir_path = self.img_dir + train_dir + "Images/"
                label_img__dir_path = self.label_dir + train_dir
    
                file_names = os.listdir(train_img_dir_path)
                for file_name in file_names:
                    img_id = file_name.split(".png")[0]
    
                    img_path = train_img_dir_path + file_name
    
                    label_img_path = label_img__dir_path + "TrainId/" + img_id + ".png"
    
                    example = {}
                    example["img_path"] = img_path
                    example["label_img_path"] = label_img_path
                    example["img_id"] = img_id
                    self.examples.append(example)
    
            self.num_examples = len(self.examples)
    
        def __getitem__(self, index):
            example = self.examples[index]
    
            img_path = example["img_path"]
            img = cv2.imread(img_path, -1) # (shape: (2160, 3840, 3))
            # resize img without interpolation (want the image to still match
            # label_img, which we resize below):
            img = cv2.resize(img, (self.new_img_w, self.new_img_h),
                             interpolation=cv2.INTER_NEAREST) # (shape: (1536, 1536, 3))
    
            label_img_path = example["label_img_path"]
            label_img = cv2.imread(label_img_path, cv2.IMREAD_GRAYSCALE) # (shape: (2160, 3840))
            # resize label_img without interpolation (want the resulting image to
            # still only contain pixel values corresponding to an object class):
            label_img = cv2.resize(label_img, (self.new_img_w, self.new_img_h),
                                   interpolation=cv2.INTER_NEAREST) # (shape: (1536, 1536))
    
            # flip the img and the label with 0.5 probability:
            flip = np.random.randint(low=0, high=2)
            if flip == 1:
                img = cv2.flip(img, 1)
                label_img = cv2.flip(label_img, 1)
    
            ########################################################################
            # randomly scale the img and the label:
            ########################################################################
            scale = np.random.uniform(low=0.7, high=2.0)
            new_img_h = int(scale*self.new_img_h)
            new_img_w = int(scale*self.new_img_w)
    
            # resize img without interpolation (want the image to still match
            # label_img, which we resize below):
            img = cv2.resize(img, (new_img_w, new_img_h),
                             interpolation=cv2.INTER_NEAREST) # (shape: (new_img_h, new_img_w, 3))
    
            # resize label_img without interpolation (want the resulting image to
            # still only contain pixel values corresponding to an object class):
            label_img = cv2.resize(label_img, (new_img_w, new_img_h),
                                   interpolation=cv2.INTER_NEAREST) # (shape: (new_img_h, new_img_w))
            ########################################################################
    
            # # # # # # # # debug visualization START
            # print (scale)
            # print (new_img_h)
            # print (new_img_w)
            #
            # cv2.imshow("test", img)
            # cv2.waitKey(0)
            #
            # cv2.imshow("test", label_img)
            # cv2.waitKey(0)
            # # # # # # # # debug visualization END
    
            ########################################################################
            # select a 768x768 random crop from the img and label:
            ########################################################################
            start_x = np.random.randint(low=0, high=(new_img_w - 768))
            end_x = start_x + 768
            start_y = np.random.randint(low=0, high=(new_img_h - 768))
            end_y = start_y + 768
    
    
            img = img[start_y:end_y, start_x:end_x] # (shape: (768, 768, 3))
            label_img = label_img[start_y:end_y, start_x:end_x] # (shape: (768, 768))
            ########################################################################
    
            # # # # # # # # debug visualization START
            # print (img.shape)
            # print (label_img.shape)
            #
            # cv2.imshow("test", img)
            # cv2.waitKey(0)
            #
            # cv2.imshow("test", label_img)
            # cv2.waitKey(0)
            # # # # # # # # debug visualization END
    
            # normalize the img (with the mean and std for the pretrained ResNet):
            img = img/255.0
            img = img - np.array([0.485, 0.456, 0.406])
            img = img/np.array([0.229, 0.224, 0.225]) # (shape: (768, 768, 3))
            img = np.transpose(img, (2, 0, 1)) # (shape: (3, 768, 768))
            img = img.astype(np.float32)
    
            # convert numpy -> torch:
            img = torch.from_numpy(img) # (shape: (3, 768, 768))
            label_img = torch.from_numpy(label_img) # (shape: (768, 768))
    
            return (img, label_img)
    
        def __len__(self):
            return self.num_examples
    
    class DatasetVal(torch.utils.data.Dataset):
        def __init__(self, uavid_data_path, uavid_meta_path):
            self.img_dir = uavid_data_path + "/valid/"
            self.label_dir = uavid_meta_path + "/labelimg/valid/"
    
            self.img_h = 2160
            self.img_w = 3840
    
            self.new_img_h = 768
            self.new_img_w = 768
    
            self.examples = []
            for val_dir in val_dirs:
                val_img_dir_path = self.img_dir + val_dir + "Images/"
                label_img__dir_path = self.label_dir + val_dir 
    
                file_names = os.listdir(val_img_dir_path)
                for file_name in file_names:
                    img_id = file_name.split(".png")[0]
    
                    img_path = val_img_dir_path + file_name 
    
                    label_img_path = label_img__dir_path + "TrainId/" + img_id + ".png"
                    # label_img = cv2.imread(label_img_path, -1) # (shape: (1024, 2048))
    
                    example = {}
                    example["img_path"] = img_path
                    example["label_img_path"] = label_img_path
                    example["img_id"] = img_id
                    self.examples.append(example)
    
            self.num_examples = len(self.examples)
    
        def __getitem__(self, index):
            example = self.examples[index]
    
            img_id = example["img_id"]
    
            img_path = example["img_path"]
            img = cv2.imread(img_path, -1) # (shape: (2160, 3840, 3))
            # resize img without interpolation (want the image to still match
            # label_img, which we resize below):
            img = cv2.resize(img, (self.new_img_w, self.new_img_h),
                             interpolation=cv2.INTER_NEAREST) # (shape: (768, 768, 3))
    
            label_img_path = example["label_img_path"]
            label_img = cv2.imread(label_img_path, cv2.IMREAD_GRAYSCALE) # (shape: (2160, 3840))
            # resize label_img without interpolation (want the resulting image to
            # still only contain pixel values corresponding to an object class):
            label_img = cv2.resize(label_img, (self.new_img_w, self.new_img_h),
                                   interpolation=cv2.INTER_NEAREST) # (shape: (768, 768))
    
            # # # # # # # # debug visualization START
            # cv2.imshow("test", img)
            # cv2.waitKey(0)
            #
            # cv2.imshow("test", label_img)
            # cv2.waitKey(0)
            # # # # # # # # debug visualization END
    
            # normalize the img (with the mean and std for the pretrained ResNet):
            img = img/255.0
            img = img - np.array([0.485, 0.456, 0.406])
            img = img/np.array([0.229, 0.224, 0.225]) # (shape: (768, 768, 3))
            img = np.transpose(img, (2, 0, 1)) # (shape: (3, 768, 768))
            img = img.astype(np.float32)
    
            # convert numpy -> torch:
            img = torch.from_numpy(img) # (shape: (3, 768, 768))
            label_img = torch.from_numpy(label_img) # (shape: (768, 768))
    
            return (img, label_img, img_id)
    
        def __len__(self):
            return self.num_examples

     

    展开全文
  • 遥感影像语义分割数据集

    千次阅读 2021-03-20 23:15:14
    遥感图像语义分割数据集 文章目录遥感图像语义分割数据集1.建筑1.1 Aerial Image Segmentation Dataset1.2 INRIA aerial image dataset1.3 WHU Building Dataset1.4 Massachusetts Buildings Dataset1.5 2020数字...

    遥感图像语义分割数据集

    1.建筑

    1.1 Aerial Image Segmentation Dataset

    该航空图像分为来自谷歌地图的航空遥感图像和来自OpenStreetMap的像素级的建筑、道路和背景标签。覆盖区域为柏林、芝加哥、巴黎、波茨坦和苏黎世。地物真实图像包括一张来自谷歌地图的东京地区航空图像,以及手动生成的、像素级的建筑、道路和背景标签。像素级标签以RGB顺序作为PNG图像提供,标记为建筑物、道路和背景的像素由RGB颜色[255,0,0]、[0,0,255]和[255,255,255]表示。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MStE7L4S-1616253306525)(pic/image-20210312220551006.png)]

    地址:https://zenodo.org/record/1154821#.XH6HtygzbIU

    1.2 INRIA aerial image dataset

    在这里插入图片描述

    地址:https://project.inria.fr/aerialimagelabeling/download/

    1.3 WHU Building Dataset

    在这里插入图片描述在这里插入图片描述

    地址:https://study.rsgis.whu.edu.cn/pages/download/building_dataset.html

    1.4 Massachusetts Buildings Dataset

    在这里插入图片描述

    地址:https://www.cs.toronto.edu/~vmnih/data/

    链接:https://pan.baidu.com/s/1w09JYGNyLOEENmdEFXngog
    提取码:RSAI

    1.5 2020数字中国创新大赛—应用赛1:建筑智能普查

    本赛事由福建省有关部门挑选出16个具有代表性的实验区,包含城市、乡镇、农村等多种不同的人居环境和土地利用场景,每个实验区覆盖12平方公里左右的面积。对于每个实验区,选取没有云雾遮挡的中国高分二号卫星遥感影像,并对其多光谱波段和全色波段进行影像融合,提供0.8m真彩色RGB影像作为比赛的原始数据,不做拉伸处理,以8-bit的tiff文件格式存储。通过人工解译的方式勾绘出每幅实验影像中所有的建筑物轮廓多边形,并存为二值化tiff文件格式,其中1代表建筑物区域,0代表非建筑物区域。赛事开始时,提供给参赛选手8幅标注好的建筑物数据作为训练集,其余8幅影像做为测试集,其中5幅影像作为A榜公开测试集,另外3幅作为B榜非公开测试集,影像数据不公开。
    在这里插入图片描述

    地址:https://tianchi.aliyun.com/competition/entrance/231767/information

    1.6 SpaceNet Buildings Dataset

    参考:https://blog.csdn.net/dou3516/article/details/105123413

    1.7 AIRS

    AIRS(用于屋顶分割的航空影像)是一个公共数据集,旨在对来自超高分辨率航空影像的屋顶分割算法进行基准测试。 AIRS的主要特征可以概括为:

    457平方公里的正射影像图像覆盖超过220,000座建筑物
    图像的极高空间分辨率(0.075m)
    严格符合屋顶轮廓的精致地面真相
    AIRS数据集几乎覆盖了新西兰南岛最大的城市基督城的整个区域。该照片是在2015年和2016年的飞行季节拍摄的,提供的图像是经过矫正的DOM,具有RGB通道和7.5cm的分辨率(在新西兰横轴墨卡托投影中)。整个区域内有226,342座标有建筑物的建筑物可供实验。为了消除救济位移的影响,对建筑物的地面基本要素进行了精心设计,使其与屋顶对齐。因此,为AIRS提出的分割任务包含两个语义类:屋顶像素和非屋顶像素。
    在这里插入图片描述

    地址:https://www.airs-dataset.com/

    2.道路

    2.1 Massachusetts Roads Dataset

    马萨诸州道路数据(Massachusetts Roads Dataset),该数据集包含高分辨率影像和对应的真实道路标签,涵盖了城市、郊区等复杂地物信息,划分好了训练集(Training set)、验证集(Validation Set)、测试集(Test Set)。该数据由同一传感器拍摄获得的影像,成像质量一致。分辨率为1.2米,每张影像像素尺寸为1500*1500。
    在这里插入图片描述

    地址:https://www.cs.toronto.edu/~vmnih/data/

    链接:https://pan.baidu.com/s/1lOLZGqhBZmDVrD-SfPfCig
    提取码:RSAI

    2.2 ERM-PAIW

    在这里插入图片描述

    地址:https://www.dlr.de/eoc/en/desktopdefault.aspx/tabid-12760/22294_read-52776

    2.3 DeepGlobe Road Detection Challenge

    数据集包含6226张训练图像,1243张验证图像,以及1101张测试图像。所有的图像尺寸均为1024*1024,图像来源于泰国、印度、印度尼西亚,图像场景包括城市、乡村、荒郊、海滨、热带雨林等多个场景。
    在这里插入图片描述

    地址:http://deepglobe.org/challenge.html

    链接:https://pan.baidu.com/s/1pTCBOsrZ2XJq479FAfcFNg
    提取码:RSAI

    2.4 “华为云杯”2020人工智能创新应用大赛

    大赛数据集来源于北京二号卫星,空间分辨率为0.8米,分为训练集和测试集2个数据集,分别包含3景遥感影像,其中训练集2景影像的尺寸分别为40391X33106、34612X29810。
    在这里插入图片描述

    地址:https://competition.huaweicloud.com/information/1000041322/introduction

    3.水体

    3.1 BH-DATASET

    BH-pools和BH-watertanks,分别带有注释的游泳池和水箱。 这两个数据集均包含来自巴西米纳斯吉拉斯州贝洛奥里藏特市几个街区的图像。 数据是通过Google Earth Pro工具获取的。 图像是从330米的眼睛高度以3840x2160(4K)的分辨率导出的,并且图像带是三个可见的带:红色,绿色和蓝色。 对于在图像上发现的目标对象的每次出现,都绘制了一个多边形以生成实例的分割蒙版。

    BH-Pools数据集包含8个不同邻域的200张4K图像(每个图像25张),并包含3980个带注释的池。 BH-WaterTanks数据集由6个邻里的150张4K图像组成(每个图像25张),并包含16216个带注释的水箱。
    在这里插入图片描述

    地址:http://www.patreo.dcc.ufmg.br/2020/07/29/bh-pools-watertanks-datasets/

    链接:https://pan.baidu.com/s/1_GwnpR8kNTnztUEbC4x48w
    提取码:RSAI

    3.2 高分辨率可见光图像水体目标自动提取

    高分二号光学数据,分辨率1m-4m。每幅图像按照像素级别进行了水体的像素级标注
    在这里插入图片描述

    地址:http://sw.chreos.org/competitionlist

    4.云

    4.1 38-Cloud dataset

    该数据集包含38幅Landsat 8 场景图像及其手动提取的像素级地物真实标签,用于云检测。这些场景的整个图像被裁剪成384×384个斑块,以适合于基于深度学习的语义分割算法。数据集被划分为8400个斑块进行训练,9201个补丁进行测试。每幅图像有4个相应的波段,分别是红色(波段4)、绿色(波段3)、蓝色(波段2)和近红外(波段5)。
    在这里插入图片描述

    地址:https://github.com/SorourMo/38-Cloud-A-Cloud-Segmentation-Dataset

    4.2 95-Cloud

    95云数据集是之前38云数据集的扩展。 95-Cloud还有57个用于“培训”的Landsat 8场景

    地址:https://github.com/SorourMo/95-Cloud-An-Extension-to-38-Cloud-Dataset

    地址:https://www.kaggle.com/sorour/95cloud-cloud-segmentation-on-satellite-images?select=95-cloud_training_only_additional_to38-cloud

    4.3 Landsat 8 Cloud Cover Assessment Validation Data

    地址:https://landsat.usgs.gov/landsat-8-cloud-cover-assessment-validation-data

    5.多类

    5.1 GID

    Gaofen Image Dataset(GID)是一个用于土地利用和土地覆盖(LULC)分类的大型数据集。它包含来自中国60多个不同城市的150幅高质量高分二号(GF-2)图像,这些图像覆盖的地理区域超过了5万km²。GID图像具有较高的类内多样性和较低的类间可分离性。GF-2是高清晰度地球观测系统(HDEOS)的第二颗卫星。GF-2卫星包括了空间分辨率为1 m的全色图像和4 m的多光谱图像,图像大小为6908×7300像素。多光谱提供了蓝色、绿色、红色和近红外波段的图像。自2014年启动以来,GF-2已被用于土地调查、环境监测、作物估算、建设规划等重要应用。
    在这里插入图片描述

    地址:http://captain.whu.edu.cn/GID/

    https://x-ytong.github.io/project/GID.html

    5.2 ISPRS

    SPRS提供了城市分类和三维建筑重建测试项目的两个最先进的机载图像数据集。该数据集采用了由高分辨率正交照片和相应的密集图像匹配技术产生的数字地表模型(DSM)。这两个数据集区域都涵盖了城市场景。Vaihingen是一个相对较小的村庄,有许多独立的建筑和小的多层建筑;Postdam是一个典型的历史城市,有着大的建筑群、狭窄的街道和密集的聚落结构。每个数据集已手动分类为6个最常见的土地覆盖类别。

    ①不透水面 (RGB: 255, 255, 255)

    ②建筑物(RGB: 0, 0, 255)

    ③低矮植被 (RGB: 0, 255, 255)

    ④树木 (RGB: 0, 255, 0)

    ⑤汽车(RGB: 255, 255, 0)

    ⑥背景 (RGB: 255, 0, 0)

    背景类包括水体和与其他已定义类别不同的物体(例如容器、网球场、游泳池),这些物体通常属于城市场景中的不感兴趣的语义对象。
    在这里插入图片描述

    地址:http://www2.isprs.org/commissions/comm3/wg4/semantic-labeling.html

    链接:https://pan.baidu.com/s/1RbxJZu5EfWEVaCZ8PAp7ww
    提取码:RSAI

    5.3 2017 IEEE GRSS Data Fusion Contest

    2017年IEEE GRSS数据融合竞赛采用分类作为主体。要执行的任务是对各种城市环境中的土地使用(即针对2012年地方气候区(LCZ))进行分类。竞赛选择了几个城市来测试LCZ预测在世界各地推广的能力。输入数据为多时相、多源和多模态,包括图像和语义层。

    数据集由4个部分组成。

    美国地质调查局提供的的地面卫星数据:包含可见光、短波和长波红外在内的8个多光谱波段,并以100 m分辨率重采样的;

    哨兵2图像:该图像空间分辨率为100 m,拥有9个多光谱波段即可见光、近红外和短红外波长(包含修改的哥白尼数据2016);

    辅助数据:开放街道图(OSM)层,具有土地利用信息:建筑、自然、道路和其他土地利用区域。其中还为建筑和土地使用区域提供分辨率为20 m的OSM层的栅格地图,可与卫星图像叠加。

    此外,对于选取的城市,还提供了城市几个地区的各种LCZ类的地面真实标签。标签为100 m分辨率的栅格图像,也可叠加到卫星图像上。
    在这里插入图片描述

    地址:http://www.grss-ieee.org/2017-ieee-grss-data-fusion-contest/http://dase.ticinumaerospace.com/index.php

    5.4 2018 IEEE GRSS Data Fusion Contest

    数据是由NCALM于2017年2月16日在16:31至18:18 GMT之间从国家机载激光测绘中心获得的。在这场比赛中使用数据收集的传感器包括:有3个不同波段的激光雷达传感器OPTech TITAM M(14sen/con340)、具有70 mm焦距的高分辨率的彩色成像仪Dimac ULTRALIGHT+、高光谱成像仪ITRES CASI 1500。多光谱激光雷达点云数据波段在1550 nm,1064 nm和532 nm。高光谱数据覆盖范围为380—1050 nm,共有48个波段,空间分辨率为1 m。高分辨率RGB遥感图像的空间分辨率为5 cm,被分割成几个单独的图片。
    在这里插入图片描述

    地址:http://www.grss-ieee.org/community/technical-committees/data-fusion/2018-ieee-grss-data-fusion-contest/

    5.5 EvLab-SS Dataset

    EvLab-SS数据集用于评估真实工程场景上的语义分割算法,旨在为遥感领域的高分辨率像素级分类任务寻找一种良好的深度学习架构。

    数据集来源于中国地理条件调查和绘图项目,每幅图像都有地理条件调查的完整注释。数据集的平均大小约为4500×4500像素。EvLab-SS数据集包含11个大类,分别是背景、农田、花园、林地、草地、建筑、道路、构筑物、挖孔桩、沙漠和水域,目前包括由不同平台和传感器拍摄的60幅图像。

    该数据集包括35幅卫星图像,其中19幅由World-View-2卫星采集,5幅由GeoEye卫星采集,5幅由Quick Bird卫星采集,6幅由GF-2卫星采集。该数据集还有25幅航空图像,其中10幅图像的空间分辨率为0.25 m,15幅图像的空间分辨率为0.1 m。
    在这里插入图片描述

    地址:http://earthvisionlab.whu.edu.cn/zm/SemanticSegmentation/index.html

    5.6 DeepGlobe Land cover Classification challenge

    DeepGlobe Land Cover Classification Challenge是一个公共数据集,提供高分辨率亚米卫星图像,重点是农村地区。由于土地覆盖类型的多样性和注释的高密度,该数据集很具挑战性。该数据集共包含10146幅卫星图像,大小为20448×20448像素,分为训练/验证/测试集,每组图像为803/171/172幅(对应70%/15%/15%)。
    在这里插入图片描述

    地址:http://deepglobe.org/index.html
    https://competitions.codalab.org/competitions/18468

    链接:https://pan.baidu.com/s/1jiadeSAxbOKTdlTyDAyrlQ
    提取码:RSAI

    5.7 Aeroscapes

    空中语义分割数据集包括使用商业无人机从5到50 m高度范围内捕获的图像。该数据集为11个类提供了3269幅720 p图像和地表真实标签。
    在这里插入图片描述

    地址:https://github.com/ishann/aeroscapes

    链接:https://pan.baidu.com/s/1sqx1xEkDc5zUGqpDU6jo4w
    提取码:RSAI

    5.8 SEN12MS

    SEN12MS是由180748张相应的3种类型遥感数据组成的一个数据集,包括了Sentinel-1双极化SAR数据,Sentinel-2多光谱图像和MODIS土地覆盖图。其中Sentinel-1图像分辨率为20 m,Sentinel-2多光谱图像分辨率为10 m,波段数为13,MODIS的土地覆盖的图像分辨率为500 m。
    在这里插入图片描述

    地址:https://mediatum.ub.tum.de/1474000

    5.9 Zurich Summer Dataset

    该数据是从2002年8月从QuickBird收购瑞士苏黎世市获得的。QuickBird图像由4个通道(NIR-RGB)组成,分别是 锐化至GSD约0.62 cm的PAN分辨率。 我们手动注释了8种不同的城市和城市郊区类别:道路,建筑物,树木,草木,裸露的土壤,水,铁路和游泳池。 类样本的累积数量高度不平衡,以反映现实情况。 请注意,注释不是完美的,也不是超密集的(并非对每个像素都进行注释),并且可能还会出现一些错误。 我们通过联合选择超像素(SLIC)和绘制(徒手绘制)区域来进行注释,我们可以放心地分配对象类。
    在这里插入图片描述

    地址:https://sites.google.com/site/michelevolpiresearch/data/zurich-dataset

    链接:https://pan.baidu.com/s/1P8QQROYnONcK3thIhjgKzQ
    提取码:RSAI

    5.10 DLRSD

    DLRSD [1]是一个密集的标签数据集,可用于多标签任务,如遥感图像检索(RSIR)和分类,以及其他基于像素的任务,如语义分割(在遥感中也称为分类)。 DLRSD共有21个大类,每个类100个图像,与UC Merced存档相同。我们在UC Merced档案库中使用以下17类标签标记了每个图像的像素,即飞机,裸土,建筑物,汽车,丛林法院,码头,田野,草地,活动房屋,人行道,沙子,大海,船,坦克,树木和水。首先在多标签RSIR存档[2]中构造和定义这17个类别标签,其中UC Merced存档中的每个图像都提供了一组多个标签。在DLRSD的标记过程中,我们改进了一些我们认为通过视觉检查标记不正确的多标记[2],然后使用/引用了修订的多标记来手动标记每个图像的像素。因此,DLRSD是UC Merced存档特别是多标签RSIR存档的扩展。

    UC Merced档案库中某些图像的大小不完全如其说明的256 * 256像素。在标记像素之前,我们将这些图像的大小调整为256 * 256。
    在这里插入图片描述

    地址:https://sites.google.com/view/zhouwx/dataset#h.p_hQS2jYeaFpV0

    链接:https://pan.baidu.com/s/1Vhxrl7s9dHGZ3OH41VIPUw
    提取码:RSAI

    5.11 WHDLD

    WHDLD是一个密集的标签数据集,可用于多标签任务,例如遥感图像检索(RSIR)和分类,以及其他基于像素的任务,例如语义分割(在遥感中也称为分类)。 我们使用以下6个类别标签标记每个图像的像素,即建筑物,道路,人行道,植被,裸露的土壤和水。
    在这里插入图片描述

    地址:https://sites.google.com/view/zhouwx/dataset#h.p_hQS2jYeaFpV0

    链接:https://pan.baidu.com/s/1DUWkwjFxdtlMfVyvZsdUMw
    提取码:RSAI

    5.12 HD-Maps

    包含4中类型的遥感第五类型,street,parking lane,walking path,buildings,background
    在这里插入图片描述

    地址:https://www.dlr.de/eoc/en/desktopdefault.aspx/tabid-12760/22294_read-52773

    链接:https://pan.baidu.com/s/1QfC4SZmZP5P7sQiE6Uk2FA
    提取码:RSAI

    5.13 BDCI 2017

    2015年某地区的高分辨率遥感影像,包括基于该遥感影像目视解译出来的地表覆盖样本数据。中国南方某地区的高分辨率遥感影像。
    影像的空间分辨率为亚米级,光谱为可见光波段(R,G,B),已去除坐标信息;训练影像为train1.png、train2.png和train3.png;
    对应的标注数据为train1_labels_8bits.png、train2_labels_8bits.png和train3_labels_8bits.png。

    五类:植被(标记1)、建筑(标记2)、水体(标记3)、道路(标记4)以及其他(标记0)。其中,耕地、林地、草地均归为植被类。影像收集的时间跨度从4月到8月,地表的变化较大。部分耕地和林地处于收获或砍伐后的状态,均被划为植被类。
    在这里插入图片描述

    地址:https://www.datafountain.cn/competitions/270/datasets

    链接:https://pan.baidu.com/s/1mEOLuOsEsOO7YGK-0SnIbA
    提取码:RSAI

    5.14 Map Challenge

    在这里插入图片描述
    地址:https://www.crowdai.org/challenges/mapping-challenge

    链接:https://pan.baidu.com/s/16RaVoWA1LjeJa0kMr741Fw
    提取码:RSAI

    5.15 UAVid

    无人机数据,包含8类地物类型,图像尺寸为4096 * 2160 * 3 3840*22160 * 3 数量是300,包括:

    building,road,static car,tree,human,moving car,background clutter
    在这里插入图片描述

    地址:https://www.uavid.nl/

    链接:https://pan.baidu.com/s/1L8OAegePAHFzin6x6inQMw
    提取码:RSAI

    5.16 “华为・昇腾杯”AI+遥感影像

    在这里插入图片描述

    a.原始影像
    影像格式为tif,包含R、G、B三个波段,训练集影像尺寸为256 * 256像素,初赛测试集影像尺寸为256 * 256像素,复赛、决赛初步确定测试集尺寸可变。
    b.标签数据
    标签格式为单通道的png,每个像素的标签值由一个三位数表示,使用‘uint16’数据类型存储,该三位数包含了一级和二级两个类别信息,百位上的一个数字表示一级类别,十位和个位上的两个数字一起表示二级类别。
    一级类别共分为8类,一级类别及对应的百位上的数字如下表所示:

    一级类别 对应标签百位上的数字
    水体 1
    交通运输 2
    建筑 3
    耕地 4
    草地 5
    林地 6
    裸土 7
    其它 8

    二级类别共分为17类,二级类别及对应的十位、个位上的数字如下表所示:

    二级类别 对应标签十位及个位上的数字
    水体 01
    道路 02
    建筑物 03
    机场 04
    火车站 05
    光伏 06
    停车场 07
    操场 08
    普通耕地 09
    农业大棚 10
    自然草地 11
    绿地绿化 12
    自然林 13
    人工林 14
    自然裸土 15
    人为裸土 16
    其它 17

    地址:https://www.datafountain.cn/competitions/457/datasets

    5.17 遥感影像地块分割(CCF BDCI)

    在这里插入图片描述

    训练集图像文件名称:train.zip
    包含140,000张分辨率为2m/pixel,尺寸为256256的JPG图片,文件名称形如T000123.jpg
    训练集标注文件名称:annotation.zip
    包含和图像文件同等数量,尺寸为256
    256的PNG格式的单通道伪彩色标注图片,图片的文件名称与train.zip中的图片名称对应, 文件名称形如T000123.png,像素值与类别对应关系如表1所示:

    像素值 类别
    0 建筑
    1 耕地
    2 林地
    3 水体
    4 道路
    5 草地
    6 其他
    255 未标注区域

    其中,255代表了未标注区域,表示对应区域的所属类别并不确定,在评测中也不会考虑这部分区域。
    测试集A文件名称:testA.zip
    包含10,000张分辨率为2m/pixel,尺寸为256256的JPG图片,文件名称形如A000123.jpg
    测试集B文件名称:testB.zip
    包含20,000张分辨率为2m/pixel,尺寸为256
    256的JPG图片,文件名称形如B000123.jpg

    地址:https://www.datafountain.cn/competitions/475/datasets

    链接:https://pan.baidu.com/s/1okfqWl4uFaPi6BN6myNd8Q
    提取码:RSAI

    5.18 rscup

    在这里插入图片描述

    地址:http://rscup.bjxintong.com.cn/#/theme/3

    链接:https://pan.baidu.com/s/1HH9LbZ0WCKJF2r316vpgNA
    提取码:RSAI

    5.19 Segmantic Drone Dataset

    在这里插入图片描述

    地址:https://www.tugraz.at/index.php?id=22387

    5.20 2021全国数字生态创新大赛-智能算法赛

    数据为覆盖0.8m-2m分辨率的高分系列遥感多光谱影像,成像波段包括R、G、B、Nir波段,数据覆盖地貌包括:山地、丘陵地区、河湖(水库)、平原、城镇等等。感谢浙江大学环境与资源学院为本赛题提供数据支持
    (2)数据规格:4万+张遥感影像及对应地物分类标记样本,影像大小为256*256像素。
    初赛:16017张高分遥感影像和标注文件训练集,A榜测试集3000张测试数据,B榜测试集4366张测试数据。
    复赛:15904张高分遥感影像和标注文件,6000张测试数据。
    (3)训练测试数据说明:
    影像保存格式为tif文件,包括R、G、B、Nir四个波段,训练测试集影像尺寸均为256 * 256像素。标签数据格式为单通道的png,每个像素的标签值和地物要素类别对应关系如下:

    {
      1: "耕地",
      2: "林地",
      3: "草地",
      4: "道路",
      5: "城镇建设用地",
      6: "农村建设用地",
      7: "工业用地",
      8: "构筑物"
      9: "水域"
      10: "裸地"
     }
    

    在这里插入图片描述

    地址:https://tianchi.aliyun.com/competition/entrance/531860/information

    5.21 Slovenia 2017 Land Cover Classification Dataset

    The full dataset contains 940 EOPatches of the size 5000 x 5000 pixels at 10 m resolution.

    地址:http://eo-learn.sentinel-hub.com/

    5.22 Dstl Satellite Imagery Feature Detection

    国防科学技术实验室(DSTL),是英国国防部的执行机构,也是这次比赛的举办方。他们所提供的训练集里包含了25个1平方公里大小地区的高分辨率卫星图像,具体任务是通过算法进行识别10个不同类型的对象,分别是:

    1. 房屋和楼房;
    2. 混杂的人工建筑;
    3. 道路;
    4. 铁路;
    5. 树木;
    6. 农作物;
    7. 河流;
    8. 积水区;
    9. 大型车辆;
    10. 小轿车。
      在这里插入图片描述

    地址:https://www.kaggle.com/c/dstl-satellite-imagery-feature-detection

    链接:https://pan.baidu.com/s/1COPS-y7x4vSRKBFFArW8ew
    提取码:RSAI

    5.23 2019 年县域农业大脑AI挑战赛

    比赛数据共包括2部分,分为 train 文件夹和 test文件夹。train 文件夹中包含原始图片 image_n.png 和对应的标注作物类型图片 image_n_label,test 文件夹中只有原始图片。

    标注作物类型图片 image_n_label 是基于原始图像的真实标签,代表一张 unint8 单通道图像。每个像素点值表示原始图片 image_n.png 中对应位置所属类别,其中“烤烟”像素值 1,“玉米”像素值 2,“薏仁米”像素值 3,“人造建筑”像素值 4,其余所有位置视为“其他”像素值 0
    在这里插入图片描述

    地址:https://tianchi.aliyun.com/competition/entrance/231717/information

    6.其他

    6.1 SAID

    在这里插入图片描述

    地址:https://captain-whu.github.io/iSAID/index.html

    6.2 Agriculture-Vision

    用于农业模式语义分割的大规模航空农田图像数据集。从美国的3,432个农田中收集了94,986张高质量的航空图像,其中每张图像均由RGB和近红外(NIR)通道组成,分辨率高达每个像素10厘米。该数据集包含六种注释:云影,双株,播种机跳过,死水,水路和杂草丛集。这些类型的田间异常对农田的潜在产量有很大的影响,因此准确定位它们非常重要。在农业视觉数据集中,由于模式之间可能存在重叠,因此这六个模式分别作为二进制掩码存储。用户可以自由决定如何使用这些注释。

    每个场图像的文件名格式为(场ID)_(x1)-(y1)-(x2)-(y2)。(jpg / png)。每个字段ID唯一标识要从中裁剪图像的农田,并且(x1,y1,x2,y2)是一个四元组,指示图像被裁剪的位置。有关如何构建数据集的更多详细信息,请参阅我们的论文。
    在这里插入图片描述

    地址:https://www.agriculture-vision.com/dataset

    6.3 HistAerialDataset

    HistAerial数据集由代表9平方公里区域的灰度图像构建而成(每幅图像每6k像素约6k)。 这些图像是采集的1970年至1990年在法国全国范围内使用光学相机安装在飞机系统上。
    提供了对应于粗略地面占用标签的分类:果园,葡萄园,城市,森林,水,作物和土地。
    在这里插入图片描述

    6.4 第二届中国“高分杯”美丽乡村大赛

    原始多光谱图像:

    1、多光谱图像一张(tif格式),8通道,覆盖面积850公里*300公里

    训练数据集:

    训练数据集是原始多光谱图像中农作物区块的部分标注数据。

    标注样本点数据,给定玉米、大豆和水稻3个类别农作物对应区块的中心点像素位置(x,y)列表,以及对应中心点对应的区块半径3

    样例:FID,Id,作物,半径,备注,x,y

    0,1,玉米,3, ,12500.7001953,-3286.5600586

    1865,1866,大豆,3, ,5941.6601563,-6966.2797852

    2086,2087,水稻,3, ,9165.4697266,-14989.2998047

    1、(x,y)为tif数据格式的坐标系;(x,y)取值为小数,选手可以四舍五入取整获得对应的像素点位置;选手可以从卫星图片中取出对应图片778作为训练样本;某些农作物区块对应的面积半径可能大于3,选手可以用算法扩展农作物区块面积,作为训练样本;

    2、多光谱图像由多张高分图像拼接而成,会有光照等影响因素使得同类农作物区块的颜色可能不同,此处考验的是选手所训练模型的泛化能力。

    数据对应关系:RasterXSize对应的是x坐标,RasterYSize对应的是y坐标,x坐标步长是1.0,y坐标步长是-1.0,左上角坐标是(0.0, 1e-07)
    在这里插入图片描述

    地址:https://dianshi.bce.baidu.com/competition/28/rule

    6.5 滑坡

    该数据集由卫星光学图像,滑坡边界的形状文件和数字高程模型组成。 该数据集中的所有图像(即770个滑坡图像(红色点)和2003年非滑坡图像)均从2018年5月至2018年8月捕获的TripleSat卫星图像中裁剪而来。
    在这里插入图片描述
    地址:http://study.rsgis.whu.edu.cn/pages/download

    展开全文
  • 遥感图像语义分割各公开数据集

    千次阅读 2020-12-03 20:41:54
    转载于:IMARS 遥感大数据智能挖掘与分析 语义分割在自然数据集的分割效果不断进步,有研究逐步应用到了遥感领域,尤其是高分辨... 本期对现有的10个遥感语义分割数据集进行总结,并附上下载链接,供大家对自己的算法


    参考:IMARS 遥感大数据智能挖掘与分析

    现有的10个遥感语义分割数据集进行总结,并附上下载链接(有部分连接失效)。

    1. Gaofen Image Dataset(GID)

    Gaofen Image Dataset(GID)是一个用于土地利用和土地覆盖(LULC)分类的大型数据集。它包含来自中国60多个不同城市的150幅高质量高分二号(GF-2)图像,这些图像覆盖的地理区域超过了5万km²。GID图像具有较高的类内多样性和较低的类间可分离性。GF-2是高清晰度地球观测系统(HDEOS)的第二颗卫星。GF-2卫星包括了空间分辨率为1 m的全色图像和4 m的多光谱图像,图像大小为6908×7300像素。多光谱提供了蓝色、绿色、红色和近红外波段的图像。自2014年启动以来,GF-2已被用于土地调查、环境监测、作物估算、建设规划等重要应用。

    下载地址链接

    参考文献:

    Tong X Y, Xia G S, Lu Q, et al. Learning Transferable Deep Models for      Land-Use Classification with High-Resolution Remote Sensing Images[J].    arXiv preprint arXiv:1807.05713, 2018.

    2. ISPRS Test Project on Urban Classification and 3D Building Reconstruction—2D SemanticLabeling Contest

    ISPRS提供了城市分类和三维建筑重建测试项目的两个最先进的机载图像数据集。该数据集采用了由高分辨率正交照片和相应的密集图像匹配技术产生的数字地表模型(DSM)。这两个数据集区域都涵盖了城市场景。Vaihingen是一个相对较小的村庄,有许多独立的建筑和小的多层建筑;Postdam是一个典型的历史城市,有着大的建筑群、狭窄的街道和密集的聚落结构。每个数据集已手动分类为6个最常见的土地覆盖类别。

    ①不透水面 (RGB: 255, 255, 255)

    ②建筑物(RGB: 0, 0, 255)

    ③低矮植被 (RGB: 0, 255, 255)

    ④树木 (RGB: 0, 255, 0)

    ⑤汽车(RGB: 255, 255, 0)

    ⑥背景 (RGB: 255, 0, 0)

    背景类包括水体和与其他已定义类别不同的物体(例如容器、网球场、游泳池),这些物体通常属于城市场景中的不感兴趣的语义对象。

    下载地址链接

    • Vaihingen

    该数据集包含33幅不同大小的遥感图像,每幅图像都是从一个更大的顶层正射影像图片提取的。顶层影像和DSM的空间分辨率为9 cm。遥感图像格式为8位TIFF文件,由近红外、红色和绿色3个波段组成。DSM是单波段的TIFF文件,灰度等级(对应于DSM高度)为32位浮点值编码。

    • Postdam

    与Vaihingen区域类似,该数据集也是由3个波段的遥感TIFF文件和单波段的DSM组成。其每幅遥感图像区域覆盖大小是相同的。这样,遥感图像和DSM是在同一个参考系统上定义的(UTM WGS84)。每幅图像都有一个仿射变换文件,以便在需要时将图像重新分解为更小的图片。

    除了DSM,数据集还提供了归一化DSM,即在地面过滤之后,每个像素的地面高度被移除,从而产生了高于地形的高度表示。这些数据是使用一些全自动过滤工作流产生的,没有人工质量控制。因此,不保证这里没有错误的数据,这是为了帮助研究人员使用高度数据,而不使用绝对的DSM。

    3. 2017 IEEE GRSS Data Fusion Contest

    2017年IEEE GRSS数据融合竞赛采用分类作为主体。要执行的任务是对各种城市环境中的土地使用(即针对2012年地方气候区(LCZ))进行分类。竞赛选择了几个城市来测试LCZ预测在世界各地推广的能力。输入数据为多时相、多源和多模态,包括图像和语义层。

    数据集由4个部分组成。

    美国地质调查局提供的的地面卫星数据:包含可见光、短波和长波红外在内的8个多光谱波段,并以100 m分辨率重采样的;

    哨兵2图像:该图像空间分辨率为100 m,拥有9个多光谱波段即可见光、近红外和短红外波长(包含修改的哥白尼数据2016);

    辅助数据:开放街道图(OSM)层,具有土地利用信息:建筑、自然、道路和其他土地利用区域。其中还为建筑和土地使用区域提供分辨率为20 m的OSM层的栅格地图,可与卫星图像叠加。

    此外,对于选取的城市,还提供了城市几个地区的各种LCZ类的地面真实标签。标签为100 m分辨率的栅格图像,也可叠加到卫星图像上。

    下载地址链接

    4. Aerial Image Segmentation Dataset

    该航空图像分为来自谷歌地图的航空遥感图像和来自OpenStreetMap的像素级的建筑、道路和背景标签。覆盖区域为柏林、芝加哥、巴黎、波茨坦和苏黎世。地物真实图像包括一张来自谷歌地图的东京地区航空图像,以及手动生成的、像素级的建筑、道路和背景标签。像素级标签以RGB顺序作为PNG图像提供,标记为建筑物、道路和背景的像素由RGB颜色[255,0,0]、[0,0,255]和[255,255,255]表示。

    下载地址链接

    5. 2018 IEEE GRSS Data Fusion Contest

    数据是由NCALM于2017年2月16日在16:31至18:18 GMT之间从国家机载激光测绘中心获得的。在这场比赛中使用数据收集的传感器包括:有3个不同波段的激光雷达传感器OPTech TITAM M(14sen/con340)、具有70 mm焦距的高分辨率的彩色成像仪Dimac ULTRALIGHT+、高光谱成像仪ITRES CASI 1500。多光谱激光雷达点云数据波段在1550 nm,1064 nm和532 nm。高光谱数据覆盖范围为380—1050 nm,共有48个波段,空间分辨率为1 m。高分辨率RGB遥感图像的空间分辨率为5 cm,被分割成几个单独的图片。

    下载地址链接

    6. EvLab-SS Dataset

    EvLab-SS数据集用于评估真实工程场景上的语义分割算法,旨在为遥感领域的高分辨率像素级分类任务寻找一种良好的深度学习架构。

    数据集来源于中国地理条件调查和绘图项目,每幅图像都有地理条件调查的完整注释。数据集的平均大小约为4500×4500像素。EvLab-SS数据集包含11个大类,分别是背景、农田、花园、林地、草地、建筑、道路、构筑物、挖孔桩、沙漠和水域,目前包括由不同平台和传感器拍摄的60幅图像。

    该数据集包括35幅卫星图像,其中19幅由World-View-2卫星采集,5幅由GeoEye卫星采集,5幅由Quick Bird卫星采集,6幅由GF-2卫星采集。该数据集还有25幅航空图像,其中10幅图像的空间分辨率为0.25 m,15幅图像的空间分辨率为0.1 m。

    下载地址链接

    参考文献:

    Zhang M, Hu X, Zhao L, et al.  Learning dual multi-scale manifold ranking for semantic segmentation of  high-resolution images[J]. Remote Sensing, 2017, 9(5): 500

    7. DeepGlobe Land Cover Classification Challenge

    DeepGlobe Land Cover Classification Challenge是一个公共数据集,提供高分辨率亚米卫星图像,重点是农村地区。由于土地覆盖类型的多样性和注释的高密度,该数据集很具挑战性。该数据集共包含10146幅卫星图像,大小为20448×20448像素,分为训练/验证/测试集,每组图像为803/171/172幅(对应70%/15%/15%)。

    下载地址链接1
    下载地址链接2

    8. 38-Cloud dataset

    该数据集包含38幅Landsat 8 场景图像及其手动提取的像素级地物真实标签,用于云检测。这些场景的整个图像被裁剪成384×384个斑块,以适合于基于深度学习的语义分割算法。数据集被划分为8400个斑块进行训练,9201个补丁进行测试。每幅图像有4个相应的波段,分别是红色(波段4)、绿色(波段3)、蓝色(波段2)和近红外(波段5)。

    下载地址链接

    参考文献

    Mohajerani S, Krammer T A, Saeedi P. Cloud Detection Algorithm for Remote Sensing Images Using Fully Convolutional Neural Networks[J]. arXiv preprint      arXiv:1810.05782, 2018

    Mohajerani S, Saeedi P. Cloud-Net: An end-to-end Cloud Detection Algorithm for Landsat 8 Imagery[J]. arXiv preprint arXiv:1901.10077, 2019

    9. Aeroscapes

    空中语义分割数据集包括使用商业无人机从5到50 m高度范围内捕获的图像。该数据集为11个类提供了3269幅720 p图像和地表真实标签。

    下载地址链接

    参考文献:

    Nigam I, Huang C, Ramanan D. Ensemble knowledge transfer for semantic segmentation[C]//2018 IEEE Winter Conference on Applications  of Computer Vision (WACV). IEEE, 2018: 1499-1508

    10. SEN12MS

    SEN12MS是由180748张相应的3种类型遥感数据组成的一个数据集,包括了Sentinel-1双极化SAR数据,Sentinel-2多光谱图像和MODIS土地覆盖图。其中Sentinel-1图像分辨率为20 m,Sentinel-2多光谱图像分辨率为10 m,波段数为13,MODIS的土地覆盖的图像分辨率为500 m。

    下载地址链接

    展开全文
  • 【Keras】基于SegNet和U-Net的遥感图像语义分割

    万次阅读 多人点赞 2018-03-03 19:51:49
    这两周数据挖掘课期末project我们组选的课题也是遥感图像的语义分割,所以刚好又把前段时间做的成果重新整理和加强了一下,故写了这篇文章,记录一下用深度学习做遥感图像语义分割的完整流程以及一些好的思路和技巧...

    from:【Keras】基于SegNet和U-Net的遥感图像语义分割

    上两个月参加了个比赛,做的是对遥感高清图像做语义分割,美其名曰“天空之眼”。这两周数据挖掘课期末project我们组选的课题也是遥感图像的语义分割,所以刚好又把前段时间做的成果重新整理和加强了一下,故写了这篇文章,记录一下用深度学习做遥感图像语义分割的完整流程以及一些好的思路和技巧。

     

    数据集

    首先介绍一下数据,我们这次采用的数据集是CCF大数据比赛提供的数据(2015年中国南方某城市的高清遥感图像),这是一个小数据集,里面包含了5张带标注的大尺寸RGB遥感图像(尺寸范围从3000×3000到6000×6000),里面一共标注了4类物体,植被(标记1)、建筑(标记2)、水体(标记3)、道路(标记4)以及其他(标记0)。其中,耕地、林地、草地均归为植被类,为了更好地观察标注情况,我们将其中三幅训练图片可视化如下:蓝色-水体,黄色-房屋,绿色-植被,棕色-马路。更多数据介绍可以参看这里

    现在说一说我们的数据处理的步骤。我们现在拥有的是5张大尺寸的遥感图像,我们不能直接把这些图像送入网络进行训练,因为内存承受不了而且他们的尺寸也各不相同。因此,我们首先将他们做随机切割,即随机生成x,y坐标,然后抠出该坐标下256*256的小图,并做以下数据增强操作:

    1. 原图和label图都需要旋转:90度,180度,270度
    2. 原图和label图都需要做沿y轴的镜像操作
    3. 原图做模糊操作
    4. 原图做光照调整操作
    5. 原图做增加噪声操作(高斯噪声,椒盐噪声)

    这里我没有采用Keras自带的数据增广函数,而是自己使用opencv编写了相应的增强函数。

    img_w = 256  
    img_h = 256  
    
    image_sets = ['1.png','2.png','3.png','4.png','5.png']
    
    def gamma_transform(img, gamma):
        gamma_table = [np.power(x / 255.0, gamma) * 255.0 for x in range(256)]
        gamma_table = np.round(np.array(gamma_table)).astype(np.uint8)
        return cv2.LUT(img, gamma_table)
    
    def random_gamma_transform(img, gamma_vari):
        log_gamma_vari = np.log(gamma_vari)
        alpha = np.random.uniform(-log_gamma_vari, log_gamma_vari)
        gamma = np.exp(alpha)
        return gamma_transform(img, gamma)
        
    
    def rotate(xb,yb,angle):
        M_rotate = cv2.getRotationMatrix2D((img_w/2, img_h/2), angle, 1)
        xb = cv2.warpAffine(xb, M_rotate, (img_w, img_h))
        yb = cv2.warpAffine(yb, M_rotate, (img_w, img_h))
        return xb,yb
        
    def blur(img):
        img = cv2.blur(img, (3, 3));
        return img
    
    def add_noise(img):
        for i in range(200): #添加点噪声
            temp_x = np.random.randint(0,img.shape[0])
            temp_y = np.random.randint(0,img.shape[1])
            img[temp_x][temp_y] = 255
        return img
        
        
    def data_augment(xb,yb):
        if np.random.random() < 0.25:
            xb,yb = rotate(xb,yb,90)
        if np.random.random() < 0.25:
            xb,yb = rotate(xb,yb,180)
        if np.random.random() < 0.25:
            xb,yb = rotate(xb,yb,270)
        if np.random.random() < 0.25:
            xb = cv2.flip(xb, 1)  # flipcode > 0:沿y轴翻转
            yb = cv2.flip(yb, 1)
            
        if np.random.random() < 0.25:
            xb = random_gamma_transform(xb,1.0)
            
        if np.random.random() < 0.25:
            xb = blur(xb)
        
        if np.random.random() < 0.2:
            xb = add_noise(xb)
            
        return xb,yb
    
    def creat_dataset(image_num = 100000, mode = 'original'):
        print('creating dataset...')
        image_each = image_num / len(image_sets)
        g_count = 0
        for i in tqdm(range(len(image_sets))):
            count = 0
            src_img = cv2.imread('./data/src/' + image_sets[i])  # 3 channels
            label_img = cv2.imread('./data/label/' + image_sets[i],cv2.IMREAD_GRAYSCALE)  # single channel
            X_height,X_width,_ = src_img.shape
            while count < image_each:
                random_width = random.randint(0, X_width - img_w - 1)
                random_height = random.randint(0, X_height - img_h - 1)
                src_roi = src_img[random_height: random_height + img_h, random_width: random_width + img_w,:]
                label_roi = label_img[random_height: random_height + img_h, random_width: random_width + img_w]
                if mode == 'augment':
                    src_roi,label_roi = data_augment(src_roi,label_roi)
                
                visualize = np.zeros((256,256)).astype(np.uint8)
                visualize = label_roi *50
                
                cv2.imwrite(('./aug/train/visualize/%d.png' % g_count),visualize)
                cv2.imwrite(('./aug/train/src/%d.png' % g_count),src_roi)
                cv2.imwrite(('./aug/train/label/%d.png' % g_count),label_roi)
                count += 1 
                g_count += 1

    经过上面数据增强操作后,我们得到了较大的训练集:100000张256*256的图片。

    卷积神经网络

    面对这类图像语义分割的任务,我们可以选取的经典网络有很多,比如FCN,U-Net,SegNet,DeepLab,RefineNet,Mask Rcnn,Hed Net这些都是非常经典而且在很多比赛都广泛采用的网络架构。所以我们就可以从中选取一两个经典网络作为我们这个分割任务的解决方案。我们根据我们小组的情况,选取了U-Net和SegNet作为我们的主体网络进行实验。

    SegNet

    SegNet已经出来好几年了,这不是一个最新、效果最好的语义分割网络,但是它胜在网络结构清晰易懂,训练快速坑少,所以我们也采取它来做同样的任务。SegNet网络结构是编码器-解码器的结构,非常优雅,值得注意的是,SegNet做语义分割时通常在末端加入CRF模块做后处理,旨在进一步精修边缘的分割结果。有兴趣深究的可以看看这里

    现在讲解代码部分,首先我们先定义好SegNet的网络结构。

    def SegNet():  
        model = Sequential()  
        #encoder  
        model.add(Conv2D(64,(3,3),strides=(1,1),input_shape=(3,img_w,img_h),padding='same',activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(64,(3,3),strides=(1,1),padding='same',activation='relu'))  
        model.add(BatchNormalization())  
        model.add(MaxPooling2D(pool_size=(2,2)))  
        #(128,128)  
        model.add(Conv2D(128, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(128, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(MaxPooling2D(pool_size=(2, 2)))  
        #(64,64)  
        model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(MaxPooling2D(pool_size=(2, 2)))  
        #(32,32)  
        model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(MaxPooling2D(pool_size=(2, 2)))  
        #(16,16)  
        model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(MaxPooling2D(pool_size=(2, 2)))  
        #(8,8)  
        #decoder  
        model.add(UpSampling2D(size=(2,2)))  
        #(16,16)  
        model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(UpSampling2D(size=(2, 2)))  
        #(32,32)  
        model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(UpSampling2D(size=(2, 2)))  
        #(64,64)  
        model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(UpSampling2D(size=(2, 2)))  
        #(128,128)  
        model.add(Conv2D(128, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(128, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(UpSampling2D(size=(2, 2)))  
        #(256,256)  
        model.add(Conv2D(64, (3, 3), strides=(1, 1), input_shape=(3,img_w, img_h), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(64, (3, 3), strides=(1, 1), padding='same', activation='relu'))  
        model.add(BatchNormalization())  
        model.add(Conv2D(n_label, (1, 1), strides=(1, 1), padding='same'))  
        model.add(Reshape((n_label,img_w*img_h)))  
        #axis=1和axis=2互换位置,等同于np.swapaxes(layer,1,2)  
        model.add(Permute((2,1)))  
        model.add(Activation('softmax'))  
        model.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])  
        model.summary()  
        return model  

    然后需要读入数据集。这里我们选择的验证集大小是训练集的0.25。

    def get_train_val(val_rate = 0.25):
        train_url = []    
        train_set = []
        val_set  = []
        for pic in os.listdir(filepath + 'src'):
            train_url.append(pic)
        random.shuffle(train_url)
        total_num = len(train_url)
        val_num = int(val_rate * total_num)
        for i in range(len(train_url)):
            if i < val_num:
                val_set.append(train_url[i]) 
            else:
                train_set.append(train_url[i])
        return train_set,val_set
        
    # data for training  
    def generateData(batch_size,data=[]):  
        #print 'generateData...'
        while True:  
            train_data = []  
            train_label = []  
            batch = 0  
            for i in (range(len(data))): 
                url = data[i]
                batch += 1 
                #print (filepath + 'src/' + url)
                #img = load_img(filepath + 'src/' + url, target_size=(img_w, img_h))  
                img = load_img(filepath + 'src/' + url)
                img = img_to_array(img) 
                # print img
                # print img.shape  
                train_data.append(img)  
                #label = load_img(filepath + 'label/' + url, target_size=(img_w, img_h),grayscale=True)
                label = load_img(filepath + 'label/' + url, grayscale=True)
                label = img_to_array(label).reshape((img_w * img_h,))  
                # print label.shape  
                train_label.append(label)  
                if batch % batch_size==0: 
                    #print 'get enough bacth!\n'
                    train_data = np.array(train_data)  
                    train_label = np.array(train_label).flatten()  
                    train_label = labelencoder.transform(train_label)  
                    train_label = to_categorical(train_label, num_classes=n_label)  
                    train_label = train_label.reshape((batch_size,img_w * img_h,n_label))  
                    yield (train_data,train_label)  
                    train_data = []  
                    train_label = []  
                    batch = 0  
     
    # data for validation 
    def generateValidData(batch_size,data=[]):  
        #print 'generateValidData...'
        while True:  
            valid_data = []  
            valid_label = []  
            batch = 0  
            for i in (range(len(data))):  
                url = data[i]
                batch += 1  
                #img = load_img(filepath + 'src/' + url, target_size=(img_w, img_h))
                img = load_img(filepath + 'src/' + url)
                #print img
                #print (filepath + 'src/' + url)
                img = img_to_array(img)  
                # print img.shape  
                valid_data.append(img)  
                #label = load_img(filepath + 'label/' + url, target_size=(img_w, img_h),grayscale=True)
                label = load_img(filepath + 'label/' + url, grayscale=True)
                label = img_to_array(label).reshape((img_w * img_h,))  
                # print label.shape  
                valid_label.append(label)  
                if batch % batch_size==0:  
                    valid_data = np.array(valid_data)  
                    valid_label = np.array(valid_label).flatten()  
                    valid_label = labelencoder.transform(valid_label)  
                    valid_label = to_categorical(valid_label, num_classes=n_label)  
                    valid_label = valid_label.reshape((batch_size,img_w * img_h,n_label))  
                    yield (valid_data,valid_label)  
                    valid_data = []  
                    valid_label = []  
                    batch = 0  

    然后定义一下我们训练的过程,在这个任务上,我们把batch size定为16,epoch定为30,每次都存储最佳model(save_best_only=True),并且在训练结束时绘制loss/acc曲线,并存储起来。

    def train(args): 
        EPOCHS = 30
        BS = 16
        model = SegNet()  
        modelcheck = ModelCheckpoint(args['model'],monitor='val_acc',save_best_only=True,mode='max')  
        callable = [modelcheck]  
        train_set,val_set = get_train_val()
        train_numb = len(train_set)  
        valid_numb = len(val_set)  
        print ("the number of train data is",train_numb)  
        print ("the number of val data is",valid_numb)
        H = model.fit_generator(generator=generateData(BS,train_set),steps_per_epoch=train_numb//BS,epochs=EPOCHS,verbose=1,  
                        validation_data=generateValidData(BS,val_set),validation_steps=valid_numb//BS,callbacks=callable,max_q_size=1)  
    
        # plot the training loss and accuracy
        plt.style.use("ggplot")
        plt.figure()
        N = EPOCHS
        plt.plot(np.arange(0, N), H.history["loss"], label="train_loss")
        plt.plot(np.arange(0, N), H.history["val_loss"], label="val_loss")
        plt.plot(np.arange(0, N), H.history["acc"], label="train_acc")
        plt.plot(np.arange(0, N), H.history["val_acc"], label="val_acc")
        plt.title("Training Loss and Accuracy on SegNet Satellite Seg")
        plt.xlabel("Epoch #")
        plt.ylabel("Loss/Accuracy")
        plt.legend(loc="lower left")
        plt.savefig(args["plot"])

    然后开始漫长的训练,训练时间接近3天,绘制出的loss/acc图如下:

    训练loss降到0.1左右,acc可以去到0.9,但是验证集的loss和acc都没那么好,貌似存在点问题。

    先不管了,先看看预测结果吧。

    这里需要思考一下怎么预测整张遥感图像。我们知道,我们训练模型时选择的图片输入是256×256,所以我们预测时也要采用256×256的图片尺寸送进模型预测。现在我们要考虑一个问题,我们该怎么将这些预测好的小图重新拼接成一个大图呢?这里给出一个最基础的方案:先给大图做padding 0操作,得到一副padding过的大图,同时我们也生成一个与该图一样大的全0图A,把图像的尺寸补齐为256的倍数,然后以256为步长切割大图,依次将小图送进模型预测,预测好的小图则放在A的相应位置上,依次进行,最终得到预测好的整张大图(即A),再做图像切割,切割成原先图片的尺寸,完成整个预测流程。

    def predict(args):
        # load the trained convolutional neural network
        print("[INFO] loading network...")
        model = load_model(args["model"])
        stride = args['stride']
        for n in range(len(TEST_SET)):
            path = TEST_SET[n]
            #load the image
            image = cv2.imread('./test/' + path)
            # pre-process the image for classification
            #image = image.astype("float") / 255.0
            #image = img_to_array(image)
            h,w,_ = image.shape
            padding_h = (h//stride + 1) * stride 
            padding_w = (w//stride + 1) * stride
            padding_img = np.zeros((padding_h,padding_w,3),dtype=np.uint8)
            padding_img[0:h,0:w,:] = image[:,:,:]
            padding_img = padding_img.astype("float") / 255.0
            padding_img = img_to_array(padding_img)
            print 'src:',padding_img.shape
            mask_whole = np.zeros((padding_h,padding_w),dtype=np.uint8)
            for i in range(padding_h//stride):
                for j in range(padding_w//stride):
                    crop = padding_img[:3,i*stride:i*stride+image_size,j*stride:j*stride+image_size]
                    _,ch,cw = crop.shape
                    if ch != 256 or cw != 256:
                        print 'invalid size!'
                        continue
                        
                    crop = np.expand_dims(crop, axis=0)
                    #print 'crop:',crop.shape
                    pred = model.predict_classes(crop,verbose=2)  
                    pred = labelencoder.inverse_transform(pred[0])  
                    #print (np.unique(pred))  
                    pred = pred.reshape((256,256)).astype(np.uint8)
                    #print 'pred:',pred.shape
                    mask_whole[i*stride:i*stride+image_size,j*stride:j*stride+image_size] = pred[:,:]
    
            
            cv2.imwrite('./predict/pre'+str(n+1)+'.png',mask_whole[0:h,0:w])

    预测的效果图如下:

    一眼看去,效果真的不错,但是仔细看一下,就会发现有个很大的问题:拼接痕迹过于明显了!那怎么解决这类边缘问题呢?很直接的想法就是缩小切割时的滑动步伐,比如我们把切割步伐改为128,那么拼接时就会有一般的图像发生重叠,这样做可以尽可能地减少拼接痕迹。

    U-Net

    对于这个语义分割任务,我们毫不犹豫地选择了U-Net作为我们的方案,原因很简单,我们参考很多类似的遥感图像分割比赛的资料,绝大多数获奖的选手使用的都是U-Net模型。在这么多的好评下,我们选择U-Net也就毫无疑问了。

    U-Net有很多优点,最大卖点就是它可以在小数据集上也能train出一个好的模型,这个优点对于我们这个任务来说真的非常适合。而且,U-Net在训练速度上也是非常快的,这对于需要短时间就得出结果的期末project来说也是非常合适。U-Net在网络架构上还是非常优雅的,整个呈现U形,故起名U-Net。这里不打算详细介绍U-Net结构,有兴趣的深究的可以看看论文。

    现在开始谈谈代码细节。首先我们定义一下U-Net的网络结构,这里用的deep learning框架还是Keras。

    注意到,我们这里训练的模型是一个多分类模型,其实更好的做法是,训练一个二分类模型(使用二分类的标签),对每一类物体进行预测,得到4张预测图,再做预测图叠加,合并成一张完整的包含4类的预测图,这个策略在效果上肯定好于一个直接4分类的模型。所以,U-Net这边我们采取的思路就是对于每一类的分类都训练一个二分类模型,最后再将每一类的预测结果组合成一个四分类的结果。

    定义U-Net结构,注意了,这里的loss function我们选了binary_crossentropy,因为我们要训练的是二分类模型。

    def unet():
        inputs = Input((3, img_w, img_h))
    
        conv1 = Conv2D(32, (3, 3), activation="relu", padding="same")(inputs)
        conv1 = Conv2D(32, (3, 3), activation="relu", padding="same")(conv1)
        pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
    
        conv2 = Conv2D(64, (3, 3), activation="relu", padding="same")(pool1)
        conv2 = Conv2D(64, (3, 3), activation="relu", padding="same")(conv2)
        pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
    
        conv3 = Conv2D(128, (3, 3), activation="relu", padding="same")(pool2)
        conv3 = Conv2D(128, (3, 3), activation="relu", padding="same")(conv3)
        pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)
    
        conv4 = Conv2D(256, (3, 3), activation="relu", padding="same")(pool3)
        conv4 = Conv2D(256, (3, 3), activation="relu", padding="same")(conv4)
        pool4 = MaxPooling2D(pool_size=(2, 2))(conv4)
    
        conv5 = Conv2D(512, (3, 3), activation="relu", padding="same")(pool4)
        conv5 = Conv2D(512, (3, 3), activation="relu", padding="same")(conv5)
    
        up6 = concatenate([UpSampling2D(size=(2, 2))(conv5), conv4], axis=1)
        conv6 = Conv2D(256, (3, 3), activation="relu", padding="same")(up6)
        conv6 = Conv2D(256, (3, 3), activation="relu", padding="same")(conv6)
    
        up7 = concatenate([UpSampling2D(size=(2, 2))(conv6), conv3], axis=1)
        conv7 = Conv2D(128, (3, 3), activation="relu", padding="same")(up7)
        conv7 = Conv2D(128, (3, 3), activation="relu", padding="same")(conv7)
    
        up8 = concatenate([UpSampling2D(size=(2, 2))(conv7), conv2], axis=1)
        conv8 = Conv2D(64, (3, 3), activation="relu", padding="same")(up8)
        conv8 = Conv2D(64, (3, 3), activation="relu", padding="same")(conv8)
    
        up9 = concatenate([UpSampling2D(size=(2, 2))(conv8), conv1], axis=1)
        conv9 = Conv2D(32, (3, 3), activation="relu", padding="same")(up9)
        conv9 = Conv2D(32, (3, 3), activation="relu", padding="same")(conv9)
    
        conv10 = Conv2D(n_label, (1, 1), activation="sigmoid")(conv9)
        #conv10 = Conv2D(n_label, (1, 1), activation="softmax")(conv9)
    
        model = Model(inputs=inputs, outputs=conv10)
        model.compile(optimizer='Adam', loss='binary_crossentropy', metrics=['accuracy'])
        return model
    

    读取数据的组织方式有一些改动。

    # data for training  
    def generateData(batch_size,data=[]):  
        #print 'generateData...'
        while True:  
            train_data = []  
            train_label = []  
            batch = 0  
            for i in (range(len(data))): 
                url = data[i]
                batch += 1 
                img = load_img(filepath + 'src/' + url)
                img = img_to_array(img) 
                train_data.append(img)  
                label = load_img(filepath + 'label/' + url, grayscale=True) 
                label = img_to_array(label)
                #print label.shape  
                train_label.append(label)  
                if batch % batch_size==0: 
                    #print 'get enough bacth!\n'
                    train_data = np.array(train_data)  
                    train_label = np.array(train_label)  
    
                    yield (train_data,train_label)  
                    train_data = []  
                    train_label = []  
                    batch = 0  
     
    # data for validation 
    def generateValidData(batch_size,data=[]):  
        #print 'generateValidData...'
        while True:  
            valid_data = []  
            valid_label = []  
            batch = 0  
            for i in (range(len(data))):  
                url = data[i]
                batch += 1  
                img = load_img(filepath + 'src/' + url)
                #print img
                img = img_to_array(img)  
                # print img.shape  
                valid_data.append(img)  
                label = load_img(filepath + 'label/' + url, grayscale=True)
                valid_label.append(label)  
                if batch % batch_size==0:  
                    valid_data = np.array(valid_data)  
                    valid_label = np.array(valid_label)  
                    yield (valid_data,valid_label)  
                    valid_data = []  
                    valid_label = []  
                    batch = 0  

    训练:指定输出model名字和训练集位置

    python unet.py --model unet_buildings20.h5 --data ./unet_train/buildings/

    预测单张遥感图像时我们分别使用4个模型做预测,那我们就会得到4张mask(比如下图就是我们用训练好的buildings模型预测的结果),我们现在要将这4张mask合并成1张,那么怎么合并会比较好呢?我思路是,通过观察每一类的预测结果,我们可以从直观上知道哪些类的预测比较准确,那么我们就可以给这些mask图排优先级了,比如:priority:building>water>road>vegetation,那么当遇到一个像素点,4个mask图都说是属于自己类别的标签时,我们就可以根据先前定义好的优先级,把该像素的标签定为优先级最高的标签。代码思路可以参照下面的代码:

    def combind_all_mask():
        for mask_num in tqdm(range(3)):
            if mask_num == 0:
                final_mask = np.zeros((5142,5664),np.uint8)#生成一个全黑全0图像,图片尺寸与原图相同
            elif mask_num == 1:
                final_mask = np.zeros((2470,4011),np.uint8)
            elif mask_num == 2:
                final_mask = np.zeros((6116,3356),np.uint8)
            #final_mask = cv2.imread('final_1_8bits_predict.png',0)
            
            if mask_num == 0:
                mask_pool = mask1_pool
            elif mask_num == 1:
                mask_pool = mask2_pool
            elif mask_num == 2:
                mask_pool = mask3_pool
            final_name = img_sets[mask_num]
            for idx,name in enumerate(mask_pool):
                img = cv2.imread('./predict_mask/'+name,0)
                height,width = img.shape
                label_value = idx+1  #coressponding labels value
                for i in tqdm(range(height)):    #priority:building>water>road>vegetation
                    for j in range(width):
                        if img[i,j] == 255:
                            if label_value == 2:
                                final_mask[i,j] = label_value
                            elif label_value == 3 and final_mask[i,j] != 2:
                                final_mask[i,j] = label_value
                            elif label_value == 4 and final_mask[i,j] != 2 and final_mask[i,j] != 3:
                                final_mask[i,j] = label_value
                            elif label_value == 1 and final_mask[i,j] == 0:
                                final_mask[i,j] = label_value
                            
            cv2.imwrite('./final_result/'+final_name,final_mask)           
                    
                    
    print 'combinding mask...'
    combind_all_mask()            

    模型融合

    集成学习的方法在这类比赛中经常使用,要想获得好成绩集成学习必须做得好。在这里简单谈谈思路,我们使用了两个模型,我们模型也会采取不同参数去训练和预测,那么我们就会得到很多预测MASK图,此时 我们可以采取模型融合的思路,对每张结果图的每个像素点采取投票表决的思路,对每张图相应位置的像素点的类别进行预测,票数最多的类别即为该像素点的类别。正所谓“三个臭皮匠,胜过诸葛亮”,我们这种ensemble的思路,可以很好地去掉一些明显分类错误的像素点,很大程度上改善模型的预测能力。

    少数服从多数的投票表决策略代码:

    import numpy as np
    import cv2
    import argparse
    
    RESULT_PREFIXX = ['./result1/','./result2/','./result3/']
    
    # each mask has 5 classes: 0~4
    
    def vote_per_image(image_id):
        result_list = []
        for j in range(len(RESULT_PREFIXX)):
            im = cv2.imread(RESULT_PREFIXX[j]+str(image_id)+'.png',0)
            result_list.append(im)
            
        # each pixel
        height,width = result_list[0].shape
        vote_mask = np.zeros((height,width))
        for h in range(height):
            for w in range(width):
                record = np.zeros((1,5))
                for n in range(len(result_list)):
                    mask = result_list[n]
                    pixel = mask[h,w]
                    #print('pix:',pixel)
                    record[0,pixel]+=1
               
                label = record.argmax()
                #print(label)
                vote_mask[h,w] = label
        
        cv2.imwrite('vote_mask'+str(image_id)+'.png',vote_mask)
            
    
    vote_per_image(3)

    模型融合后的预测结果:

    可以看出,模型融合后的预测效果确实有较大提升,明显错误分类的像素点消失了。

    额外的思路:GAN

    我们对数据方面思考得更多一些,我们针对数据集小的问题,我们有个想法:使用生成对抗网络去生成虚假的卫星地图,旨在进一步扩大数据集。我们的想法就是,使用这些虚假+真实的数据集去训练网络,网络的泛化能力肯定有更大的提升。我们的想法是根据这篇论文(pix2pix)来展开的,这是一篇很有意思的论文,它主要讲的是用图像生成图像的方法。里面提到了用标注好的卫星地图生成虚假的卫星地图的想法,真的让人耳目一新,我们也想根据该思路,生成属于我们的虚假卫星地图数据集。 Map to Aerial的效果是多么的震撼。

    但是我们自己实现起来的效果却不容乐观(如下图所示,右面那幅就是我们生成的假图),效果不好的原因有很多,标注的问题最大,因为生成的虚假卫星地图质量不好,所以该想法以失败告终,生成的假图也没有拿去做训练。但感觉思路还是可行的,如果给的标注合适的话,还是可以生成非常像的虚假地图。

    总结

    对于这类遥感图像的语义分割,思路还有很多,最容易想到的思路就是,将各种语义分割经典网络都实现以下,看看哪个效果最好,再做模型融合,只要集成学习做得好,效果一般都会很不错的。我们仅靠上面那个简单思路(数据增强,经典模型搭建,集成学习),就已经可以获得比赛的TOP 5%了,当然还有一些tricks可以使效果更进一步提升,这里就不细说了,总的建模思路掌握就行。完整的代码可以在我的github获取。

     

    数据下载:

    链接:https://pan.baidu.com/s/1i6oMukH

    密码:yqj2

    展开全文
  • 农村地区遥感图像语义分割是进行城乡规划、植被以及农用地检测的基础。农村地区高分辨率遥感图像含有较为复杂的地物信息,对其进行语义分割难度较大。基于此,提出一种改进的对称编码-解码网络结构SegProNet,利用池化...
  • 基于U-Net模型, 提出了一个全卷积网络(FCN)模型, 用于高分辨率遥感图像语义分割, 其中数据预处理采用了数据标准化和数据增强, 模型训练过程采用Adam优化器, 模型性能评估采用平均Jaccard指数。为提高小类预测的准确...
  • 这两周数据挖掘课期末project我们组选的课题也是遥感图像的语义分割,所以刚好又把前段时间做的成果重新整理和加强了一下,故写了这篇文章,记录一下用深度学习做遥感图像语义分割的完整流程以及一些好的思路和技巧...
  • 对原始数据集做了扩充,对每一类地物目标训练一个二分类模型,随后将各预测子图组合生成最终语义分割图像。采用了集成学习策略来提高分割精度,在“CCF卫星影像的AI分类与识别竞赛”数据集上取得了94%的训练准确率和...
  • **基于SegNet和U-Net的遥感图像语义分割(一)** 代码: https://github.com/AstarLight/Satellite-Segmentation 数据集 链接:https://pan.baidu.com/s/1ajdS8ZRKY4ihrn0sf-2q2w 提取码:i4wr 解压后得到3个文件...
  • 数据集: vnet2d网络如下,因为目标区域较大这里我们采用传统的交叉熵损失。 import numpy as np import os import skimage.io as io import skimage.transform as trans import keras.backend as K from...
  • 预测整张遥感影像:unet_predict.py 代码: ... 前期的工作是裁剪数据,...这里需要思考一下怎么预测整张遥感图像。我们知道,我们训练模型时选择的图片输入是256×256,所以我们预测时也要采用256×256的图片尺寸送进...
  • 1.数据集介绍以及预处理 1.1数据集介绍 上图中左侧为航拍原图,右侧为标签(类别标签 像素值分别为 0,1,2,3,4,所以人的肉眼不能够分辨出区别,本文对标签进行可 视化处理 (实际训练中不做可视化处理),...
  • 小菊的语义分割——对ISPRS数据集中的遥感图像进行切分,制作自己的训练数据集1. 为什么要对遥感图像进行切分?2. 切分图像,制作数据集 1. 为什么要对遥感图像进行切分? 一般的遥感图像尺寸都是非常大的,就像这里...
  • 遥感图像语义分割 存储库包含用于解决两个公开可用的航空图像上的遥感图像语义分割的代码: 为了能够训练和测试所提议的网络,应该从这些数据集中提取训练,验证和测试样本。 然后,必须将提取的样本存储在文件...
  • 数据集共包含约800张机场区域的遥感图像,大约300张来自武汉大学的aid遥感数据集,其余的来自geogle地图的截图。其中约400张已经进行了语义分割标注。
  • 利用Unet结构进行语义分割,得到各个地物类型的场景分割图像,Unet结构和官方论文不太一样,自己根据理解进行了一些微调,改变了输出通道的数量,和上采样层后通道数量,每个巻积层后面加了batchNromalize层,正确率...
  • 遥感数据集 1. UC Merced Land-Use Data Set 图像像素大小为256*256,总包含21类场景图像,每一类有100张,共2100张。 http://weegee.vision.ucmerced.edu/datasets/landuse.html 2. WHU-RS19 Data Set 图像...
  • 随着深度学习的迅速发展并广泛应用到语义分割...然后,归纳了当前主流的公共数据集遥感数据集,并 在此基础对比主流图像语义分割方法的实验结果。最后,对语义分割技术面临的挑战以及未 来工作的发展方向进行了展望
  • 另一方面,基于深度学习(DL)的语义分割遥感分类中显示出高性能,并且需要以监督学习的方式来处理大型数据集。 提出了一种基于卷积神经网络的多源遥感影像融合语义分割方法,并将其应用于农作物的识别。 ...
  • 记录遥感影像分割

    千次阅读 多人点赞 2019-08-19 20:43:33
    这两周数据挖掘课期末project我们组选的课题也是遥感图像的语义分割,所以刚好又把前段时间做的成果重新整理和加强了一下,故写了这篇文章,记录一下用深度学习做遥感图像语义分割的完整流程以及一些好的思路和技巧...
  • 目录前言赛题介绍初赛阶段评测指标...遥感影像地块分割,旨在对遥感影像进行像素级内容分析,对遥感影像中感兴趣的类别进行提取和分类(说白了就是语义分割任务,只是对象是遥感图像)。 本次比赛分类的类别有七类,
  • 遥感——深度学习

    2020-08-31 23:29:40
    遥感语义分割预训练模型 ...基于SegNet和U-Net的遥感图像语义分割 3、Patch-Based网络结构 基于深度卷积神经网络的城市遥感图像小物体语义分割及不确定性建模 4、Deeplab网络 深度学习高分辨率遥感影像语义分割 ...
  • 遥感图像稀疏表征与智能分析竞赛参赛笔记

    千次阅读 热门讨论 2019-09-23 20:26:33
    我参加的是语义分割主题,数据来源于高分二号MSS影像,分辨率为四米,影像尺寸为7200x6800,包括NIR,R, G, B四个波段。由于原始影像是用ENVI classic做的预处理,所以会导致一些读取错误,所以我都使用了ima...

空空如也

空空如也

1 2 3
收藏数 41
精华内容 16
关键字:

遥感图像语义分割数据集