OpenLayers 加载GeoTIFF影像波段组合

前言

Landsat卫星数据具有很多波段,每种波段都有不同的用途。而对波段进行合成,根据波段类型组合形成不同的遥感影像对研究、应用具有更大的价值。遥感影像波段组合不仅能够获取更加全面和丰富的信息,还能提高影像的清晰度和增强地质解译能力。

1. 波段组合

在示例中,默认加载4、3、2波段

arduino 复制代码
const bandSources = [
    {
        // red band
        url: BAND_URL + "B4.TIF",
        max: 15000,
        // min: 6842
    },
    {
        // green band
        url: BAND_URL + "B3.TIF",
        max: 15000,
        // min: 6566
    },
    {
        // blue band
        url: BAND_URL + "B2.TIF",
        max: 15000,
        // min: 4967
    },
]

在开关按钮事件中更新数据源对象,开关打开时显示添加,关闭时显示移除,并更新波段数组对象。如果只有一个开关时,设置不能关闭开关,将checked值设置为true然后返回。

javascript 复制代码
form.on('switch(switch-box-filter)', function (data) {

    const elem = data.elem; // 获得 checkbox 原始 DOM 对象
    const checked = elem.checked; // 获得 checkbox 选中状态
    const value = elem.value; // 获得 checkbox 值
    console.log("复选框信息:", data)
    if (checked) {
        const url = BAND_URL + elem.name + ".TIF"
        bandSources.push({ url: url, max: 15000 })

    } else {
        if (bandSources.length === 1) {
            layer.msg("不能取消最后一个波段!")
            elem.checked = true
            return
        }
        // 查找目标对象索引
        const index = bandSources.findIndex(band => band.name === elem.name)
        bandSources.splice(index, 1)
    }
    bandSources.sort()

    // 重新创建数据源
    const source = new ol.source.GeoTIFF({
        sources: bandSources,
        nodata: 0, // 设置无效数据为0
        // opaque: false, // 开启透明
        // convertToRGB: true // 将色彩系统转换为RGB
    })
    tiffLayer.setSource(source)
});

2. 调整影像值

可以调整影像波段最大max最小值min,查看影像显示效果。对于波段像素值的大小,可以在ArcMap中进行查看。

3. 波段显示效果

  • 432: 自然真彩色
  • 543: 标准假彩色图像
  • 754: 短波红外
  • 753: 假彩色

4. 完整代码

其中libs文件夹下的包需要更换为自己下载的本地包或者引用在线资源。本示例引用了layui组件,请自行替换。

