网易首页 > 网易号 > 正文 申请入驻

【教程】Python实现随机森林遥感图像分类

0
分享至

本期以landsat提取植被为例,更新如何用python实现随机森林遥感图像分类,原作者知乎王振庆,如对该文有任何疑问,请点击文章最下方阅读原文,与作者沟通交流。

1

随机森林(RandomForest)

随机森林,顾名思义是用随机的方式建立一个森林,森林里面有很多的决策树组成,随机森林的每一棵决策树之间是没有关联的。

随机森林的构造过程:

假如有N个样本,则有放回的随机选择N个样本(每次随机选择一个样本,然后返回继续选择)。这选择好了的N个样本用来训练一个决策树,作为决策树根节点处的样本。

当每个样本有M个属性时,在决策树的每个节点需要分裂时,随机从这M个属性中选取出m个属性,满足条件m << M。然后从这m个属性中采用某种策略(比如说信息增益)来选择1个属性作为该节点的分裂属性。

决策树形成过程中每个节点都要按照步骤2来分裂(很容易理解,如果下一次该节点选出来的那一个属性是刚刚其父节点分裂时用过的属性,则该节点已经达到了叶子节点,无须继续分裂了)。一直到不能够再分裂为止。注意整个决策树形成过程中没有进行剪枝。

2

随机森林遥感图像分类

以landsat提取植被为例,其实不论什么影像分什么类,操作都是一样的。

(1) 制作样本

a. 数字矢量化样本标签图

随机森林属于监督分类,监督分类是一定需要样本的。我们在Arcgis(ENVI也可)中目视解译矢量化一些植被与非植被的典型样本,然后【要素转栅格】将矢量数据转为栅格标签图。其中要注意:植被与非植被的值要设置为不同;转栅格的范围要与遥感图像一致。这样做的目的是为了方便抓取与标签图对应位置的遥感图像各波段值。

图1 Lanset真彩色图像

图2 栅格标签图

图1是landset的真彩色图像,图2是数字化样本并转成栅格的标签图像,标签图为单波段灰度图,为了更好地展示,我进行了RGB渲染。其中绿色的为植被样本,紫色的为非植被样本。

b. 样本数据集制作

样本数据集为txt,格式如图3所示。每行的前7个数为landset的7个波段值,Vegetation和Non-Vegetation表示该数据为植被还是非植被。具体制作过程直接上代码,注释很详细。

图3 样本数据集示意图


import gdalimport osimport random#读取tif数据集def readTif(fileName):dataset = gdal.Open(fileName)if dataset == None:print(fileName+"文件无法打开")return datasetLandset_Path = r"D:\ROI.tif"LabelPath = r"D:\label.tif"txt_Path = r"D:\data.txt"# 读取图像数据dataset = readTif(Landset_Path)Tif_width = dataset.RasterXSize #栅格矩阵的列数Tif_height = dataset.RasterYSize #栅格矩阵的行数Tif_bands = dataset.RasterCount #波段数Tif_geotrans = dataset.GetGeoTransform()#获取仿射矩阵信息Landset_data = dataset.ReadAsArray(0,0,Tif_width,Tif_height)dataset = readTif(LabelPath)Label_data = dataset.ReadAsArray(0,0,Tif_width,Tif_height)# 写之前,先检验文件是否存在,存在就删掉if os.path.exists(txt_Path):os.remove(txt_Path)# 以写的方式打开文件,如果文件不存在,就会自动创建file_write_obj = open(txt_Path, 'w')#首先收集植被类别样本,#遍历所有像素值,#为植被的像元全部收集。count = 0for i in range(Label_data.shape[0]):for j in range(Label_data.shape[1]):# 我设置的植被类别在标签图中像元值为1if(Label_data[i][j] == 1):var = ""for k in range(Landset_data.shape[0]):var = var + str(Landset_data[k][i][j])+","var = var + "Vegetation"file_write_obj.writelines(var)file_write_obj.write('\n')count = count + 1#其次收集非植被类别样本,#因为非植被样本比植被样本多很多,#所以采用在所有非植被类别中随机选择非植被样本,#数量与植被样本数量保持一致。Threshold = countcount = 0for i in range(10000000000):X_random = random.randint(0,Label_data.shape[0]-1)Y_random = random.randint(0,Label_data.shape[1]-1)# 我设置的非植被类别在标签图中像元值为0if(Label_data[X_random][Y_random] == 0):var = ""for k in range(Landset_data.shape[0]):var = var + str(Landset_data[k][X_random][Y_random])+","var = var + "Non-Vegetation"file_write_obj.writelines(var)file_write_obj.write('\n')count = count + 1if(count == Threshold):breakfile_write_obj.close()

