最近在学这方面,但是首先岩石分类的代码很少,其实很多软件都做的很成熟了,也没必要自己写,主要就学习一下吧。其次云平台关于高光谱的分析教程也不多,可能和数据不好获取有关吧。基于上面两点,差不多都没有找到基于云平台的高光谱岩石分类的现成代码- - 自己整合了一个,希望帮助到需要的人。
一、原理
高光谱分类和多光谱分类在常用算法上具有一定差别。本实验以光谱角匹配为例。大概解释一下,就是Image中的每个像素与参考光谱进行计算,设置阈值,最后给像素赋值。
二、数据说明:
1.var image = ee.Image('users/xxx/GF5') 高分5预处理后301波段数据 地表反射数据(0-0.5左右范围)
2.var csvDataset = ee.FeatureCollection('users/xxx/RockSpectrum6class'); 参考光谱 .csv文件 每列以1,2,...,301为列名。整体为一个6x301矩阵,即6类岩石,301band。原文件为.sli文件,用python转的.csv,如果需要这部分代码可留言。
三、代码(自写自用 有些注释很具体 以及有些内容稍冗余 自行修改):
/***********************************************
rock classification with SAM // copyrights by Lo
***********************************************/
// select the image
var image = ee.Image('users/xxx/GF5')
Map.addLayer(image, {bands: ['b51', 'b31', 'b21'], min: 0, max: 0.5}, 'original image'); //add layer
Map.centerObject(image,9); //Zoom to layer extent
// compute the image length
var arrayImage1D = image.toArray();
var arrayImage2D = arrayImage1D.toArray(1);
var arrayImage2D_2 = arrayImage2D.arrayTranspose(0, 1);
var arrayImage2D_3 = arrayImage2D_2.matrixMultiply(arrayImage2D)
.arrayProject([0])
.arrayFlatten([['Img']])
.sqrt();
// 访问上传到GEE中的CSV数据集
var csvDataset = ee.FeatureCollection('users/xxx/RockSpectrum6class');
// 初始化一个空数组来存储每个类别的SAM图层
var samLayers = [];
// 获取数据集的所有特征
var allFeatures = csvDataset.toList(csvDataset.size());
// print(allFeatures)
// 循环处理每个类别的数据集
for (var i = 0; i < allFeatures.size().getInfo(); i++) {
var currentFeature = ee.Feature(allFeatures.get(i));
// 初始化一个空数组
var dataArray = [];
// 循环遍历 301 列数据并添加到数组中
for (var j = 1; j <= 301; j++) {
var columnName = j.toString();
// var columnName = 'band_' + j; // 如果列名为 band_1, band_2, ..., band_301
var value = ee.Number.parse(currentFeature.get(columnName));
dataArray.push(value);
//dataArray.push(value.multiply(10000));
}
// 将数组转换为 Earth Engine 的数组对象
var STD_SampleValue = ee.Array([dataArray]); // 将数组转换为 Earth Engine 数组对象
// 计算标准光谱曲线的长度
// compute the STD_SampleValue length
var STD_SampleValue = ee.Image(STD_SampleValue);
var STD_SampleValue_T = STD_SampleValue.arrayTranspose(0,1);
var STD_SampleValue_Length = STD_SampleValue.matrixMultiply(STD_SampleValue_T)
.arrayProject([0])
.arrayFlatten([['Standard']])
.sqrt();
// compute the SAM
var samImage = ee.Image(STD_SampleValue)
.matrixMultiply(arrayImage2D)
.arrayProject([0])
.arrayFlatten([['brightness']]);
var sam = samImage.divide(arrayImage2D_3).divide(STD_SampleValue_Length).acos();
//Map.addLayer(sam, null, 'the value of SAM'); //加载SAM图层,每个像素点有6个SAM值,从而更好地设置阈值。
// 添加计算得到的SAM图像到samLayers数组中
samLayers.push(sam.mask(sam.lte(0.3)));
}
// Merge SAM layers into a single image 'min' and vis
var mergedSAM = ee.ImageCollection.fromImages(samLayers).reduce(ee.Reducer.min());
var visParam = {
min: 0,
max: 0.3,
palette: 'ff0000, ffff00, 0000ff, 556B2F, ffa500, 808080'
};
Map.addLayer(mergedSAM, visParam, 'Merged SAM');
// 将所有类别SAM lte0.3合并为一个图层进行可视化
var SAM_6class = ee.Image(samLayers);
print(SAM_6class,'SAMLayer') //output and lookfor the information
// 用数字表示最接近的岩石类别
var closestClass = SAM_6class.eq(ee.ImageCollection(samLayers).reduce(ee.Reducer.min())) // 找到最小值所在的波段
.multiply(ee.Image([1, 2, 3, 4, 5, 6])) // 乘以一个序列来为不同的波段分配不同的类别编号
.reduce(ee.Reducer.sum()) // 求和,以获取非零值对应的类别编号
.rename('Closest_Rock_Class'); //对结果图像进行重命名为,在地图中添加图层时,将图层标识为最接近岩石类别的像素编号。
// 可视化最接近的岩石类别
Map.addLayer(closestClass, {min: 1, max: 6, palette: ['red', 'blue', 'green', 'yellow', 'purple', 'orange']}, 'Closest Rock Class');
四、结果
原始影像不放了,简单放个结果。
上面的图GEE跑出来的,下面的图ENVI SAM 单阈值0.3跑出来的 感觉问题不大。
Note:转载注明出处