【PythonRS】植被显示增强(多光谱、正射、照片等)

        很多时候我们需要某个区域的正射图,虽然正射图一般都运用了匀色的算法,整体色彩比较均衡。但如果研究区内有大量的植被,这个时候植被突出显示就很有必要了。所以今天给大家分享一下使用Python对多光谱、正射影像进行植被显示增强的算法。

一、加载需要的库

        这里的主要库是numpy用来读取图片的数组,gdal库用来读取多光谱数据。

import numpy as np
from osgeo import gdal
import tkinter.filedialog
# 创建窗口打开图片模块

二、多光谱数据增强

1.获取影像的基本信息

        这一步没啥用,可以不放进代码。主要让你先了解一下自己的数据。

def Get_data(filepath):""":param filepath: 输入数据路径:return: 输出影像的基本信息"""ds = gdal.Open(filepath)  # 打开数据集datasetds_width = ds.RasterXSize  # 获取数据宽度ds_height = ds.RasterYSize  # 获取数据高度ds_bands = ds.RasterCount  # 获取波段数ds_geo = ds.GetGeoTransform()  # 获取仿射地理变换参数ds_prj = ds.GetProjection()  # 获取投影信息print("影像的宽度为:" + str(ds_width))print("影像的高度为:" + str(ds_height))print("影像的波段数为:" + str(ds_bands))print("仿射地理变换参数为:" + str(ds_geo))print("投影坐标系为:" + str(ds_prj))# data = ds.ReadAsArray(0, 0, ds_width, ds_height)  # 以数组的形式读取整个数据集

2.算法核心

        由于多光谱是包含近红外波段的,同时呢,我们知道植被对于近红外波段有着很强的反射,其栅格值也会很大。所以这里我们使用近红外波段近似代替绿波段,这样就可以达到植被显示增强的目的了。但如果只是单纯的替代,那么其他对绿波段有反射的地物的颜色就会失真,你就会发现增强后,整个图变得非常奇怪。所以这里我们设定一个阈值,将绿波段和近红外波段综合起来再去代替绿波段。

Green = Green*0.8+NIR*0.2

3.代码实现

        这里我就不过多的解释了,因为里面的一些函数我之前发布的博文里都已经解释过了,同时代码我也做了详细的注释,所以大家直接看吧

def Enhance_Veg(filepath, out_path, green, nir):""":param filepath: 输入需要增强的图片路径:param out_path: 输入保存文件的路径:param green: 输入绿波段:param nir: 输入近红外波段:return:"""ds = gdal.Open(filepath)  # 打开数据集datasetds_width = ds.RasterXSize  # 获取数据宽度ds_height = ds.RasterYSize  # 获取数据高度ds_geo = ds.GetGeoTransform()  # 获取仿射地理变换参数ds_prj = ds.GetProjection()  # 获取投影信息ds_bands = ds.RasterCount  # 获取波段数driver = gdal.GetDriverByName('GTiff')  # 载入数据驱动,用于存储内存中的数组ds_result = driver.Create(out_path, ds_width, ds_height, bands=ds_bands+1, eType=gdal.GDT_Float64)# 创建一个数组,宽高为原始尺寸ds_result.SetGeoTransform(ds_geo)  # 导入仿射地理变换参数ds_result.SetProjection(ds_prj)  # 导入投影信息array_green = ds.GetRasterBand(green).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float64)array_nir = ds.GetRasterBand(nir).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float64)array_new_green = array_green * 0.8 + array_nir * 0.2for i in range(1, ds_bands):array_band = ds.GetRasterBand(i).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float64)ds_result.GetRasterBand(i).SetNoDataValue(0)  # 将无效值设为0ds_result.GetRasterBand(i).WriteArray(array_band)  # 将每个波段写入新的文件中ds_result.GetRasterBand(ds_bands+1).WriteArray(array_new_green)  # 将计算好的新绿波段写入del ds_result# 删除内存中的结果,否则结果不会写入图像中

三、RGB图像植被增强(正射影像)

1.算法核心

        由于RGB影像是没有近红外波段的,那么我们该怎么才能即增强植被的显示效果,又不改变其他地物的显示效果呢?这里我通过计算两种无需近红外波段就能计算的植被指数作为阈值计算的对象。很多植被指数我都试验过了,就这两种效果比较好:

1)绿叶指数 (GLI)

        GLI 指数在识别所有这些绿色和深色时非常敏感。负值将显示裸露的土壤、水体和人造基础设施。相反,正值就是类似于 NDVI 的颜色渐变来识别植被覆盖。如果你所在的区域有阴影、绿色潮湿的区域或裸露、潮湿和深色的土壤,应注意不要将植物覆盖分类错误。

