使用ArcGis+Python(GDAL)制作语义分割遥感数据集


制作遥感数据集首先要有遥感影像数据。影像数据种类、来源很多,这里以GF-2的影像数据为例,制作用于 语义分割的数据集。直接获取的遥感影像需要进行预处理,进行大气校正、辐射定标等,这里不再介绍。这里使用预处理过后的GF-2影像(多光谱)进行数据集制作。

一、选择裁剪合适的影像区域

一景影像的数据非常大,我们所要使用的区域可能仅仅是一小部分,多余部分反而对数据集造成影像,而且影像尺寸过大,制作标签非常耗时耗力。因此要选择并裁剪所需要的区域。
选取技巧及原则:
1、选取矩形区域(利于滑动裁剪)
2、选择所要区分地物影像特征较强、对比明显的区域
3、类间差距大,类内差距小

1.1 打开ArcMap,加载影像。注意,实际上是4通道。制作的标签为RGB三通道,后面实际导出了三通道的影像。
在这里插入图片描述

1.2 新建shpfie文件,注意设置坐标系与影像一致。!!!
1.3画出所要选择的区域,尽量是矩形
1.4 使用裁剪工具裁剪
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可使用data export导出三通道tif
在这里插入图片描述
结果:原始影像area_4_1.tif就做好了,(5332,3587,3)

二、创建标签shp文件,目视解译勾画标签区域

影像数据是tif,我们需要的标签数据也应是tif,但是要先通过矢量文件勾画标签区域,再转化为栅格数据。
2.1创建shp面文件,注意,设置坐标系与原始影像一致!!
2.2目视解译勾画区域,需要结合地物在遥感影像上的特点。结合色调(全色影像)、颜色(彩色影像)、阴影*、形状、纹理、大小等特征进行判断。
在这里插入图片描述

三、标签shp修改属性并转换为tif文件

3.1 我们制作好标签shp后,修改它的属性id字段为255(0-255,RGB)。
在这里插入图片描述
3.2 转换为tif文件,注意:一定要设置像元大小与原始图像一致!!
否则有精度丢失!!
在这里插入图片描述
3.3 使用reclassify工具将生成tif文件的背景Nodata修改为0(0-255)

结果标签文件lable_4.tif
注意检查影像与标签的尺寸大小是否相同,必须相同才能进行下一步。
在这里插入图片描述

四、使用python滑动裁剪图像及标签

上述获得的影像数据和标签数据尺寸是几千几千,对于模型来说过大,这里使用python+gdal库自动裁剪为256256(或其他尺寸,2的n次方)的图像,并按一定命名方式存储(1,2,3。。。命名)
同时对影像数据标签数据裁剪。
代码:

import os
import gdal
import numpy as np
#  读取tif数据集
def readTif(fileName):
    dataset = gdal.Open(fileName)
    if dataset == None:
        print(fileName + "文件无法打开")
    return dataset
#  保存tif文件函数
def writeTiff(im_data, im_geotrans, im_proj, path):
    if 'int8' in im_data.dtype.name:
        datatype = gdal.GDT_Byte
    elif 'int16' in im_data.dtype.name:
        datatype = gdal.GDT_UInt16
    else:
        datatype = gdal.GDT_Float32
    if len(im_data.shape) == 3:
        im_bands, im_height, im_width = im_data.shape
    elif len(im_data.shape) == 2:
        im_data = np.array([im_data])
        im_bands, im_height, im_width = im_data.shape
    # 创建文件
    driver = gdal.GetDriverByName("GTiff")
    dataset = driver.Create(path, int(im_width), int(im_height), int(im_bands), datatype)
    if (dataset != None):
        dataset.SetGeoTransform(im_geotrans)  # 写入仿射变换参数
        dataset.SetProjection(im_proj)  # 写入投影
    for i in range(im_bands):
        dataset.GetRasterBand(i + 1).WriteArray(im_data[i])
    del dataset