(2) 模型训练

随机森林模型我们采用sklearn库中自带的随机森林模型RandomForestClassifier。具体训练过程直接上代码,注释很详细。


from sklearn.ensemble import RandomForestClassifierimport numpy as npfrom sklearn import model_selectionimport pickle# 定义字典,便于来解析样本数据集txtdef Iris_label(s):it={b'Vegetation':0, b'Non-Vegetation':1}return it[s]path=r"D:\data.txt"SavePath = r"D:\model.pickle"# 1.读取数据集data=np.loadtxt(path, dtype=float, delimiter=',', converters={7:Iris_label} )# converters={7:Iris_label}中“7”指的是第8列:将第8列的str转化为label(number)# 2.划分数据与标签x,y=np.split(data,indices_or_sections=(7,),axis=1) #x为数据,y为标签x=x[:,0:7] #选取前7个波段作为特征train_data,test_data,train_label,test_label = model_selection.train_test_split(x,y, random_state=1, train_size=0.9,test_size=0.1)# 3.用100个树来创建随机森林模型,训练随机森林classifier = RandomForestClassifier(n_estimators=100,bootstrap = True,max_features = 'sqrt')classifier.fit(train_data, train_label.ravel())#ravel函数拉伸到一维# 4.计算随机森林的准确率print("训练集:",classifier.score(train_data,train_label))print("测试集:",classifier.score(test_data,test_label))# 5.保存模型#以二进制的方式打开文件:file = open(SavePath, "wb")#将模型写入文件:pickle.dump(classifier, file)#最后关闭文件:file.close()

(3) 模型预测

训练好了模型,就该进行我们遥感图像的预测了。具体预测过程依旧直接上代码,注释很详细。


import numpy as npimport gdalimport pickle#读取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_Byteelif 'int16' in im_data.dtype.name:datatype = gdal.GDT_UInt16else:datatype = gdal.GDT_Float32if len(im_data.shape) == 3:im_bands, im_height, im_width = im_data.shapeelif 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 datasetRFpath = r"D:\model.pickle"Landset_Path = r"D:\20130514_ROI.tif"SavePath = r"D:\save.tif"dataset = readTif(Landset_Path)Tif_width = dataset.RasterXSize #栅格矩阵的列数Tif_height = dataset.RasterYSize #栅格矩阵的行数Tif_geotrans = dataset.GetGeoTransform()#获取仿射矩阵信息Tif_proj = dataset.GetProjection()#获取投影信息Landset_data = dataset.ReadAsArray(0,0,Tif_width,Tif_height)#调用保存好的模型#以读二进制的方式打开文件file = open(RFpath, "rb")#把模型从文件中读取出来rf_model = pickle.load(file)#关闭文件file.close()#用读入的模型进行预测# 在与测试前要调整一下数据的格式data = np.zeros((Landset_data.shape[0],Landset_data.shape[1]*Landset_data.shape[2]))for i in range(Landset_data.shape[0]):data[i] = Landset_data[i].flatten()data = data.swapaxes(0,1)# 对调整好格式的数据进行预测pred = rf_model.predict(data)# 同样地,我们对预测好的数据调整为我们图像的格式pred = pred.reshape(Landset_data.shape[1],Landset_data.shape[2])*255pred = pred.astype(np.uint8)# 将结果写到tif图像里writeTiff(pred,Tif_geotrans,Tif_proj,SavePath)

预测结果如下:

图4 RF预测结果结果图像

-----END-----

(请添加下方小助手微信)

来源:生态遥感笔记

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
曼联4200万可签德里赫特!拉爵或改变新中卫目标,大英铁卫亦候选

曼联4200万可签德里赫特!拉爵或改变新中卫目标,大英铁卫亦候选

罗米的曼联博客
2024-06-16 09:09:49
广东深圳,男子喜获双胞胎儿子,可他无意间发现,两个儿子竟然两个爹

广东深圳,男子喜获双胞胎儿子,可他无意间发现,两个儿子竟然两个爹

娱乐圈见解说
2024-06-16 07:05:18
张天爱自拍大秀“凶器”,身材气质绝佳!曾和娜扎联手锤渣男?

张天爱自拍大秀“凶器”,身材气质绝佳!曾和娜扎联手锤渣男?

狐飞火
2024-06-15 00:40:03
德布劳内:有些球队比我们更热门 我们需要取得一个好的开始

德布劳内:有些球队比我们更热门 我们需要取得一个好的开始

直播吧
2024-06-16 11:44:15
张镇麟晒新疆旅游照:原谅我的拍照技术 只会直男视角

张镇麟晒新疆旅游照:原谅我的拍照技术 只会直男视角

