【遥感】遥感影像中的QA波段(质量评估波段)存储方式介绍

导语:

在遥感图像处理过程中,我们常使用的波段有可见光、红外、微波等波段。但是,在获取Landsat、Sentinel等卫星影像数据时,往往有其他波段影像存在,QA波段就是其中之一。QA波段是什么,它又有什么作用呢?


文件信息介绍

图1是Landsat卫星OLI影像文件的主要数据信息。从文件名可以分析出这是一景Landsat8的矫正等级Level2的影像,行列号为132027,时间是2019年8月16日,处理时间是2020年8月27日(从最后的修改日期也可以看出),产品级别为Collecton 2 Tier 1。
【遥感】遥感影像中的QA波段(质量评估波段)存储方式介绍_第1张图片
图1 Landsat 8数据内容


波段数据可视化


正如导语所说,我们常用的Landsat 8影像数据有B1-B7(第1-7波段),但也有其他波段存在,其中QA_PIXEL(QA波段)是Landsat5-8每个产品中都存在的。下面代码展示了影像QA波段读入和展示的过程。

from osgeo import gdal
import os
import matplotlib.pyplot as plt
import numpy as np
os.chdir(r'D:\Users\Administrator\Downloads\LC08_L2SP_132027_20190816_20200827_02_T1')
def readtiff(fileName):
    """
        输入:影像文件名
        输出:numpy格式数据
    """
    dataset = gdal.Open(fileName)
    im_width = dataset.RasterXSize #列数
    im_height = dataset.RasterYSize #行数
    im_bands = dataset.RasterCount #波段数
    im_data = dataset.ReadAsArray(0,0,im_width,im_height)
    return im_data
def stretch_2_precentage(gray):
    """
        输入:灰度图像
        输出:2%线性拉伸之后的图像
    """
    high_value = np.percentile(gray, 98)#98%
    low_value = np.percentile(gray, 2)#2%
    min_v = gray.min()
    max_v = gray.max()
    streched_gray = np.clip(gray, a_min=low_value, a_max=high_value) 
    results = ((streched_gray - low_value)/(high_value - low_value))
    return results
data = readtiff(r'LC08_L2SP_132027_20190816_20200827_02_T1_QA_PIXEL.TIF')
plt.figure(figsize=(10,10))
plt.imshow(stretch_2_precentage(data),'gray')
plt.axis("off")
plt.show()

【遥感】遥感影像中的QA波段(质量评估波段)存储方式介绍_第2张图片
图2 标准假彩色合成波段
【遥感】遥感影像中的QA波段(质量评估波段)存储方式介绍_第3张图片
图3 QA波段


QA波段介绍

QA波段即Quality Assessment Band,是利用FMASK算法得到的影像质量评估数据,对比图2、图3不难发现其中包含了云、云影、卷云、水体等信息。该波段与其他常用波段的差异主要在,(1)QA波段是一种产品,是FMASK算法得到的地物信息产品,其他常用波段是观测数据。(2)QA波段数据是间断的,其数值的大小没有可比较的意义。而可见光、红外等波段是连续,其数值的大小表示了地物反射率、发射率的大小。(3)QA波段是二进制数据转十进制实现的。赋予二进制不同位置数值的含义,最后转成十进制。其思想与机器学习中的one-hot编码有异曲同工之妙。
表1 QA波段各位数信息

位数 信息
Bit 0 Fill
Bit 1 Dilated Cloud
Bit 2 Cirrus (high confidence)
Bit 3 Cloud
Bit 4 Cloud Shadow
Bit 5 Snow
Bit 6 Clear
0 Cloud or Dilated Cloud bits are set
1 Cloud and Dilated Cloud bits are not set
Bit 7 Water
Bits 8-9 Cloud Confidence
0 None
1 Low
2 Medium
3 High
Bits 10-11 Cloud Shadow Confidence
0 None
1 Low
2 Medium
3 High
Bits 12-13 Snow/Ice Confidence
0 None
1 Low
2 Medium
3 High
Bits 14-15 Cirrus Confidence
0 None
1 Low
2 Medium
3 High

如上表所示,不同bit记录了不同地物信息。其中,0-7位记录了地物类型,包括云、云影、水体、冰雪等。8-15位则记录了云、云影、冰雪、卷云地类的可能性,由两位组成,00,01,10,11分别表示无、低、中、高四种可能性。下面举个例子以便更详细了解QA波段(以前8bit为例)。


QA波段操作实例


假设pixel-qa波段中一个像元值为173(以前8bit为例),则其转换为二进制数据为10101101,则如表3所示,该像元包含了水体,雪,云,卷云。

表3 二进制数据含义
【遥感】遥感影像中的QA波段(质量评估波段)存储方式介绍_第4张图片
因此,在去云过程中,我们常利用QA波段进行云提取。因为这些信息是按位存储的,所以也需要进行按位运算。表4记录了像元是云的可能性,其余位数不考虑。
**表4 **
【遥感】遥感影像中的QA波段(质量评估波段)存储方式介绍_第5张图片
这里主要有rightShift和bitWiseAnd两种按位运算的参与。其中rightShift表示按位右移。例如“01100110”,按位右移一位为“0110011”,右移三位为““01100”。bitWiseAnd表示同一位数都为1则返回该位数为1,否则返回0。例如,bitWiseAnd运算“01100110”与“1101”,返回值为“0100”,bitWiseAnd运算“01100110”与“01001011”,返回值为“01000010”。因此判断像元是否为云,可以通过righShift(1)右移一位,再与15(“1111”)做bitWiseAnd运算,若返回值为0,则表示该区域无云,反之可能存在云/云影/卷云/扩散云。去云代码如下所示:

