arcgis字段计算器赋值_开源图像分割样本转换成ArcGIS可用格式

 从公众号一位读者那获取到了用地分类的开源样本集,记录一下开源样本集转换成ArcGIS格式的过程。希望能够帮助到大家。

01

查看样本数据

废话不多说,先看一下获取到的样本是啥样子的吧

851ce9aabc2dc721ea53a423e506204f.png

近红外影像:

5aa4272494c5c32578a97005482a8716.png

RGB图像:

88ca4589c9b0567330113968d98dcfb8.png

label:

58716154ac34a60826a821577367fc97.png

通过详细查看之后对影像有一个初步的认识:

  • RGB影像为8位三波段影像,满足要求。

  • 不管是影像还是label,都需要进一步裁剪才能参与到训练当中。

  • label标签为三波段,分为15类与5类。每一类都对应着特定的颜色,readme.txt中有写到:

387cc1e3a0da79247a4daf1f0e13ab85.png

  • 标签名称比原始影像名称多了一个_label,可以通过此规则一一对应。

其中label是三波段数据,既不满足互联网上多数图像分割的格式也不满足ArcGIS的格式,所以需要写代码进行处理。(此时你们肯定在想,那要处理成什么样子呢?e1cd4a44ebce611bd0a38f07b4efd3e4.png,下个部分讲解)

02

label数据处理

其实不管是什么样子的label,都要跟ArcGIS Pro自己生产的label保持相同格式。ArcGIS Pro生产的label是通过`训练样本管理器`或者是`标注对象以供深度学习使用`工具生成。

0474cd6a45be4798ebef8cf5fc7e66c9.png

不管是用哪个工具生成的样本,最终保存成矢量数据时属性表字段都差不多是一个样子的:

31f8183fb8f9036e9f182d98addbdbe1.png

这种格式就是我们想要的label格式,因为拿到这种矢量数据之后就可以使用`导出训练数据进行深度学习`工具导出成ArcGIS中深度学习样本格式。

那么我们的目标就很明确了,将三波段影像数据转换成矢量数据。既然是栅格转矢量,很明确ArcGIS Pro中有`栅格砖面`工具可以直接转,但是貌似三波段好像不太合适,所以还是要处理成单波段,然后转成矢量(心里默默nice!)。所以现在问题就转换成,如何将三波段转换成单波段,那在我的技术栈里面,就只会写代码转(如果有其他工具我不晓得的,还请一定要在讨论区留言),顺带着熟悉一下Arcpy。

那就开搞,在Pro中新建一个notebook,双击打开,然后开始写代码。首先导包:

import arcpyimport osimport numpy as np

定义工作区间等,并使用arcpy中的Raster类加载label栅格数据:

gdbpath = r'F:\pro_project\GID_landuse\GID_landuse.gdb'worksapce = r'F:\pro_project\GID_landuse'label_tif_path = os.path.join(worksapce,'GF2_PMS1__L1A0001765574-MSS1_label.tif')# 使用arcpy中Raster类读取栅格数据label_raster = arcpy.Raster(label_tif_path)label_raster

26006448ef596f9def2475f3a5dcca24.png

然后需要读取几个重要的属性:

width = label_raster.widthheight = label_raster.heightminx = label_raster.extent.YMinminy = label_raster.extent.XMincellsizeX = label_raster.meanCellWidthcellsizeY = label_raster.meanCellHeightspatialReference = label_raster.spatialReference
  • width:宽

  • height:高

  • Xmin,Ymin:栅格数据左下角的点

  • meanCellWidth:x方向像元大小

  • meanCellHeight:y方向像元大小

  • spatialReference:空间参考

更多Raster的属性可以查阅官网帮助:

https://pro.arcgis.com/zh-cn/pro-app/arcpy/classes/raster-object.htm

数据加载完之后,转换成numpy数组:

label_nd = arcpy.RasterToNumPyArray(label_raster)label_nd.shape # (3,6800,7200)

转换成numpy数组之后接下来就可以直接通过numpy进行操作了,RGB三个波段分别对应着label_nd[0]、label_nd[1]、label_nd[2]。接下来可以直接处理将三波段转换成单波段,每个地方的值对应着不同的类别,从1-5(我们在这里就直接使用5类数据做示例),背景值为0:

