parent
ea9bb47b62
commit
64121d31d8
20 changed files with 392 additions and 477 deletions
@ -1,3 +1 @@ |
|||||||
# 开发规范 |
# PaddleRS文档 |
||||||
请注意,paddlers/models/ppxxx系列除了修改import路径和支持多通道模型外,不要增删改任何代码。 |
|
||||||
新增的模型需放在paddlers/models/下的seg、det、clas、cd目录下。 |
|
||||||
|
@ -1,33 +0,0 @@ |
|||||||
# 模型库 |
|
||||||
|
|
||||||
PaddleRS的基础模型库来自[PaddleClas](https://github.com/PaddlePaddle/PaddleClas/blob/release/2.3/docs/zh_CN/algorithm_introduction/ImageNet_models.md)、[PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.4/docs/model_zoo_overview_cn.md)、[PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection/blob/release/2.3/README_cn.md#模型库)以及[PaddleGAN](https://github.com/PaddlePaddle/PaddleGAN/blob/develop/README_cn.md#模型库),可以通过相关的链接进行查看。而在此之外,PaddleRS也针对遥感任务添加了一些特有的模型库,可用于遥感图像语义分割、遥感变化检测等。 |
|
||||||
|
|
||||||
## 遥感专用模型库 |
|
||||||
|
|
||||||
| 模型名称 | 用途 | |
|
||||||
| --------------- | -------- | |
|
||||||
| FarSeg | 语义分割 | |
|
||||||
| BIT | 变化检测 | |
|
||||||
| CDNet | 变化检测 | |
|
||||||
| DSIFN | 变化检测 | |
|
||||||
| STANet | 变化检测 | |
|
||||||
| SNUNet | 变化检测 | |
|
||||||
| DSAMNet | 变化检测 | |
|
||||||
| FCEarlyFusion | 变化检测 | |
|
||||||
| FCSiamConc | 变化检测 | |
|
||||||
| FCSiamDiff | 变化检测 | |
|
||||||
|
|
||||||
|
|
||||||
## 如何导入 |
|
||||||
|
|
||||||
模型均位于`paddlers/models`和`paddlers/rs_models`中,对于套件中的模型可以通过如下方法进行使用 |
|
||||||
|
|
||||||
```python |
|
||||||
from paddlers.models import xxxx |
|
||||||
``` |
|
||||||
|
|
||||||
而PaddleRS所特有的模型可以通过如下方法调用 |
|
||||||
|
|
||||||
```python |
|
||||||
from paddlers.rs_models import xxxx |
|
||||||
``` |
|
@ -1,53 +0,0 @@ |
|||||||
# 数据增强 |
|
||||||
|
|
||||||
PaddleRS将多种任务需要的数据增强进行了有机整合,均通过`Compose`进行使用,数据读取方面通过`DecodeImg`可以对不只三通道RGB图像进行读取,还可以对SAR以及多通道图像进行读取,提供有转为`uint8`的选项。此外提供以下数据增强的方法。 |
|
||||||
|
|
||||||
| 数据增强名称 | 用途 | 任务 | ... | |
|
||||||
| -------------------- | ----------------------------------------------- | -------- | ---- | |
|
||||||
| Resize | 调整输入大小 | 所有 | ... | |
|
||||||
| RandomResize | 随机调整输入大小 | 所有 | ... | |
|
||||||
| ResizeByShort | 调整输入大小,保持纵横比不变 | 所有 | ... | |
|
||||||
| RandomResizeByShort | 随机调整输入大小,保持纵横比不变 | 所有 | ... | |
|
||||||
| ResizeByLong | 调整输入大小,保持纵横比不变 | 所有 | ... | |
|
||||||
| RandomHorizontalFlip | 随机水平翻转输入 | 所有 | ... | |
|
||||||
| RandomVerticalFlip | 随机竖直翻转输入 | 所有 | ... | |
|
||||||
| Normalize | 对输入中的图像应用最小-最大标准化 | 所有 | ... | |
|
||||||
| CenterCrop | 对输入进行中心裁剪 | 所有 | ... | |
|
||||||
| RandomCrop | 对输入进行随机中心裁剪 | 所有 | ... | |
|
||||||
| RandomScaleAspect | 裁剪输入并重新调整大小至原始大小 | 所有 | ... | |
|
||||||
| RandomExpand | 通过根据随机偏移填充来随机扩展输入 | 所有 | ... | |
|
||||||
| Pad | 将输入填充到指定的大小 | 所有 | ... | |
|
||||||
| MixupImage | 将两张图片和它们的`gt_bbbox/gt_score`混合在一起 | 目标检测 | ... | |
|
||||||
| RandomDistort | 对输入进行随机色彩变换 | 所有 | ... | |
|
||||||
| RandomBlur | 对输入进行随机模糊 | 所有 | ... | |
|
||||||
| Dehaze | 对输入图像进行去雾 | 所有 | ... | |
|
||||||
| ReduceDim | 对输入图像进行降维 | 所有 | ... | |
|
||||||
| SelectBand | 选择输入图像的波段 | 所有 | ... | |
|
||||||
| RandomSwap | 随机交换两个输入图像 | 变化检测 | ... | |
|
||||||
| ... | ... | | ... | |
|
||||||
|
|
||||||
## 如何使用 |
|
||||||
|
|
||||||
以变化检测任务为例,其余任务的使用方法与此类似。 |
|
||||||
|
|
||||||
```python |
|
||||||
import paddlers.transforms as T |
|
||||||
from paddlers.datasets import CDDataset |
|
||||||
|
|
||||||
|
|
||||||
train_transforms = T.Compose([ |
|
||||||
T.DecodeImg(), |
|
||||||
T.Resize(target_size=512), |
|
||||||
T.RandomHorizontalFlip(), |
|
||||||
T.Normalize( |
|
||||||
mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]), |
|
||||||
T.ArrangeChangeDetector('train') |
|
||||||
]) |
|
||||||
|
|
||||||
train_dataset = CDDataset( |
|
||||||
data_dir='xxx/xxx', |
|
||||||
file_list='xxx/train_list.txt', |
|
||||||
label_list='xxx/labels.txt', |
|
||||||
transforms=train_transforms, |
|
||||||
shuffle=True) |
|
||||||
``` |
|
@ -0,0 +1,19 @@ |
|||||||
|
# 遥感开源数据集 |
||||||
|
|
||||||
|
PaddleRS搜集汇总了遥感领域常用的**开源**深度学习数据集,提供每个数据集的以下信息:数据集说明,影像信息,标注信息,源地址,AI Studio备份链接。这些数据集按任务类型可分为**图像分类、图像分割、变化检测、目标检测、目标跟踪、多标签分类、图像生成**等多种类型。目前已收录的遥感数据集有: |
||||||
|
|
||||||
|
* 图像分类数据集32个; |
||||||
|
* 目标检测数据集40个; |
||||||
|
* 图像分割数据集70个; |
||||||
|
* 变化检测数据集28个; |
||||||
|
* 实例分割数据集7个; |
||||||
|
* 多标签分类数据集3个; |
||||||
|
* 目标跟踪数据集9个; |
||||||
|
* 图像标题数据集3个; |
||||||
|
* 图像生成数据集8个。 |
||||||
|
|
||||||
|
欢迎访问[遥感数据集汇总](./dataset_summary.md),以获取详细信息。 |
||||||
|
|
||||||
|
## 特别贡献数据集 |
||||||
|
|
||||||
|
* 2020年中国典型城市道路样本数据CHN6-CUG,由中国地质大学[朱祺琪](http://grzy.cug.edu.cn/zhuqiqi)教授提供。相关介绍和下载方式请参考[此处](http://grzy.cug.edu.cn/zhuqiqi/zh_CN/yjgk/32368/content/1733.htm)。 |
@ -1,20 +0,0 @@ |
|||||||
## 公开数据集 |
|
||||||
|
|
||||||
PaddleRS搜集汇总了 遥感影像领域 常用的 **开源**深度学习数据集,每个数据集信息包括:数据集说明,影像信息,标注信息,源地址,aistudio备份链接。这些数据集按任务类型可分为 **图像分类、图像分割、变化检测、目标检测、目标跟踪、多标签分类、图像生成** 等多种类型,目前已收录的遥感数据集: |
|
||||||
|
|
||||||
* 图像分类数据集32个; |
|
||||||
* 目标检测数据集40个; |
|
||||||
* 图像分割数据集70个; |
|
||||||
* 变化检测数据集28个; |
|
||||||
* 实例分割数据集7个; |
|
||||||
* 多标签分类数据集3个; |
|
||||||
* 目标跟踪数据集9个; |
|
||||||
* 图像标题数据集3个; |
|
||||||
* 图像生成数据集8个 |
|
||||||
|
|
||||||
|
|
||||||
欢迎访问[遥感数据集汇总](./dataset_summary.md),获取详细数据集内容。 |
|
||||||
|
|
||||||
## 特别贡献数据集 |
|
||||||
|
|
||||||
* 2020年中国典型城市道路样本数据CHN6-CUG,由中国地质大学[朱祺琪](http://grzy.cug.edu.cn/zhuqiqi)教授提供,相关介绍和下载方式请参考[该地址](http://grzy.cug.edu.cn/zhuqiqi/zh_CN/yjgk/32368/content/1733.htm)。 |
|
@ -0,0 +1,80 @@ |
|||||||
|
# 遥感数据介绍 |
||||||
|
|
||||||
|
广义上,遥感指的是"遥远的感知",即在不直接接触的情况下,对目标或自然现象进行远距离探测和感知。狭义上的遥感一般指电磁波遥感技术,即在某种平台(如飞机或卫星)上利用传感器探测电磁波的反射特性、并从中提取信息的过程。这个过程获取的影像数据被称作遥感数据,一般包括卫星和航空影像。遥感数据的用途广泛,在诸如空间分析等GIS任务中、或是包括场景分类、影像分割与目标检测在内的计算机视觉(Computer Vision, CV)领域都可以见到它们的身影。 |
||||||
|
|
||||||
|
相比航空影像,卫星影像的覆盖面积更广,因此得到了更加长足的应用。常见的卫星影像可能由商业卫星摄制,也可能来自NASA、ESA等机构的开放数据库。 |
||||||
|
|
||||||
|
## 遥感影像的分类 |
||||||
|
|
||||||
|
遥感影像具有覆盖面积广、波段数多、来源多样等特点。根据存储方式,可将遥感影像分为栅格数据和矢量数据两种类型;根据波段数,又可分为多光谱影像、高光谱影像等类型。本文档旨在为不具备遥感专业背景的开发者提供快速了解的途径,因此仅介绍几种常见的遥感影像类型。 |
||||||
|
|
||||||
|
### 栅格数据 |
||||||
|
|
||||||
|
栅格是一种基于像素的数据格式,可以有效地表示连续表面。栅格中的信息存储在网格结构中,每个信息单元或像素具有相同的大小和形状,但值不同。数码照片、正射影像和卫星影像都可以这种格式存储。 |
||||||
|
|
||||||
|
栅格格式非常适合用于查看空间和时间变化的分析,因为每个数据值都有一个基于网格的可访问位置。这使我们能够访问两个或多个不同栅格中的相同地理位置并比较它们的值。 |
||||||
|
|
||||||
|
当地球观测卫星拍摄照片时,传感器会读取并记录从沿电磁光谱的波长收集的反射率值,并利用反射率计算各个栅格像元的DN值(Digital Number),即遥感影像像元的亮度值,从而记录地物的灰度值。 |
||||||
|
|
||||||
|
通过DN值,可以反求地物的辐照率和反射率。它们之间的关系如以下公式所示,其中$gain$和$bias$分别指传感器的增益和偏移;$L$是辐射率,也称为辐射亮度值;$\rho$是地物反射率;$d_{s}$、$E_{0}$和$\theta$分别表示日地天文单位距离、太阳辐照度以及太阳天顶角。 |
||||||
|
|
||||||
|
$$ |
||||||
|
L = gain * DN + bias \\ |
||||||
|
\rho = \pi Ld^{2}_{s}/(E_{0}\cos{\theta}) |
||||||
|
$$ |
||||||
|
|
||||||
|
电磁波谱是人类根据电磁波的波长或频率、波数、能量等的大小顺序进行排列的成果。在电磁波谱中人眼只能感受到一个很小的波段范围,这个范围被称为可见光,波长范围在0.38-0.76μm。这是因为我们的视觉进化为在太阳发出最多光的地方最敏感,并且广泛地局限于构成我们所谓的红色、绿色和蓝色的波长。但卫星传感器可以感知范围更广的电磁频谱,这使得我们能够与借助传感器感知更多的频谱范围。 |
||||||
|
|
||||||
|
![band](../images/band.jpg) |
||||||
|
|
||||||
|
电磁波谱范围很广,使用一个传感器同时收集所有波长的信息是不切实际的。在实际中,不同的传感器优先考虑从不同波长的光谱收集信息。由传感器捕获和分类的频谱的每个部分都被归类为一个信息带。信息带的大小各不相同,可以编译成不同类型的合成影像,每幅合成影像都强调不同的物理特性。同时,大多数遥感影像都为16位的图像,与传统的8位图像不同,它能表示更精细的光谱信息。 |
||||||
|
|
||||||
|
#### RGB影像 |
||||||
|
|
||||||
|
RGB影像与生活中常见的自然图像类似,其中显示的地物特征也符合人类的视觉常识(如树是绿色的、水泥是灰色的等),三个通道分别表示红、绿和蓝。下图展示了一幅RGB遥感影像: |
||||||
|
|
||||||
|
![rgb](../images/rgb.jpg) |
||||||
|
|
||||||
|
由于当前大多数CV任务的处理流程都是基于自然图像设计的,因此RGB类型的遥感数据集在CV领域使用较多。 |
||||||
|
|
||||||
|
#### MSI/HSI影像 |
||||||
|
|
||||||
|
MSI(Multispectral Image,多光谱影像)和HSI(Hyperspectral Image,高光谱影像)通常包括数个到数百个不等的波段,二者以不同的光谱分辨率(*光谱分辨率是指传感器所能记录的电磁波谱中某一特定的波长范围值,波长范围值越宽,则光谱分辨率越低*)进行区分。通常光谱分辨率在波长的1/10数量级范围内称为多光谱。MSI的波段数相对HSI较少,谱带较宽,空间分辨率较高;而HSI的波段数较多,谱带较窄,光谱分辨率较高。 |
||||||
|
|
||||||
|
在实际中常常根据应用需求选取MSI/HSI的一些特定波段:例如中红外波段的透射率在60%-70%,包含地物反射及发射光谱,可以用来探测火灾等高温目标;红边波段(*绿色植物在0.67-0.76μm之间反射率增高最快的点,也是一阶导数光谱在该区间内的拐点*)是指示绿色植物生长状况的敏感性波段,可以有效地监测植被的生长状况,用于研究植物养分、健康状态监测、植被识别和生理生化参数等信息等。 |
||||||
|
|
||||||
|
下面以天宫一号高光谱成像仪拍摄的北京大兴机场为例,简单介绍一下MSI/HSI处理中常见的波段组合、光谱曲线和波段选择的概念。天宫一号高光谱数据集根据波段信噪比和信息熵评价结果剔除信噪比和信息熵较低的波段,并结合影像实际目视结果剔除部分波段,共保留可见近红外谱段54个、短波红外谱段52个以及全色谱段数据。 |
||||||
|
|
||||||
|
**波段组合** |
||||||
|
|
||||||
|
波段组合是指在MSI/HSI中选择三个波段数据进行组合、代替RGB三个通道所得到的结果,称为彩色图(*使用真实的RGB三波段合成的结果称为真彩色图,否则称为假彩色图*)。不同波段的组合能够突出不同的地物特征,下图展示了几种不同组合的目视效果: |
||||||
|
|
||||||
|
![图片3](../images/band_combination.jpg) |
||||||
|
|
||||||
|
**光谱曲线解读** |
||||||
|
|
||||||
|
光谱信息往往能够反映地物特征,不同的波段反映的地物特征也不尽相同。以电磁波的波长或频率为横轴,反射率为纵轴,可以绘制光谱曲线。以植被的光谱曲线为例,如下图所示,植被在0.8μm波段反射率大于40%,相比在0.6μm波段10%左右的反射率明显更大,因此在成像时反射回更多的辐射能量。体现在图中,植被部分在0.8μm的影像中看起来更加明亮。 |
||||||
|
|
||||||
|
![band_mean](../images/band_mean.jpg) |
||||||
|
|
||||||
|
**波段选择** |
||||||
|
|
||||||
|
MSI/HSI包含的波段数量可能较多。一方面,并不是所有波段都适用于待处理的任务;另一方面,过多的波段数可能带来沉重的资源负担。在实际应用中,可以根据需求选用MSI/HSI的部分波段完成任务,也可以使用如PCA、小波变换等方法对MSI/HSI进行降维处理,以减少冗余,节省计算资源。 |
||||||
|
|
||||||
|
#### SAR影像 |
||||||
|
|
||||||
|
SAR(Synthetic Aperture Radar)指的是主动式侧视雷达系统。SAR的成像几何属于斜距投影类型,因此SAR影像与光学影像在成像机理、几何特征、辐射特征等方面都有较大的区别。 |
||||||
|
|
||||||
|
光学影像中不同波段的信息来自于不同波长电磁波的反射能量,而SAR影像则以二进制复数形式记录了不同极化(*即电磁波发射和接收的振动方向*)的回波信息。基于记录的复数数据,可将原始的SAR影像通过变换提取相应的振幅和相位信息。人类无法直接分辨相位信息,但可以直观地感知振幅信息,利用振幅信息可以得到强度图像,如下图所示: |
||||||
|
|
||||||
|
![sar](../images/sar.jpg) |
||||||
|
|
||||||
|
由于SAR影像的特殊成像机理,其分辨率相对较低,信噪比也较低,所以SAR影像中所包含的振幅信息远达不到光学影像的成像水平。这也是为什么SAR影像在CV领域中的应用较少。目前,SAR影像被主要用于基于相位信息的沉降检测反演、三维重建等。值得一提的是,由于SAR的波长较长,具有一定的云层和地表穿透能力,因此在部分应用场景中有其独特的优势。 |
||||||
|
|
||||||
|
#### RGBD影像 |
||||||
|
|
||||||
|
RGBD影像与RGB影像的区别在于多了一个D通道,即深度(depth)。深度影像类似于灰度图像,只是其中的每个像素值代表的是传感器距离物体的实际距离。通常RGBD影像中的RGB数据和深度数据是相互配准的。如下图所示为无人机航摄的RGBD影像,其中可以看出建筑物与地面之间的相对高度。 |
||||||
|
|
||||||
|
![rgbd](../images/rgbd.jpg) |
||||||
|
|
||||||
|
深度影像提供了RGB影像所不具有的高度信息,能够在某些下游任务中对一些光谱特征相似的地物起到一定的区分作用。 |
@ -1,80 +0,0 @@ |
|||||||
# 遥感数据介绍 |
|
||||||
|
|
||||||
广义上,遥感是指遥远的感知,是指在不直接接触的情况下,对目标或自然现象远距离探测和感知的一种技术。一般我们所说的遥感为电磁波遥感,即在某平台上利用传感器探测电磁波反射或发射,并从中提取信息的过程。这个过程获取的图像数据一般即为卫星和航空影像。遥感数据可以被用于各种应用程序中,为空间分析等提供数据源,也可以在包括场景分类、图像分割与检测等CV领域进行判别或提取。 |
|
||||||
|
|
||||||
目前常用的遥感影像来自各种商业卫星影像提供商如Google等,以及来自NASA、ESA等的开放数据。可以从它们的官网中找到更多信息。 |
|
||||||
|
|
||||||
## 图像的工作原理 |
|
||||||
|
|
||||||
卫星和航空图像来自各种来源的栅格数据,经过接收方的部分处理后进行发布,如几何校正、辐射校正、大气校正或者色彩校正等,使其可以进行较准确的定量分析或具有更加逼真的视觉效果。 |
|
||||||
|
|
||||||
### 栅格数据 |
|
||||||
|
|
||||||
所有卫星和航空图像都以光栅格式存储。栅格是一种基于像素的数据格式,可以有效地表示连续表面。栅格中的信息存储在网格结构中,每个信息单元或像素具有相同的大小和形状,但值不同。数码照片、正射影像和卫星图像都以这种格式存储。 |
|
||||||
|
|
||||||
栅格格式非常适合用于查看空间和时间变化的分析,因为每个数据值都有一个基于网格的可访问位置。这使我们能够访问两个或多个不同栅格中的相同地理位置并比较它们的值。 |
|
||||||
|
|
||||||
### 卫星栅格 |
|
||||||
|
|
||||||
当地球观测卫星拍摄照片时,传感器会读取并记录从沿电磁光谱的波长收集的反射率值,并利用反射率计算各个栅格像元的DN值(Digital Number),即遥感影像像元的亮度值,记录的地物的灰度值。 |
|
||||||
|
|
||||||
而利用遥感图像的目的之一就是使用DN值可以反算地物的辐照率和反射率。它们之间的关系如下公式所示,其中$gain$和$bias$分别指传感器的增益和偏移;$L$是辐射率,也称为辐射亮度值;$\rho$是地物反射率;$d_{s}$、$E_{0}$和$\theta$分别表示日地天文单位距离、太阳辐照度以及太阳天顶角。 |
|
||||||
|
|
||||||
$$ |
|
||||||
L = gain * DN + bias \\ |
|
||||||
\rho = \pi Ld^{2}_{s}/(E_{0}\cos{\theta}) |
|
||||||
$$ |
|
||||||
|
|
||||||
电磁波谱是人类根据电磁波的波长或频率、波数、能量等的大小顺序进行排列的成果。在电磁波谱中人眼只能感受到一个很小的波段范围,这个范围被称为可见光,波长范围在0.38-0.76μm。这是因为我们的视觉进化为在太阳发出最多光的地方最敏感,并且广泛地局限于构成我们所谓的红色、绿色和蓝色的波长。但卫星传感器可以感知范围更广的电磁频谱,这使得我们能够与借助传感器感知更多的频谱范围。 |
|
||||||
|
|
||||||
![band](../images/band.jpg) |
|
||||||
|
|
||||||
电磁波谱范围很广,传感器同时收集所有波长的信息是不切实际的。相反,不同的传感器优先考虑从不同波长的光谱收集信息。由传感器捕获和分类的频谱的每个部分都被归类为一个信息带。信息带的大小各不相同,可以编译成不同类型的合成图像,每个图像都强调不同的物理特性。同时,大多数遥感图像都为16位的图像,与传统的8位图像不同,它能表示更精细的光谱信息。 |
|
||||||
|
|
||||||
#### RGB |
|
||||||
|
|
||||||
RGB图像与我们常见的自然图像类似,也符合人类的视觉常识(如树是绿色的、水泥是灰色的等),三个通道分别表示红、绿和蓝。一般的RGB数据来自于无人机影像、各种电子地图下载器等,如下图所示。 |
|
||||||
|
|
||||||
![rgb](../images/rgb.jpg) |
|
||||||
|
|
||||||
由于当前大多数CV任务的流程都是基于自然图像进行设计的,因此RGB类型的遥感数据集依然是使用较多的。 |
|
||||||
|
|
||||||
#### MSI/HSI |
|
||||||
|
|
||||||
MSI(*Multispectral Image,多光谱图像*)和HSI(*Hyperspectral Image,高光谱图像*)均是一种波段数均大于3的遥感影像,其波段由几个到几百个不等,以不同的光谱分辨率(*光谱分辨率是指传感器所能记录的电磁波谱中,某一特定的波长范围值,波长范围值越宽,光谱分辨率越低*)进行区分。通常光谱分辨率在波长的1/10数量级范围内称为多光谱。其中多光谱影像的波段较少,谱带较宽,空间分辨率较高;而高光谱影像的波段较多,谱带较窄,光谱分辨率较高。 |
|
||||||
|
|
||||||
在使用中,MSI/HSI有一些常用波段具有不同的作用,例如中红外波段的透射率在60%-70%,包含地物反射及发射光谱,可以用来探测火灾等高温目标;红边波段(*绿色植物在0.67-0.76μm之间反射率增高最快的点,也是一阶导数光谱在该区间内的拐点*)是指示绿色植物生长状况的敏感性波段,可以有效地监测植被的生长状况,用于研究植物养分、健康状态监测、植被识别和生理生化参数等信息等。 |
|
||||||
|
|
||||||
下面以天宫一号高光谱成像仪拍摄的北京大兴机场为例,简单介绍一下波段组合和光谱曲线。天宫一号高光谱数据集根据波段信噪比和信息熵评价结果,剔除信噪比和信息熵较低的波段,结合图像实际目视结果,剔除了部分波段,共有可见近红外谱段54 个;短波红外谱段 52 个以及1个全色谱段数据。 |
|
||||||
|
|
||||||
##### 波段组合 |
|
||||||
|
|
||||||
波段组合是指在MSI/HSI中选择三个波段数据进行组合,代替RGB三个通道所得到的结果,称为彩色图(*RGB三波段的合成图称为真彩色图,任意非RGB波段的合成图称为假彩色图*)。不同彩色图的组合能够突出不同的地物特征,下图展示了不同的几种组合的效果。 |
|
||||||
|
|
||||||
![图片3](../images/band_combination.jpg) |
|
||||||
|
|
||||||
##### 光谱曲线解读 |
|
||||||
|
|
||||||
不同的光谱能够突出不同的地物特征,以植物的光谱曲线为例,如下图所示,植被在0.8μm波段,反射率大于40%,相比在0.6μm波段10%左右的反射率明显更大,因此在成像时反射回更多的辐射能量。所以成像时0.8μm波段的植被亮度大于0.6μm波段的植被亮度,也就是图上看起来就更明亮了。 |
|
||||||
|
|
||||||
![band_mean](../images/band_mean.jpg) |
|
||||||
|
|
||||||
了解MSI/HSI的波段后,可以根据资源使用不同数量和不同组合方式的使用MSI/HSI完成各类任务,也可以使用如PCA、小波变换等方法对MSI/HSI进行降维处理,以减少冗余,使用更少的计算资源完成任务。 |
|
||||||
|
|
||||||
#### SAR |
|
||||||
|
|
||||||
SAR(Synthetic Aperture Radar)是主动式侧视雷达系统,且成像几何属于斜距投影类型。因此SAR图像与光学图像在成像机理、几何特征、辐射特征等方面都有较大的区别。 |
|
||||||
|
|
||||||
与光学图像不同,光学图像不同波段的信息来自不不同波长的电磁波反射,以便于识别目标和分类提取;SAR图像则记录了不同极化(*即电磁波发射和接收的振动方向*)的回波信息,以二进制复数形式记录下来,并且基于每个像素的复数数据可变换提取相应的振幅和相位信息。相位信息人类无法直接分辨,但振幅信息可以,利用振幅信息可以得到强度图像如下图所示。 |
|
||||||
|
|
||||||
![sar](../images/sar.jpg) |
|
||||||
|
|
||||||
由于SAR图像的成像机理的不同,SAR影像分辨率相对较低、信噪比较低,所以SAR影像中所包含的振幅信息远达不到同光学影像的成像水平,因此在CV领域使用较少。而其的主要作用在于基于相位信息可以进行沉降检测反演、三维重建等,同时SAR卫星波长较长,具有一定的云层和地表穿透能力,有其独特的使用优势。 |
|
||||||
|
|
||||||
#### RGBD |
|
||||||
|
|
||||||
RGBD与RGB图像的区别在于多了一个D通道,即深度。深度图像类似于灰度图像,只是它的每个像素值是传感器距离物体的实际距离。通常RGB图像和深度图像是配准的,因而两幅图像对应于同一空间位置的点是一一对应的。如下图所示为部分无人机航摄的RGBD图像,其中可以看出建筑物与地面之间的相对高度。 |
|
||||||
|
|
||||||
![rgbd](../images/rgbd.jpg) |
|
||||||
|
|
||||||
深度图像提供了RGB图像所不具有的高度信息,能够在下游任务中对一些光谱特征相似的地物起到一定的区分作用。 |
|
@ -0,0 +1,34 @@ |
|||||||
|
# 模型库 |
||||||
|
|
||||||
|
PaddleRS的基础模型库来自Paddle-CV系列套件:[PaddleClas](https://github.com/PaddlePaddle/PaddleClas/blob/release/2.3/docs/zh_CN/algorithm_introduction/ImageNet_models.md)、[PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.4/docs/model_zoo_overview_cn.md)、[PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection/blob/release/2.3/README_cn.md#模型库)以及[PaddleGAN](https://github.com/PaddlePaddle/PaddleGAN/blob/develop/README_cn.md#模型库)。除此之外,PaddleRS也包含一系列遥感特色模型,可用于遥感影像分割、变化检测等。 |
||||||
|
|
||||||
|
## PaddleRS支持的模型列表 |
||||||
|
|
||||||
|
PaddleRS支持的全部模型如下(标注\*的为遥感专用模型): |
||||||
|
|
||||||
|
| 任务 | 模型 | |
||||||
|
|--------|---------| |
||||||
|
| 变化检测 | \*BIT | |
||||||
|
| 变化检测 | \*CDNet | |
||||||
|
| 变化检测 | \*DSAMNet | |
||||||
|
| 变化检测 | \*DSIFN | |
||||||
|
| 变化检测 | \*SNUNet | |
||||||
|
| 变化检测 | \*STANet | |
||||||
|
| 变化检测 | \*FC-EF | |
||||||
|
| 变化检测 | \*FC-Siam-conc | |
||||||
|
| 变化检测 | \*FC-Siam-diff | |
||||||
|
| 场景分类 | HRNet | |
||||||
|
| 场景分类 | MobileNetV3 | |
||||||
|
| 场景分类 | ResNet50-vd | |
||||||
|
| 场景分类 | CondenseNetV2 | |
||||||
|
| 图像复原 | DRN | |
||||||
|
| 图像复原 | ESRGAN | |
||||||
|
| 图像复原 | LESRCNN | |
||||||
|
| 目标检测 | Faster R-CNN | |
||||||
|
| 目标检测 | PP-YOLO | |
||||||
|
| 目标检测 | PP-YOLO Tiny | |
||||||
|
| 目标检测 | PP-YOLOv2 | |
||||||
|
| 目标检测 | YOLOv3 | |
||||||
|
| 图像分割 | DeepLab V3+ | |
||||||
|
| 图像分割 | UNet | |
||||||
|
| 图像分割 | \*FarSeg | |
@ -0,0 +1,27 @@ |
|||||||
|
# 数据预处理/数据增强 |
||||||
|
|
||||||
|
PaddleRS对不同遥感任务需要的数据预处理/数据增强策略进行了有机整合,设计统一的算子,并通过`paddlers.transforms.DecodeImg`对各种格式的遥感影像进行读取。PaddleRS提供的所有数据预处理/数据增强算子如下表: |
||||||
|
|
||||||
|
| 数据预处理/数据增强算子名 | 用途 | 任务 | ... | |
||||||
|
| -------------------- | ------------------------------------------------- | -------- | ---- | |
||||||
|
| Resize | 调整输入影像大小 | 所有任务 | ... | |
||||||
|
| RandomResize | 随机调整输入影像大小 | 所有任务 | ... | |
||||||
|
| ResizeByShort | 调整输入影像大小,保持纵横比不变(根据短边计算缩放系数) | 所有任务 | ... | |
||||||
|
| RandomResizeByShort | 随机调整输入影像大小,保持纵横比不变(根据短边计算缩放系数) | 所有任务 | ... | |
||||||
|
| ResizeByLong | 调整输入影像大小,保持纵横比不变(根据长边计算缩放系数) | 所有任务 | ... | |
||||||
|
| RandomHorizontalFlip | 随机水平翻转输入影像 | 所有任务 | ... | |
||||||
|
| RandomVerticalFlip | 随机竖直翻转输入影像 | 所有任务 | ... | |
||||||
|
| Normalize | 对输入影像应用标准化 | 所有任务 | ... | |
||||||
|
| CenterCrop | 对输入影像进行中心裁剪 | 所有任务 | ... | |
||||||
|
| RandomCrop | 对输入影像进行随机中心裁剪 | 所有任务 | ... | |
||||||
|
| RandomScaleAspect | 裁剪输入影像并重新缩放到原始尺寸 | 所有任务 | ... | |
||||||
|
| RandomExpand | 根据随机偏移扩展输入影像 | 所有任务 | ... | |
||||||
|
| Pad | 将输入影像填充到指定的大小 | 所有任务 | ... | |
||||||
|
| MixupImage | 将两幅影像(及对应的目标检测标注)混合在一起作为新的样本 | 目标检测 | ... | |
||||||
|
| RandomDistort | 对输入施加随机色彩变换 | 所有任务 | ... | |
||||||
|
| RandomBlur | 对输入施加随机模糊 | 所有任务 | ... | |
||||||
|
| Dehaze | 对输入图像进行去雾 | 所有任务 | ... | |
||||||
|
| ReduceDim | 对输入图像进行波段降维 | 所有任务 | ... | |
||||||
|
| SelectBand | 对输入影像进行波段选择 | 所有任务 | ... | |
||||||
|
| RandomSwap | 随机交换两个时相的输入影像 | 变化检测 | ... | |
||||||
|
| ... | ... | ... | ... | |
@ -1,42 +0,0 @@ |
|||||||
|
|
||||||
## 环境准备 |
|
||||||
|
|
||||||
- [PaddlePaddle安装](https://www.paddlepaddle.org.cn/install/quick) |
|
||||||
* 版本要求:PaddlePaddle>=2.1.0 |
|
||||||
|
|
||||||
- PaddleRS安装 |
|
||||||
|
|
||||||
|
|
||||||
PaddleRS代码会跟随开发进度不断更新,可以安装develop分支的代码使用最新的功能,安装方式如下: |
|
||||||
|
|
||||||
``` |
|
||||||
git clone https://github.com/PaddlePaddle/PaddleRS |
|
||||||
cd PaddleRS |
|
||||||
git checkout develop |
|
||||||
pip install -r requirements.txt |
|
||||||
python setup.py install |
|
||||||
``` |
|
||||||
|
|
||||||
## 开始训练 |
|
||||||
* 在安装PaddleRS后,使用如下命令开始训练,代码会自动下载训练数据, 并均使用单张GPU卡进行训练。 |
|
||||||
|
|
||||||
```commandline |
|
||||||
export CUDA_VISIBLE_DEVICES=0 |
|
||||||
python tutorials/train/semantic_segmentation/deeplabv3p_resnet50_multi_channel.py |
|
||||||
``` |
|
||||||
|
|
||||||
* 若需使用多张GPU卡进行训练,例如使用2张卡时执行: |
|
||||||
|
|
||||||
```commandline |
|
||||||
python -m paddle.distributed.launch --gpus 0,1 tutorials/train/semantic_segmentation/deeplabv3p_resnet50_multi_channel.py |
|
||||||
``` |
|
||||||
使用多卡时,参考[训练参数调整](../../docs/parameters.md)调整学习率和批量大小。 |
|
||||||
|
|
||||||
|
|
||||||
## VisualDL可视化训练指标 |
|
||||||
在模型训练过程,在`train`函数中,将`use_vdl`设为True,则训练过程会自动将训练日志以VisualDL的格式打点在`save_dir`(用户自己指定的路径)下的`vdl_log`目录,用户可以使用如下命令启动VisualDL服务,查看可视化指标 |
|
||||||
```commandline |
|
||||||
visualdl --logdir output/deeplabv3p_resnet50_multi_channel/vdl_log --port 8001 |
|
||||||
``` |
|
||||||
|
|
||||||
服务启动后,使用浏览器打开 https://0.0.0.0:8001 或 https://localhost:8001 |
|
@ -1,105 +1,105 @@ |
|||||||
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. |
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. |
||||||
# |
# |
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
# you may not use this file except in compliance with the License. |
# you may not use this file except in compliance with the License. |
||||||
# You may obtain a copy of the License at |
# You may obtain a copy of the License at |
||||||
# |
# |
||||||
# http://www.apache.org/licenses/LICENSE-2.0 |
# http://www.apache.org/licenses/LICENSE-2.0 |
||||||
# |
# |
||||||
# Unless required by applicable law or agreed to in writing, software |
# Unless required by applicable law or agreed to in writing, software |
||||||
# distributed under the License is distributed on an "AS IS" BASIS, |
# distributed under the License is distributed on an "AS IS" BASIS, |
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
# See the License for the specific language governing permissions and |
# See the License for the specific language governing permissions and |
||||||
# limitations under the License. |
# limitations under the License. |
||||||
|
|
||||||
import os |
import os |
||||||
import os.path as osp |
import os.path as osp |
||||||
import argparse |
import argparse |
||||||
|
|
||||||
import numpy as np |
import numpy as np |
||||||
from PIL import Image |
from PIL import Image |
||||||
try: |
try: |
||||||
from osgeo import gdal, ogr, osr |
from osgeo import gdal, ogr, osr |
||||||
except ImportError: |
except ImportError: |
||||||
import gdal |
import gdal |
||||||
import ogr |
import ogr |
||||||
import osr |
import osr |
||||||
|
|
||||||
from utils import Raster, save_geotiff, time_it |
from utils import Raster, save_geotiff, time_it |
||||||
|
|
||||||
|
|
||||||
def _mask2tif(mask_path, tmp_path, proj, geot): |
def _mask2tif(mask_path, tmp_path, proj, geot): |
||||||
dst_ds = save_geotiff( |
dst_ds = save_geotiff( |
||||||
np.asarray(Image.open(mask_path)), tmp_path, proj, geot, |
np.asarray(Image.open(mask_path)), tmp_path, proj, geot, |
||||||
gdal.GDT_UInt16, False) |
gdal.GDT_UInt16, False) |
||||||
return dst_ds |
return dst_ds |
||||||
|
|
||||||
|
|
||||||
def _polygonize_raster(mask_path, vec_save_path, proj, geot, ignore_index, ext): |
def _polygonize_raster(mask_path, vec_save_path, proj, geot, ignore_index, ext): |
||||||
if proj is None or geot is None: |
if proj is None or geot is None: |
||||||
tmp_path = None |
tmp_path = None |
||||||
ds = gdal.Open(mask_path) |
ds = gdal.Open(mask_path) |
||||||
else: |
else: |
||||||
tmp_path = vec_save_path.replace("." + ext, ".tif") |
tmp_path = vec_save_path.replace("." + ext, ".tif") |
||||||
ds = _mask2tif(mask_path, tmp_path, proj, geot) |
ds = _mask2tif(mask_path, tmp_path, proj, geot) |
||||||
srcband = ds.GetRasterBand(1) |
srcband = ds.GetRasterBand(1) |
||||||
maskband = srcband.GetMaskBand() |
maskband = srcband.GetMaskBand() |
||||||
gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES") |
gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES") |
||||||
gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8") |
gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8") |
||||||
ogr.RegisterAll() |
ogr.RegisterAll() |
||||||
drv = ogr.GetDriverByName("ESRI Shapefile" if ext == "shp" else "GeoJSON") |
drv = ogr.GetDriverByName("ESRI Shapefile" if ext == "shp" else "GeoJSON") |
||||||
if osp.exists(vec_save_path): |
if osp.exists(vec_save_path): |
||||||
os.remove(vec_save_path) |
os.remove(vec_save_path) |
||||||
dst_ds = drv.CreateDataSource(vec_save_path) |
dst_ds = drv.CreateDataSource(vec_save_path) |
||||||
prosrs = osr.SpatialReference(wkt=ds.GetProjection()) |
prosrs = osr.SpatialReference(wkt=ds.GetProjection()) |
||||||
dst_layer = dst_ds.CreateLayer( |
dst_layer = dst_ds.CreateLayer( |
||||||
"POLYGON", geom_type=ogr.wkbPolygon, srs=prosrs) |
"POLYGON", geom_type=ogr.wkbPolygon, srs=prosrs) |
||||||
dst_fieldname = "CLAS" |
dst_fieldname = "CLAS" |
||||||
fd = ogr.FieldDefn(dst_fieldname, ogr.OFTInteger) |
fd = ogr.FieldDefn(dst_fieldname, ogr.OFTInteger) |
||||||
dst_layer.CreateField(fd) |
dst_layer.CreateField(fd) |
||||||
gdal.Polygonize(srcband, maskband, dst_layer, 0, []) |
gdal.Polygonize(srcband, maskband, dst_layer, 0, []) |
||||||
# TODO: temporary: delete ignored values |
# TODO: temporary: delete ignored values |
||||||
dst_ds.Destroy() |
dst_ds.Destroy() |
||||||
ds = None |
ds = None |
||||||
vec_ds = drv.Open(vec_save_path, 1) |
vec_ds = drv.Open(vec_save_path, 1) |
||||||
lyr = vec_ds.GetLayer() |
lyr = vec_ds.GetLayer() |
||||||
lyr.SetAttributeFilter("{} = '{}'".format(dst_fieldname, str(ignore_index))) |
lyr.SetAttributeFilter("{} = '{}'".format(dst_fieldname, str(ignore_index))) |
||||||
for holes in lyr: |
for holes in lyr: |
||||||
lyr.DeleteFeature(holes.GetFID()) |
lyr.DeleteFeature(holes.GetFID()) |
||||||
vec_ds.Destroy() |
vec_ds.Destroy() |
||||||
if tmp_path is not None: |
if tmp_path is not None: |
||||||
os.remove(tmp_path) |
os.remove(tmp_path) |
||||||
|
|
||||||
|
|
||||||
@time_it |
@time_it |
||||||
def raster2vector(srcimg_path, mask_path, save_path, ignore_index=255): |
def mask2shape(srcimg_path, mask_path, save_path, ignore_index=255): |
||||||
vec_ext = save_path.split(".")[-1].lower() |
vec_ext = save_path.split(".")[-1].lower() |
||||||
if vec_ext not in ["json", "geojson", "shp"]: |
if vec_ext not in ["json", "geojson", "shp"]: |
||||||
raise ValueError( |
raise ValueError( |
||||||
"The extension of `save_path` must be 'json/geojson' or 'shp', not {}.". |
"The extension of `save_path` must be 'json/geojson' or 'shp', not {}.". |
||||||
format(vec_ext)) |
format(vec_ext)) |
||||||
ras_ext = srcimg_path.split(".")[-1].lower() |
ras_ext = srcimg_path.split(".")[-1].lower() |
||||||
if osp.exists(srcimg_path) and ras_ext in ["tif", "tiff", "geotiff", "img"]: |
if osp.exists(srcimg_path) and ras_ext in ["tif", "tiff", "geotiff", "img"]: |
||||||
src = Raster(srcimg_path) |
src = Raster(srcimg_path) |
||||||
_polygonize_raster(mask_path, save_path, src.proj, src.geot, |
_polygonize_raster(mask_path, save_path, src.proj, src.geot, |
||||||
ignore_index, vec_ext) |
ignore_index, vec_ext) |
||||||
src = None |
src = None |
||||||
else: |
else: |
||||||
_polygonize_raster(mask_path, save_path, None, None, ignore_index, |
_polygonize_raster(mask_path, save_path, None, None, ignore_index, |
||||||
vec_ext) |
vec_ext) |
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser() |
parser = argparse.ArgumentParser() |
||||||
parser.add_argument("--mask_path", type=str, required=True, \ |
parser.add_argument("--mask_path", type=str, required=True, \ |
||||||
help="Path of mask data.") |
help="Path of mask data.") |
||||||
parser.add_argument("--save_path", type=str, required=True, \ |
parser.add_argument("--save_path", type=str, required=True, \ |
||||||
help="Path to save the shape file (the extension is .json/geojson or .shp).") |
help="Path to save the shape file (the extension is .json/geojson or .shp).") |
||||||
parser.add_argument("--srcimg_path", type=str, default="", \ |
parser.add_argument("--srcimg_path", type=str, default="", \ |
||||||
help="Path of original data with geoinfo. Default to empty.") |
help="Path of original data with geoinfo. Default to empty.") |
||||||
parser.add_argument("--ignore_index", type=int, default=255, \ |
parser.add_argument("--ignore_index", type=int, default=255, \ |
||||||
help="The ignored index will not be converted to a value in the shape file. Default value is 255.") |
help="The ignored index will not be converted to a value in the shape file. Default value is 255.") |
||||||
|
|
||||||
if __name__ == "__main__": |
if __name__ == "__main__": |
||||||
args = parser.parse_args() |
args = parser.parse_args() |
||||||
raster2vector(args.srcimg_path, args.mask_path, args.save_path, |
mask2shape(args.srcimg_path, args.mask_path, args.save_path, |
||||||
args.ignore_index) |
args.ignore_index) |
Loading…
Reference in new issue