GLI = ((绿 - 红) + (绿 - 蓝)) / ((2 * 绿) + 红 + 蓝)

2)红绿蓝植被指数 (RGBVI)

        利用可见光的三个波段。需要对值进行无监督的分类,以将植物与其他土地覆盖区分开来。

RGBVI = ((绿 * 绿) - (红 * 蓝)) / ((绿 * 绿) + (红 + 蓝))

        我们得到两种植被指数后,就需要建立一个合适的算法,去近似代替绿波段。这里我自己提出了两种算法,都是我实验之后效果比较好的:

Green = Green+Green*GLI

Green = Green*0.8+RGBVI*255*0.2

2.代码实现

        这个函数在运行时,会询问你需要使用哪种算法,再程序询问时,输入1或者2回车即可。

def Enhance_Veg_RGB(filepath, out_path, red, green, blue):""":param filepath: 输入需要增强的图片路径:param out_path: 输入保存文件的路径:param red: 输入红波段:param green: 输入绿波段:param blue: 输入蓝波段:return:"""np.seterr(divide='ignore', invalid='ignore')ds = gdal.Open(filepath)  # 打开数据集datasetds_width = ds.RasterXSize  # 获取数据宽度ds_height = ds.RasterYSize  # 获取数据高度ds_geo = ds.GetGeoTransform()  # 获取仿射地理变换参数ds_prj = ds.GetProjection()  # 获取投影信息ds_bands = ds.RasterCount  # 获取波段数driver = gdal.GetDriverByName('GTiff')  # 载入数据驱动,用于存储内存中的数组ds_result = driver.Create(out_path, ds_width, ds_height, bands=ds_bands+1, eType=gdal.GDT_Float64)# 创建一个数组,宽高为原始尺寸ds_result.SetGeoTransform(ds_geo)  # 导入仿射地理变换参数ds_result.SetProjection(ds_prj)  # 导入投影信息array_red = ds.GetRasterBand(red).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float64)array_green = ds.GetRasterBand(green).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float64)array_blue = ds.GetRasterBand(blue).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float64)GLI = ((array_green-array_red) + (array_green-array_blue))/((array_green*2)+array_red+array_blue)RGBVI = ((array_green*array_green)-(array_red*array_blue))/((array_green*array_green)+(array_red+array_blue))array_new_green = 0chance = int(input("请选择增强算法:1:GLI, 2:RGBVI\n"))if chance == 1:array_new_green = array_green + array_green*GLIelif chance == 2:array_new_green = array_green*0.8+RGBVI*0.2*255else:print('选择错误!')for i in range(1, ds_bands+1):array_band = ds.GetRasterBand(i).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float64)ds_result.GetRasterBand(i).SetNoDataValue(0)  # 将无效值设为0ds_result.GetRasterBand(i).WriteArray(array_band)  # 将每个波段写入新的文件中ds_result.GetRasterBand(ds_bands+1).SetNoDataValue(0)ds_result.GetRasterBand(ds_bands+1).WriteArray(array_new_green)  # 将计算好的新绿波段写入del ds_result# 删除内存中的结果,否则结果不会写入图像中

四、完整代码

        我这里使用了tkinter.filedialog调用了GUI窗口,以便于更方便地选取需要增强的图片。本来还想封装成程序的,但我太懒了。本来还想再出个ENVI实现的教程的,但我太懒了。所以现在还需要手动输入波段索引,同时还需要自己确定使用多光谱还是RGB增强函数。

        我这里还写了一个压缩函数,可以不要但不能没有。代码中已经注释掉了,不会用就不用。