'''
滑动窗口裁剪函数
TifPath 影像路径
SavePath 裁剪后保存目录
CropSize 裁剪尺寸
RepetitionRate 重复率
'''
def TifCrop(TifPath, SavePath, CropSize, RepetitionRate):
    dataset_img = readTif(TifPath)
    width = dataset_img.RasterXSize
    height = dataset_img.RasterYSize
    proj = dataset_img.GetProjection()
    geotrans = dataset_img.GetGeoTransform()
    img = dataset_img.ReadAsArray(0, 0, width, height)  # 获取数据

    #  获取当前文件夹的文件个数len,并以len+1命名即将裁剪得到的图像
    new_name = len(os.listdir(SavePath))
    #  裁剪图片,重复率为RepetitionRate

    for i in range(int((height - CropSize * RepetitionRate) / (CropSize * (1 - RepetitionRate)))):
        for j in range(int((width - CropSize * RepetitionRate) / (CropSize * (1 - RepetitionRate)))):
            #  如果图像是单波段
            if (len(img.shape) == 2):
                cropped = img[
                          int(i * CropSize * (1 - RepetitionRate)): int(i * CropSize * (1 - RepetitionRate)) + CropSize,
                          int(j * CropSize * (1 - RepetitionRate)): int(j * CropSize * (1 - RepetitionRate)) + CropSize]
            #  如果图像是多波段
            else:
                cropped = img[:,
                          int(i * CropSize * (1 - RepetitionRate)): int(i * CropSize * (1 - RepetitionRate)) + CropSize,
                          int(j * CropSize * (1 - RepetitionRate)): int(j * CropSize * (1 - RepetitionRate)) + CropSize]
            #  写图像
            writeTiff(cropped, geotrans, proj, SavePath + "/%d.tif" % new_name)
            #  文件名 + 1
            new_name = new_name + 1
    #  向前裁剪最后一列
    for i in range(int((height - CropSize * RepetitionRate) / (CropSize * (1 - RepetitionRate)))):
        if (len(img.shape) == 2):
            cropped = img[int(i * CropSize * (1 - RepetitionRate)): int(i * CropSize * (1 - RepetitionRate)) + CropSize,
                      (width - CropSize): width]
        else:
            cropped = img[:,
                      int(i * CropSize * (1 - RepetitionRate)): int(i * CropSize * (1 - RepetitionRate)) + CropSize,
                      (width - CropSize): width]
        #  写图像
        writeTiff(cropped, geotrans, proj, SavePath + "/%d.tif" % new_name)
        new_name = new_name + 1
    #  向前裁剪最后一行
    for j in range(int((width - CropSize * RepetitionRate) / (CropSize * (1 - RepetitionRate)))):
        if (len(img.shape) == 2):
            cropped = img[(height - CropSize): height,
                      int(j * CropSize * (1 - RepetitionRate)): int(j * CropSize * (1 - RepetitionRate)) + CropSize]
        else:
            cropped = img[:,
                      (height - CropSize): height,
                      int(j * CropSize * (1 - RepetitionRate)): int(j * CropSize * (1 - RepetitionRate)) + CropSize]
        writeTiff(cropped, geotrans, proj, SavePath + "/%d.tif" % new_name)
        #  文件名 + 1
        new_name = new_name + 1
    #  裁剪右下角
    if (len(img.shape) == 2):
        cropped = img[(height - CropSize): height,
                  (width - CropSize): width]
    else:
        cropped = img[:,
                  (height - CropSize): height,
                  (width - CropSize): width]
    writeTiff(cropped, geotrans, proj, SavePath + "/%d.tif" % new_name)
    new_name = new_name + 1
#训练集和验证集都要裁剪
#裁剪出 图像   特征。拿到  影像数据增强中进行数据增强
#  将影像1裁剪为重复率为0.1的256×256的数据集
#图像
TifCrop(r"E:\python\dx_data\area_3.tif",
        r"E:\python\dx_data\train\image1", 256, 0.1)
#标签
# TifCrop(r"E:\python\dx_data\lable.tif",
#         r"E:\python\dx_data\train\lable1", 256, 0.1)
#标签裁剪不正确????标签255问题????
#可能是无背景的原因

#已解决
#见笔记

结果
影像
在这里插入图片描述
标签
在这里插入图片描述

五、数据增强

数据增强是根据上述获得的裁剪后的256*256的影像和标签进行图像变换,实现数据集增多。
代码:

import gdal
import numpy as np
import os
import cv2


#  读取tif数据集
def readTif(fileName, xoff=0, yoff=0, data_width=0, data_height=0):
    dataset = gdal.Open(fileName)
    if dataset == None:
        print(fileName + "文件无法打开")
    #  栅格矩阵的列数
    width = dataset.RasterXSize
    #  栅格矩阵的行数
    height = dataset.RasterYSize
    #  波段数
    bands = dataset.RasterCount
    #  获取数据
    if (data_width == 0 and data_height == 0):
        data_width = width
        data_height = height
    data = dataset.ReadAsArray(xoff, yoff, data_width, data_height)
    #  获取仿射矩阵信息
    geotrans = dataset.GetGeoTransform()
    #  获取投影信息
    proj = dataset.GetProjection()
    return width, height, bands, data, geotrans, proj
