Python干货 | 制作遥感影像图

0.前言

近50年来,Landsat系列卫星为我们提供了非常长时间序列的地球表面观测信息,现阶段Landsat卫星仍然在服役,为全球治理和科学研究提供了非常宝贵的数据。

Python干货 | 制作遥感影像图_第1张图片

图源:USGS

现在是大数据时代,作为地球科学领域来说,遥感资料是不折不扣的宝贵的一手实测资料,且数据量非常的庞大。现阶段来说,可能大部分遥感资料生产的速度远远大于我们去利用它的速度,所以大部分遥感资料还是处于沉睡状态,在等待着技术的继续革新,唤醒这沉睡的数据,使其发光发热。

今天我们来探索一下使用Landsat数据来制作一张遥感影像图。先上图!图示为杭州湾 

Python干货 | 制作遥感影像图_第2张图片

东南形胜,三吴都会,钱塘自古繁华

1.准备工作

先准备下载好的Landsat8数据集,Landsat8中包括11个波段,在数据文件夹中,每个波段一个tif文件,这个tif文件中包括了坐标信息、波段值等信息,可以通过Pythonrasterio模块来读取(如果有需要的话,可以详细写一下使用这个库来读取tif文件信息)。

导入接下来要用到的Python库。

import numpy as np
import os
import matplotlib.pyplot as plt
import tifffile as tiff
from skimage import exposure

使用遥感影像制作底图时,通常是选取三个波段的数据分别作为图像RGB的三个通道,其中RGB表示红绿蓝三个通道,不同波段组合将得到不同的效果。

我们使用比较多的Google earth 中就用到了Landsat数据,他的波段组合是432。即使用Landsat的B4、B3和B2三个波段作为影像的三个通道。

上图的杭州湾图使用的是753。 

如果波段组合是432情况下的效果如下图所示,432波段合成的真彩色图片,比较接近地物真实色彩,图像平淡,色调偏暗。

Python干货 | 制作遥感影像图_第3张图片

2.动起手来

首先把Landsat各个波段的数据读取出来。用到了一丢丢Python小技能,参见:

8个你应该掌握的Python列表技能

7个你应该掌握的Python字典操作

l8path = r'pathOfLandsat8\LC08_L1TP_118039_20160126_20170330_01_T1'
fileName = l8path.split("\")[-1]
prefix = os.path.join(l8path,fileName)
bands = ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B10', 'B11']
n_bands = len(bands)
temp = tiff.imread(prefix + "_B1.TIF")
arr = np.zeros((n_bands, np.shape(temp)[0], np.shape(temp)[1]), dtype=np.float)
for i in range(n_bands):
    file2read = prefix + "_" + bands[i] + ".TIF"
    arr[i, :, :] = tiff.imread(file2read)
选取三个波段
rgb=(6, 4, 2) #Python下界为0,其实是753
rgb_bands = arr[rgb, :, :]
rgb_bands = _stretch_im(rgb_bands, 2)
rgb_bands = bytescale(rgb_bands).transpose([1, 2, 0])
plt.close('all')
fig, ax = plt.subplots(figsize=figSize)
ax.imshow(rgb_bands, extent=extent)
ax.set_title(title)
ax.set(xticks=[], yticks=[])
其中用到了两个函数,其中一个是提高图像的对比度,另外一个将波段数据归一化到像素点常用的[0,255]区间内。
def _stretch_im(arr, str_clip):
  s_min = str_clip
  s_max = 100 - str_clip
  arr_rescaled = np.zeros_like(arr)
  pLow, pHigh = np.percentile(arr[arr > 0], (s_min, s_max))
  arr_rescaled = exposure.rescale_intensity(arr, in_range=(pLow, pHigh))
  return arr_rescaled.copy()
def bytescale(data, high=255, low=0, cmin=None, cmax=None):
  if data.dtype == "uint8":
    return data
  if high > 255:
    raise ValueError("high should be less than or equal to 255.")
  if low < 0:
    raise ValueError("low should be greater than or equal to 0.")
  if high < low:
    raise ValueError("high should be greater than or equal to low.")
  if cmin is None or (cmin < data.min()):
    cmin = float(data.min())
  if (cmax is None) or (cmax > data.max()):
    cmax = float(data.max())
  # Calculate range of values
  crange = cmax - cmin
  if crange < 0:
    raise ValueError("cmax should be larger than cmin.")
  elif crange == 0:
    raise ValueError(
      "cmax and cmin should not be the same value. Please specify "
      "cmax > cmin"
    )
  scale = float(high - low) / crange
  # If cmax is less than the data max, then this scale parameter will create
  # data > 1.0. clip the data to cmax first.
  data[data > cmax] = cmax
  bytedata = (data - cmin) * scale + low
  return (bytedata.clip(low, high) + 0.5).astype("uint8")

3.小结

大功告成!

这个遥感影像图,可以作为我们出图的底图,还可以实现两张遥感影像图的融合,在影像图上叠加自己想要叠加的数据,欲知详情,且听下回分解....

因遥感数据较大,关注公众号 海洋纪 ,后台回复 Landsat   获取数据及源码。

Tips:不同波段组合情况可以实现不同的效果,大家可以自己试试看。如543,652,765等。

最后,感谢阅读。

你可能感兴趣的:(Python,python,大数据)