# -*- coding: utf-8 -*-
"""
@Time : 2023/8/10 17:45
@Auth : RS迷途小书童
@File :Vegetation Enhancement.py
@IDE :PyCharm
@Purpose :影像中植被增强显示
"""
import numpy as np
from osgeo import gdal
import tkinter.filedialog
# 创建窗口打开图片模块def Get_data(filepath):""":param filepath: 输入数据路径:return: 输出影像的基本信息"""ds = gdal.Open(filepath)  # 打开数据集datasetds_width = ds.RasterXSize  # 获取数据宽度ds_height = ds.RasterYSize  # 获取数据高度ds_bands = ds.RasterCount  # 获取波段数ds_geo = ds.GetGeoTransform()  # 获取仿射地理变换参数ds_prj = ds.GetProjection()  # 获取投影信息print("影像的宽度为:" + str(ds_width))print("影像的高度为:" + str(ds_height))print("影像的波段数为:" + str(ds_bands))print("仿射地理变换参数为:" + str(ds_geo))print("投影坐标系为:" + str(ds_prj))# data = ds.ReadAsArray(0, 0, ds_width, ds_height)  # 以数组的形式读取整个数据集def Enhance_Veg(filepath, out_path, green, nir):""":param filepath: 输入需要增强的图片路径:param out_path: 输入保存文件的路径:param green: 输入绿波段:param nir: 输入近红外波段:return:"""ds = gdal.Open(filepath)  # 打开数据集datasetds_width = ds.RasterXSize  # 获取数据宽度ds_height = ds.RasterYSize  # 获取数据高度ds_geo = ds.GetGeoTransform()  # 获取仿射地理变换参数ds_prj = ds.GetProjection()  # 获取投影信息ds_bands = ds.RasterCount  # 获取波段数driver = gdal.GetDriverByName('GTiff')  # 载入数据驱动,用于存储内存中的数组ds_result = driver.Create(out_path, ds_width, ds_height, bands=ds_bands+1, eType=gdal.GDT_Float64)# 创建一个数组,宽高为原始尺寸ds_result.SetGeoTransform(ds_geo)  # 导入仿射地理变换参数ds_result.SetProjection(ds_prj)  # 导入投影信息array_green = ds.GetRasterBand(green).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float64)array_nir = ds.GetRasterBand(nir).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float64)array_new_green = array_green * 0.8 + array_nir * 0.2for i in range(1, ds_bands):array_band = ds.GetRasterBand(i).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float64)ds_result.GetRasterBand(i).SetNoDataValue(0)  # 将无效值设为0ds_result.GetRasterBand(i).WriteArray(array_band)  # 将每个波段写入新的文件中ds_result.GetRasterBand(ds_bands+1).WriteArray(array_new_green)  # 将计算好的新绿波段写入del ds_result# 删除内存中的结果,否则结果不会写入图像中def Image_Compress(path_image, path_out_image):""":param path_image: 输入需要压缩的影像路径:param path_out_image: 输出压缩后的影像路径:return: None"""ds = gdal.Open(path_image)# 打开影像数据driver = gdal.GetDriverByName('GTiff')# 创建输出的数据驱动driver.CreateCopy(path_out_image, ds, strict=1, options=["TILED=YES", "COMPRESS=PACKBITS", "BIGTIFF=YES"])# 设置压缩参数"""PACKBITS:连续字节压缩,快速无损压缩LZW:所有信息全部保留(可逆),以某一数值代替字符串,快速无损压缩"""del dsdef Enhance_Veg_RGB(filepath, out_path, red, green, blue):""":param filepath: 输入需要增强的图片路径:param out_path: 输入保存文件的路径:param red: 输入红波段:param green: 输入绿波段:param blue: 输入蓝波段:return:"""np.seterr(divide='ignore', invalid='ignore')ds = gdal.Open(filepath)  # 打开数据集datasetds_width = ds.RasterXSize  # 获取数据宽度ds_height = ds.RasterYSize  # 获取数据高度ds_geo = ds.GetGeoTransform()  # 获取仿射地理变换参数ds_prj = ds.GetProjection()  # 获取投影信息ds_bands = ds.RasterCount  # 获取波段数driver = gdal.GetDriverByName('GTiff')  # 载入数据驱动,用于存储内存中的数组ds_result = driver.Create(out_path, ds_width, ds_height, bands=ds_bands+1, eType=gdal.GDT_Float64)# 创建一个数组,宽高为原始尺寸ds_result.SetGeoTransform(ds_geo)  # 导入仿射地理变换参数ds_result.SetProjection(ds_prj)  # 导入投影信息array_red = ds.GetRasterBand(red).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float64)array_green = ds.GetRasterBand(green).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float64)array_blue = ds.GetRasterBand(blue).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float64)GLI = ((array_green-array_red) + (array_green-array_blue))/((array_green*2)+array_red+array_blue)RGBVI = ((array_green*array_green)-(array_red*array_blue))/((array_green*array_green)+(array_red+array_blue))array_new_green = 0chance = int(input("请选择增强算法:1:GLI, 2:RGBVI\n"))if chance == 1:array_new_green = array_green + array_green*GLIelif chance == 2:array_new_green = array_green*0.8+RGBVI*0.2*255else:print('选择错误!')for i in range(1, ds_bands+1):array_band = ds.GetRasterBand(i).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float64)ds_result.GetRasterBand(i).SetNoDataValue(0)  # 将无效值设为0ds_result.GetRasterBand(i).WriteArray(array_band)  # 将每个波段写入新的文件中ds_result.GetRasterBand(ds_bands+1).SetNoDataValue(0)ds_result.GetRasterBand(ds_bands+1).WriteArray(array_new_green)  # 将计算好的新绿波段写入del ds_result# 删除内存中的结果,否则结果不会写入图像中if __name__ == "__main__":fn_input = open(tkinter.filedialog.askopenfilename(title='选择图片', filetypes=[('所有文件', '.*'), ('JPG', '.jpg'), ('JPG', '.jpeg'),('TIFF', '.tif'), ('DAT', '.dat'), ('PNG', '.png')]), 'rb')# 输入的栅格数据路径fn_output = tkinter.filedialog.asksaveasfilename(defaultextension='.tif')# 导出的文件路径Get_data(fn_input.name)# Enhance_Veg(fn_input.name, fn_output, green=2, nir=4)  # 执行多光谱植被增强函数Enhance_Veg_RGB(fn_input.name, fn_output, red=1, green=2, blue=3)  # 执行RGB植被增强函数# Image_Compress(fn_output, fn_output)

五、效果图

        两图均是2%线性拉伸显示的效果。植被增强的效果很明显。

图1   原始图像

 图2   植被增强后

        需要注意的是,我为了保护原始文件,将新计算的绿波段加在了最后一个波段,所以要想查看增强效果,就用最后一个波段当成绿波段去真彩色显示!!!

        总的来说,本次博文分享的算法效果还不错。但代码并没有集成好,勉勉强强能用就行,感兴趣的话可以自己将它封装成程序。

        由于我代码中已给详细的解释,所以就不单独加以文字说明了。本文章主要是分享个人在学习Python过程中写过的一些代码。有些部分借鉴了前人以及官网的教程,如有侵权请联系作者删除,大家有问题可以随时留言交流,博主会及时回复。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/32367.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【学习FreeRTOS】第2章——FreeRTOS基础知识

1.任务调度 1.1.任务调度简介 调度器就是使用相关的调度算法来决定当前需要执行的哪个任务FreeRTOS 一共支持三种任务调度方式: 抢占式调度:针对优先级不同的任务,每个任务都有一个优先级,优先级高的任务可以抢占优先级低的任务…

【前端】CSS垂直居中的7种方法

文章目录 line-height绝对定位margin:autoflex绝对定位margin:负值定位transformvertical-align:middledisplay:table-cell思维导图 前文:【前端】CSS水平居中的6种方法_karshey的博客-CSDN博客 有很多相似的部分。 line-height 适用于单行的行内元素设置line-he…

模仿火星科技 基于cesium+角度测量+高度测量+可编辑

1. 创建提示窗: 启动Cesium应用,地图场景将打开,欢迎您进入编辑模式。 在屏幕的一角,一个友好的提示窗将呈现,随着您的操作,它会为您提供有用的信息和指导。 2. 绘制面积: 轻轻点击鼠标左键&a…

MySQL之 show profile 相关总结

MySQL之 show profile 相关总结 MySQL官网show profile介绍:https://dev.mysql.com/doc/refman/8.0/en/show-profile.html 1. 简介 show profile 和 show profiles 命令用于展示SQL语句的资源使用情况,包括CPU的使用,CPU上下文切换&#xf…

Docker 数据管理

文章目录 前言1、Dcoker 文件体系2、volume挂载案例2.1、挂载运行一个容器实例方法1方法2 3、volumes-from 案例4、备份/恢复数据卷5、删除数据卷 前言 为什么要有数据管理? 因为: Docker 是不提供持久化的 ,容器是不稳定的;一个…

mac ssh连接另一台window虚拟机vm

vmware配置端口映射 编辑(E) > 虚拟网络编辑器(N)... > NAT设置(S)... window防火墙,入站规则添加5555端口 控制面板 > 系统和安全 > Windows 防火墙>高级设置>入站规则>新建规则... tips windows查看端口命令:netstat -ano | f…

java-IDEA MAVEN查看依赖树,解决jar包重复和冲突

如果这里面的依赖关系有红线,就说明有包冲突,一般都是版本不一致,可以在idea里下一个插件Maven Helper,点击install并重启IDEA 打开pom.xml文件,在下方会出现Dependency Analyzer,选择它会出现重复依赖列表,选择对应的依赖,右键红…

BI技巧丨利用Index计算半累计

在实际的业务场景中,特别是财务模块和库存管理模块,经常需要我们针对每个月的期初期末进行相关指标计算,这也是我们之前曾经提到的Calculate基础应用——半累计计算。 现在我们也可以通过微软新推出的Index开窗函数来解决这一问题。 INDEX函…

Mapbox加载天地图CGCS2000矢量瓦片地图

1.背景 最近在做天地图的项目,要基于MapBox添加CGCS2000矢量切片数据,但是 Mapbox 只支持web 墨卡托(3857)坐标系的数据。Github有专业用户修改了mapbox-gl的相关代码,支持CGCS2000的切片数据加载,并且修改…

手动实现 Spring 底层机制 实现任务阶段一编写自己 Spring 容器-准备篇【2】

😀前言 手动实现 Spring 底层机制的第2篇 实现了任务阶段一编写自己 Spring 容器-准备篇【2】 🏠个人主页:尘觉主页 🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的…

后端进阶之路——深入理解Spring Security配置(二)

前言 「作者主页」:雪碧有白泡泡 「个人网站」:雪碧的个人网站 「推荐专栏」: ★java一站式服务 ★ ★前端炫酷代码分享 ★ ★ uniapp-从构建到提升★ ★ 从0到英雄,vue成神之路★ ★ 解决算法,一个专栏就够了★ ★ 架…

【STM32RT-Thread零基础入门】 2. 新建RT-Thread项目

硬件:STM32F103ZET6、ST-LINK、usb转串口工具 文章目录 前言一、新建RT-Thread项目二、项目结构三、构建项目四、下载程序(调试器下载)五、终端交互总结 前言 RT-Thread的全称是Real Time Thread,顾名思义,它是一个嵌…

UE中低延时播放RTSP监控视频解决方案

第1章 方案简介 1.1 行业痛点 在各种智慧城市、智慧社区、智慧水利、智慧矿山等数字孪生项目中,经常使用通UE来开发三维可视化场景。在这些场景中通常都需要把现场的各种监控视频在UE的可视化场景中接入,主要包含海康威视、大华、宇视、华为等众多监控…

Rust 编程小技巧摘选(8)

目录 Rust 编程小技巧(8) 1. 取整函数 floor() 2. 取整函数ceil() 3. 取整函数 round() 4. 保留小数位数 5. 字符串转整数 unwrap() unwrap_or() Rust 编程小技巧(8) 1. 取整函数 floor() floor函数对浮点数进行向下取整 示例代码: fn main() {let x: …

[C++项目] Boost文档 站内搜索引擎(5): cpphttplib实现网络服务、html页面实现、服务器部署...

在前四篇文章中, 我们实现了从文档文件的清理 到 搜索的所有内容: 项目背景: 🫦[C项目] Boost文档 站内搜索引擎(1): 项目背景介绍、相关技术栈、相关概念介绍…文档解析、处理模块parser的实现: 🫦[C项目] Boost文档 站内搜索引擎(2): 文档文本解析模块…

0基础学习VR全景平台篇 第80篇:Insta360 影石如何直播推流

一、下载Insta360 Pro APP 1、手机进入Insta360官网Insta360 | Action Cameras | 360 Cameras | VR Cameras,页面往下滑动到Insta360 Pro2相机处,点击相机图片进入详情页。详情页继续下滑到到手机APP处,根据自己的手机系统选择对应的客户端进…

计算机网络(6) --- https协议

计算机网络(5) --- http协议_哈里沃克的博客-CSDN博客http协议https://blog.csdn.net/m0_63488627/article/details/132089130?spm1001.2014.3001.5501 目录 1.HTTPS的出现 1.HTTPS协议介绍 2.补充概念 1.加密 1.解释 2.原因 3.加密方式 对称加…

【Linux】网络基础1

文章目录 网络基础11. 计算机网络背景1.1 网络发展 2. 认识协议2.1 网络协议2.2 OSI七层模型2.3 TCP/IP五层(或四层)模型 3. 网络传输基本流程3. 1 数据报封装和分用 4. 网络中的地址管理4.1 认识IP地址 5. 认识MAC地址 网络基础1 1. 计算机网络背景 1…

Flink-串讲面试题

1. 概念 有状态的流式计算框架 可以处理源源不断的实时数据,数据以event为单位,就是一条数据。 2. 开发流程 先获取执行环境env,然后添加source数据源,转换成datastream,然后使用各种算子进行计算,使用s…

数据结构 | 树的定义及实现

目录 一、树的术语及定义 二、树的实现 2.1 列表之列表 2.2 节点与引用 一、树的术语及定义 节点: 节点是树的基础部分。它可以有自己的名字,我们称作“键”。节点也可以带有附加信息,我们称作“有效载荷”。有效载荷信息对于很多树算法…