FY-4A建立中国区域图像行列号转经纬度的经纬度查找表进行几何校正

自从数据发布以来局部中国区域文件官方只给出了图像文件,并未给出对应的经纬度查找表,而对于只研究中国区域的同学来说,下载全圆盘图像文件显得费时费力,然后处理起来又占据内存。为了对中国区域图像文件进行几何校正,将标称投影转为等经纬度投影,博主和同学老王进行了交流,终成此文。

下面将利用Python实现区域图像文件的经纬度查找表建立!~

将中国区域行列号转为经纬度查找表,并且存为tiff文件,band1为经度,band2为纬度。在ENVI中建立GLT,rotation选择0,即图像正上为正北方向,其他不变,然后利用GLT进行几何校正,投影选择等经纬度。其他不变。这是Python实现区域经纬度查找表tiff文件的程序。选择文件为中国区域GEO 4km定位文件。下载好4km定位文件后,自行修改后缀为HDF5!

程序路径的话,自行修改路径~

# -*- coding: utf-8 -*-
"""
Created on Tue Apr 23 11:39:02 2019

@author: Administrator
"""


import os
import numpy as np 
import math
import h5py 
import gdal
import operator

#读取FY4A-_AGRI--_N_DISK_1047E_L1-_GEO-_MULT_NOM文件,空间分辨率4km
#此程序仅限于此类文件

#该文件中仅用于获得FY4A-_AGRI--_N_REGC_1047E_L1_***_4000M_***.HDF文件
#中数据的行列号转换成经纬度

def Get_Line_Col_in_Disk(File_Full_Path):
    #print('#########################################')
    #判读输入文件是否为FY4A-_AGRI--_N_REGC_1047E_L1_***_4000M_***.HDF文件
    #如果不是,则输出文件是错误的,退出程序
    fname = os.path.basename(File_Full_Path)
    #print('fname =',fname)
                        
    str_GEO_value = fname.find('GEO')    
    #print(str_GEO_value)   
    str_REGC_value = fname.find('REGC')    
    #print(str_REGC_value) 
    str_4000M_value = fname.find('4000M')    
    #print(str_4000M_value)  
    if  str_GEO_value == -1 or str_REGC_value == -1 or str_4000M_value == -1:
        return None
    #以只读的方式打开hdf5文件
    InFile_REGC_GEO_4KM = h5py.File(File_Full_Path,'r')

    #ColumnNumber对应的数据,以numpy.ndarray方式存储
    #中国区域文件各个像点对应于全圆盘的列号
    Data_Col_Num_in_Disk_GDAL = InFile_REGC_GEO_4KM['ColumnNumber'][:]
    Data_Col_Num_in_Disk = Data_Col_Num_in_Disk_GDAL.astype('f4') 
    print(Data_Col_Num_in_Disk_GDAL.dtype)
    print(Data_Col_Num_in_Disk.dtype)
    
    #LineNumber对应的数据,以numpy.ndarray方式存储
    #中国区域文件各个像点对应于全圆盘的行号
    Data_Line_Num_in_Disk_GDAL = InFile_REGC_GEO_4KM['LineNumber'][:]
    Data_Line_Num_in_Disk = Data_Line_Num_in_Disk_GDAL.astype('f4')
    
    InFile_REGC_GEO_4KM.close() 
    return Data_Line_Num_in_Disk,Data_Col_Num_in_Disk
    
def Convert_Line_Col_To_Lon_Lat(Data_Line_Num_in_Disk,Data_Col_Num_in_Disk):
    #print('##########################################')  
    ##根据中国区域在全圆盘中的行列号计算经纬度
    #注意:各个文件中在全圆盘的行列号会有所不同
    #中国区域内的有效行列号
           
    Valid_Value_Index = np.where(Data_Line_Num_in_Disk != -1.0 )
    Line = Data_Line_Num_in_Disk[Valid_Value_Index]     
    Column = Data_Col_Num_in_Disk[Valid_Value_Index] 
     
   
    #地球的长半轴,单位km
    ea = 6378.137
    #地球的短半轴,单位km
    eb = 6356.7523
    #地心到卫星质心的距离,单位km
    h = 42164
    #卫星星下点的经度
    Lon_Sate = 104.7
    #COFF全圆盘列偏移,4km对应的数值
    COFF = 1373.5
    #CFAC全圆盘列比例因子,4km对应的数值
    CFAC = 10233137
    #LOFF全圆盘行偏移,4km对应的数值
    LOFF = 1373.5
    #LFAC全圆盘列比例因子,4km对应的数值
    LFAC = 10233137
    
    tmp = np.pi/(180*math.pow(2,-16))
    #print('tmp =',tmp)
    
    x = tmp * (Column - COFF)/CFAC
    #print('x =',x)
    
    y = tmp * (Line - LOFF)/LFAC
    #print('y =',y)

    sinx = np.sin(x)
    cosx = np.cos(x)
    siny = np.sin(y)
    cosy = np.cos(y)
    
    cosxy = cosx * cosy
    tmp2 = cosy*cosy + siny*siny * ea*ea /(eb*eb) 
    #print('tmp2=',tmp)
    sd = np.power((h*cosxy)*(h*cosxy) - tmp2*(h*h-ea*ea),0.5)
    sn = ( h*cosxy - sd ) / tmp2
    s1 = h - sn * cosxy
    s2 = sn * sinx * cosy
    s3 = -sn * siny
    sxy = np.power(s1*s1 + s2*s2,0.5)
    
    tmp3 = 180 / np.pi
    lon = tmp3 * np.arctan(s2/s1) + Lon_Sate
    lat = tmp3 * np.arctan((ea*ea*s3)/(eb*eb*sxy))
    #print('lon =',lon)
    #print('lat =',lat)
    
    Data_Lon = np.zeros(Data_Line_Num_in_Disk.shape, dtype = np.float64,order = 'C' )
    Data_Lon[:,:] = 999    
    Data_Lon[Valid_Value_Index] = lon
        
    Data_Lat = np.zeros(Data_Line_Num_in_Disk.shape, dtype = np.float64,order = 'C' )
    Data_Lat[:,:] = 999
    Data_Lat[Valid_Value_Index] = lat 
    
    return Data_Lon,Data_Lat
    