#  保存tif文件函数
def writeTiff(im_data, im_geotrans, im_proj, path):
    if 'int8' in im_data.dtype.name:
        datatype = gdal.GDT_Byte
    elif 'int16' in im_data.dtype.name:
        datatype = gdal.GDT_UInt16
    else:
        datatype = gdal.GDT_Float32
    if len(im_data.shape) == 3:
        im_bands, im_height, im_width = im_data.shape
    elif len(im_data.shape) == 2:
        im_data = np.array([im_data])
        im_bands, im_height, im_width = im_data.shape
    # 创建文件
    driver = gdal.GetDriverByName("GTiff")
    dataset = driver.Create(path, int(im_width), int(im_height), int(im_bands), datatype)
    if (dataset != None):
        dataset.SetGeoTransform(im_geotrans)  # 写入仿射变换参数
        dataset.SetProjection(im_proj)  # 写入投影
    for i in range(im_bands):
        dataset.GetRasterBand(i + 1).WriteArray(im_data[i])
    del dataset
#训练集的数据及标签
train_image_path = r"E:\python\dx_data\train\image1"
train_label_path = r"E:\python\dx_data\train\lable1"
#  进行几何变换数据增强
imageList = os.listdir(train_image_path)
labelList = os.listdir(train_label_path)
tran_num = len(imageList) + 1
for i in range(len(imageList)):
    #  图像
    img_file = train_image_path + "\\" + imageList[i]
    im_width, im_height, im_bands, im_data, im_geotrans, im_proj = readTif(img_file)
    #  标签
    label_file = train_label_path + "\\" + labelList[i]
    label = cv2.imread(label_file)

    #  图像水平翻转
    im_data_hor = np.flip(im_data, axis=2)
    hor_path = train_image_path + "\\" + str(tran_num) + imageList[i][-4:]
    writeTiff(im_data_hor, im_geotrans, im_proj, hor_path)
    #  标签水平翻转
    Hor = cv2.flip(label, 1)
    hor_path = train_label_path + "\\" + str(tran_num) + labelList[i][-4:]
    cv2.imwrite(hor_path, Hor)
    tran_num += 1

    #  图像垂直翻转
    im_data_vec = np.flip(im_data, axis=1)
    vec_path = train_image_path + "\\" + str(tran_num) + imageList[i][-4:]
    writeTiff(im_data_vec, im_geotrans, im_proj, vec_path)
    #  标签垂直翻转
    Vec = cv2.flip(label, 0)
    vec_path = train_label_path + "\\" + str(tran_num) + labelList[i][-4:]
    cv2.imwrite(vec_path, Vec)
    tran_num += 1

    #  图像对角镜像
    im_data_dia = np.flip(im_data_vec, axis=2)
    dia_path = train_image_path + "\\" + str(tran_num) + imageList[i][-4:]
    writeTiff(im_data_dia, im_geotrans, im_proj, dia_path)
    #  标签对角镜像
    Dia = cv2.flip(label, -1)
    dia_path = train_label_path + "\\" + str(tran_num) + labelList[i][-4:]
    cv2.imwrite(dia_path, Dia)
    tran_num += 1

获得的数据将继续按顺序使用数字命名在相同文件夹下

六、训练集(图像,标签)和验证集(图像,标签)

结果上述步骤,获得众多影像数据和标签数据。
在这里插入图片描述
这里需要手动分割出验证集,新建文件夹存放,按一定比例分割。
注意影像要与标签一一对应,即名称相同
在这里插入图片描述
这样就制作好了一份遥感数据集用于语义分割,包括训练集(影像,标签)和验证集(影像,标签)
可在模型训练过程中不断调整数据集。