直播吧
2024-06-15 22:15:04
汶川9岁英雄,被姚明抱上奥运会,发誓考清华,16年后竟活成这样

汶川9岁英雄,被姚明抱上奥运会,发誓考清华,16年后竟活成这样

华人星光
2024-06-14 16:18:28
加强漏洞!美国媒体:4换1交易曝光,火箭势必崛起,森林狼不亏!

加强漏洞!美国媒体:4换1交易曝光,火箭势必崛起,森林狼不亏!

元爸体育
2024-06-16 07:39:47
“难度直线飙升,堪比高考”!上海中考作文题公布,进来挑战→

“难度直线飙升,堪比高考”!上海中考作文题公布,进来挑战→

上观新闻
2024-06-15 18:19:51
张学良临终吐露,当年被蒋介石扣押后,救他一命的其实不是宋美龄

张学良临终吐露,当年被蒋介石扣押后,救他一命的其实不是宋美龄

小金鱼的眼泪
2024-06-16 10:25:00
同房后,精子进入女人体内没“受精”,女人身体会有什么感觉?

同房后,精子进入女人体内没“受精”,女人身体会有什么感觉?

荷兰豆爱健康
2024-06-16 07:45:07
又上当了!老美急哭:我只是想吓吓你们而已,不要当真啊

又上当了!老美急哭:我只是想吓吓你们而已,不要当真啊

芯怡飞
2024-06-10 10:49:06
孙中山临终前想睡在地上,还要求有冰,侧室听后哭道:他还记得

孙中山临终前想睡在地上,还要求有冰,侧室听后哭道:他还记得

否知
2024-06-14 09:55:31
这16岁?!亚马尔1v4单挑克罗地亚整条防线,2次变向直接晃倒对手

这16岁?!亚马尔1v4单挑克罗地亚整条防线,2次变向直接晃倒对手

直播吧
2024-06-16 01:37:13
G7统一对华施压,中国改签货币协议,降息潮来临,人民币汇率回调

G7统一对华施压,中国改签货币协议,降息潮来临,人民币汇率回调

说天说地说实事
2024-06-15 19:50:03
千里马姜萍改变伯乐王闰秋命运,这里隐藏着一个神奇密码?

千里马姜萍改变伯乐王闰秋命运,这里隐藏着一个神奇密码?

解筱文
2024-06-16 00:06:54
他曾是中央政治局常委,后却被秘密处决,尸骨至今仍下落不明

他曾是中央政治局常委,后却被秘密处决,尸骨至今仍下落不明

燕小姐说历史
2024-06-15 08:49:56
主动发声!马刺引爆联盟,法国前锋或联手文班,莱特太会办事了

主动发声!马刺引爆联盟,法国前锋或联手文班,莱特太会办事了

体育晓二
2024-06-16 11:14:59
回顾上海华山医生杀妻细节曝光,疑与出轨有关,妻子执意打掉二胎

回顾上海华山医生杀妻细节曝光,疑与出轨有关,妻子执意打掉二胎

琪琪故事记
2024-06-16 07:17:04
2-0!瑞士“廉价前锋”破门,利物浦巨星全场隐身,破欧洲杯纪录

2-0!瑞士“廉价前锋”破门,利物浦巨星全场隐身,破欧洲杯纪录

汪星人哟
2024-06-15 21:50:55
俄专家:俄中双方在三年内启动大约3000个投资项目

俄专家:俄中双方在三年内启动大约3000个投资项目

俄罗斯卫星通讯社
2024-06-15 16:05:26
2024-06-16 12:10:44
测绘之家
测绘之家
有测绘的地方,就有测绘之家!
4900文章数 3490关注度
往期回顾 全部

科技要闻

iPhone 16会杀死大模型APP吗?

头条要闻

法国股市暴跌引发恐慌 马克龙:法国处于非常严峻时刻

头条要闻

法国股市暴跌引发恐慌 马克龙:法国处于非常严峻时刻

体育要闻

没人永远年轻 但青春如此无敌还是离谱了些

娱乐要闻

上影节红毯:倪妮好松弛,娜扎吸睛

财经要闻

打断妻子多根肋骨 上市公司创始人被公诉

汽车要闻

售17.68万-21.68万元 极狐阿尔法S5正式上市

态度原创

亲子
本地
游戏
旅游
家居

亲子要闻

孩子吃饭时习惯让别人盛饭,外婆是这样做的...

本地新闻

粽情一夏|海河龙舟赛,竟然成了外国人的大party!

回暖!《绝地潜兵2》更新之后PC玩家数量飙升86%

旅游要闻

@毕业生,江苏这些景区可享免票或优惠

家居要闻

空谷来音 朴素留白的侘寂之美

无障碍浏览 进入关怀版