def writeTiff(im_data,im_width,im_height,im_bands,path):#im_geotrans,im_proj,path):
    if 'int8' in im_data.dtype.name:
        datatype = gdal.GDT_Byte
    elif 'int16' in im_data.dtype.name:
        datatype = gdal.GDT_UInt16
    else:
        datatype = gdal.GDT_Float64

    if len(im_data.shape) == 3:
        im_bands, im_height, im_width = im_data.shape
    elif len(im_data.shape) == 2:
        im_data = np.array([im_data])
    else:
        im_bands, (im_height, im_width) = 1,im_data.shape
        #创建文件
    driver = gdal.GetDriverByName("GTiff")
    dataset = driver.Create(path, im_width, im_height, im_bands, datatype)
    #if(dataset!= None):
        #dataset.SetGeoTransform(im_geotrans) #写入仿射变换参数
        #dataset.SetProjection(im_proj) #写入投影
    for i in range(im_bands):
        dataset.GetRasterBand(i+1).WriteArray(im_data[i])
    del dataset
     

#主程序
if __name__ =='__main__': 
    
    GEO_File_Full_Path = 'E:\FY-4A大创\几何校正\python_FY-4A\FY4A-_AGRI--_N_REGC_1047E_L1-_GEO-_MULT_NOM_20190310003000_20190310003416_4000M_V0001.HDF5'   
    GEO_file_name = os.path.basename(GEO_File_Full_Path)
    first = GEO_file_name[44:57]
    print(first)
    second = GEO_file_name[73:79]
    print(second)
    out_name = first + second + '经纬度查找表'
  
    Data_line_col = Get_Line_Col_in_Disk(GEO_File_Full_Path)      
    Lon_Lat = Convert_Line_Col_To_Lon_Lat(Data_line_col[0],Data_line_col[1])

       
    #print(type(Lon_Lat))
    if Lon_Lat is None :
        print ('wrong file')
    #elif (id(GEO_file_name[44:73]) is not id(Ocean_file_name[44:73])):
        #print(type(GEO_file_name[44:73]))
        #print('Geo file does not match Ocean file')
    else:
        
        Lon = Lon_Lat[0] 
        Lat = Lon_Lat[1]        
    
    im_data = np.array([Lon,Lat])
    im_bands, im_height, im_width = im_data.shape
    
    #保存tif文件函数
    path = 'E:\FY-4A大创\几何校正\python_FY-4A\\'+ out_name + '.tif'
    writeTiff(im_data, im_width, im_height,im_bands,path) 

tif命名为:成像时间+空间分辨率+经纬度查找表,例如 2019031000300_4000M经纬度查找表.tif

生成的查找表如图:
在这里插入图片描述
band1为经度,band2为纬度
建立GLT的过程参考链接[3],在建立GLT的过程中一定要注意,要先对生成的经纬度查找表做一个感兴趣区域的裁剪,用ENVI Resize Data(special/spectral)工具进行,裁剪一个矩形的就好,既包括研究区又要大一些,不可以取到外围999的无效值,ENVI在建立GLT的过程中,一旦有外围999的无效值在,建立GLT时就会产生一个巨大无比的文件,并且一段时间后磁盘爆满,电脑未响应死机。
在这里插入图片描述
利用GLT工具几何校正结果如图:
在这里插入图片描述
在这里插入图片描述
这样的话整个过程不超过5分钟!
博主用的是4km区域定位文件(GEO文件):
FY4A-_AGRI–_N_REGC_1047E_L1-_GEO-_MULT_NOM_20190310003000_20190310003416_4000M_V0001

博主用的3月10号的定位文件对3月8号的区域图像进行的几何校正,效果完全可以。不过据说,每次的区域文件严格地讲,其大小会有一两个像元的偏差。

写入tiff部分的程序鸣谢train_for_skills参考:
[1]: https://blog.csdn.net/t46414704152abc/article/details/77482747
[2]:http://satellite.nsmc.org.cn/PortalSite/StaticContent/DocumentDownload.aspx?TypeID=3
[3]:http://blog.sina.com.cn/s/blog_764b1e9d0101da96.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章