<think>好的,用户想了解如何制作遥感图像多类别语义分割数据集。我需要先回忆相关的引用内容,然后结合这些信息给出步骤。 首先,根据引用[2],制作数据集需要标注工具和注意事项。常用的工像是Labelme、ENVI或ArcGIS,可能需要高精度标注。另外,要注意地理坐标对齐和影像预处理,比如辐射校正和几何校正。 然后,引用[3]中提到云数据集的标签是单通道8位图片,每个像素值对应类别。比如0是无云,1是有云。多类别的话可能需要扩展像素值,比如0到N对应不同类别,每个类别有唯一的颜色或数值。 接下来,用户需要多类别,所以步骤可能包括:数据采集、预处理、标注、格式转换、数据增强、划分数据集。每个步骤需要详细说明。 数据采集部分要确保覆盖所有目标地物类型,分辨率一致。引用[3]中的数据集分辨率从0.5到15米不等,但实际制作时可能需要统一分辨率,避免模型训练问题。 预处理部分,引用[2]提到辐射和几何校正,确保影像质量。还有可能需要裁剪成小尺寸,比如引用[3]中的1280x720,但可能需要更小的块,如512x512,以适应模型输入。 标注工具方面,引用[2]建议使用专业的遥感工具如ENVI或ArcGIS,或者通用工具如Labelme。但Labelme生成的JSON需要转换成单通道的标签图。可能需要编写脚本转换,确保每个类别的像素值正确。 标签格式方面,引用[3]使用单通道8位,像素值对应类别。多类别同理,比如0背景,1建筑,2植被等。需要制作对照表,并检查标注准确性。 数据增强部分,旋转、翻转、色彩调整等,引用[2]提到实际业务中的数据增强方法。可能还需要处理类别不平衡问题,比如过采样或损失函数加权。 数据集划分,按比例分为训练、验证、测试集,确保分布均匀。引用[3]的数据集有150张,可能较小,所以划分时要注意代表性。 此外,质量检查很重要,如引用[2]提到的目视检查和逻辑校验。比如检查标注边界是否准确,是否存在漏标或错标。 最后,生成相关问题时,要考虑用户可能遇到的下一步问题,比如标注工具选择、处理不同分辨率、数据增强技巧等。</think>制作遥感图像多类别语义分割数据集的完整流程可分为以下步骤: ### 一、数据采集与预处理 1. **影像获取** 采集覆盖目标地物类型(如建筑、水体、植被等)的高分辨率遥感影像,需确保影像质量满足以下要求: - 空间分辨率一致(建议统一为0.5-2米级) - 包含多光谱或RGB三通道数据 - 覆盖不同季节、光照条件和地理环境[^2] 2. **影像预处理** - 几何校正:消除地形畸变和投影变形 - 辐射校正:调整光照差异和传感器噪声 - 影像裁剪:将大图分割为适合模型输入的尺寸(如512×512像素)[^3] ### 二、标注工具与方法 1. **标注工具选择** - 专业工具:ENVI/ArcGIS的ROI标注模块(支持地理坐标对齐) - 通用工具:Labelme(需后期坐标转换) - 自研工具:开发适配遥感影像特性的标注平台 2. **标注规范制定** ```markdown 类别定义示例: 0 - 背景 | RGB(0,0,0) 1 - 建筑物 | RGB(255,0,0) 2 - 道路 | RGB(0,255,0) 3 - 水体 | RGB(0,0,255) ``` - 需建立类别对照表并规定边界处理规则(如道路与建筑重叠处理) ### 三、标签文件生成 1. **格式转换** 将标注结果转换为单通道索引图: $$ \text{像素值} = \begin{cases} 0 & \text{背景} \\ 1 & \text{类别1} \\ 2 & \text{类别2} \\ \vdots & \vdots \end{cases} $$ 使用Python脚本实现矢量标注到栅格标签的转换: ```python import gdal, numpy as np def vector_to_raster(shp_path, tif_path, output_path): # 读取参考影像地理信息 dataset = gdal.Open(tif_path) # 创建同尺寸单通道标签文件 driver = gdal.GetDriverByName('GTiff') label_ds = driver.Create(output_path, dataset.RasterXSize, dataset.RasterYSize, 1, gdal.GDT_Byte) # 矢量栅格化处理... ``` ### 四、质量检查与增强 1. **质量验证** - 空间对齐检查:叠加原始影像与标签,偏移需小于1像素 - 类别完整性:统计各类别像素占比,避免样本失衡 - 逻辑校验:检查水体与道路的拓扑关系等地理逻辑 2. **数据增强策略** ```python from albumentations import ( HorizontalFlip, RandomRotate90, RandomBrightnessContrast ) train_transform = Compose([ HorizontalFlip(p=0.5), RandomRotate90(p=0.5), RandomBrightnessContrast(p=0.2), ]) ``` ### 五、数据集组织 推荐目录结构: ``` dataset/ ├── images/ │ ├── area1_001.tif │ └── area2_002.tif ├── labels/ │ ├── area1_001.tif │ └── area2_002.tif └── class_mapping.csv ```
评论 55
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值