xml 复制代码
<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>OpenLayers 加载GeoTIFF影像波段组合</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="../../../libs/js/geotiff.min.js"></script>
    <style>
        * {
            padding: 0;
            margin: 0;
            font-size: 14px;
            font-family: '微软雅黑';
        }

        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: 15%;
            left: 20px;
            width: 30%;
            bottom: 5%;
            background: #fff;
            color: #fff;
            border: 1px solid #ddd;
            border-radius: 2.5px;
        }

        .layer-head {
            background: #16baaa;
            padding: 10px;
            margin-bottom: 15px;
        }

        .layer-form {
            padding: 0 10px;
        }

        .layui-form-label {
            width: 100%;
            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-icon-custome {
            color: #ccc;
        }

        .layui-icon-custome:hover {
            cursor: pointer;
            color: #1E9FFF;
        }

        .layer-prop-set {
            display: none;
            position: absolute;
            padding: 10px;
            margin-top: 120px;
            margin-left: 345px;
            width: 250px;
            background: #fff;
            border-radius: 5px;
            box-shadow: 5px 6px 6px 2px #d3d3d3;
        }

        .layer-prop-item {
            display: flex;
            justify-content: space-between;
            flex-direction: row;
            margin: 10px 0;

        }

        .layer-slider-item {
            width: 70%;
            margin-top: 7px;
        }

        .clearfix::after {
            display: block;
            content: "";
            clear: both;
        }

        .band-table {
            padding: 5px;
            max-height: 80%;
            overflow-y: scroll;
        }
    </style>
</head>

<body>
    <div id="top-content">
        <span>OpenLayers 加载Landsat GeoTIFF 波段组合</span>
    </div>
    <div id="map" title="地图显示"></div>
    <div id="layer-container">
        <h2 class="layer-head">Landsat8 卫星影像波段组合</h2>
        <div class="band-table">
            <table class="layui-table">
                <!-- <colgroup>
                    <col>
                    <col>
                    <col>
                </colgroup> -->
                <thead>
                    <tr>
                        <th width="30px">序号</th>
                        <th width="130px">波段</th>
                        <th>用途</th>
                        <th width="60px">操作</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>1</td>
                        <td>Coastal(海岸波段)</td>
                        <td>主要用于海岸带观测</td>
                        <td class="layui-form">
                            <input type="checkbox" lay-filter="switch-box-filter" title="添加|移除" name="B1"
                                lay-skin="switch">
                        </td>
                    </tr>
                    <tr>
                        <td>2</td>
                        <td>Blue(蓝波段)</td>
                        <td>用于水体穿透,分辨土壤植被</td>
                        <td class="layui-form">
                            <input type="checkbox" checked lay-filter="switch-box-filter" title="添加|移除" name="B2"
                                lay-skin="switch">
                        </td>
                    </tr>
                    <tr>
                        <td>3</td>
                        <td>Green(绿波段)</td>
                        <td>用于分辨植被</td>
                        <td class="layui-form">
                            <input type="checkbox" checked lay-filter="switch-box-filter" title="添加|移除" name="B3"
                                lay-skin="switch">
                        </td>
                    </tr>
                    <tr>
                        <td>4</td>
                        <td>Red(红波段)</td>
                        <td>处于叶绿素吸收区,用于观测道路,裸露土壤,植被种类等</td>
                        <td class="layui-form">
                            <input type="checkbox" checked lay-filter="switch-box-filter" title="添加|移除" name="B4"
                                lay-skin="switch">
                        </td>
                    </tr>
                    <tr>
                        <td>5</td>
                        <td>NIR(近红外波段)</td>
                        <td>用于估算生物量,分辨潮湿土壤</td>
                        <td class="layui-form">
                            <input type="checkbox" lay-filter="switch-box-filter" title="添加|移除" name="B5"
                                lay-skin="switch">
                        </td>
                    <tr>
                        <td>6</td>
                        <td>SWIR 1(短波红外1)</td>
                        <td class="layui-form">用于分辨道路,裸露土壤,水,还能在不同植被之间有好的对比度,并且有较好的大气、云雾分辨能力</td>
                        <td class="layui-form">
                            <input type="checkbox" lay-filter="switch-box-filter" title="添加|移除" name="B6"
                                lay-skin="switch">
                        </td>
                    </tr>
                    <tr>
                        <td>7</td>
                        <td>SWIR 2(短波红外2)</td>
                        <td>用于岩石,矿物的分辨很有用,也可用于辨识植被覆盖和湿润土壤</td>
                        <td class="layui-form">
                            <input type="checkbox" lay-filter="switch-box-filter" title="添加|移除" name="B7"
                                lay-skin="switch">
                        </td>
                    </tr>
                    <tr>
                        <td>8</td>
                        <td>Pan(全色波段)</td>
                        <td>为15米分辨率的黑白图像,用于增强分辨率</td>
                        <td class="layui-form">
                            <input type="checkbox" lay-filter="switch-box-filter" title="添加|移除" name="B8"
                                lay-skin="switch">
                        </td>
                    </tr>
                    <tr>
                        <td>9</td>
                        <td>Cirrus(卷云波段)</td>
                        <td>包含水汽强吸收特征,可用于云检测</td>
                        <td class="layui-form">
                            <input type="checkbox" lay-filter="switch-box-filter" title="添加|移除" name="B9"
                                lay-skin="switch">
                        </td>
                    </tr>
                    <tr>
                        <td>10</td>
                        <td>TIRS 1(热红外1)</td>
                        <td>感应热辐射的目标</td>
                        <td class="layui-form">
                            <input type="checkbox" lay-filter="switch-box-filter" title="添加|移除" name="B10"
                                lay-skin="switch">
                        </td>
                    </tr>
                    <tr>
                        <td>11</td>
                        <td>TIRS 2(热红外2)</td>
                        <td>感应热辐射的目标</td>
                        <td class="layui-form">
                            <input class="" type="checkbox" lay-filter="switch-box-filter" title="添加|移除" name="B11"
                                lay-skin="switch">
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
</body>

</html>

<script>
    const BAND_URL = "http://localhost/GeoTIFF/LC08_L2SP_129043_20211120_20211130_02_T1/LC08_L2SP_129043_20211120_20211130_02_T1_SR_"

    // const BAND_URL = "http://localhost/GeoTIFF/LC81300422021043LGN00/LC08_L1TP_130042_20210212_20210304_01_T1_"

    const bandSources = [
        {
            // red band
            url: BAND_URL + "B4.TIF",
            max: 15000,
            // min: 6842
        },
        {
            // green band
            url: BAND_URL + "B3.TIF",
            max: 15000,
            // min: 6566
        },
        {
            // blue band
            url: BAND_URL + "B2.TIF",
            max: 15000,
            // min: 4967
        },
    ]
    layui.use(function () {
        const form = layui.form;
        const layer = layui.layer

        // checkbox 事件
        form.on('switch(switch-box-filter)', function (data) {

            const elem = data.elem; // 获得 checkbox 原始 DOM 对象
            const checked = elem.checked; // 获得 checkbox 选中状态
            const value = elem.value; // 获得 checkbox 值
            console.log("复选框信息:", data)
            if (checked) {
                const url = BAND_URL + elem.name + ".TIF"
                bandSources.push({ url: url, max: 15000 })

            } else {
                if (bandSources.length === 1) {
                    layer.msg("不能取消最后一个波段!")
                    elem.checked = true
                    return
                }
                // 查找目标对象索引
                const index = bandSources.findIndex(band => band.name === elem.name)
                bandSources.splice(index, 1)
            }
            bandSources.sort()

            const source = new ol.source.GeoTIFF({
                sources: bandSources,
                nodata: 0, // 设置无效数据为0
                // opaque: false, // 开启透明
                // convertToRGB: true // 将色彩系统转换为RGB
            })
            tiffLayer.setSource(source)
        });
    });

    function createLayer(bandSources) {
        const source = new ol.source.GeoTIFF({
            sources: bandSources,
            nodata: 0, // 设置无效数据为0
            // opaque: false, // 开启透明
            // convertToRGB: true // 将色彩系统转换为RGB
        })
        // 加载GeoTIFF影像数据
        const tiffLayer = new ol.layer.WebGLTile({
            source: source
        })
        return tiffLayer
    }
    const tiffLayer = createLayer(bandSources)
    const source = tiffLayer.getSource()
    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)
</script>

Reference

波段数据组合介绍:www.yuque.com/u37362584/p...

相关推荐
崔庆才丨静觅4 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60615 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了5 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅5 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅6 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment6 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅6 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊6 小时前
jwt介绍
前端
爱敲代码的小鱼6 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax