基于Python 中创建 Sentinel-2 RGB 合成图像

一、前言

下面的python代码将带您了解如何从原始 Sentinel-2 图像创建 RGB 合成图像的过程。

免费注册后,可以从 Open Access Hub 下载原始图像。 请注意,激活您的帐户可能需要 24 小时!

二、准备工作

(1)导入必要的库


import matplotlib.pyplot as plt
import numpy as np
import rasterio
import os
from osgeo import gdal

加载库后,我们必须定义输入和输出文件夹。 输入文件夹是您必须放置下载的 Sentinel-2 图像的地方。 输出文件夹是我们的脚本将保存 RGB 合成图像的地方。

(2)还必须为每个波段指定输入文件名。


fp_in='input/'
fp_out='output/'

fn_blue='Tihany_T33TYN_A021798_20210509T094028_B02'
fn_green='Tihany_T33TYN_A021798_20210509T094028_B03'
fn_red='Tihany_T33TYN_A021798_20210509T094028_B04'

要使用 Sentinel-2 图像,首先我们必须将它们从 '.jp2' 文件格式转换为 '.tif' 文件格式,因为 Rasterio 库只能处理后者。


bandList = [band for band in os.listdir(fp_in) if band[-4:]=='.jp2']
for band in bandList:
    in_image = gdal.Open(fp_in+band)
    driver = gdal.GetDriverByName("GTiff")
    fp_tif = fp_in+band[:-4]+'.tif'
    out_image = driver.CreateCopy(fp_tif, in_image, 0)
    in_image = None
    out_image = None   

三、创建原始 RGB 合成

让我们为每个转换后的 Sentinel-2 图像定义文件路径,并使用 Rasterio 打开它们。


band_02=rasterio.open(fp_in+fn_blue+'.tif')
band_03=rasterio.open(fp_in+fn_green+'.tif')
band_04=rasterio.open(fp_in+fn_red+'.tif')

现在我们必须读入打开的文件。


red = band_04.read(1)
green = band_03.read(1)
blue = band_02.read(1)

(1) 如果我们查看红色波段栅格,我们将看到以下内容:


plt.imshow(red)

蓝色图像基本上是一个强度图,其中每个像素代表 Sentinel-2 传感器在红色波段中捕获的反射光量。 较亮的像素(较高的值)代表更多的红色内容,而较暗的像素(较低的值)代表较少的红色内容。

我们可以使用“cmap”命令更改蓝色表示。 在下面的示例中,我选择了“Reds”表示。

(请注意,还有许多其他选项。有关更多详细信息,请查看 Matplotlib 文档)。


plt.imshow(red, cmap='Reds')

现在让我们看看红色、绿色和蓝色通道图像是什么样子的。


fig = plt.figure(figsize=(20,6))
ax1 = fig.add_subplot(1,3,1)
ax1.imshow(red, cmap='Reds')
ax1 = fig.add_subplot(1,3,2)
ax1.imshow(green, cmap='Greens')
ax1 = fig.add_subplot(1,3,3)
ax1.imshow(blue, cmap='Blues')

您可以使用 shape 命令获取红色带图像的大小,如下所示。

如您所见,此图像是一个具有 582 行和 981 列的二维数组。

要制作 RGB 合成图,我们必须使用 np.dstack 命令将红色、绿色和蓝色波段图像堆叠在一起成为一个图像。

如果我们在新创建的 RGB 合成上再次调用形状命令,我们将看到,现在我们得到了一个包含红色、绿色和蓝色通道的 3D 数组。


rgb_composite_raw= np.dstack((red, green, blue))
rgb_composite_raw.shape

现在让我们看一下 RGB 图像...


plt.imshow(rgb_composite_raw)

这不是我们要找的,对吧? 问题的根源在于大多数图像的像素值范围为 0-255 或 0-1。 如果我们查看红色带的最大像素值,我们会得到超过 255。

(2) 我们现在能做什么? 此问题的解决方案是对 0..1 之间的所有像素值进行归一化。


def normalize(band):
    band_min, band_max = (band.min(), band.max())
    return ((band-band_min)/((band_max - band_min)))

red_n = normalize(red)
green_n = normalize(green)
blue_n = normalize(blue)

在对我们的图像进行归一化处理后,一个波段的最大值和最小值应为 0 和 1。

现在让我们再次进行 RGB 堆栈,看看我们得到了什么结果。


rgb_composite_n= np.dstack((red_n, green_n, blue_n))
plt.imshow(rgb_composite_n)

最后我们可以看到我们感兴趣的区域,但是颜色似乎不太真实,整个图像有点暗。

四、基本图像处理技术

(1)波段运算

为了解决这个问题,我们必须先使每个波段变亮,然后将它们归一化并进行叠加。从数学的角度来看,增亮函数将每个像素值与“alpha”相乘,并在必要时添加“beta”值。如果完成此操作,我们必须将结果像素值裁剪在 0..255 之间。


def brighten(band):
    alpha=0.13
    beta=0
    return np.clip(alpha*band+beta, 0,255)

red_b=brighten(red)
blue_b=brighten(blue)
green_b=brighten(green)

red_bn = normalize(red_b)
green_bn = normalize(green_b)
blue_bn = normalize(blue_b)

现在让我们看一下对波段进行增亮和标准化后的新 RGB 合成图。


rgb_composite_bn= np.dstack((red_bn, green_bn, blue_bn))
plt.imshow(rgb_composite_bn)

现在我们的图像看起来非常逼真。 请注意,此图像并不代表真实的反射率值。

另一种图像处理技术是伽马校正。 它背后的数学原理是我们采用每个像素的强度值并将其提高到 (1/gamma) 的幂,其中 gamma 值由我们指定。

让我们使用我们的原始图像,进行伽马校正和归一化。


def gammacorr(band):
    gamma=2
    return np.power(band, 1/gamma)

red_g=gammacorr(red)
blue_g=gammacorr(blue)
green_g=gammacorr(green)

red_gn = normalize(red_g)
green_gn = normalize(green_g)
blue_gn = normalize(blue_g)

现在让我们看看结果。


rgb_composite_gn= np.dstack((red_gn, green_gn, blue_gn))
plt.imshow(rgb_composite_gn)

(2)将图像保存为PNG

此时大多数人想做的是将图像保存到文件中。这可以通过以下代码行来完成,将亮化和规范化的图像保存到 PNG 文件中。

请注意,给出了一种插值方法来平滑图像,并且还可以控制 dpi 值。有关详细信息,请访问 Pyplot 文档。


rgb_plot=plt.imshow(rgb_composite_bn, interpolation='lanczos')
plt.axis('off')
plt.savefig(fp_out+'tihany_rgb_composite.png',dpi=200,bbox_inches='tight')
plt.close('all')

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Mybatis-Plus篇】Mybatis-Plus基本使用

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

跳转应用市场详情页market

关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、商业变现、人工智能等,希望大家多多支持。 未经允许不得转载 目录 一、导读二、概览三、跳转到各大厂商应…

思科模拟器操作命令

模式 思科模拟器常见的模式有 用户模式 能够操作的命令比较少 特权模式特权模式下面可以操作的比较多 全局模式 接口模式 用户模式进入特权模式: 命令enable 特权模式进行全局模式命令: configure terminal 退出命令 exit命令:返回上一层,即一步一步…

Windows核心编程 进程间通信

目录 进程间通信概述 发送消息 WM_COPYDATA DLL共享段 文件映射 文件相关API CreateFile ReadFile WriteFile CloseHandle SetFilePointerEx 设置文件指针 获取文件大小 GetFileSize 结构体 LARGE_INTEGER 文件映射用于读写文件数据 文件映射用于进程间通信(带文…

百度搜索框中的下拉提示关键词提取

效果图 代码有点多,绑定资源了 导出excel如下 贴心养眼背景图鼠标点击小爱心

pat实现基于邻接矩阵表示的深度优先遍历

void DFS(Graph G, int v) {visited[v] 1;printf("%c ", G.vexs[v]);for (int i 0; i < G.vexnum; i) {if (!visited[i] && G.arcs[v][i]) DFS(G, i);} }

C# 读写FDX-B(ISO11784/85)动物标签源码

本示例使用的发卡器&#xff1a;EM4305 EM4469 ISO11784/85协议125K低频FXD-B动物标签读写发卡器-淘宝网 (taobao.com) using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using S…

API 设计:使用 Node.js 和 Express.js 的综合教程

API&#xff08;应用程序编程接口&#xff09;设计涉及创建一个高效而强大的接口&#xff0c;允许不同的软件应用程序相互交互。 说明 本教程将指导您使用 Node.js 和 Express.js 作为核心技术来规划、设计和构建 API。但是&#xff0c;这些原则可以应用于任何语言或框架。我们…

APP软件外包开发需要注意的问题

在进行APP软件开发时&#xff0c;有一些关键问题需要特别注意&#xff0c;以确保项目的成功和用户满意度。以下是一些需要注意的问题&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 清晰的需求定义&a…

详解STUN与TR111

STUN协议定义了三类测试过程来检测NAT类型&#xff1a; Test1&#xff1a;STUN Client通过端口{IP-C1:Port-C1}向STUN Server{IP-S1:Port-S1}发送一个Binding Request&#xff08;没有设置任何属性&#xff09;。STUN Server收到该请求后&#xff0c;通过端口{IP-S1:Port-S1}把…

统计二叉树中的伪回文路径 : 用位运用来加速??

题目描述 这是 LeetCode 上的 「1457. 二叉树中的伪回文路径」 &#xff0c;难度为 「中等」。 Tag : 「DFS」、「位运算」 给你一棵二叉树&#xff0c;每个节点的值为 1 到 9 。 我们称二叉树中的一条路径是 「伪回文」的&#xff0c;当它满足&#xff1a;路径经过的所有节点值…

一个正整数转为2进制和8进制,1的个数相同的第23个数是什么?

package cn.com;import java.lang.*;//默认加载public class C2 {//10进制转8进制static int HtoO(int n){int cnt 0;while(n!0){cntn%8;n/8;}return cnt;}//10进制转2进制static int HtoB(int n){int cnt 0;while(n!0){cntn%2;n/2;}return cnt;}public static void main(Str…

Windows服务设置多个服务依赖项避免服务启动失败找不到数据库

添加多个服务依赖项建议通过命令行的方式添加&#xff1a; winr键打开命令行 cmd 命令行添加命令如下&#xff1a; sc config "thinvent-auth" depend "MySQL57"/"RabbitMQ"/"Redis" sc config "服务A" depend "服务…

C#,《小白学程序》第十四课:随机数(Random)第一,几种随机数的计算方法与代码

1 文本格式 /// <summary> /// 《小白学程序》第十四课&#xff1a;随机数&#xff08;Random&#xff09;第一&#xff0c;几种随机数的计算方法与代码 /// 本课初步接触一下随机数。 /// </summary> /// <param name"sender"></param> ///…

LiveVIS视图库1400-如何切换数据库?默认使用的数据库是什么?如何切换到Mysql/MariaDB?

LiveVIS视图库1400-如何切换数据库&#xff1f;默认使用的数据库是什么&#xff1f;如何切换到Mysql/MariaDB? 1、切换成Mysql/Mariadb数据库1.1 连接数据库1.2 创建数据库实例1.3 配置.ini文件1.4 重启完成切换 1、切换成Mysql/Mariadb数据库 LiveVIS 默认使用 sqlite3 文件…

重新开启GPT Plus充值通道——基于前端开发者工具

chatGPT PLUS充值通道的关闭 由于chatGPT用户激增&#xff0c;近日&#xff0c;OpenAI的CEO Sam Altman宣布需要暂停新用户对ChatGPT Plus的订阅。在X上&#xff0c;他表达了对于确保用户体验的承诺&#xff0c;同时也提到了用户可以通过应用程序内的通知功能来了解服务恢复的…

笔记本电脑可以投屏到电视吗?Win、Mac、Linux分别怎么投屏?

如果你的电视是安卓电视&#xff0c;那么答案是&#xff1a;完全可以&#xff01; 不管你的笔记本电脑是Windows系统、macOS系统还是Linux系统&#xff0c;你都可以借助AirDroid Cast的电脑客户端或网页版&#xff0c;将电脑屏幕投屏到安卓智能电视上。 首先&#xff0c;你需要…

Unity技美35——再URP管线环境下,配置post后期效果插件(post processing)

前两年在我的unity文章第10篇写过&#xff0c;后效滤镜的使用&#xff0c;那时候大部分项目用的还是unity的基础管线&#xff0c;stander管线。 但是现在随着unity的发展&#xff0c;大部分项目都用了URO管线&#xff0c;甚至很多PC端用的都是高效果的HDRP管线&#xff0c;这就…

网络数据结构skb_buff原理

skb_buff基本原理 内核中sk_buff结构体在各层协议之间传输不是用拷贝sk_buff结构体&#xff0c;而是通过增加协议头和移动指针来操作的。如果是从L4传输到L2&#xff0c;则是通过往sk_buff结构体中增加该层协议头来操作&#xff1b;如果是从L4到L2&#xff0c;则是通过移动sk_…

井盖位移传感器怎么监测井盖安全

井盖在城市基础设施建设中扮演着不可或缺的角色&#xff0c;虽然看似并不起眼但确实是城市规划中一个重要的组成部分。在城市规划建设之初都需要首先考虑排水系统的设计&#xff0c;而井盖作为排水系统的一个重要组成部分&#xff0c;一旦出现问题便会造成交通中断或者环境受影…