^ 关注我,带你一起学GIS ^
注:当前使用的是 ol [9.2.4] 版本,天地图使用的
key
请到天地图官网申请,并替换为自己的key
前言
❝NDVI(Normalized Difference Vegetation Index)即归一化植被指数,是反应农作物长势和营养信息的重要参数之一,用于监测植物生长状态、植被覆盖度和消除部分辐射误差。其值在[-1,1]之间,-1表示可见光高反射;0表示有岩石或裸土等,NIR和R近似相等;正值,表示有植被覆盖,且值越大,表明植被覆盖度越高。计算公式:NDVI = (NIR – RED)/ (NIR + RED)
1. 加载数据源
在Landsat
卫星影像中,B4
为红色通道,B5
为近红外通道,所以加载B4
、B5
通道数据,并设置无值数据为0,设置图层为不透明度。
const source = new ol.source.GeoTIFF({
sources: [
{
// red band
url: "http://localhost/GeoTIFF/LC08_L2SP_129043_20211120_20211130_02_T1/LC08_L2SP_129043_20211120_20211130_02_T1_SR_B4.TIF",
max: 40000
},
{
// near infraed
url: "http://localhost/GeoTIFF/LC08_L2SP_129043_20211120_20211130_02_T1/LC08_L2SP_129043_20211120_20211130_02_T1_SR_B5.TIF",
max: 45000
}
],
nodata: 0, // 设置无效数据为0
opaque: true, // 设置不透明
// convertToRGB: true // 将色彩系统转换为RGB
})
2. 加载GeoTIFF图层
根据公式计算NDVI
值,并进行可视化表达。其中['/', value1, value2]
表示用value2
除以value1
,['-', ['band', 2], ['band', 1]]
表示用band2
–band1
,也就是近红外减去红外,['+', ['band', 2], ['band', 1]]
表示band2
+band1
,也就是近红外加上红外。
const tiffLayer = new ol.layer.WebGLTile({
source: source,
style: {
color: [
'interpolate',
['linear'],
// 计算NDVI值
['/', ['-', ['band', 2], ['band', 1]], ['+', ['band', 2], ['band', 1]]],
// NDVI色带,其值为[-1,1]
-0.2,
[191, 191, 191],
-0.1,
[219, 219, 219],
0,
[255, 255, 224],
0.025,
[255, 250, 204],
0.05,
[237, 232, 181],
0.075,
[222, 217, 156],
0.1,
[204, 199, 130],
0.125,
[189, 184, 107],
0.15,
[176, 194, 97],
0.175,
[163, 204, 89],
0.2,
[145, 191, 82],
0.25,
[128, 179, 71],
0.3,
[112, 163, 64],
0.35,
[97, 150, 54],
0.4,
[79, 138, 46],
0.45,
[64, 125, 36],
0.5,
[48, 110, 28],
0.55,
[33, 97, 18],
0.6,
[15, 84, 10],
0.65,
[0, 69, 0],
]
}
})
3. 显示NDVI值
鼠标在地图上移动或者点击地图时,显示NDVI值。
const displayPixelValue = (event) => {
// 返回像素位置数据,根据数据类型而定
const data = tiffLayer.getData(event.pixel)
if (!data) {
return
}
const red = data[0]
const nir = data[1]
const ndvi = (nir - red) / (nir + red)
const ndviInput = document.querySelector(".layui-input")
ndviInput.value = ndvi.toFixed(4)
}
// 监听鼠标移动和点击事件
map.on(["pointermove", "click"], displayPixelValue)
4. 完整代码
其中libs
文件夹下的包需要更换为自己下载的本地包或者引用在线资源。本示例引用了layui
组件,请自行替换。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>OpenLayers 根据Landsat计算NDVI</title>
<meta charset="utf-8" />
<script src="../../../libs/proj4.js"></script>
<script src="../../../js/ol9.2.4.js"></script>
<script src="../../../libs/layui/layui.js"></script>
<link rel="stylesheet" href="../../../css/ol9.2.4.css">
<link rel="stylesheet" href="../../../libs/layui/css/layui.css">
<script src="https://cdn.jsdelivr.net/npm/geotiff@2.1.3/dist-browser/geotiff.min.js"></script>
<style>
* {
padding: 0;
margin: 0;
font-size: 14px;
font-family: '微软雅黑';
}
.clearfix::after {
display: block;
content: "";
clear: both;
}
html,
body {
width: 100%;
height: 100%;
}
#map {
position: absolute;
top: 50px;
bottom: 0;
width: 100%;
}
#top-content {
position: absolute;
width: 100%;
height: 50px;
line-height: 50px;
background: linear-gradient(135deg, #ff00cc, #ffcc00, #00ffcc, #ff0066);
color: #fff;
text-align: center;
font-size: 32px;
}
#top-content span {
font-size: 32px;
}
#layer-container {
position: absolute;
top: 20%;
left: 20px;
width: 250px;
padding: 10px;
background: #fff;
color: #fff;
border: 1px solid #ddd;
border-radius: 2.5px;
}
.layer-head {
background: #16baaa;
padding: 10px;
margin-bottom: 15px;
}
.layer-form {
width: 100%;
}
.layui-form-label {
width: 44%;
padding: 8px 15px;
height: 38px;
line-height: 20px;
border-width: 1px;
border-style: solid;
border-radius: 2px 0 0 2px;
text-align: center;
background-color: #fafafa;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
box-sizing: border-box;
border-color: #eee;
font-weight: 400;
color: #000;
}
.layui-form-item {
margin-bottom: 0;
}
.layui-input[disabled] {
background-color: #fff;
}
</style>
</head>
<body>
<div id="top-content">
<span>OpenLayers 根据Landsat计算NDVI</span>
</div>
<div id="map" title="地图显示"></div>
<div id="layer-container">
<div class="layer-form">
<div class="layui-form-item">
<label class="layui-form-label">NDVI值</label>
<div class="layui-input-block">
<input type="number" disabled lay-affix="number" min="0" max="1" placeholder="显示NDVI值"
class="layui-input rectangle-layer">
</div>
</div>
</div>
</div>
</body>
</html>
<script>
const source = new ol.source.GeoTIFF({
sources: [
{
// red band
url: "http://localhost/GeoTIFF/LC08_L2SP_129043_20211120_20211130_02_T1/LC08_L2SP_129043_20211120_20211130_02_T1_SR_B4.TIF",
max: 40000
},
{
// near infraed
url: "http://localhost/GeoTIFF/LC08_L2SP_129043_20211120_20211130_02_T1/LC08_L2SP_129043_20211120_20211130_02_T1_SR_B5.TIF",
max: 45000
}
],
nodata: 0, // 设置无效数据为0
opaque: false, // 开启透明
// convertToRGB: true // 将色彩系统转换为RGB
})
// 加载GeoTIFF影像数据
const tiffLayer = new ol.layer.WebGLTile({
source: source,
style: {
color: [
'interpolate',
['linear'],
// 计算NDVI值
['/', ['-', ['band', 2], ['band', 1]], ['+', ['band', 2], ['band', 1]]],
// NDVI色带,其值为[-1,1]
-0.2,
[191, 191, 191],
-0.1,
[219, 219, 219],
0,
[255, 255, 224],
0.025,
[255, 250, 204],
0.05,
[237, 232, 181],
0.075,
[222, 217, 156],
0.1,
[204, 199, 130],
0.125,
[189, 184, 107],
0.15,
[176, 194, 97],
0.175,
[163, 204, 89],
0.2,
[145, 191, 82],
0.25,
[128, 179, 71],
0.3,
[112, 163, 64],
0.35,
[97, 150, 54],
0.4,
[79, 138, 46],
0.45,
[64, 125, 36],
0.5,
[48, 110, 28],
0.55,
[33, 97, 18],
0.6,
[15, 84, 10],
0.65,
[0, 69, 0],
]
}
})
source.getView().then(res => {
console.log(res)
})
const map = new ol.Map({
target: "map",
loadTilesWhileInteracting: true,
view: source.getView(),
// 地图默认控件
controls: ol.control.defaults.defaults({
zoom: false,
attribution: true,
rotate: true
})
})
map.addLayer(tiffLayer)
const displayPixelValue = (event) => {
// 返回像素位置数据,根据数据类型而定
const data = tiffLayer.getData(event.pixel)
if (!data) {
return
}
const red = data[0]
const nir = data[1]
const ndvi = (nir - red) / (nir + red)
const ndviInput = document.querySelector(".layui-input")
ndviInput.value = ndvi.toFixed(4)
}
map.on(["pointermove", "click"], displayPixelValue)
</script>
如何下载Landsat
卫星影像请参考:https://mp.weixin.qq.com/s?__biz=MzkwOTEzNjI5NQ==&mid=2247485131&idx=1&sn=6bf2af3b75f98a573ccc96a347fe837a&chksm=c13e1e03f649971529861ab97834750ea1bc824f992a32f3325f74a6a3174309b64cffb8f759#rd
如何加载GeoTIFF
影像请参考:https://mp.weixin.qq.com/s?__biz=MzkwOTEzNjI5NQ==&mid=2247485173&idx=1&sn=2e52d6df4ee71b67e1db8e32c9a22693&chksm=c13e1e3df649972b6f9edb7d7b2a452d9edcd81c535f88d1ffce7f480884f7a2fffdc017bfd9#rd
如何加载GeoTIFF
投影坐标请参考:https://mp.weixin.qq.com/s?__biz=MzkwOTEzNjI5NQ==&mid=2247485224&idx=1&sn=6d4e81a1f6e98deece1f427c9737542f&chksm=c13e1fe0f64996f6ed98101539b5270e0076bc933f05769f956f33059025dff252dbe7666501#rd
❝
OpenLayers示例数据下载,请在公众号后台回复:ol数据
全国信息化工程师-GIS 应用水平考试资料,请在公众号后台回复:GIS考试
❝
GIS之路公众号已经接入了智能助手,欢迎大家前来提问。
欢迎访问我的博客网站-长谈GIS:
http://shanhaitalk.com
都看到这了,不要忘记点赞、收藏+关注 哦!
本号不定时更新有关 GIS开发 相关内容,欢迎关注