def cloud(data):
    """
        提取云
        输入:原始pixel_qa数据
        输出:云掩膜
    """
    return np.bitwise_and(np.right_shift(data,1),15) == 0
def cloud_free(cloud, img):
    """
        对影像掩膜
        输入:云掩膜,图像数据
        输出:掩膜后的影像
    """
    re = []
    for i in range(7):
        re.append(img[:,:,i]*cloud)
    return np.array(re).transpose([1,2,0])
c = cloud(data)
f_img = cloud_free(c, y)
plt.figure(figsize=(10,10))
plt.imshow(c,'gray')
plt.axis('off')
plt.figure(figsize=(10,10))
plt.imshow(f_img[:,:,4:1:-1])
plt.axis("off")

【遥感】遥感影像中的QA波段(质量评估波段)存储方式介绍_第6张图片
图4 云掩膜
【遥感】遥感影像中的QA波段(质量评估波段)存储方式介绍_第7张图片
图5 去云影像

经过上述步骤,就得到了一景去云影像,若要获得该区域的无云影像,则需要对不同时间该位置影像做去云处理,然后镶嵌。这种数据量比较大的操作建议在Google Earth Engine中操作。
同样的,若要获得单景影像的水体信息,也可以利用上述方式得到。代码如下:

water = np.bitwise_and(np.right_shift(data,7),1)
plt.figure(figsize=(10,10))
plt.imshow(water,'gray')
plt.axis('off')
plt.show()

【遥感】遥感影像中的QA波段(质量评估波段)存储方式介绍_第8张图片
图6 水体提取结果

所有代码如下:

from osgeo import gdal
import os
import matplotlib.pyplot as plt
import numpy as np
os.chdir(r'D:\Users\Administrator\Downloads\LC08_L2SP_132027_20190816_20200827_02_T1')
def readtiff(fileName):
    """
        输入:影像文件名
        输出:numpy格式数据
    """
    dataset = gdal.Open(fileName)
    im_width = dataset.RasterXSize #列数
    im_height = dataset.RasterYSize #行数
    im_bands = dataset.RasterCount #波段数
    im_data = dataset.ReadAsArray(0,0,im_width,im_height)
    return im_data
def stretch_2_precentage(gray):
    """
        输入:灰度图像
        输出:2%线性拉伸之后的图像
    """
    high_value = np.percentile(gray, 98)#98%
    low_value = np.percentile(gray, 2)#2%
    min_v = gray.min()
    max_v = gray.max()
    streched_gray = np.clip(gray, a_min=low_value, a_max=high_value) 
    results = ((streched_gray - low_value)/(high_value - low_value))
    return results
data = readtiff(r'LC08_L2SP_132027_20190816_20200827_02_T1_QA_PIXEL.TIF')
plt.figure(figsize=(10,10))
plt.imshow(stretch_2_precentage(data),'gray')
plt.axis("off")
plt.show()
def read_multibands_tiff(fileName):
    """
        输入:影像文件名
        输出:numpy格式数据
    """
    
    re = []
    for i in range(7):
        dataset = gdal.Open(fileName+str(i+1)+".TIF")
        im_width = dataset.RasterXSize #列数
        im_height = dataset.RasterYSize #行数
        im = dataset.ReadAsArray(0,0,im_width,im_height)
        re.append(im)
    return np.array(re)
y = read_multibands_tiff(r'LC08_L2SP_132027_20190816_20200827_02_T1_SR_B')
re = []
for i in y:
    re.append(stretch_2_precentage(i))
y = np.array(re).transpose([1,2,0])
plt.figure(figsize=(10,10))
plt.imshow(y[:,:,4:1:-1])
plt.axis('off')
def cloud(data):
    """
        提取云
        输入:原始pixel_qa数据
        输出:云掩膜
    """
    return np.bitwise_and(np.right_shift(data,1),15) == 0
def cloud_free(cloud, img):
    """
        对影像掩膜
        输入:云掩膜,图像数据
        输出:掩膜后的影像
    """
    re = []
    for i in range(7):
        re.append(img[:,:,i]*cloud)
    return np.array(re).transpose([1,2,0])
c = cloud(data)
f_img = cloud_free(c, y)
plt.figure(figsize=(10,10))
plt.imshow(c,'gray')
plt.axis('off')
plt.figure(figsize=(10,10))
plt.imshow(f_img[:,:,4:1:-1])
plt.axis("off")
water = np.bitwise_and(np.right_shift(data,7),1)
plt.figure(figsize=(10,10))
plt.imshow(water,'gray')
plt.axis('off')
plt.show()

参考文献:

[1] Landsat数据下载与介绍 - icydengyw - 博客园 (cnblogs.com)
[2] Landsat Collection 1 Level-1 Quality Assessment Band | U.S. Geological Survey (usgs.gov)


你可能感兴趣的:(图像处理)