# 首先建立一个全为0的数组作为结果数组res_label = np.zeros([height,width],dtype=int)# 根据readme中的类别颜色进行掩膜式索引res_label[(label_nd[0,:,:] == 255) * (label_nd[1,:,:] == 0) * (label_nd[2,:,:] == 0)] = 1res_label[(label_nd[0,:,:] == 0) * (label_nd[1,:,:] == 255) * (label_nd[2,:,:] == 0)] = 2res_label[(label_nd[0,:,:] == 0) * (label_nd[1,:,:] == 255) * (label_nd[2,:,:] == 255)] = 3res_label[(label_nd[0,:,:] == 255) * (label_nd[1,:,:] == 255) * (label_nd[2,:,:] == 0)] = 4res_label[(label_nd[0,:,:] == 0) * (label_nd[1,:,:] == 0) * (label_nd[2,:,:] == 255)] = 5

很多人看到这里可能不知道在操作什么了,emmmm,就是将新建的结果数组按照索引赋值,生成索引的条件是原label数组中的是三个波段值。(emmmmm,别问我是怎么来的,问就是语法糖,也别问我语法糖是啥,问就是讨论区大佬留言解释。)为了便于理解,可以参考这个:

4804a4c50bbcde62b7b7aaa5512d22f4.png

(上一个配图与整体思路无关,只是为了方便理解而已。可以不去理解,用就是了10e200454216a26c35d0174eeea7b06a.png)

那么上一步的代码中就完全将三波段转换成单波段了。接下来转换成栅格,然后保存:

res_raster = arcpy.NumPyArrayToRaster(res_label,arcpy.Point(minx,miny),cellsizeX,cellsizeY)res_raster

b5a2318a402adfac68447aa28b8485dc.png

对比之前刚加载的栅格,可以看到大致转换成功了,后续可以加载至ArcGIS Pro中再次进行验证。接下来保存。

res_raster.save(os.path.join(gdbpath,'res_label'))

在Pro中设置透明度叠加影像之后:

92f6dc86cee61dc9793af01038490ca3.png

然后就可以使用工具转换成矢量了:

a2ba58a41450017e0734f76ef4a332d8.png

8fd65e8e5fd74328d2471810685576ed.png

03

字段转换与增加

现在矢量也转了,看起来也像那么回事了,就差最后的字段转换了。这一步可以用字段计算器来做,但是数量大起来之后会比较繁琐,所有我们选择ArcGIS API for Python处理236803cee46ad1cfd92f15c3d1073583.png。(依然使用notebook完成)

首先还是导包:

import pandas as pdfrom arcgis.features import GeoAccessor,GeoSeriesAccessor

然后加载矢量数据:

sdf = pd.DataFrame.spatial.from_featureclass(os.path.join(gdbpath,'samples'))sdf

e4022e4aa1ea1e1768836c81cccba99c.png

(我们看到有个SHAPE字段,有这个字段就代表着属于ArcGIS API for Python中的Spatial DataFrame。有兴趣的随机读取一条查看一下。)

因为要添加的字段值都是固定的,所以我们建立一个字典方便操作:

mapdic = {1: {"Classname": "built-up",              "Classvalue": 1,              "Classcode": 1,              "RED": 255,              "GREEN": 0,              "BLUE": 0              },          2: {"Classname": "farmland",              "Classvalue": 2,              "Classcode": 2,              "RED": 0,              "GREEN": 255,              "BLUE": 0              },          3: {"Classname": "forest",              "Classvalue": 3,              "Classcode": 3,              "RED": 0,              "GREEN": 255,              "BLUE": 255              },          4: {"Classname": "meadow",              "Classvalue": 4,              "Classcode": 4,              "RED": 255,              "GREEN": 255,              "BLUE": 0              },          5: {"Classname": "water",              "Classvalue": 5,              "Classcode": 5,              "RED": 0,              "GREEN": 0,              "BLUE": 255              },          0: {"Classname": "background",              "Classvalue": 0,              "Classcode": 0,              "RED": 0,              "GREEN": 0,              "BLUE": 0              }          }

然后增加字段:

# 拷贝一个作为最后输出结果resdf = sdf.copy()for col in ['Classname', 'Classvalue', 'Classcode', 'RED', 'GREEN', 'BLUE']:    resdf[col] = resdf.gridcode.apply(lambda x:mapdic[x][col])

8ee002981f6c156880fa6759bbb438b2.png

ok了,然后保存就可以了

resdf.spatial.to_featureclass(os.path.join(gdbpath,'samples_last'))

如果是使用字段计算器的话,可以类似这么使用(不过需要提前建字段,保证Classvalue、RED、BLUE、GREEN三个字段为长整形):

1f4955dd4f35c3c2c5f7a0e93bdc30f5.png

那么到这一步就可以使用ArcGIS Pro的`导出训练数据进行深度学习`工具进行样本导出了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值