Переглянути джерело

Support multi-channel for UNet and some transforms. Add install doc

chulutao 3 роки тому
батько
коміт
174919b790

+ 11 - 0
docs/install.md

@@ -0,0 +1,11 @@
+PaddleRS develop安装
+
+github代码会跟随开发进度不断更新,可以安装develop分支的代码使用最新的功能,安装方式如下:
+
+```commandline
+git clone https://github.com/PaddleCV-SIG/PaddleRS
+cd PaddleRS
+git checkout develop
+pip install -r requirements.txt
+python setup.py install
+```

+ 0 - 0
paddlers/models/gan/__init__.py


+ 0 - 0
paddlers/models/ppgan/__init__.py


+ 4 - 3
paddlers/models/ppseg/models/unet.py

@@ -41,12 +41,13 @@ class UNet(nn.Layer):
 
 
     def __init__(self,
     def __init__(self,
                  num_classes,
                  num_classes,
+                 input_channel=3,
                  align_corners=False,
                  align_corners=False,
                  use_deconv=False,
                  use_deconv=False,
                  pretrained=None):
                  pretrained=None):
         super().__init__()
         super().__init__()
 
 
-        self.encode = Encoder()
+        self.encode = Encoder(input_channel)
         self.decode = Decoder(align_corners, use_deconv=use_deconv)
         self.decode = Decoder(align_corners, use_deconv=use_deconv)
         self.cls = self.conv = nn.Conv2D(
         self.cls = self.conv = nn.Conv2D(
             in_channels=64,
             in_channels=64,
@@ -72,11 +73,11 @@ class UNet(nn.Layer):
 
 
 
 
 class Encoder(nn.Layer):
 class Encoder(nn.Layer):
-    def __init__(self):
+    def __init__(self, input_channel=3):
         super().__init__()
         super().__init__()
 
 
         self.double_conv = nn.Sequential(
         self.double_conv = nn.Sequential(
-            layers.ConvBNReLU(3, 64, 3), layers.ConvBNReLU(64, 64, 3))
+            layers.ConvBNReLU(input_channel, 64, 3), layers.ConvBNReLU(64, 64, 3))
         down_channels = [[64, 128], [128, 256], [256, 512], [512, 512]]
         down_channels = [[64, 128], [128, 256], [256, 512], [512, 512]]
         self.down_sample_list = nn.LayerList([
         self.down_sample_list = nn.LayerList([
             self.down_sampling(channel[0], channel[1])
             self.down_sampling(channel[0], channel[1])

+ 2 - 0
paddlers/tasks/segmenter.py

@@ -661,6 +661,7 @@ class BaseSegmenter(BaseModel):
 
 
 class UNet(BaseSegmenter):
 class UNet(BaseSegmenter):
     def __init__(self,
     def __init__(self,
+                 input_channel=3,
                  num_classes=2,
                  num_classes=2,
                  use_mixed_loss=False,
                  use_mixed_loss=False,
                  use_deconv=False,
                  use_deconv=False,
@@ -672,6 +673,7 @@ class UNet(BaseSegmenter):
         })
         })
         super(UNet, self).__init__(
         super(UNet, self).__init__(
             model_name='UNet',
             model_name='UNet',
+            input_channel=input_channel,
             num_classes=num_classes,
             num_classes=num_classes,
             use_mixed_loss=use_mixed_loss,
             use_mixed_loss=use_mixed_loss,
             **params)
             **params)

+ 4 - 8
paddlers/transforms/operators.py

@@ -927,7 +927,7 @@ class RandomExpand(Transform):
     def __init__(self,
     def __init__(self,
                  upper_ratio=4.,
                  upper_ratio=4.,
                  prob=.5,
                  prob=.5,
-                 im_padding_value=(127.5, 127.5, 127.5),
+                 im_padding_value=127.5,
                  label_padding_value=255):
                  label_padding_value=255):
         super(RandomExpand, self).__init__()
         super(RandomExpand, self).__init__()
         assert upper_ratio > 1.01, "expand ratio must be larger than 1.01"
         assert upper_ratio > 1.01, "expand ratio must be larger than 1.01"
@@ -935,10 +935,6 @@ class RandomExpand(Transform):
         self.prob = prob
         self.prob = prob
         assert isinstance(im_padding_value, (Number, Sequence)), \
         assert isinstance(im_padding_value, (Number, Sequence)), \
             "fill value must be either float or sequence"
             "fill value must be either float or sequence"
-        if isinstance(im_padding_value, Number):
-            im_padding_value = (im_padding_value, ) * 3
-        if not isinstance(im_padding_value, tuple):
-            im_padding_value = tuple(im_padding_value)
         self.im_padding_value = im_padding_value
         self.im_padding_value = im_padding_value
         self.label_padding_value = label_padding_value
         self.label_padding_value = label_padding_value
 
 
@@ -967,7 +963,7 @@ class Padding(Transform):
                  target_size=None,
                  target_size=None,
                  pad_mode=0,
                  pad_mode=0,
                  offsets=None,
                  offsets=None,
-                 im_padding_value=(127.5, 127.5, 127.5),
+                 im_padding_value=127.5,
                  label_padding_value=255,
                  label_padding_value=255,
                  size_divisor=32):
                  size_divisor=32):
         """
         """
@@ -1005,9 +1001,9 @@ class Padding(Transform):
 
 
     def apply_im(self, image, offsets, target_size):
     def apply_im(self, image, offsets, target_size):
         x, y = offsets
         x, y = offsets
-        im_h, im_w = image.shape[:2]
+        im_h, im_w, channel = image.shape[:3]
         h, w = target_size
         h, w = target_size
-        canvas = np.ones((h, w, 3), dtype=np.float32)
+        canvas = np.ones((h, w, channel), dtype=np.float32)
         canvas *= np.array(self.im_padding_value, dtype=np.float32)
         canvas *= np.array(self.im_padding_value, dtype=np.float32)
         canvas[y:y + im_h, x:x + im_w, :] = image.astype(np.float32)
         canvas[y:y + im_h, x:x + im_w, :] = image.astype(np.float32)
         return canvas
         return canvas

+ 1 - 6
tutorials/train/README.md

@@ -22,14 +22,9 @@
 - [PaddlePaddle安装](https://www.paddlepaddle.org.cn/install/quick)
 - [PaddlePaddle安装](https://www.paddlepaddle.org.cn/install/quick)
 * 版本要求:PaddlePaddle>=2.1.0
 * 版本要求:PaddlePaddle>=2.1.0
 
 
-<!-- - [PaddleRS安装](../../docs/install.md) -->
+- [PaddleRS安装](../../docs/install.md)
 
 
 ## 开始训练
 ## 开始训练
-* 修改tutorials/train/semantic_segmentation/deeplabv3p_resnet50_multi_channel.py中sys.path路径
-```
-sys.path.append("your/PaddleRS/path")
-```
-
 * 在安装PaddleRS后,使用如下命令开始训练,代码会自动下载训练数据, 并均使用单张GPU卡进行训练。
 * 在安装PaddleRS后,使用如下命令开始训练,代码会自动下载训练数据, 并均使用单张GPU卡进行训练。
 
 
 ```commandline
 ```commandline

+ 5 - 10
tutorials/train/semantic_segmentation/deeplabv3p_resnet50_multi_channel.py

@@ -1,6 +1,5 @@
-import sys
-
-sys.path.append("/mnt/chulutao/PaddleRS")
+import os
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
 
 
 import paddlers as pdrs
 import paddlers as pdrs
 from paddlers import transforms as T
 from paddlers import transforms as T
@@ -10,23 +9,21 @@ dataset = 'https://paddleseg.bj.bcebos.com/dataset/remote_sensing_seg.zip'
 pdrs.utils.download_and_decompress(dataset, path='./data')
 pdrs.utils.download_and_decompress(dataset, path='./data')
 
 
 # 定义训练和验证时的transforms
 # 定义训练和验证时的transforms
-# API说明:https://github.com/PaddlePaddle/paddlers/blob/develop/docs/apis/transforms/transforms.md
 channel = 10
 channel = 10
 train_transforms = T.Compose([
 train_transforms = T.Compose([
     T.Resize(target_size=512),
     T.Resize(target_size=512),
     T.RandomHorizontalFlip(),
     T.RandomHorizontalFlip(),
     T.Normalize(
     T.Normalize(
-        mean=[0.5] * 10, std=[0.5] * 10),
+        mean=[0.5] * channel, std=[0.5] * channel),
 ])
 ])
 
 
 eval_transforms = T.Compose([
 eval_transforms = T.Compose([
     T.Resize(target_size=512),
     T.Resize(target_size=512),
     T.Normalize(
     T.Normalize(
-        mean=[0.5] * 10, std=[0.5] * 10),
+        mean=[0.5] * channel, std=[0.5] * channel),
 ])
 ])
 
 
 # 定义训练和验证所用的数据集
 # 定义训练和验证所用的数据集
-# API说明:https://github.com/PaddlePaddle/paddlers/blob/develop/docs/apis/datasets.md
 train_dataset = pdrs.datasets.SegDataset(
 train_dataset = pdrs.datasets.SegDataset(
     data_dir='./data/remote_sensing_seg',
     data_dir='./data/remote_sensing_seg',
     file_list='./data/remote_sensing_seg/train.txt',
     file_list='./data/remote_sensing_seg/train.txt',
@@ -44,12 +41,10 @@ eval_dataset = pdrs.datasets.SegDataset(
     shuffle=False)
     shuffle=False)
 
 
 # 初始化模型,并进行训练
 # 初始化模型,并进行训练
-# 可使用VisualDL查看训练指标,参考https://github.com/PaddlePaddle/paddlers/blob/develop/docs/visualdl.md
+# 可使用VisualDL查看训练指标
 num_classes = len(train_dataset.labels)
 num_classes = len(train_dataset.labels)
 model = pdrs.tasks.DeepLabV3P(input_channel=channel, num_classes=num_classes, backbone='ResNet50_vd')
 model = pdrs.tasks.DeepLabV3P(input_channel=channel, num_classes=num_classes, backbone='ResNet50_vd')
 
 
-# API说明:https://github.com/PaddlePaddle/paddlers/blob/develop/docs/apis/models/semantic_segmentation.md
-# 各参数介绍与调整说明:https://github.com/PaddlePaddle/paddlers/blob/develop/docs/parameters.md
 model.train(
 model.train(
     num_epochs=10,
     num_epochs=10,
     train_dataset=train_dataset,
     train_dataset=train_dataset,

+ 2 - 3
tutorials/train/semantic_segmentation/farseg_test.py

@@ -1,6 +1,5 @@
-import sys
-
-sys.path.append("E:/dataFiles/github/PaddleRS")
+import os
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
 
 
 import paddlers as pdrs
 import paddlers as pdrs
 from paddlers import transforms as T
 from paddlers import transforms as T

+ 59 - 0
tutorials/train/semantic_segmentation/unet_multi_channel.py

@@ -0,0 +1,59 @@
+import os
+os.environ['CUDA_VISIBLE_DEVICES'] = '0'
+
+import paddlers as pdrs
+from paddlers import transforms as T
+
+# 下载和解压多光谱地块分类数据集
+dataset = 'https://paddleseg.bj.bcebos.com/dataset/remote_sensing_seg.zip'
+pdrs.utils.download_and_decompress(dataset, path='./data')
+
+# 定义训练和验证时的transforms
+channel = 10
+train_transforms = T.Compose([
+    T.Resize(target_size=512),
+    T.RandomHorizontalFlip(),
+    T.RandomBlur(1),
+    T.Padding(768),
+    T.RandomExpand(1.5, prob=1),
+    T.Resize(target_size=512),
+    T.Normalize(
+        mean=[0.5] * channel, std=[0.5] * channel),
+])
+
+eval_transforms = T.Compose([
+    T.Resize(target_size=512),
+    T.Normalize(
+        mean=[0.5] * channel, std=[0.5] * channel),
+])
+
+# 定义训练和验证所用的数据集
+train_dataset = pdrs.datasets.SegDataset(
+    data_dir='./data/remote_sensing_seg',
+    file_list='./data/remote_sensing_seg/train.txt',
+    label_list='./data/remote_sensing_seg/labels.txt',
+    transforms=train_transforms,
+    num_workers=0,
+    shuffle=True)
+
+eval_dataset = pdrs.datasets.SegDataset(
+    data_dir='./data/remote_sensing_seg',
+    file_list='./data/remote_sensing_seg/val.txt',
+    label_list='./data/remote_sensing_seg/labels.txt',
+    transforms=eval_transforms,
+    num_workers=0,
+    shuffle=False)
+
+# 初始化模型,并进行训练
+# 可使用VisualDL查看训练指标
+num_classes = len(train_dataset.labels)
+model = pdrs.tasks.UNet(input_channel=channel, num_classes=num_classes)
+
+model.train(
+    num_epochs=20,
+    train_dataset=train_dataset,
+    train_batch_size=4,
+    eval_dataset=eval_dataset,
+    learning_rate=0.01,
+    save_dir='output/unet',
+    use_vdl=True)